From 3b15c6f10fe0c205a6a2c263483eb896e13cc79d Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 13 Jun 2000 19:56:15 +0000 Subject: [PATCH] Merge latest devel codes into releng 2 branch. Remove back-perl, back-sql, back-tcl from branch as they have yet to be updated. Additional changes are needed prior to release of alpha4. --- ANNOUNCEMENT | 155 +- COPYRIGHT | 2 +- INSTALL | 11 +- LICENSE | 51 + Makefile.in | 5 +- README | 53 +- acconfig.h | 22 +- acinclude.m4 | 3 +- aclocal.m4 | 16 +- build/build.dsp | 172 + build/build.mak | 10 + build/dir.mk | 7 +- build/info.mk | 2 +- build/install-sh | 2 +- build/lib-shared.mk | 41 +- build/lib-static.mk | 4 +- build/lib.mk | 5 +- build/ltconfig | 3069 ++++++++ build/ltmain.sh | 63 +- build/main.dsw | 91 +- build/man.mk | 12 +- build/mkdep | 2 +- build/mkdep.aix | 4 + build/mkrelease | 3 +- build/mkversion | 4 +- build/mod.mk | 32 +- build/openldap.m4 | 442 +- build/rules.mk | 5 +- build/srv.mk | 4 +- build/top.mk | 42 +- build/version | 2 +- clients/Makefile.in | 4 +- clients/fax500/Makefile.in | 17 +- clients/fax500/main.c | 10 +- clients/finger/Makefile.in | 14 +- clients/finger/main.c | 6 +- clients/gopher/Makefile.in | 20 +- clients/gopher/go500.c | 15 +- clients/gopher/go500gw.c | 19 +- clients/mail500/Makefile.in | 13 +- clients/mail500/README | 20 +- clients/mail500/mail500.m4 | 51 + clients/mail500/main.c | 1668 ++--- clients/mail500/sendmail.cf | 5 + clients/maildap/Makefile.in | 31 + clients/maildap/README | 357 + clients/maildap/maildap.m4 | 53 + clients/maildap/main.c | 2062 ++++++ clients/rcpt500/Makefile.in | 18 +- clients/rcpt500/cmds.c | 2 +- clients/rcpt500/main.c | 16 +- clients/rcpt500/rcpt500.h | 2 +- clients/tools/Makefile.in | 23 +- clients/tools/ldapdelete.c | 307 +- clients/tools/ldapdelete.dsp | 149 + clients/tools/ldapmodify.c | 240 +- clients/tools/ldapmodify.dsp | 149 + clients/tools/ldapmodrdn.c | 257 +- clients/tools/ldapmodrdn.dsp | 149 + clients/tools/ldappasswd.c | 866 +-- clients/tools/ldappasswd.dsp | 145 + clients/tools/ldapsearch.c | 275 +- clients/tools/ldapsearch.dsp | 149 + clients/ud/Makefile.in | 17 +- clients/ud/auth.c | 37 +- clients/ud/edit.c | 34 +- clients/ud/find.c | 33 +- clients/ud/globals.c | 13 +- clients/ud/group.c | 14 +- clients/ud/help.c | 4 + clients/ud/main.c | 17 +- clients/ud/mod.c | 35 +- clients/ud/print.c | 22 +- clients/ud/string_to_key.c | 17 +- clients/ud/ud.dsp | 188 + clients/ud/ud.h | 15 +- clients/ud/util.c | 12 +- configure | 6200 ++++++++++------- configure.in | 841 ++- contrib/Makefile.in | 2 +- contrib/README | 34 +- contrib/gtk-tool/COPYRIGHT | 8 + contrib/gtk-tool/ChangeLog | 95 + contrib/gtk-tool/Gtk_LdapServer.cc | 446 ++ contrib/gtk-tool/Gtk_LdapServer.h | 53 + contrib/gtk-tool/Gtk_LdapTree.cc | 26 + contrib/gtk-tool/Gtk_LdapTreeItem.cc | 376 + contrib/gtk-tool/Gtk_LdapTreeItem.h | 83 + contrib/gtk-tool/INSTALL | 13 + contrib/gtk-tool/Makefile | 32 + contrib/gtk-tool/My_Window.cc | 187 + contrib/gtk-tool/My_Window.h | 30 + contrib/gtk-tool/README | 39 + contrib/gtk-tool/TODO | 18 + contrib/gtk-tool/common.h | 13 + contrib/gtk-tool/cpluscommon.h | 10 + contrib/gtk-tool/gtk.h | 14 + contrib/gtk-tool/icons/monitor.h | 286 + contrib/gtk-tool/main.cc | 113 + contrib/gtk-tool/utils.cc | 17 + contrib/ldaptcl/Makefile.in | 10 +- contrib/ldaptcl/configure.in | 2 +- contrib/ldaptcl/ldap.n | 373 + contrib/ldaptcl/neoXldap.c | 385 +- contrib/ldaptcl/tkAppInit.c | 119 + contrib/php3-tool/COPYRIGHT | 8 + contrib/php3-tool/index.php3 | 111 + contrib/saucer/Makefile.in | 8 +- contrib/saucer/main.c | 2 +- contrib/tweb/Makefile.openldap | 9 +- contrib/tweb/README | 15 +- contrib/tweb/dn.c | 16 +- contrib/tweb/html.c | 4 +- contrib/tweb/queries.c | 53 +- contrib/tweb/tgeneral.h | 22 +- contrib/tweb/tglobal.h | 15 +- contrib/tweb/tweb.h | 17 +- contrib/tweb/x500.c | 58 +- contrib/web_ldap/Makefile.in | 4 +- contrib/whois++/Makefile | 29 +- contrib/whois++/whois++.c | 14 +- doc/Makefile.in | 2 +- doc/devel/asn-layman.txt | 1855 +++++ doc/devel/guidelines | 110 + doc/drafts/README | 8 + doc/drafts/draft-good-ldap-ldif-xx.txt | 609 +- .../draft-ietf-asid-ldapv3-attributes-03.txt | 2261 ++++++ .../draft-ietf-ldapext-acl-model-xx.txt | 2075 +++--- doc/drafts/draft-ietf-ldapext-authmeth-xx.txt | 784 --- .../draft-ietf-ldapext-ldap-c-api-xx.txt | 3032 ++++---- .../draft-ietf-ldapext-ldapv3-vlv-xx.txt | 655 ++ doc/drafts/draft-ietf-ldapext-locate-xx.txt | 205 + doc/drafts/draft-ietf-ldapext-sorting-xx.txt | 303 + doc/drafts/draft-ietf-ldup-framing-xx.txt | 340 + doc/drafts/draft-ietf-ldup-infomod-xx.txt | 1021 +++ doc/drafts/draft-ietf-ldup-model-xx.txt | 2468 +++++++ doc/drafts/draft-ietf-ldup-protocol-xx.txt | 895 +++ doc/drafts/draft-ietf-ldup-replica-req-xx.txt | 1035 +++ doc/drafts/draft-ietf-ldup-subentry-xx.txt | 132 +- doc/drafts/draft-ietf-ldup-urp-xx.txt | 1554 +++++ ...aft-lachman-laser-ldap-mail-routing-xx.txt | 615 ++ doc/drafts/draft-leach-uuids-guids-01.txt | 1708 +++++ .../draft-rharrison-ldap-extpartresp-xx.txt | 176 + .../draft-smith-ldap-c-api-ext-vlv-xx.txt | 468 ++ doc/man/Makefile.in | 6 + doc/man/man1/Makefile.in | 6 + doc/man/man1/ldapdelete.1 | 65 +- doc/man/man1/ldapmodify.1 | 79 +- doc/man/man1/ldapmodrdn.1 | 59 +- doc/man/man1/ldappasswd.1 | 151 + doc/man/man1/ldapsearch.1 | 59 +- doc/man/man1/ud.1 | 31 +- doc/man/man3/Makefile.in | 6 + doc/man/man3/cldap_close.3 | 11 +- doc/man/man3/cldap_open.3 | 11 +- doc/man/man3/cldap_search_s.3 | 11 +- doc/man/man3/cldap_setretryinfo.3 | 11 +- doc/man/man3/lber-decode.3 | 242 +- doc/man/man3/lber-decode.3.links | 13 + doc/man/man3/lber-encode.3 | 175 +- doc/man/man3/lber-encode.3.links | 11 + doc/man/man3/ldap.3 | 30 +- doc/man/man3/ldap_abandon.3 | 11 +- doc/man/man3/ldap_add.3 | 11 +- doc/man/man3/ldap_bind.3 | 11 +- doc/man/man3/ldap_cache.3 | 11 +- doc/man/man3/ldap_charset.3 | 13 +- doc/man/man3/ldap_compare.3 | 11 +- doc/man/man3/ldap_delete.3 | 11 +- doc/man/man3/ldap_disptmpl.3 | 10 +- doc/man/man3/ldap_entry2text.3 | 11 +- doc/man/man3/ldap_error.3 | 16 +- doc/man/man3/ldap_first_attribute.3 | 28 +- doc/man/man3/ldap_first_entry.3 | 11 +- doc/man/man3/ldap_friendly.3 | 29 +- doc/man/man3/ldap_get_dn.3 | 48 +- doc/man/man3/ldap_get_values.3 | 14 +- doc/man/man3/ldap_getfilter.3 | 15 +- doc/man/man3/ldap_modify.3 | 11 +- doc/man/man3/ldap_modrdn.3 | 11 +- doc/man/man3/ldap_open.3 | 15 +- doc/man/man3/ldap_result.3 | 37 +- doc/man/man3/ldap_schema.3 | 328 + doc/man/man3/ldap_schema.3.links | 17 + doc/man/man3/ldap_search.3 | 27 +- doc/man/man3/ldap_searchprefs.3 | 10 +- doc/man/man3/ldap_sort.3 | 15 +- doc/man/man3/ldap_ufn.3 | 15 +- doc/man/man3/ldap_url.3 | 15 +- doc/man/man5/Makefile.in | 6 + doc/man/man5/ldap.conf.5 | 19 +- doc/man/man5/ldapfilter.conf.5 | 10 +- doc/man/man5/ldapfriendly.5 | 20 +- doc/man/man5/ldapsearchprefs.conf.5 | 10 +- doc/man/man5/ldaptemplates.conf.5 | 3 + doc/man/man5/ldif.5 | 3 + doc/man/man5/slapd.conf.5 | 108 +- doc/man/man5/slapd.replog.5 | 10 +- doc/man/man5/ud.conf.5 | 22 +- doc/man/man8/Makefile.in | 6 + doc/man/man8/centipede.8 | 16 +- doc/man/man8/chlog2replog.8 | 18 +- doc/man/man8/edb2ldif.8 | 3 + doc/man/man8/go500.8 | 20 +- doc/man/man8/go500gw.8 | 20 +- doc/man/man8/in.xfingerd.8 | 14 +- doc/man/man8/ldif.8 | 3 + doc/man/man8/mail500.8 | 18 +- doc/man/man8/rcpt500.8 | 16 +- doc/man/man8/slapadd.8 | 3 + doc/man/man8/slapcat.8 | 3 + doc/man/man8/slapd.8 | 35 +- doc/man/man8/slurpd.8 | 3 + doc/rfc/rfc1488.txt | 619 -- doc/rfc/rfc1558.txt | 171 - doc/rfc/rfc2119.txt | 171 + doc/rfc/rfc2222.txt | 899 +++ doc/rfc/rfc2649.txt | 563 ++ doc/rfc/rfc2657.txt | 675 ++ doc/rfc/rfc2696.txt | 395 ++ doc/rfc/rfc2713.txt | 1179 ++++ doc/rfc/rfc2714.txt | 563 ++ doc/rfc/rfc2798.txt | 1123 +++ doc/rfc/rfc2829.txt | 899 +++ doc/rfc/rfc2830.txt | 675 ++ doc/rfc/rfc2831.txt | 1515 ++++ include/Makefile.in | 17 +- include/ac/alloca.h | 2 +- include/ac/assert.h | 6 +- include/ac/bytes.h | 23 +- include/ac/crypt.h | 25 + include/ac/ctype.h | 2 +- include/ac/dirent.h | 2 +- include/ac/errno.h | 8 +- include/ac/krb.h | 8 +- include/ac/krb5.h | 22 + include/ac/param.h | 26 + include/ac/regex.h | 2 +- include/ac/setproctitle.h | 8 +- include/ac/signal.h | 8 +- include/ac/socket.h | 41 +- include/ac/stdarg.h | 2 +- include/ac/stdlib.h | 2 +- include/ac/string.h | 19 +- include/ac/sysexits.h | 2 +- include/ac/syslog.h | 2 +- include/ac/termios.h | 2 +- include/ac/time.h | 2 +- include/ac/unistd.h | 36 +- include/ac/wait.h | 2 +- include/avl.h | 24 +- include/disptmpl.h | 38 +- include/getopt-compat.h | 19 +- include/lber.h | 354 +- include/lber_pvt.h | 34 +- include/lber_types.h.in | 35 +- include/lber_types.nt | 42 +- include/ldap.h | 818 ++- include/ldap_cdefs.h | 77 +- include/ldap_config.h.in | 6 +- include/ldap_config.nt | 4 +- include/ldap_defaults.h | 24 +- include/ldap_features.h.in | 12 +- include/ldap_features.nt | 13 +- include/ldap_int_thread.h | 201 + include/ldap_log.h | 8 +- include/ldap_pvt.h | 149 +- include/ldap_pvt_thread.h | 274 +- include/ldap_schema.h | 68 +- include/ldbm.h | 182 +- include/ldif.h | 19 +- include/lutil.h | 62 +- include/lutil_lockf.h | 6 +- include/lutil_md5.h | 28 +- include/lutil_sha1.h | 21 +- include/portable.h.in | 233 +- include/portable.nt | 68 +- include/setup.dsp | 97 +- include/setup.mak | 2 +- include/srchpref.h | 12 +- include/sysexits-compat.h | 2 +- libraries/Makefile.in | 6 +- libraries/libavl/Makefile.in | 2 + libraries/libavl/avl.c | 2 +- libraries/libavl/libavl.dsp | 137 + libraries/libavl/testavl.c | 4 + libraries/libavl/testavl.dsp | 143 + libraries/liblber/Makefile.in | 24 +- libraries/liblber/assert.c | 2 +- libraries/liblber/bprint.c | 58 +- libraries/liblber/decode.c | 122 +- libraries/liblber/dtest.c | 8 +- libraries/liblber/dtest.dsp | 200 + libraries/liblber/encode.c | 152 +- libraries/liblber/etest.c | 6 +- libraries/liblber/etest.dsp | 145 + libraries/liblber/idtest.c | 2 +- libraries/liblber/io.c | 95 +- libraries/liblber/lber-int.h | 184 +- libraries/liblber/liblber.dsp | 225 + libraries/liblber/memory.c | 186 +- libraries/{liblutil => liblber}/nt_err.c | 48 +- libraries/liblber/options.c | 44 +- libraries/liblber/sockbuf.c | 1414 ++-- libraries/libldap/Makefile.in | 52 +- libraries/libldap/abandon.c | 4 +- libraries/libldap/add.c | 2 +- libraries/libldap/addentry.c | 2 +- libraries/libldap/apitest.c | 2 +- libraries/libldap/apitest.dsp | 145 + libraries/libldap/bind.c | 19 +- libraries/libldap/cache.c | 5 +- libraries/libldap/charray.c | 14 +- libraries/libldap/charset.c | 1806 ----- libraries/libldap/cldap.c | 35 +- libraries/libldap/compare.c | 4 +- libraries/libldap/controls.c | 86 +- libraries/libldap/delete.c | 2 +- libraries/libldap/digest.c | 382 - libraries/libldap/disptmpl.c | 68 +- libraries/libldap/dn.c | 41 +- libraries/libldap/dnssrv.c | 307 + libraries/libldap/dsparse.c | 21 +- libraries/libldap/error.c | 33 +- libraries/libldap/extended.c | 29 +- libraries/libldap/free.c | 2 +- libraries/libldap/friendly.c | 2 +- libraries/libldap/getattr.c | 2 +- libraries/libldap/getdn.c | 273 +- libraries/libldap/getdxbyname.c | 199 - libraries/libldap/getentry.c | 2 +- libraries/libldap/getfilter.c | 12 +- libraries/libldap/getvalues.c | 2 +- libraries/libldap/init.c | 220 +- libraries/libldap/kbind.c | 51 +- libraries/libldap/ldap-int.h | 254 +- libraries/libldap/libldap.dsp | 60 +- libraries/libldap/ltest.dsp | 143 + libraries/libldap/messages.c | 2 +- libraries/libldap/modify.c | 2 +- libraries/libldap/modrdn.c | 33 +- libraries/libldap/open.c | 336 +- libraries/libldap/options.c | 157 +- libraries/libldap/os-ip.c | 97 +- libraries/libldap/os-local.c | 219 + libraries/libldap/print.c | 4 +- libraries/libldap/references.c | 4 +- libraries/libldap/request.c | 682 +- libraries/libldap/result.c | 172 +- libraries/libldap/sasl.c | 895 ++- libraries/libldap/sbind.c | 4 +- libraries/libldap/schema.c | 229 +- libraries/libldap/search.c | 46 +- libraries/libldap/sort.c | 10 +- libraries/libldap/sortctrl.c | 467 ++ libraries/libldap/srchpref.c | 58 +- libraries/libldap/string.c | 21 +- libraries/libldap/test.c | 78 +- libraries/libldap/tls.c | 550 +- libraries/libldap/tmplout.c | 24 +- libraries/libldap/tmpltest.c | 2 +- libraries/libldap/ufn.c | 25 +- libraries/libldap/unbind.c | 30 +- libraries/libldap/url.c | 461 +- libraries/libldap/utf-8.c | 461 ++ libraries/libldap/util-int.c | 56 +- libraries/libldap/vlvctrl.c | 280 + libraries/libldap_r/Makefile.in | 48 +- libraries/libldap_r/apitest_r.dsp | 146 + libraries/libldap_r/libldap_r.dsp | 374 + libraries/libldap_r/ltest_r.dsp | 143 + libraries/libldap_r/rdwr.c | 125 +- libraries/libldap_r/thr_cthreads.c | 6 +- libraries/libldap_r/thr_lwp.c | 16 +- libraries/libldap_r/thr_nt.c | 14 +- libraries/libldap_r/thr_posix.c | 90 +- libraries/libldap_r/thr_pth.c | 58 +- libraries/libldap_r/thr_sleep.c | 57 - libraries/libldap_r/thr_stub.c | 48 +- libraries/libldap_r/thr_thr.c | 15 +- libraries/libldap_r/threads.c | 87 + libraries/libldap_r/tpool.c | 396 ++ libraries/libldbm/Makefile.in | 6 + libraries/libldbm/ldbm.c | 227 +- libraries/libldbm/libldbm.dsp | 137 + libraries/libldif/Makefile.in | 5 + libraries/libldif/fetch.c | 2 +- libraries/libldif/libldif.dsp | 28 +- libraries/libldif/line64.c | 38 +- libraries/liblutil/Makefile.in | 34 +- libraries/liblutil/authpasswd.c | 929 +++ libraries/liblutil/base64.c | 2 +- libraries/liblutil/debug.c | 7 +- libraries/liblutil/detach.c | 42 +- libraries/liblutil/entropy.c | 151 + libraries/liblutil/getopt.c | 4 +- libraries/liblutil/getpass.c | 15 +- libraries/liblutil/liblutil.dsp | 48 +- libraries/liblutil/lockf.c | 6 +- libraries/liblutil/md5.c | 32 +- libraries/liblutil/ntservice.c | 68 +- libraries/liblutil/passwd.c | 1085 ++- libraries/liblutil/passwd.dsp | 201 + libraries/liblutil/passwd.dsw | 44 + libraries/liblutil/ptest.c | 105 + libraries/liblutil/sha1.c | 16 +- libraries/liblutil/slapdmsg.bin | Bin 0 -> 140 bytes libraries/liblutil/slapdmsg.h | 65 + libraries/liblutil/slapdmsg.rc | 2 + libraries/liblutil/sockpair.c | 4 +- libraries/liblutil/utils.c | 7 +- servers/Makefile.in | 2 +- servers/slapd/Makefile.in | 206 +- servers/slapd/abandon.c | 2 +- servers/slapd/acl.c | 1089 ++- servers/slapd/aclparse.c | 810 ++- servers/slapd/ad.c | 245 + servers/slapd/add.c | 224 +- servers/slapd/at.c | 386 + servers/slapd/attr.c | 604 +- servers/slapd/ava.c | 71 +- servers/slapd/back-bdb2/Makefile.in | 31 - servers/slapd/back-bdb2/abandon.c | 47 - servers/slapd/back-bdb2/add.c | 325 - servers/slapd/back-bdb2/alias.c | 285 - servers/slapd/back-bdb2/attr.c | 174 - servers/slapd/back-bdb2/back-bdb2.h | 207 - servers/slapd/back-bdb2/bind.c | 347 - servers/slapd/back-bdb2/cache.c | 590 -- servers/slapd/back-bdb2/close.c | 62 - servers/slapd/back-bdb2/compare.c | 136 - servers/slapd/back-bdb2/config.c | 202 - servers/slapd/back-bdb2/dbcache.c | 187 - servers/slapd/back-bdb2/delete.c | 199 - servers/slapd/back-bdb2/dn2id.c | 307 - servers/slapd/back-bdb2/entry.c | 30 - servers/slapd/back-bdb2/external.h | 77 - servers/slapd/back-bdb2/filterindex.c | 369 - servers/slapd/back-bdb2/group.c | 182 - servers/slapd/back-bdb2/id2children.c | 55 - servers/slapd/back-bdb2/id2entry.c | 179 - servers/slapd/back-bdb2/idl.c | 1050 --- servers/slapd/back-bdb2/index.c | 379 - servers/slapd/back-bdb2/init.c | 240 - servers/slapd/back-bdb2/kerberos.c | 49 - servers/slapd/back-bdb2/modify.c | 323 - servers/slapd/back-bdb2/modrdn.c | 510 -- servers/slapd/back-bdb2/nextid.c | 74 - servers/slapd/back-bdb2/porter.c | 143 - servers/slapd/back-bdb2/proto-back-bdb2.h | 251 - servers/slapd/back-bdb2/search.c | 482 -- servers/slapd/back-bdb2/startup.c | 260 - servers/slapd/back-bdb2/timing.c | 70 - servers/slapd/back-bdb2/tools.c | 249 - servers/slapd/back-bdb2/txn.c | 825 --- servers/slapd/back-bdb2/txn.h | 51 - servers/slapd/back-bdb2/unbind.c | 39 - servers/slapd/back-dnssrv/Makefile.in | 34 + servers/slapd/back-dnssrv/add.c | 28 + servers/slapd/back-dnssrv/back-dnssrv.h | 29 + servers/slapd/back-dnssrv/bind.c | 59 + servers/slapd/back-dnssrv/compare.c | 30 + servers/slapd/back-dnssrv/config.c | 43 + servers/slapd/back-dnssrv/delete.c | 30 + servers/slapd/back-dnssrv/external.h | 63 + servers/slapd/back-dnssrv/init.c | 122 + servers/slapd/back-dnssrv/modify.c | 31 + servers/slapd/back-dnssrv/modrdn.c | 32 + servers/slapd/back-dnssrv/request.c | 231 + servers/slapd/back-dnssrv/search.c | 39 + servers/slapd/back-ldap/Makefile.in | 5 +- servers/slapd/back-ldap/add.c | 2 +- servers/slapd/back-ldap/back-ldap.h | 5 +- servers/slapd/back-ldap/bind.c | 9 +- servers/slapd/back-ldap/compare.c | 7 +- servers/slapd/back-ldap/config.c | 48 +- servers/slapd/back-ldap/delete.c | 3 +- servers/slapd/back-ldap/external.h | 30 +- servers/slapd/back-ldap/group.c | 109 + servers/slapd/back-ldap/init.c | 26 +- servers/slapd/back-ldap/modify.c | 36 +- servers/slapd/back-ldap/modrdn.c | 9 +- servers/slapd/back-ldap/search.c | 21 +- servers/slapd/back-ldap/unbind.c | 3 +- servers/slapd/back-ldbm/Makefile.in | 18 +- servers/slapd/back-ldbm/abandon.c | 2 +- servers/slapd/back-ldbm/add.c | 60 +- servers/slapd/back-ldbm/alias.c | 35 +- servers/slapd/back-ldbm/attr.c | 293 +- servers/slapd/back-ldbm/back-ldbm.h | 56 +- servers/slapd/back-ldbm/backldbm.dsp | 32 +- servers/slapd/back-ldbm/bind.c | 132 +- servers/slapd/back-ldbm/cache.c | 7 +- servers/slapd/back-ldbm/close.c | 2 +- servers/slapd/back-ldbm/compare.c | 43 +- servers/slapd/back-ldbm/config.c | 19 +- servers/slapd/back-ldbm/dbcache.c | 38 +- servers/slapd/back-ldbm/delete.c | 24 +- servers/slapd/back-ldbm/dn2id.c | 4 +- servers/slapd/back-ldbm/entry.c | 2 +- servers/slapd/back-ldbm/extended.c | 56 + servers/slapd/back-ldbm/external.h | 52 +- servers/slapd/back-ldbm/filterindex.c | 443 +- servers/slapd/back-ldbm/group.c | 61 +- servers/slapd/back-ldbm/id2children.c | 2 +- servers/slapd/back-ldbm/id2entry.c | 5 +- servers/slapd/back-ldbm/idl.c | 190 +- servers/slapd/back-ldbm/index.c | 624 +- servers/slapd/back-ldbm/init.c | 34 +- servers/slapd/back-ldbm/key.c | 80 + servers/slapd/back-ldbm/modify.c | 298 +- servers/slapd/back-ldbm/modrdn.c | 146 +- servers/slapd/back-ldbm/nextid.c | 4 +- servers/slapd/back-ldbm/passwd.c | 161 + servers/slapd/back-ldbm/proto-back-ldbm.h | 110 +- servers/slapd/back-ldbm/sasl.c | 59 + servers/slapd/back-ldbm/search.c | 156 +- servers/slapd/back-ldbm/startup.c | 103 - servers/slapd/back-ldbm/tools.c | 33 +- servers/slapd/back-ldbm/unbind.c | 2 +- servers/slapd/back-passwd/Makefile.in | 1 - servers/slapd/back-passwd/external.h | 6 +- servers/slapd/back-passwd/init.c | 10 +- servers/slapd/back-passwd/search.c | 105 +- servers/slapd/back-perl/Makefile.in | 35 - servers/slapd/back-perl/add.c | 77 - servers/slapd/back-perl/bind.c | 82 - servers/slapd/back-perl/close.c | 65 - servers/slapd/back-perl/compare.c | 85 - servers/slapd/back-perl/config.c | 134 - servers/slapd/back-perl/delete.c | 74 - servers/slapd/back-perl/external.h | 53 - servers/slapd/back-perl/init.c | 124 - servers/slapd/back-perl/modify.c | 108 - servers/slapd/back-perl/modrdn.c | 97 - servers/slapd/back-perl/perl_back.h | 23 - servers/slapd/back-perl/search.c | 125 - servers/slapd/back-perl/unbind.c | 41 - servers/slapd/back-shell/Makefile.in | 3 +- servers/slapd/back-shell/abandon.c | 4 + servers/slapd/back-shell/add.c | 4 + servers/slapd/back-shell/bind.c | 8 +- servers/slapd/back-shell/compare.c | 18 +- servers/slapd/back-shell/config.c | 4 + servers/slapd/back-shell/delete.c | 7 +- servers/slapd/back-shell/external.h | 26 +- servers/slapd/back-shell/fork.c | 4 + servers/slapd/back-shell/init.c | 14 +- servers/slapd/back-shell/modify.c | 34 +- servers/slapd/back-shell/modrdn.c | 11 +- servers/slapd/back-shell/result.c | 6 + servers/slapd/back-shell/search.c | 9 +- servers/slapd/back-shell/searchexample.conf | 7 +- servers/slapd/back-shell/searchexample.sh | 7 +- servers/slapd/back-shell/shell.h | 4 + servers/slapd/back-shell/unbind.c | 4 + servers/slapd/back-tcl/Makefile.in | 37 - servers/slapd/back-tcl/external.h | 58 - servers/slapd/back-tcl/tcl_abandon.c | 58 - servers/slapd/back-tcl/tcl_add.c | 69 - servers/slapd/back-tcl/tcl_back.h | 64 - servers/slapd/back-tcl/tcl_bind.c | 73 - servers/slapd/back-tcl/tcl_close.c | 82 - servers/slapd/back-tcl/tcl_compare.c | 69 - servers/slapd/back-tcl/tcl_config.c | 182 - servers/slapd/back-tcl/tcl_delete.c | 65 - servers/slapd/back-tcl/tcl_init.c | 154 - servers/slapd/back-tcl/tcl_modify.c | 116 - servers/slapd/back-tcl/tcl_modrdn.c | 90 - servers/slapd/back-tcl/tcl_search.c | 86 - servers/slapd/back-tcl/tcl_unbind.c | 57 - servers/slapd/back-tcl/tcl_util.c | 190 - servers/slapd/backend.c | 138 +- servers/slapd/bind.c | 176 +- servers/slapd/ch_malloc.c | 2 +- servers/slapd/charray.c | 32 +- servers/slapd/compare.c | 119 +- servers/slapd/config.c | 125 +- servers/slapd/configinfo.c | 43 +- servers/slapd/connection.c | 204 +- servers/slapd/controls.c | 16 +- servers/slapd/daemon.c | 451 +- servers/slapd/delete.c | 72 +- servers/slapd/dn.c | 182 +- servers/slapd/entry.c | 101 +- servers/slapd/extended.c | 213 +- servers/slapd/filter.c | 482 +- servers/slapd/filterentry.c | 431 +- servers/slapd/index.c | 68 + servers/slapd/init.c | 22 +- servers/slapd/{back-ldbm => }/kerberos.c | 8 +- servers/slapd/libslapd.dsp | 68 +- servers/slapd/lock.c | 6 +- servers/slapd/main.c | 225 +- servers/slapd/modify.c | 444 +- servers/slapd/modrdn.c | 126 +- servers/slapd/module.c | 245 +- servers/slapd/monitor.c | 72 +- servers/slapd/mr.c | 224 + servers/slapd/nt_svc.c | 42 +- servers/slapd/oc.c | 413 ++ servers/slapd/operation.c | 2 +- servers/slapd/passwd.c | 275 + servers/slapd/phonetic.c | 2 +- servers/slapd/proto-slap.h | 843 ++- servers/slapd/repl.c | 30 +- servers/slapd/result.c | 328 +- servers/slapd/root_dse.c | 79 +- servers/slapd/sasl.c | 251 +- servers/slapd/schema.c | 1257 +--- servers/slapd/schema/core.schema | 408 +- servers/slapd/schema/cosine.schema | 2516 +++++++ servers/slapd/schema/inetorgperson.schema | 145 + servers/slapd/schema/internet_mail.at.conf | 71 - servers/slapd/schema/internet_mail.oc.conf | 50 - servers/slapd/schema/microsoft.ext.schema | 5383 ++++++++++++++ servers/slapd/schema/microsoft.schema | 4830 +++++++++++++ servers/slapd/schema/microsoft.std.schema | 480 ++ servers/slapd/schema/misc.schema | 39 +- servers/slapd/schema/nadf.schema | 24 +- servers/slapd/schema/nis.at.conf | 297 - servers/slapd/schema/nis.oc.conf | 244 - servers/slapd/schema/nis.schema | 76 +- servers/slapd/schema/openldap.schema | 25 + servers/slapd/schema/others_nis.at.conf | 283 - servers/slapd/schema/others_nis.oc.conf | 137 - servers/slapd/schema/pilot.schema | 120 +- servers/slapd/schema_check.c | 203 + servers/slapd/schema_init.c | 1368 ++++ servers/slapd/schema_prep.c | 171 + servers/slapd/schemaparse.c | 369 +- servers/slapd/search.c | 111 +- servers/slapd/shell-backends/Makefile.in | 2 + servers/slapd/shell-backends/passwd-shell.c | 4 +- servers/slapd/shell-backends/pwd-Version.c | 14 - servers/slapd/shell-backends/shellutil.c | 3 +- servers/slapd/slap.h | 863 ++- servers/slapd/slapd.at.conf | 25 - servers/slapd/slapd.conf | 37 +- servers/slapd/slapd.dsp | 161 + servers/slapd/slapd.oc.conf | 924 --- servers/slapd/starttls.c | 96 + servers/slapd/str2filter.c | 91 +- servers/slapd/suffixalias.c | 4 +- servers/slapd/syntax.c | 198 + servers/slapd/tools/Makefile.in | 92 +- servers/slapd/tools/ldbmtest.c | 6 +- servers/slapd/tools/ldbmtest.dsp | 24 +- servers/slapd/tools/ldif.c | 2 +- servers/slapd/tools/ldif.dsp | 24 +- servers/slapd/tools/mimic.c | 51 +- servers/slapd/tools/slapadd.c | 31 +- servers/slapd/tools/slapadd.dsp | 24 +- servers/slapd/tools/slapcat.c | 2 +- servers/slapd/tools/slapcat.dsp | 24 +- servers/slapd/tools/slapcommon.c | 18 +- servers/slapd/tools/slapcommon.h | 2 +- servers/slapd/tools/slapindex.c | 63 +- servers/slapd/tools/slapindex.dsp | 24 +- servers/slapd/tools/slappasswd.c | 116 + servers/slapd/unbind.c | 2 +- servers/slapd/user.c | 2 +- servers/slapd/value.c | 215 +- servers/slurpd/Makefile.in | 18 +- servers/slurpd/args.c | 17 +- servers/slurpd/config.c | 8 +- servers/slurpd/globals.c | 6 +- servers/slurpd/globals.h | 4 +- servers/slurpd/ldap_op.c | 24 +- servers/slurpd/lock.c | 4 +- servers/slurpd/main.c | 37 +- servers/slurpd/replog.c | 5 +- servers/slurpd/rq.c | 23 +- servers/slurpd/sanity.c | 2 +- servers/slurpd/slurp.h | 4 +- servers/slurpd/st.c | 2 +- tests/Makefile.in | 46 +- tests/README | 12 +- tests/data/acl.out.master | 67 +- tests/data/do_add.1 | 7 +- tests/data/modify.out.master | 97 +- tests/data/modrdn.out.master | 94 +- tests/data/modrdn.out.master.0 | 94 +- tests/data/modrdn.out.master.1 | 7 +- tests/data/modrdn.out.master.2 | 20 + tests/data/modrdn.out.master.3 | 7 +- tests/data/passwd.ldif | 28 + tests/data/search.out.master | 90 +- tests/data/slapd-acl.conf | 31 +- tests/data/slapd-bdb2-acl.conf | 2 +- tests/data/slapd-bdb2-pw.conf | 39 + tests/data/slapd-bdb2-repl-slave.conf | 1 - tests/data/slapd-dnssrv.conf | 17 + tests/data/slapd-master.conf | 14 +- tests/data/slapd-passwd.conf | 7 +- tests/data/slapd-pw.conf | 41 + tests/data/slapd-ref-slave.conf | 13 +- tests/data/slapd-repl-master.conf | 13 +- tests/data/slapd-repl-slave.conf | 12 +- tests/data/slapd.at.conf | 25 - tests/data/slapd.oc.conf | 912 --- tests/data/test-ordered.ldif | 94 +- tests/data/test.ldif | 94 +- tests/progs/Makefile.in | 6 +- tests/progs/slapd-addel.c | 7 +- tests/progs/slapd-read.c | 12 +- tests/progs/slapd-search.c | 6 +- tests/progs/slapd-tester.c | 6 +- tests/scripts/defines.sh | 13 +- tests/scripts/passwd-search | 2 +- tests/scripts/test001-slapadd | 4 +- tests/scripts/test002-populate | 4 +- tests/scripts/test003-search | 8 +- tests/scripts/test004-modify | 19 +- tests/scripts/test005-modrdn | 12 +- tests/scripts/test006-acls | 8 +- tests/scripts/test007-replication | 14 +- tests/scripts/test008-concurrency | 4 +- tests/scripts/test009-referral | 10 +- tests/scripts/test010-passwd | 131 + 720 files changed, 88742 insertions(+), 38868 deletions(-) create mode 100644 LICENSE create mode 100644 build/build.dsp create mode 100644 build/build.mak create mode 100755 build/ltconfig create mode 100755 build/mkdep.aix create mode 100644 clients/mail500/mail500.m4 create mode 100644 clients/maildap/Makefile.in create mode 100644 clients/maildap/README create mode 100644 clients/maildap/maildap.m4 create mode 100644 clients/maildap/main.c create mode 100644 clients/tools/ldapdelete.dsp create mode 100644 clients/tools/ldapmodify.dsp create mode 100644 clients/tools/ldapmodrdn.dsp create mode 100644 clients/tools/ldappasswd.dsp create mode 100644 clients/tools/ldapsearch.dsp create mode 100644 clients/ud/ud.dsp create mode 100644 contrib/gtk-tool/COPYRIGHT create mode 100644 contrib/gtk-tool/ChangeLog create mode 100644 contrib/gtk-tool/Gtk_LdapServer.cc create mode 100644 contrib/gtk-tool/Gtk_LdapServer.h create mode 100644 contrib/gtk-tool/Gtk_LdapTree.cc create mode 100644 contrib/gtk-tool/Gtk_LdapTreeItem.cc create mode 100644 contrib/gtk-tool/Gtk_LdapTreeItem.h create mode 100644 contrib/gtk-tool/INSTALL create mode 100644 contrib/gtk-tool/Makefile create mode 100644 contrib/gtk-tool/My_Window.cc create mode 100644 contrib/gtk-tool/My_Window.h create mode 100644 contrib/gtk-tool/README create mode 100644 contrib/gtk-tool/TODO create mode 100644 contrib/gtk-tool/common.h create mode 100644 contrib/gtk-tool/cpluscommon.h create mode 100644 contrib/gtk-tool/gtk.h create mode 100644 contrib/gtk-tool/icons/monitor.h create mode 100644 contrib/gtk-tool/main.cc create mode 100644 contrib/gtk-tool/utils.cc create mode 100644 contrib/ldaptcl/ldap.n create mode 100644 contrib/ldaptcl/tkAppInit.c create mode 100644 contrib/php3-tool/COPYRIGHT create mode 100644 contrib/php3-tool/index.php3 create mode 100644 doc/devel/asn-layman.txt create mode 100644 doc/devel/guidelines create mode 100644 doc/drafts/draft-ietf-asid-ldapv3-attributes-03.txt delete mode 100644 doc/drafts/draft-ietf-ldapext-authmeth-xx.txt create mode 100644 doc/drafts/draft-ietf-ldapext-ldapv3-vlv-xx.txt create mode 100644 doc/drafts/draft-ietf-ldapext-locate-xx.txt create mode 100644 doc/drafts/draft-ietf-ldapext-sorting-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-framing-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-infomod-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-model-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-protocol-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-replica-req-xx.txt create mode 100644 doc/drafts/draft-ietf-ldup-urp-xx.txt create mode 100644 doc/drafts/draft-lachman-laser-ldap-mail-routing-xx.txt create mode 100644 doc/drafts/draft-leach-uuids-guids-01.txt create mode 100644 doc/drafts/draft-rharrison-ldap-extpartresp-xx.txt create mode 100644 doc/drafts/draft-smith-ldap-c-api-ext-vlv-xx.txt create mode 100644 doc/man/Makefile.in create mode 100644 doc/man/man1/Makefile.in create mode 100644 doc/man/man1/ldappasswd.1 create mode 100644 doc/man/man3/Makefile.in create mode 100644 doc/man/man3/lber-decode.3.links create mode 100644 doc/man/man3/lber-encode.3.links create mode 100644 doc/man/man3/ldap_schema.3 create mode 100644 doc/man/man3/ldap_schema.3.links create mode 100644 doc/man/man5/Makefile.in create mode 100644 doc/man/man8/Makefile.in delete mode 100644 doc/rfc/rfc1488.txt delete mode 100644 doc/rfc/rfc1558.txt create mode 100644 doc/rfc/rfc2119.txt create mode 100644 doc/rfc/rfc2222.txt create mode 100644 doc/rfc/rfc2649.txt create mode 100644 doc/rfc/rfc2657.txt create mode 100644 doc/rfc/rfc2696.txt create mode 100644 doc/rfc/rfc2713.txt create mode 100644 doc/rfc/rfc2714.txt create mode 100644 doc/rfc/rfc2798.txt create mode 100644 doc/rfc/rfc2829.txt create mode 100644 doc/rfc/rfc2830.txt create mode 100644 doc/rfc/rfc2831.txt create mode 100644 include/ac/crypt.h create mode 100644 include/ac/krb5.h create mode 100644 include/ac/param.h create mode 100644 include/ldap_int_thread.h create mode 100644 libraries/libavl/libavl.dsp create mode 100644 libraries/libavl/testavl.dsp create mode 100644 libraries/liblber/dtest.dsp create mode 100644 libraries/liblber/etest.dsp create mode 100644 libraries/liblber/liblber.dsp rename libraries/{liblutil => liblber}/nt_err.c (80%) create mode 100644 libraries/libldap/apitest.dsp delete mode 100644 libraries/libldap/charset.c delete mode 100644 libraries/libldap/digest.c create mode 100644 libraries/libldap/dnssrv.c delete mode 100644 libraries/libldap/getdxbyname.c create mode 100644 libraries/libldap/ltest.dsp create mode 100644 libraries/libldap/os-local.c create mode 100644 libraries/libldap/sortctrl.c create mode 100644 libraries/libldap/utf-8.c create mode 100644 libraries/libldap/vlvctrl.c create mode 100644 libraries/libldap_r/apitest_r.dsp create mode 100644 libraries/libldap_r/libldap_r.dsp create mode 100644 libraries/libldap_r/ltest_r.dsp delete mode 100644 libraries/libldap_r/thr_sleep.c create mode 100644 libraries/libldap_r/threads.c create mode 100644 libraries/libldap_r/tpool.c create mode 100644 libraries/libldbm/libldbm.dsp create mode 100644 libraries/liblutil/authpasswd.c create mode 100644 libraries/liblutil/entropy.c create mode 100644 libraries/liblutil/passwd.dsp create mode 100644 libraries/liblutil/passwd.dsw create mode 100644 libraries/liblutil/ptest.c create mode 100644 libraries/liblutil/slapdmsg.bin create mode 100644 libraries/liblutil/slapdmsg.h create mode 100644 libraries/liblutil/slapdmsg.rc create mode 100644 servers/slapd/ad.c create mode 100644 servers/slapd/at.c delete mode 100644 servers/slapd/back-bdb2/Makefile.in delete mode 100644 servers/slapd/back-bdb2/abandon.c delete mode 100644 servers/slapd/back-bdb2/add.c delete mode 100644 servers/slapd/back-bdb2/alias.c delete mode 100644 servers/slapd/back-bdb2/attr.c delete mode 100644 servers/slapd/back-bdb2/back-bdb2.h delete mode 100644 servers/slapd/back-bdb2/bind.c delete mode 100644 servers/slapd/back-bdb2/cache.c delete mode 100644 servers/slapd/back-bdb2/close.c delete mode 100644 servers/slapd/back-bdb2/compare.c delete mode 100644 servers/slapd/back-bdb2/config.c delete mode 100644 servers/slapd/back-bdb2/dbcache.c delete mode 100644 servers/slapd/back-bdb2/delete.c delete mode 100644 servers/slapd/back-bdb2/dn2id.c delete mode 100644 servers/slapd/back-bdb2/entry.c delete mode 100644 servers/slapd/back-bdb2/external.h delete mode 100644 servers/slapd/back-bdb2/filterindex.c delete mode 100644 servers/slapd/back-bdb2/group.c delete mode 100644 servers/slapd/back-bdb2/id2children.c delete mode 100644 servers/slapd/back-bdb2/id2entry.c delete mode 100644 servers/slapd/back-bdb2/idl.c delete mode 100644 servers/slapd/back-bdb2/index.c delete mode 100644 servers/slapd/back-bdb2/init.c delete mode 100644 servers/slapd/back-bdb2/kerberos.c delete mode 100644 servers/slapd/back-bdb2/modify.c delete mode 100644 servers/slapd/back-bdb2/modrdn.c delete mode 100644 servers/slapd/back-bdb2/nextid.c delete mode 100644 servers/slapd/back-bdb2/porter.c delete mode 100644 servers/slapd/back-bdb2/proto-back-bdb2.h delete mode 100644 servers/slapd/back-bdb2/search.c delete mode 100644 servers/slapd/back-bdb2/startup.c delete mode 100644 servers/slapd/back-bdb2/timing.c delete mode 100644 servers/slapd/back-bdb2/tools.c delete mode 100644 servers/slapd/back-bdb2/txn.c delete mode 100644 servers/slapd/back-bdb2/txn.h delete mode 100644 servers/slapd/back-bdb2/unbind.c create mode 100644 servers/slapd/back-dnssrv/Makefile.in create mode 100644 servers/slapd/back-dnssrv/add.c create mode 100644 servers/slapd/back-dnssrv/back-dnssrv.h create mode 100644 servers/slapd/back-dnssrv/bind.c create mode 100644 servers/slapd/back-dnssrv/compare.c create mode 100644 servers/slapd/back-dnssrv/config.c create mode 100644 servers/slapd/back-dnssrv/delete.c create mode 100644 servers/slapd/back-dnssrv/external.h create mode 100644 servers/slapd/back-dnssrv/init.c create mode 100644 servers/slapd/back-dnssrv/modify.c create mode 100644 servers/slapd/back-dnssrv/modrdn.c create mode 100644 servers/slapd/back-dnssrv/request.c create mode 100644 servers/slapd/back-dnssrv/search.c create mode 100644 servers/slapd/back-ldap/group.c create mode 100644 servers/slapd/back-ldbm/extended.c create mode 100644 servers/slapd/back-ldbm/key.c create mode 100644 servers/slapd/back-ldbm/passwd.c create mode 100644 servers/slapd/back-ldbm/sasl.c delete mode 100644 servers/slapd/back-ldbm/startup.c delete mode 100644 servers/slapd/back-perl/Makefile.in delete mode 100644 servers/slapd/back-perl/add.c delete mode 100644 servers/slapd/back-perl/bind.c delete mode 100644 servers/slapd/back-perl/close.c delete mode 100644 servers/slapd/back-perl/compare.c delete mode 100644 servers/slapd/back-perl/config.c delete mode 100644 servers/slapd/back-perl/delete.c delete mode 100644 servers/slapd/back-perl/external.h delete mode 100644 servers/slapd/back-perl/init.c delete mode 100644 servers/slapd/back-perl/modify.c delete mode 100644 servers/slapd/back-perl/modrdn.c delete mode 100644 servers/slapd/back-perl/perl_back.h delete mode 100644 servers/slapd/back-perl/search.c delete mode 100644 servers/slapd/back-perl/unbind.c delete mode 100644 servers/slapd/back-tcl/Makefile.in delete mode 100644 servers/slapd/back-tcl/external.h delete mode 100644 servers/slapd/back-tcl/tcl_abandon.c delete mode 100644 servers/slapd/back-tcl/tcl_add.c delete mode 100644 servers/slapd/back-tcl/tcl_back.h delete mode 100644 servers/slapd/back-tcl/tcl_bind.c delete mode 100644 servers/slapd/back-tcl/tcl_close.c delete mode 100644 servers/slapd/back-tcl/tcl_compare.c delete mode 100644 servers/slapd/back-tcl/tcl_config.c delete mode 100644 servers/slapd/back-tcl/tcl_delete.c delete mode 100644 servers/slapd/back-tcl/tcl_init.c delete mode 100644 servers/slapd/back-tcl/tcl_modify.c delete mode 100644 servers/slapd/back-tcl/tcl_modrdn.c delete mode 100644 servers/slapd/back-tcl/tcl_search.c delete mode 100644 servers/slapd/back-tcl/tcl_unbind.c delete mode 100644 servers/slapd/back-tcl/tcl_util.c create mode 100644 servers/slapd/index.c rename servers/slapd/{back-ldbm => }/kerberos.c (85%) create mode 100644 servers/slapd/mr.c create mode 100644 servers/slapd/oc.c create mode 100644 servers/slapd/passwd.c create mode 100644 servers/slapd/schema/cosine.schema create mode 100644 servers/slapd/schema/inetorgperson.schema delete mode 100644 servers/slapd/schema/internet_mail.at.conf delete mode 100644 servers/slapd/schema/internet_mail.oc.conf create mode 100644 servers/slapd/schema/microsoft.ext.schema create mode 100644 servers/slapd/schema/microsoft.schema create mode 100644 servers/slapd/schema/microsoft.std.schema delete mode 100644 servers/slapd/schema/nis.at.conf delete mode 100644 servers/slapd/schema/nis.oc.conf create mode 100644 servers/slapd/schema/openldap.schema delete mode 100644 servers/slapd/schema/others_nis.at.conf delete mode 100644 servers/slapd/schema/others_nis.oc.conf create mode 100644 servers/slapd/schema_check.c create mode 100644 servers/slapd/schema_init.c create mode 100644 servers/slapd/schema_prep.c delete mode 100644 servers/slapd/shell-backends/pwd-Version.c delete mode 100644 servers/slapd/slapd.at.conf create mode 100644 servers/slapd/slapd.dsp delete mode 100644 servers/slapd/slapd.oc.conf create mode 100644 servers/slapd/starttls.c create mode 100644 servers/slapd/syntax.c create mode 100644 servers/slapd/tools/slappasswd.c create mode 100644 tests/data/modrdn.out.master.2 create mode 100644 tests/data/passwd.ldif create mode 100644 tests/data/slapd-bdb2-pw.conf create mode 100644 tests/data/slapd-dnssrv.conf create mode 100644 tests/data/slapd-pw.conf delete mode 100644 tests/data/slapd.at.conf delete mode 100644 tests/data/slapd.oc.conf create mode 100755 tests/scripts/test010-passwd diff --git a/ANNOUNCEMENT b/ANNOUNCEMENT index 0075060e70..eed58ebbe1 100644 --- a/ANNOUNCEMENT +++ b/ANNOUNCEMENT @@ -1,90 +1,101 @@ - A N N O U N C E M E N T - - LDAP 3.3 - - The University of Michigan is pleased to announce release 3.3 of - UM-LDAP, an implementation of the Lightweight Directory Access - Protocol. LDAP is a draft Internet standard directory service - protocol that runs over TCP/IP. It can be used to provide a - stand-alone directory service, or to provide lightweight access to - the X.500 directory. LDAP is defined by RFC 1777 and RFC 1778. - - This release includes the following components: - - - slapd - a stand-alone LDAP directory server - - slurpd - a stand-alone LDAP replication server - - ldapd - an LDAP-to-X.500 gateway server - - centipede - an LDAP centroid generation and maintenance program - - libldap - an LDAP client library - - liblber - a lightweight BER/DER encoding/decoding library - - ldif tools - data conversion tools for use with slapd - - in.xfingerd - a finger-to-LDAP gateway server - - go500 - a gopher-to-LDAP gateway server for searching - - go500gw - a gopher-to-LDAP gateway server for searching and browsing - - rcpt500 - an email-to-LDAP query responder - - mail500 - an LDAP-capable mailer - - fax500 - an LDAP-capable mailer that supports remote printing - - LDAP tools - A collection of shell-based LDAP utility programs - - In addition, there are some contributed components: - - - web500 - an HTTP-to-LDAP gateway - - whois++d - a WHOIS++-to-LDAP gateway - - saucer - a simple command-line oriented client program - -CHANGES - - Changes since release 3.2 of LDAP include - - - slurpd has been rewritten as a single process threaded daemon - - ldaptools (ldapsearch, etc) now support the LDIF format - - support for LDAP URLs added to libldap - - improved support for LDAP referrals in libldap - - preliminary test scripts included - - support for additional platforms - - various bug fixes and build fixes - - See the CHANGES file in the distribution for more details. + A N N O U N C E M E N T + + OpenLDAP 2.0-Alpha + + The OpenLDAP Project is pleased to announce the availability + of OpenLDAP 2.0-Alpha, a suite of the Lightweight Weight + Directory Protocol servers, clients, utilities, and development tools. + + This alpha release is for REFERENCE PURPOSES ONLY. + This alpha release is NOT for GENERAL USE. + This alpha release is NOT feature complete nor well tested. + + This release contains the following major enhancements: + + * LDAPv3 support + + RFC2251-2256 + + named referrals + + DNS SRV location + * SASL support + * TLS/SSL support + * IPv6 support + * LDAP over IPC support + * Updated C API + * Enhanced Standalone LDAP Server: + + Updated Access Control System + + Thread Pooling + + DNS SRV referral backend + + LDAP backend + + Better tools + + This release includes the following major components: + + * slapd - a stand-alone LDAP directory server + * slurpd - a stand-alone LDAP replication server + * -lldap - an LDAP client library + * -llber - a lightweight BER/DER encoding/decoding library + * LDIF tools - data conversion tools for use with slapd + * LDAP gateways - finger, gopher, email to LDAP gateways + * LDAP mailer - sendmail-compatibile mail delivery agents + * LDAP tools - A collection of command line LDAP utility programs + + In addition, there are some contributed components: + + * ldapTCL - the NeoSoft TCL LDAP SDK + * gtk-tool - a demonstration ldap interface written gtk + * php3-tool - a demonstration ldap interface written php3 + * saucer - a simple command-line oriented client program + * whois++d - a WHOIS++-to-LDAP gateway + + +ACKNOWLEDGEMENTS + + OpenLDAP is developed by a team of volunteers whose use + the Internet to coordinate their activities. The project is + managed by the OpenLDAP Foundation. + + OpenLDAP LDAP implementation is derived from University of + Michigan LDAP release 3.3. + AVAILABILITY - This software is freely available to anyone for any lawful purpose, - subject to the U-M copyright notice and disclaimer. The software is - available for anonymous ftp from the following location: + This software is available under the OpenLDAP Public License, + an unrestrictive, "free," OSS-approved open source license. + For download information is available at: + + http://www.OpenLDAP.org/software/download/ - ftp://terminator.rs.itd.umich.edu/ldap/ldap-3.3.tar.Z SUPPORT - The software is provided as is without any express or implied - warranty, but there is a bug reporting mail address which is - responded to on a best-effort basis: + OpenLDAP software is user supported + + http://www.openldap.org/support/ + + The project maintains a FAQ which you may find useful: + + http://www.openldap.org/faq/ - ldap-support@umich.edu + In addition, there are also a number of discussion lists + related OpenLDAP. A list of mailing lists is available at: - In addition, there is a discussion list for issues relating to this - implementation of ldap: + http://www.OpenLDAP.org/lists/ - ldap@umich.edu -- discussion list - ldap-request@umich.edu -- to join the list + To report bugs, please use project's Issue Tracking System: - Comments or questions about the LDAP protocol in general should be - sent to the IETF ASID discussion group: + http://www.openldap.org/its/ - ietf-asid@umich.edu -- discussion list - ietf-asid-request@umich.edu -- to join the list + The OpenLDAP home page containing lots of interesting information + and online documentation is available at this URL: - An LDAP home page containing lots of interesting information and - online documentation is available at this URL: + http://www.OpenLDAP.org/ - http://www.umich.edu/~rsug/ldap/ SUPPORTED PLATFORMS - This release has been ported to many UNIX platforms, including - SunOS 4.1.x, Solaris 2.x, Ultrix 4.3, HP-UX 9.05, AIX 3.2.5, - SCO, FreeBSD, NetBSD, LINUX, IRIX, Digital Unix (OSF/1), and - NeXTSTEP 3.2. This release has also been ported to VMS. + This release has been ported to many UNIX (and UNIX-like) platforms + including FreeBSD, Linux, NetBSD, OpenBSD and most commericial + UNIX systems. The release has also been ported (in part or in whole) + to other platforms including BeOS, MacOS, and MS Windows NT/2000. - The client libraries and some clients have also been ported to - MacOS 7.x, MSDOS (some TCP stacks), and MS Windows 3.1/95/NT. diff --git a/COPYRIGHT b/COPYRIGHT index 5450dd0d1d..305fc2609f 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA +Copyright 1998-2000 The OpenLDAP Foundation All rights reserved. Redistribution and use in source and binary forms are permitted only diff --git a/INSTALL b/INSTALL index 8f3685d085..77fe82016a 100644 --- a/INSTALL +++ b/INSTALL @@ -4,8 +4,7 @@ Making and Installing the OpenLDAP Distribution ** It is recommended that you read or at least skim through ALL of the ** instructions in this file before attempting to build the software. ** -** A Quick Start Guide, which may be used in conjunction with this -** document, is available at: +** The OpenLDAP Quick Start Guide is available at: ** http://www.openldap.org/faq/index.cgi?file=172 ** ** The OpenLDAP Installation FAQ is available at: @@ -91,8 +90,7 @@ these steps: 7. install the binaries and man pages. You may need to be superuser to do this (depending on where you are installing things): - % su - # make install + % su root -c make install That's it! @@ -157,8 +155,9 @@ The configure script will also use your environmental variables for determining compiler/linker options. This can be used to manual specify features and compilation options. -NOTE: If you change environment setting, be sure to remove - any config.cache before running ./configure. +WARNING: Executable built in your environment may not run + in your user's environments. The portability of + executables between environments is your responsibility. Supported Environmental Variables CC C compiler (cc, egcc) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..123dfc37ae --- /dev/null +++ b/LICENSE @@ -0,0 +1,51 @@ +The OpenLDAP Public License + Version 2.2.1, 1 March 2000 + +Redistribution and use of this software and associated documentation +("Software"), with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions of source code must retain copyright statements +and notices. Redistributions must also contain a copy of this +document. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +3. The name "OpenLDAP" must not be used to endorse or promote +products derived from this Software without prior written permission +of the OpenLDAP Foundation. + +4. Products derived from this Software may not be called "OpenLDAP" +nor may "OpenLDAP" appear in their names without prior written +permission of the OpenLDAP Foundation. + +5. Due credit should be given to the OpenLDAP Project +(http://www.openldap.org/). + +6. The OpenLDAP Foundation may revise this license from time to +time. Each revision is distinguished by a version number. You +may use the Software under terms of this license revision or under +the terms of any subsequent revision of the license. + +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE OPENLDAP FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +OpenLDAP is a trademark of the OpenLDAP Foundation. + +Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, +California, USA. All Rights Reserved. Permission to copy and +distributed verbatim copies of this document is granted. + diff --git a/Makefile.in b/Makefile.in index a4c7025afa..3a33861dd6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ # $OpenLDAP$ # Master Makefile for OpenLDAP ## -## Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA +## Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA ## All rights reserved. ## ## Redistribution and use in source and binary forms are permitted only @@ -28,3 +28,6 @@ veryclean-local: FORCE $(RM) config.cache config.status libtool stamp-h stamp-h.in distclean: veryclean FORCE + +test: FORCE + cd tests; make test diff --git a/README b/README index 6c4371cca3..dcbf546807 100644 --- a/README +++ b/README @@ -1,16 +1,21 @@ -OpenLDAP Release README - For a description of what this distribution contains, see the - ANNOUNCEMENT file in this directory. For a description of - changes from previous releases, see the CHANGES file in this - directory. +OpenLDAP 2.0 Alpha README + This is an alpha release of OpenLDAP 2.0. It is provided + for reference purposes only. It is not for general use. + + The OpenLDAP Developer's FAQ is available at: + http://www.openldap.org/faq/index.cgi?file=4 + + Developer's and early testers should provide feedback regarding + this release to the openldap-devel@openldap.org mailing list. + As this release is not intended for general use, no general + use questions will be answered. Developer's wishing to + contribute changes should work with latest devel codes, this + snapshot is for reference purposes only. For a more detailed description of how to make an install the distribution, see the INSTALL file in this directory. Additional - installation information, such as per platform hints can be found - in the doc/install directory. - - For more information: - http://www.OpenLDAP.org/software/ + installation information can be found on the OpenLDAP website: + http://www.openldap.org/ REQUIRED SOFTWARE @@ -26,7 +31,7 @@ REQUIRED SOFTWARE SLURPD: LTHREAD compatible thread package - (POSIX pthreads, MIT pthreads, Mach Cthreads or Sun LWP) + (POSIX threads, Mach Cthreads, Sun LWP, or GNU Pth) CLIENTS/CONTRIB ware: Depends on package. See per package README. @@ -52,21 +57,21 @@ DOCUMENTATION etc.. It is located at: http://www.OpenLDAP.org/ + The OpenLDAP Quick Start Guide is available at: + http://www.openldap.org/faq/index.cgi?file=172 + The OpenLDAP Software FAQ is available at: http://www.openldap.org/faq/index.cgi?file=2 -FEEDBACK / PROBLEM REPORTS / DISCUSSIONS - We would appreciate any feedback you can provide. If you have - problems, report them using our Issue Tracking System: - - http://www.OpenLDAP.com/its/ - - or by sending e-mail to: - - OpenLDAP-its@OpenLDAP.org - - Additional mailing lists are available. Please see: - - http://www.OpenLDAP.com/lists/ +SUPPORT / FEEDBACK / PROBLEM REPORTS / DISCUSSIONS + OpenLDAP is user supported. If you have problems, please + review the OpenLDAP FAQ and + archives of the OpenLDAP-software and OpenLDAP-bugs mailing + lists . + Issues, such as bug reports, should be reported using our + our Issue Tracking System or + by sending mail to OpenLDAP-its@OpenLDAP.org. Do not use + this system for general or software equiries. Please direct + these to the appropriate mailing list. diff --git a/acconfig.h b/acconfig.h index 9c89097b37..cd6ad29d45 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,5 +1,5 @@ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -12,6 +12,12 @@ #define _LDAP_PORTABLE_H /* end of preamble */ + +#if !defined(SLAPD_SCHEMA_COMPAT) && !defined(SLAPD_SCHEMA_NOT_COMPAT) + /* define SLAPD_SCHEMA_COMPAT if you want old schema codes */ +#define SLAPD_SCHEMA_NOT_COMPAT 1 +#endif + @TOP@ /* define this if needed to get reentrant functions */ @@ -47,7 +53,7 @@ /* LDAP_API_FEATURE_X_OPENLDAP_REENTRANT LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE - LDAP_API_FEATURE_X_OPENLDAP_V2_DNS + LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ @@ -59,12 +65,24 @@ LBER_TAG_T */ +/* define to character address type */ +#undef caddr_t + +/* define to signed size type */ +#undef ssize_t + /* Leave that blank line there!! Autoheader needs it. */ @BOTTOM@ + /* begin of postamble */ +#ifdef _WIN32 + /* don't suck in all of the win32 api */ +# define WIN32_LEAN_AND_MEAN 1 +#endif + #ifndef __NEED_PROTOTYPES /* force LDAP_P to always include prototypes */ #define __NEED_PROTOTYPES 1 diff --git a/acinclude.m4 b/acinclude.m4 index 35f9931fee..5590d0fc99 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,8 +1,9 @@ dnl $OpenLDAP$ dnl -dnl Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +dnl Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. dnl COPYING RESTRICTIONS APPLY, See COPYRIGHT file dnl dnl OpenLDAP Autoconf Macros dnl +divert(-1) builtin(include, build/openldap.m4)dnl diff --git a/aclocal.m4 b/aclocal.m4 index 008ce71664..9e714628bc 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -12,11 +12,12 @@ dnl PARTICULAR PURPOSE. dnl $OpenLDAP$ dnl -dnl Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +dnl Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. dnl COPYING RESTRICTIONS APPLY, See COPYRIGHT file dnl dnl OpenLDAP Autoconf Macros dnl +divert(-1) builtin(include, build/openldap.m4)dnl # Do all the work for Automake. This macro actually does too much -- @@ -147,7 +148,7 @@ LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ -$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \ || AC_MSG_ERROR([libtool configure failed]) # Reload cache, that may have been modified by ltconfig @@ -179,6 +180,11 @@ AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([AC_PROG_LN_S])dnl dnl +case "$target" in +NONE) lt_target="$host" ;; +*) lt_target="$target" ;; +esac + # Check for any special flags to pass to ltconfig. libtool_flags="--cache-file=$cache_file" test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" @@ -197,7 +203,7 @@ test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" # Some flags need to be propagated to the compiler or linker for good # libtool support. -case "$host" in +case "$lt_target" in *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext @@ -413,7 +419,6 @@ else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) -AC_SUBST(LD) AC_PROG_LD_GNU ]) @@ -459,14 +464,13 @@ else fi]) NM="$ac_cv_path_NM" AC_MSG_RESULT([$NM]) -AC_SUBST(NM) ]) # AC_CHECK_LIBM - check for math library AC_DEFUN(AC_CHECK_LIBM, [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= -case "$host" in +case "$lt_target" in *-*-beos* | *-*-cygwin*) # These system don't have libm ;; diff --git a/build/build.dsp b/build/build.dsp new file mode 100644 index 0000000000..3103133c2c --- /dev/null +++ b/build/build.dsp @@ -0,0 +1,172 @@ +# Microsoft Developer Studio Project File - Name="build" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=build - Win32 DLL Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "build.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "build.mak" CFG="build - Win32 DLL Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "build - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "build - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE "build - Win32 Single Debug" (based on "Win32 (x86) External Target") +!MESSAGE "build - Win32 Single Release" (based on\ + "Win32 (x86) External Target") +!MESSAGE "build - Win32 DLL Debug" (based on "Win32 (x86) External Target") +!MESSAGE "build - Win32 DLL Release" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "build - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f build.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "build.exe" +# PROP BASE Bsc_Name "build.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "NMAKE /f build.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "build.txt" +# PROP Bsc_Name "build.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "build - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f build.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "build.exe" +# PROP BASE Bsc_Name "build.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "" +# PROP Rebuild_Opt "" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "build - Win32 Single Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "build___" +# PROP BASE Intermediate_Dir "build___" +# PROP BASE Cmd_Line "" +# PROP BASE Rebuild_Opt "" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "build___" +# PROP Intermediate_Dir "build___" +# PROP Cmd_Line "" +# PROP Rebuild_Opt "" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "build - Win32 Single Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "build__0" +# PROP BASE Intermediate_Dir "build__0" +# PROP BASE Cmd_Line "NMAKE /f build.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "build.exe" +# PROP BASE Bsc_Name "build.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "build__0" +# PROP Intermediate_Dir "build__0" +# PROP Cmd_Line "NMAKE /f build.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "build.exe" +# PROP Bsc_Name "build.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "build - Win32 DLL Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "build__1" +# PROP BASE Intermediate_Dir "build__1" +# PROP BASE Cmd_Line "" +# PROP BASE Rebuild_Opt "" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "build__1" +# PROP Intermediate_Dir "build__1" +# PROP Cmd_Line "" +# PROP Rebuild_Opt "" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "build - Win32 DLL Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "build__2" +# PROP BASE Intermediate_Dir "build__2" +# PROP BASE Cmd_Line "NMAKE /f build.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "build.exe" +# PROP BASE Bsc_Name "build.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "build__2" +# PROP Intermediate_Dir "build__2" +# PROP Cmd_Line "NMAKE /f build.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "build.exe" +# PROP Bsc_Name "build.bsc" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "build - Win32 Release" +# Name "build - Win32 Debug" +# Name "build - Win32 Single Debug" +# Name "build - Win32 Single Release" +# Name "build - Win32 DLL Debug" +# Name "build - Win32 DLL Release" + +!IF "$(CFG)" == "build - Win32 Release" + +!ELSEIF "$(CFG)" == "build - Win32 Debug" + +!ELSEIF "$(CFG)" == "build - Win32 Single Debug" + +!ELSEIF "$(CFG)" == "build - Win32 Single Release" + +!ELSEIF "$(CFG)" == "build - Win32 DLL Debug" + +!ELSEIF "$(CFG)" == "build - Win32 DLL Release" + +!ENDIF + +# Begin Source File + +SOURCE=.\build.mak +# End Source File +# End Target +# End Project diff --git a/build/build.mak b/build/build.mak new file mode 100644 index 0000000000..7071624512 --- /dev/null +++ b/build/build.mak @@ -0,0 +1,10 @@ +# $OpenLDAP$ +# +# Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +# COPYING RESTRICTIONS APPLY, see COPYRIGHT file +# + +all: build.txt + +build.txt: version + copy version build.txt diff --git a/build/dir.mk b/build/dir.mk index 7f163fdc0d..efda69262e 100644 --- a/build/dir.mk +++ b/build/dir.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -13,6 +13,7 @@ all-common: FORCE @for i in $(SUBDIRS) $(ALLDIRS); do \ echo " Entering subdirectory $$i"; \ ( cd $$i; $(MAKE) $(MFLAGS) all ); \ + if test $$? != 0 ; then exit 1; fi ; \ echo " "; \ done @@ -21,6 +22,7 @@ install-common: FORCE @for i in $(SUBDIRS) $(INSTALLDIRS); do \ echo " Entering subdirectory $$i"; \ ( cd $$i; $(MAKE) $(MFLAGS) install ); \ + if test $$? != 0 ; then exit 1; fi ; \ echo " "; \ done @@ -29,6 +31,7 @@ clean-common: FORCE @for i in $(SUBDIRS) $(CLEANDIRS); do \ echo " Entering subdirectory $$i"; \ ( cd $$i; $(MAKE) $(MFLAGS) clean ); \ + if test $$? != 0 ; then exit 1; fi ; \ echo " "; \ done @@ -37,6 +40,7 @@ veryclean-common: FORCE @for i in $(SUBDIRS) $(CLEANDIRS); do \ echo " Entering subdirectory $$i"; \ ( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \ + if test $$? != 0 ; then exit 1; fi ; \ echo " "; \ done @@ -45,6 +49,7 @@ depend-common: FORCE @for i in $(SUBDIRS) $(DEPENDDIRS); do \ echo " Entering subdirectory $$i"; \ ( cd $$i; $(MAKE) $(MFLAGS) depend ); \ + if test $$? != 0 ; then exit 1; fi ; \ echo " "; \ done diff --git a/build/info.mk b/build/info.mk index df9d94ddb4..d6091ffb3c 100644 --- a/build/info.mk +++ b/build/info.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- diff --git a/build/install-sh b/build/install-sh index c7348ecd25..e91ee1db75 100755 --- a/build/install-sh +++ b/build/install-sh @@ -1,6 +1,6 @@ #! /bin/sh # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. # diff --git a/build/lib-shared.mk b/build/lib-shared.mk index 776972ac6d..3952bcf3c9 100644 --- a/build/lib-shared.mk +++ b/build/lib-shared.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -7,7 +7,16 @@ ## Makefile Template for Shared Libraries ## -COMPILE = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c +NT_LTFLAGS = --only-$(LINKAGE) +LTFLAGS = $(@PLAT@_LTFLAGS) + +NT_DYN_LT_NO_UNDEF = -no-undefined +LT_NO_UNDEF = $(@PLAT@_@LIB_LINKAGE@_LT_NO_UNDEF) + +COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CFLAGS) $(EXTRA_DEFS) -c +LTLIBLINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) \ + $(LTVERSION) $(LT_NO_UNDEF) + MKDEPFLAG = -l .SUFFIXES: .c .o .lo @@ -15,11 +24,29 @@ MKDEPFLAG = -l .c.lo: $(COMPILE) $< + +# DYN_EXT (@DYN_EXT@) describes the extension assoicated with a +# dynamic library, e.g. so, dll + +DYN_EXT=@DYN_EXT@ + $(LIBRARY): version.lo - $(LTLIBLINK) -rpath $(libdir) -o $@ $(OBJS) version.lo - $(RM) ../$@; \ - (d=`$(PWD)` ; $(LN_S) `$(BASENAME) $$d`/$@ ../$@) - $(RM) ../`$(BASENAME) $@ .la`.a; \ - (d=`$(PWD)`; t=`$(BASENAME) $@ .la`.a; $(LN_S) `$(BASENAME) $$d`/.libs/$$t ../$$t) + $(LTLIBLINK) -rpath $(libdir) -o $@ $(OBJS) version.lo $(EXTRA_LIBS) + $(RM) ../$@ + d=`$(PWD)`; d=`$(BASENAME) $$d`; cd ..; $(LN_S) $$d/$@ $@; \ + t=`$(BASENAME) $@ .la`.a; $(RM) $$t; $(LN_S) $$d/.libs/$$t $$t + @# If we want our binaries to link dynamically with libldap{,_r} liblber + @# We also symlink the .so, so we can run the tests without installing + if test "$(LINK_BINS_DYNAMIC)" = "yes"; then \ + d=`$(PWD)`; d=`$(BASENAME) $$d`; b=`$(BASENAME) $@ .la`; \ + cd .libs; t=`echo $$b*.$(DYN_EXT)`; (cd ../.. ; $(RM) $$t; \ + $(LN_S) $$d/.libs/$$t $$t); \ + if test "$(DYN_EXT)" != dll; then \ + t=`echo $$b.$(DYN_EXT).?`; cd ../.. ; \ + $(RM) $$t; \ + $(LN_S) $$d/.libs/$$t $$t; \ + fi \ + fi Makefile: $(top_srcdir)/build/lib-shared.mk + diff --git a/build/lib-static.mk b/build/lib-static.mk index ad0d14669c..272408b98e 100644 --- a/build/lib-static.mk +++ b/build/lib-static.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -11,6 +11,6 @@ $(LIBRARY): version.o $(AR) ru $@ $(OBJS) version.o @$(RANLIB) $@; \ $(RM) ../$@; \ - (d=`$(PWD)` ; $(LN_S) `$(BASENAME) $$d`/$@ ../$@) + (d=`$(PWD)` ; cd .. ; $(LN_S) `$(BASENAME) $$d`/$@ $@) Makefile: $(top_srcdir)/build/lib-static.mk diff --git a/build/lib.mk b/build/lib.mk index 9bf542d340..b647665842 100644 --- a/build/lib.mk +++ b/build/lib.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -24,7 +24,8 @@ lint5: lint5-local FORCE clean-common: FORCE $(RM) $(LIBRARY) ../$(LIBRARY) $(XLIBRARY) \ $(PROGRAMS) $(XPROGRAMS) $(XSRCS) $(XXSRCS) \ - *.o *.lo a.out core version.c .libs/* + *.o *.lo a.out *.exe core version.c .libs/* \ + ../`$(BASENAME) $(LIBRARY) .la`{.a,.so*,*.dll} depend-common: FORCE $(MKDEP) $(DEFS) $(DEFINES) $(SRCS) $(XXSRCS) diff --git a/build/ltconfig b/build/ltconfig new file mode 100755 index 0000000000..c09e49483f --- /dev/null +++ b/build/ltconfig @@ -0,0 +1,3069 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A lot of this script is taken from autoconf-2.10. + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} +echo=echo +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec "$SHELL" "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null`} + case X$UNAME in + *-DOS) PATH_SEPARATOR=';' ;; + *) PATH_SEPARATOR=':' ;; + esac +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +if test "X${echo_test_string+set}" != "Xset"; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || + test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running ltconfig again with it. + ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf "%s\n"' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # Cool, printf works + : + elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.3.3 +TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)" +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +default_ofile=libtool +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +enable_static=yes +enable_fast_install=yes +enable_dlopen=unknown +enable_win32_dll=no +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +ofile="$default_ofile" +verify_host=yes +with_gcc=no +with_gnu_ld=no +need_locks=yes +ac_ext=c +objext=o +libext=a +exeext= +cache_file= + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LDFLAGS="$LDFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_LIBS="$LIBS" +old_NM="$NM" +old_RANLIB="$RANLIB" +old_DLLTOOL="$DLLTOOL" +old_OBJDUMP="$OBJDUMP" +old_AS="$AS" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test ! -f "$ltmain"; then + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test -n "$cache_file" && test -r "$cache_file"; then + echo "loading cache $cache_file within ltconfig" + . $cache_file +fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to LTMAIN. + srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$SHELL $ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$SHELL $ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# Set a sane default for `OBJDUMP'. +test -z "$OBJDUMP" && OBJDUMP=objdump + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +fi + +# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$AS" && AS=as + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc || test -f $dir/cc$ac_exeext; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:581: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for object suffix... $ac_c" 1>&6 +$rm conftest* +echo 'int i = 1;' > conftest.c +echo "$progname:603: checking for object suffix" >& 5 +if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* +echo "$ac_t$objext" 1>&6 + +echo $ac_n "checking for executable suffix... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_exeext="no" + $rm conftest* + echo 'main () { return 0; }' > conftest.c + echo "$progname:629: checking for executable suffix" >& 5 + if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c | *.err | *.$objext ) ;; + *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; + esac + done + else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* +fi +if test "X$ac_cv_exeext" = Xno; then + exeext="" +else + exeext="$ac_cv_exeext" +fi +echo "$ac_t$ac_cv_exeext" 1>&6 + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + + case "$host_os" in + beos* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # we not sure about C++ programs. + link_static_flag="$link_static_flag ${wl}-lC" + ;; + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + sysv4*MP*) + if test -d /usr/nec; then + pic_flag=-Kconform_pic + fi + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + sysv4*MP*) + if test -d /usr/nec ;then + pic_flag='-Kconform_pic' + link_static_flag='-Bstatic' + fi + ;; + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + case "$host_os" in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + ;; + *) + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + ;; + esac + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check to see if options -o and -c are simultaneously supported by compiler +echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +$rm conftest* +echo "int some_variable = 0;" > conftest.c +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.o" +echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 +if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + echo "$ac_t"no 1>&6 + compiler_c_o=no + else + echo "$ac_t"yes 1>&6 + compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&5 + compiler_c_o=no + echo "$ac_t"no 1>&6 +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 +if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_o_lo=no + else + echo "$ac_t"yes 1>&6 + compiler_o_lo=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_o_lo=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + compiler_o_lo=no +fi + +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$ac_t$hard_links" 1>&6 + $rm conftest* + if test "$hard_links" = no; then + echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 + need_locks=warn + fi +else + need_locks=no +fi + +if test "$with_gcc" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" + echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_rtti_exceptions=no + else + echo "$ac_t"yes 1>&6 + compiler_rtti_exceptions=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_rtti_exceptions=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi + +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftest.dat + if ln -s X conftest.dat 2>/dev/null; then + $rm conftest.dat + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:991: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:1015: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:1018: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_default_flag= +hardcode_shlibpath_var=unsupported +runpath_var= +link_export= +link_export_all= +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. + +case "$host_os" in +cygwin* | mingw*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$with_gcc" != yes; then + with_gnu_ld=no + fi + ;; + +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case "$host_os" in + aix3* | aix4*) + # On AIX, the GNU linker is very broken + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + # HACK - this is actually determined at configure time in newer versions + # of libtool + lt_cv_need_dllmain=yes + lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" + + # cygwin and mingw dlls have different entry points and sets of symbols + # to exclude. + # FIXME: what about values for MSVC? + dll_entry=__cygwin_dll_entry@12 + case "$host_os" in + mingw*) + # mingw values + dll_entry=_DllMainCRTStartup@12 + lt_cv_need_dllmain=no + lt_cv_cc_dll_switch=-mdll + ;; + esac + + # mingw and cygwin differ, and it's simplest to just exclude the union + # of the two symbol sets. + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one (in ltdll.c) + if test "x$lt_cv_need_dllmain" = "xyes"; then + ltdll_obj='$objdir/$soname-ltdll.'"$objext " + ltdll_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~' + else + ltdll_obj= + ltdll_cmds= + fi + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + # Be careful not to strip the DATA tag left be newer dlltools. + export_symbols_cmds="$ltdll_cmds"' + $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols' + + # If DATA tags from a recent dlltool are present, honour them! + archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ + _lt_hint=1; + cat $export_symbols | while read symbol; do + set dummy \$symbol; + case \$# in + 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;; + *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;; + esac; + _lt_hint=`expr 1 + \$_lt_hint`; + done~ + '"$ltdll_cmds"' + $CC -Wl,--base-file,$objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $lib '$ltdll_obj'$libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $lib '$ltdll_obj'$libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC $objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $lib '$ltdll_obj'$libobjs $deplibs $linkopts' + + old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' + ;; + + netbsd*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' + # can we support soname and/or expsyms with a.out? -oliva + fi + ;; + + solaris*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + link_export=' -bE:$export_symbols' + archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + hardcode_libdir_flag_spec='${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' + hardcode_libdir_separator=':' + if test "$with_gcc" = yes; then + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + shared_flag='-shared' + else + shared_flag='${wl}-bM:SRE' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_default_flag='${wl}-b nolibpath' + fi + allow_undefined_flag=' ${wl}-berok' + archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' + link_export=' ${wl}-bE:$export_symbols' + link_export_all=' ${wl}-bexpall' + always_export_symbols=yes + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs' + fix_srcfile_path='`cygpath -w $srcfile`' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case "$host_os" in + hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF + fi + hardcode_libdir_flag_spec='${wl}-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case "$host_os" in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs' + archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + *) + ld_shlibs=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 +test "$ld_shlibs" = no && can_build_shared=no + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + break + else + NM=${NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + symcode='[BCDEGRST]' + ;; +solaris*) + symcode='[BDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + $rm conftest* + cat > conftest.c <&5 + if { (eval echo $progname:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:1596: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$objext conftstm.$objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + global_symbol_pipe= + fi +done +if test "$pipe_works" = yes; then + echo "${ac_t}ok" 1>&6 +else + echo "${ac_t}failed" 1>&6 +fi + +if test -z "$global_symbol_pipe"; then + global_symbol_to_cdecl= +fi + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$ac_t$hardcode_action" 1>&6 + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linkers may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" 1>&6 +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +file_magic_cmd= +file_magic_test_file= +deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [regex]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + lt_cv_dlopen_self=yes + need_lib_prefix=no + ;; + +aix4*) + version_type=linux + # AIX has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + # We preserve .a as extension for shared libraries though AIX4.2 + # and later linker supports .so + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' + shlibpath_var=LIBPATH + deplibs_check_method=pass_all + lt_cv_dlopen_self=yes + need_lib_prefix=no + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + deplibs_check_method=pass_all + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + +bsdi4*) + version_type=linux + library_names_spec='${libname}.so$major ${libname}.so' + soname_spec='${libname}.so' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw*) + version_type=windows + need_version=no + need_lib_prefix=no + if test "$with_gcc" = yes; then + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' + else + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' + fi + dynamic_linker='Win32 ld.exe' + deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + file_magic_cmd='${OBJDUMP} -f' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case "$version_type" in + freebsd-elf*) + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + deplibs_check_method=unknown + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + case "$host_os" in + freebsd2* | freebsd3.[01]*) + shlibpath_overrides_runpath=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=irix + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' + case "$host_os" in + irix5*) + libsuff= shlibsuff= + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case "$LD" in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib${libsuff}/libc.so*` + deplibs_check_method='pass_all' + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd*) + version_type=sunos + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + ;; + +openbsd*) + version_type=sunos + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + need_version=no + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method='file_magic COFF format alpha shared library' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + deplibs_check_method='pass_all' + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" + file_magic_cmd=/usr/bin/file + file_magic_test_file=/lib/libc.so + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case "$host_vendor" in + ncr) + deplibs_check_method='pass_all' + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" 1>&6 +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in +# configure.in, otherwise build static only libraries. +case "$host_os" in +cygwin* | mingw* | os2*) + if test x$can_build_shared = xyes; then + test x$enable_win32_dll = xno && can_build_shared=no + echo "checking if package supports dlls... $can_build_shared" 1>&6 + fi +;; +esac + +if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then + case "$deplibs_check_method" in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac +fi + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else +if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then + lt_cv_dlopen=no lt_cv_dlopen_libs= +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "$progname:2170: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dlopen""... $ac_c" 1>&6 +echo "$progname:2207: checking for dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +dlopen(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_dlopen=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_dlopen=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 +echo "$progname:2251: checking for dld_link in -ldld" >&5 +ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load""... $ac_c" 1>&6 +echo "$progname:2288: checking for shl_load" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +shl_load(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shl_load=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shl_load=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 +echo "$progname:2333: checking for shl_load in -ldld" >&5 +ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +fi + + +fi + + +fi + + +fi + + +fi + +fi + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + fi + + case "$lt_cv_dlopen" in + dlopen) +for ac_hdr in dlfcn.h; do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "$progname:2395: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int fnord = 0; +EOF +ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo $progname:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +done + + if test "x$ac_cv_header_dlfcn_h" = xyes; then + CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + fi + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2433: checking whether a program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self" 1>&6 + + if test "$lt_cv_dlopen_self" = yes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2506: checking whether a statically linked program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self_static=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self_static=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self_static=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 +fi + ;; + esac + + case "$lt_cv_dlopen_self" in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case "$lt_cv_dlopen_self_static" in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" +if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ltecho="$CONFIG_SHELL \$0 --fallback-echo" +fi +LTSHELL="$SHELL" + +LTCONFIG_VERSION="$VERSION" + +# Only quote variables if we're using ltmain.sh. +case "$ltmain" in +*.sh) + # Now quote all the things that may contain metacharacters. + for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ + AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ + file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case "$ltecho" in + *'\$0 --fallback-echo"') + ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + + trap "$rm \"$ofile\"; exit 1" 1 2 15 + echo "creating $ofile" + $rm "$ofile" + cat < "$ofile" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +### BEGIN LIBTOOL CONFIG +EOF + cfgfile="$ofile" + ;; + +*) + # Double-quote the variables that need it (for aesthetics). + for var in old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do + eval "$var=\\\"\$var\\\"" + done + + # Just create a config file. + cfgfile="$ofile.cfg" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + echo "creating $cfgfile" + $rm "$cfgfile" + cat < "$cfgfile" +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +EOF + ;; +esac + +cat <> "$cfgfile" +# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ +# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ +# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ +# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# The version of $progname that generated this script. +LTCONFIG_VERSION=$LTCONFIG_VERSION + +# Shell to use when invoking shell scripts. +SHELL=$LTSHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$ltecho + +# The archiver. +AR=$AR + +# The default C compiler. +CC=$CC + +# The linker used to build libraries. +LD=$LD + +# Whether we need hard or soft links. +LN_S=$LN_S + +# A BSD-compatible nm program. +NM=$NM + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$reload_flag +reload_cmds=$reload_cmds + +# How to pass a linker flag through the compiler. +wl=$wl + +# Object file suffix (normally "o"). +objext="$objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$pic_flag + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$RANLIB +old_archive_cmds=$old_archive_cmds +old_postinstall_cmds=$old_postinstall_cmds +old_postuninstall_cmds=$old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$old_archive_from_new_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$archive_cmds +archive_expsym_cmds=$archive_expsym_cmds +postinstall_cmds=$postinstall_cmds +postuninstall_cmds=$postuninstall_cmds + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$global_symbol_to_cdecl + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Flag to force default rpath, to bypass effect of -L +hardcode_default_flag='$hardcode_default_flag' + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# Set to use export list when linking programs. +link_export='$link_export' +link_export_all='$link_export_all' + +# The commands to list exported symbols. +export_symbols_cmds=$export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$include_expsyms + +EOF + +case "$ltmain" in +*.sh) + echo '### END LIBTOOL CONFIG' >> "$ofile" + echo >> "$ofile" + case "$host_os" in + aix3*) + cat <<\EOF >> "$ofile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # Append the ltmain.sh script. + sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) + + chmod +x "$ofile" + ;; + +*) + # Compile the libtool program. + echo "FIXME: would compile $ltmain" + ;; +esac + +test -n "$cache_file" || exit 0 + +# AC_CACHE_SAVE +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build/ltmain.sh b/build/ltmain.sh index f886d7e5c6..3ca937b978 100755 --- a/build/ltmain.sh +++ b/build/ltmain.sh @@ -1086,7 +1086,7 @@ compiler." -l*) if test "$arg" = "-lc"; then case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | *-*-aix*) # These systems don't actually have c library (as such) continue ;; @@ -1629,6 +1629,9 @@ compiler." $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" + if test -n "$hardcode_default_flag"; then + eval linkopts=\"$linkopts$hardcode_default_flag\" + fi oldlibs= if test -z "$rpath"; then @@ -1803,7 +1806,7 @@ compiler." dependency_libs="$deplibs" case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | *-*-aix*) # these systems don't actually have a c library (as such)! ;; *) @@ -2445,6 +2448,14 @@ EOF fi finalize_rpath="$rpath" + if test -z "$compile_rpath" -a -n "$hardcode_default_flag"; then + eval compile_rpath=\" $hardcode_default_flag\" + fi + + if test -z "$finalize_rpath" -a -n "$hardcode_default_flag"; then + eval finalize_rpath=\" $hardcode_default_flag\" + fi + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" @@ -2538,6 +2549,32 @@ extern \"C\" { fi fi + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes -a -n "$link_export_all"; then + eval link_export=\"$link_export_all\" + elif test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$output'" + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + libobjs="$objs" + eval cmds=\"$export_symbols_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | sed -e 's%^.*/%%'` @@ -2649,10 +2686,15 @@ static const void *lt_preloaded_setup() { finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi + link_export_opt= + if test -n "$export_symbols" -o -n "$dlsyms"; then + eval link_export_opt=\"$link_export\" + fi + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" + link_command="$compile_command$compile_rpath$link_export_opt" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" @@ -2739,6 +2781,8 @@ static const void *lt_preloaded_setup() { # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + link_command="$link_command$link_export_opt" + # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname @@ -2918,7 +2962,7 @@ else # Run the actual program with our arguments. " case $host in - *-*-cygwin* | *-*-mingw | *-*-os2*) + *-*-cygwin* | *-*-mingw* | *-*-os2*) # win32 systems need to use the prog path for dll # lookup to work $echo >> $output "\ @@ -3308,7 +3352,14 @@ libdir='$install_libdir'\ $show "$install_prog $dir/$realname $destdir/$realname" $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? - if test $# -gt 0; then + # Windows does not have any symlinks to DLLs, despite what + # library_names has been set to. + skip_syms=false + case $host in + *-*-cygwin* | *-*-mingw*) skip_syms=true ;; + esac + + if test "$skip_syms" = "false" && test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do @@ -3338,7 +3389,7 @@ libdir='$install_libdir'\ $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + test -n "$old_library" -a $build_old_libs = yes && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) diff --git a/build/main.dsw b/build/main.dsw index 0dee32c0c0..bc84913c00 100644 --- a/build/main.dsw +++ b/build/main.dsw @@ -87,9 +87,6 @@ Package=<4> Project_Dep_Name ldapsearch End Project Dependency Begin Project Dependency - Project_Dep_Name ldbmtest - End Project Dependency - Begin Project Dependency Project_Dep_Name ldif End Project Dependency Begin Project Dependency @@ -128,6 +125,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name ltest_r End Project Dependency + Begin Project Dependency + Project_Dep_Name passwd + End Project Dependency }}} ############################################################################### @@ -273,7 +273,7 @@ Package=<4> ############################################################################### -Project: "ldbmtest"=..\servers\slapd\tools\ldbmtest.dsp - Package Owner=<4> +Project: "ldif"=..\servers\slapd\tools\ldif.dsp - Package Owner=<4> Package=<5> {{{ @@ -281,35 +281,23 @@ Package=<5> Package=<4> {{{ - Begin Project Dependency - Project_Dep_Name backldbm - End Project Dependency Begin Project Dependency Project_Dep_Name liblber End Project Dependency Begin Project Dependency - Project_Dep_Name libldap_r + Project_Dep_Name libldif End Project Dependency Begin Project Dependency - Project_Dep_Name libldbm + Project_Dep_Name libldap End Project Dependency Begin Project Dependency Project_Dep_Name liblutil End Project Dependency - Begin Project Dependency - Project_Dep_Name libslapd - End Project Dependency - Begin Project Dependency - Project_Dep_Name libavl - End Project Dependency - Begin Project Dependency - Project_Dep_Name libldif - End Project Dependency }}} ############################################################################### -Project: "ldif"=..\servers\slapd\tools\ldif.dsp - Package Owner=<4> +Project: "libavl"=..\libraries\libavl\libavl.dsp - Package Owner=<4> Package=<5> {{{ @@ -318,22 +306,13 @@ Package=<5> Package=<4> {{{ Begin Project Dependency - Project_Dep_Name liblber - End Project Dependency - Begin Project Dependency - Project_Dep_Name libldif - End Project Dependency - Begin Project Dependency - Project_Dep_Name libldap - End Project Dependency - Begin Project Dependency - Project_Dep_Name liblutil + Project_Dep_Name setup End Project Dependency }}} ############################################################################### -Project: "libavl"=..\libraries\libavl\libavl.dsp - Package Owner=<4> +Project: "liblber"=..\libraries\liblber\liblber.dsp - Package Owner=<4> Package=<5> {{{ @@ -341,11 +320,14 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### -Project: "liblber"=..\libraries\liblber\liblber.dsp - Package Owner=<4> +Project: "libldap"=..\libraries\libldap\libldap.dsp - Package Owner=<4> Package=<5> {{{ @@ -353,11 +335,14 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### -Project: "libldap"=..\libraries\libldap\libldap.dsp - Package Owner=<4> +Project: "libldap_r"=..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4> Package=<5> {{{ @@ -365,11 +350,14 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### -Project: "libldap_r"=..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4> +Project: "libldbm"=..\libraries\libldbm\libldbm.dsp - Package Owner=<4> Package=<5> {{{ @@ -377,11 +365,14 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### -Project: "libldbm"=..\libraries\libldbm\libldbm.dsp - Package Owner=<4> +Project: "libldif"=..\libraries\libldif\libldif.dsp - Package Owner=<4> Package=<5> {{{ @@ -389,11 +380,14 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### -Project: "libldif"=..\libraries\libldif\libldif.dsp - Package Owner=<4> +Project: "liblunicode"=..\libraries\liblunicode\liblunicode.dsp - Package Owner=<4> Package=<5> {{{ @@ -401,6 +395,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### @@ -413,6 +410,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### @@ -425,6 +425,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name setup + End Project Dependency }}} ############################################################################### @@ -471,6 +474,24 @@ Package=<4> ############################################################################### +Project: "passwd"=..\libraries\liblutil\passwd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency + Begin Project Dependency + Project_Dep_Name liblutil + End Project Dependency +}}} + +############################################################################### + Project: "setup"=..\include\setup.dsp - Package Owner=<4> Package=<5> diff --git a/build/man.mk b/build/man.mk index 91a96065cb..a63385d88a 100644 --- a/build/man.mk +++ b/build/man.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -26,17 +26,17 @@ all-common: done install-common: - -$(MKDIR) $(MANDIR) + -$(MKDIR) $(DESTDIR)$(MANDIR) PAGES=`cd $(srcdir); echo *.$(MANSECT)`; \ for page in $$PAGES; do \ echo "installing $(MANDIR)/$$page"; \ - $(RM) $(MANDIR)/$$page; \ - $(INSTALL) $(INSTALLFLAGS) -m 644 $$page.$(TMP_SUFFIX) $(MANDIR)/$$page; \ + $(RM) $(DESTDIR)$(MANDIR)/$$page; \ + $(INSTALL) $(INSTALLFLAGS) -m 644 $$page.$(TMP_SUFFIX) $(DESTDIR)$(MANDIR)/$$page; \ if test -f "$(srcdir)/$$page.links" ; then \ for link in `$(CAT) $(srcdir)/$$page.links`; do \ echo "installing $(MANDIR)/$$link as link to $$page"; \ - $(RM) $(MANDIR)/$$link ; \ - $(LN_S) $$page $(MANDIR)/$$link; \ + $(RM) $(DESTDIR)$(MANDIR)/$$link ; \ + $(LN_S) $$page $(DESTDIR)$(MANDIR)/$$link; \ done; \ fi; \ done diff --git a/build/mkdep b/build/mkdep index 55ef1e4c50..d2e316865e 100755 --- a/build/mkdep +++ b/build/mkdep @@ -1,6 +1,6 @@ #! /bin/sh - # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. # diff --git a/build/mkdep.aix b/build/mkdep.aix new file mode 100755 index 0000000000..1339a1d23a --- /dev/null +++ b/build/mkdep.aix @@ -0,0 +1,4 @@ +#! /bin/sh +cc_r -ME $* > /dev/null +cat *.u +rm *.u diff --git a/build/mkrelease b/build/mkrelease index c694984f3c..90bf90552d 100755 --- a/build/mkrelease +++ b/build/mkrelease @@ -1,6 +1,6 @@ #! /bin/sh # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. # @@ -45,6 +45,7 @@ fi tar cf $RELNAME.tar $RELNAME gzip -9 -c $RELNAME.tar > $RELNAME.tgz md5 $RELNAME.tgz > $RELNAME.md5 +rm -f $RELNAME.tar ls -l $RELNAME.* cat $RELNAME/build/version diff --git a/build/mkversion b/build/mkversion index d0ba1373a1..d8c98914e2 100755 --- a/build/mkversion +++ b/build/mkversion @@ -1,6 +1,6 @@ #! /bin/sh # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. # @@ -47,7 +47,7 @@ WHOWHERE="$USER@`uname -n`:`pwd`" cat << __EOF__ /* - * Copyright 1998,1999 The OpenLDAP Foundation + * Copyright 1998-2000 The OpenLDAP Foundation * COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory * of this package for details. */ diff --git a/build/mod.mk b/build/mod.mk index 380e1dc78c..7433cf0789 100644 --- a/build/mod.mk +++ b/build/mod.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -9,8 +9,20 @@ LIBRARY = $(LIBBASE).la LIBSTAT = lib$(LIBBASE).a + LTFLAGS = --only-$(LINKAGE) +COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CFLAGS) $(MODDEFS) -c +LTLIBLINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) \ + $(LTVERSION) $(LT_NO_UNDEF) + +MKDEPFLAG = -l + +.SUFFIXES: .c .o .lo + +.c.lo: + $(COMPILE) $< + all-no lint-no 5lint-no depend-no install-no: FORCE @echo "run configure with $(BUILD_OPT) to make $(LIBBASE)" @@ -20,8 +32,9 @@ version.c: $(OBJS) $(RM) $@ $(MKVERSION) $(LIBBASE) > $@ -$(LIBRARY): version.lo - $(LTLIBLINK) -module -rpath $(moduledir) -o $@ $(OBJS) version.lo +$(LIBRARY): $(MODDEPS) version.lo + $(LTLIBLINK) -module -rpath $(moduledir) -o $@ $(OBJS) version.lo \ + $(MODLIBS) $(LIBSTAT): version.lo $(AR) ruv $@ `echo $(OBJS) | sed 's/\.lo/.o/g'` version.o @@ -46,8 +59,8 @@ all-local-lib: all-yes: $(LIBSTAT) all-local-lib FORCE install-mod: $(LIBRARY) - @-$(MKDIR) $(moduledir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 $(LIBRARY) $(moduledir) + @-$(MKDIR) $(DESTDIR)$(moduledir) + $(LTINSTALL) $(INSTALLFLAGS) -m 755 $(LIBRARY) $(DESTDIR)$(moduledir) install-local-lib: install-yes: install-local-lib FORCE @@ -71,12 +84,5 @@ depend-yes depend-mod: depend-local-lib FORCE veryclean-local-lib: veryclean-lib: clean-lib veryclean-local-lib -COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CFLAGS) -c -MKDEPFLAG = -l - -.SUFFIXES: .c .o .lo - -.c.lo: - $(COMPILE) $< - Makefile: $(top_srcdir)/build/mod.mk + diff --git a/build/openldap.m4 b/build/openldap.m4 index 4ceadfe3e1..1ce490ff12 100644 --- a/build/openldap.m4 +++ b/build/openldap.m4 @@ -1,6 +1,6 @@ dnl $OpenLDAP$ dnl -dnl Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +dnl Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. dnl COPYING RESTRICTIONS APPLY, See COPYRIGHT file dnl dnl OpenLDAP Autoconf Macros @@ -56,6 +56,33 @@ dnl AC_VERBOSE(OpenLDAP --with-$1 $ol_with_$1) ])dnl dnl dnl ==================================================================== +dnl +AC_DEFUN(AC_COMPILE_CHECK_SIZEOF, +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[for ac_size in 4 8 1 2 16 $2 ; do # List sizes in rough order of prevalence. + AC_TRY_COMPILE([#include "confdefs.h" +#include +$2 +], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size) + if test x$AC_CV_NAME != x ; then break; fi +done +]) +if test x$AC_CV_NAME = x ; then + AC_MSG_ERROR([cannot determine a size for $1]) +fi +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) +dnl ==================================================================== dnl check if hard links are supported. dnl AC_DEFUN([OL_PROG_LN_H], [# test for ln hardlink support @@ -211,141 +238,166 @@ fi ]) dnl dnl ==================================================================== -dnl Check if db.h is Berkeley DB2 +dnl Berkeley DB macros dnl -dnl defines ol_cv_header_db2 to 'yes' or 'no' -dnl -dnl uses: -dnl AC_CHECK_HEADERS(db.h) -dnl -AC_DEFUN([OL_HEADER_BERKELEY_DB2], -[AC_CHECK_HEADERS(db.h) -if test $ac_cv_header_db_h = yes ; then - AC_CACHE_CHECK([if db.h is DB2], [ol_cv_header_db2],[ - AC_EGREP_CPP(__db_version_2,[ -# include - /* this check could be improved */ -# ifdef DB_VERSION_MAJOR -# if DB_VERSION_MAJOR == 2 - __db_version_2 -# endif -# endif - ], ol_cv_header_db2=yes, ol_cv_header_db2=no)]) -else - ol_cv_header_db2=no -fi -])dnl dnl -------------------------------------------------------------------- -dnl Check if Berkeley DB2 library exists -dnl Check for dbopen in standard libraries or -ldb -dnl -dnl defines ol_cv_lib_db2 to '-ldb' or 'no' -dnl -dnl uses: -dnl AC_CHECK_LIB(db,db_open) -dnl -AC_DEFUN([OL_LIB_BERKELEY_DB2], -[AC_CACHE_CHECK([for DB2 library], [ol_cv_lib_db2], -[ ol_LIBS="$LIBS" - AC_CHECK_LIB(db,db_open,[ol_cv_lib_db2=-ldb],[ol_cv_lib_db2=no]) +dnl Try to link +AC_DEFUN([OL_BERKELEY_DB_TRY], +[if test $ol_cv_lib_db = no ; then + AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1], +[ + ol_DB_LIB=ifelse($2,,,$2) + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" + + AC_TRY_LINK([ +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif +],[ +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif +],[$1=yes],[$1=no]) + LIBS="$ol_LIBS" ]) -])dnl -dnl -dnl -------------------------------------------------------------------- -dnl Check if Berkeley db2 exists -dnl -dnl defines ol_cv_berkeley_db2 to 'yes' or 'no' -dnl -dnl uses: -dnl OL_LIB_BERKELEY_DB2 -dnl OL_HEADER_BERKELEY_DB2 -dnl -AC_DEFUN([OL_BERKELEY_DB2], -[AC_REQUIRE([OL_LIB_BERKELEY_DB2]) - AC_REQUIRE([OL_HEADER_BERKELEY_DB2]) - AC_CACHE_CHECK([for Berkeley DB2], [ol_cv_berkeley_db2], [ - if test "$ol_cv_lib_db2" = no -o "$ol_cv_header_db2" = no ; then - ol_cv_berkeley_db2=no - else - ol_cv_berkeley_db2=yes - fi -]) - if test $ol_cv_berkeley_db2 = yes ; then - AC_DEFINE(HAVE_BERKELEY_DB2,1, [define if Berkeley DBv2 is available]) - fi -])dnl -dnl -dnl ==================================================================== -dnl Check for db.h/db_185.h is Berkeley DB -dnl -dnl defines ol_cv_header_db to 'yes' or 'no' -dnl -dnl uses: -dnl OL_HEADER_BERKELEY_DB2 -dnl AC_CHECK_HEADERS(db_185.h) -dnl -AC_DEFUN([OL_HEADER_BERKELEY_DB], -[AC_REQUIRE([OL_HEADER_BERKELEY_DB2]) -AC_CHECK_HEADERS(db_185.h) -if test "$ol_cv_header_db2" = yes ; then - dnl db.h is db2! - ol_cv_header_db=$ac_cv_header_db_185_h -else - ol_cv_header_db=$ac_cv_header_db_h + if test $$1 = yes ; then + ol_cv_lib_db=ifelse($2,,yes,$2) + fi fi -])dnl +]) dnl dnl -------------------------------------------------------------------- -dnl Check if Berkeley DB library exists -dnl Check for dbopen in standard libraries or -ldb -dnl -dnl defines ol_cv_lib_db to 'yes' or '-ldb' or 'no' -dnl 'yes' implies dbopen is in $LIBS -dnl -dnl uses: -dnl AC_CHECK_FUNC(dbopen) -dnl AC_CHECK_LIB(db,dbopen) +dnl Try to locate appropriate library +AC_DEFUN([OL_BERKELEY_DB_LINK], +[ol_cv_lib_db=no +OL_BERKELEY_DB_TRY(ol_cv_db_none) +OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb]) +OL_BERKELEY_DB_TRY(ol_cv_db_db3,[-ldb3]) +OL_BERKELEY_DB_TRY(ol_cv_db_db2,[-ldb2]) +OL_BERKELEY_DB_TRY(ol_cv_db_db1,[-ldb1]) +]) dnl -AC_DEFUN([OL_LIB_BERKELEY_DB], -[AC_CACHE_CHECK([for Berkeley DB library], [ol_cv_lib_db], -[ - AC_CHECK_HEADERS(db1/db.h) +dnl -------------------------------------------------------------------- +dnl Check if Berkeley DB supports DB_THREAD +AC_DEFUN([OL_BERKELEY_DB_THREAD], +[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [ ol_LIBS="$LIBS" - AC_CHECK_FUNC(dbopen,[ol_cv_lib_db=yes], [ - AC_CHECK_LIB(db1,dbopen,[ol_cv_lib_db=-ldb1],[ - AC_CHECK_LIB(db,dbopen,[ol_cv_lib_db=-ldb], - [ol_cv_lib_db=no]) - ]) - ]) + if test $ol_cv_lib_db != yes ; then + LIBS="$ol_cv_lib_db" + fi + + AC_TRY_RUN([ +#ifdef HAVE_DB_185_H + choke me; +#else +#include +#endif +#ifndef NULL +#define NULL ((void *)0) +#endif +main() +{ + int rc; + u_int32_t flags = DB_CREATE | DB_THREAD; + + +#if DB_VERSION_MAJOR > 2 + DB_ENV *env = NULL; + + rc = db_env_create( &env, 0 ); + + if( rc == 0 ) { + rc = env->open( env, NULL, NULL, flags, 0 ); + } + +#else + DB_ENV env; + memset( &env, '\0', sizeof(env) ); + + rc = db_appinit( NULL, NULL, &env, flags ); + + if( rc == 0 ) { + db_appexit( &env ); + } +#endif + + return rc; +}], + [ol_cv_berkeley_db_thread=yes], + [ol_cv_berkeley_db_thread=no], + [ol_cv_berkeley_db_thread=cross]) + LIBS="$ol_LIBS" -]) -])dnl + + if test $ol_cv_berkeley_db_thread != no ; then + AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1, + [define if Berkeley DB has DB_THREAD support]) + fi +])])dnl dnl dnl -------------------------------------------------------------------- -dnl Check if Berkeley DB exists -dnl -dnl defines ol_cv_berkeley_db to 'yes' or 'no' -dnl -dnl uses: -dnl OL_LIB_BERKELEY_DB -dnl OL_HEADER_BERKELEY_DB -dnl +dnl Find any DB AC_DEFUN([OL_BERKELEY_DB], -[AC_REQUIRE([OL_LIB_BERKELEY_DB]) - AC_REQUIRE([OL_HEADER_BERKELEY_DB]) - AC_CACHE_CHECK([for Berkeley DB], [ol_cv_berkeley_db], [ - if test "$ol_cv_lib_db" = no -o "$ol_cv_header_db" = no ; then - ol_cv_berkeley_db=no - else +[ol_cv_berkeley_db=no +AC_CHECK_HEADERS(db.h) +if test $ac_cv_header_db_h = yes; then + OL_BERKELEY_DB_LINK + if test "$ol_cv_lib_db" != no ; then ol_cv_berkeley_db=yes + OL_BERKELEY_DB_THREAD fi +fi +]) +dnl +dnl -------------------------------------------------------------------- +dnl Find old Berkeley DB 1.85/1.86 +AC_DEFUN([OL_BERKELEY_COMPAT_DB], +[ol_cv_berkeley_db=no +AC_CHECK_HEADERS(db_185.h db.h) +if test $ac_cv_header_db_185_h = yes -o $ac_cv_header_db_h = yes; then + AC_CACHE_CHECK([if Berkeley DB header compatibility], [ol_cv_header_db1],[ + AC_EGREP_CPP(__db_version_1,[ +#if HAVE_DB_185_H +# include +#else +# include +#endif + + /* this check could be improved */ +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#if DB_VERSION_MAJOR == 1 + __db_version_1 +#endif +], [ol_cv_header_db1=yes], [ol_cv_header_db1=no])]) + + if test ol_cv_header_db1=yes ; then + OL_BERKELEY_DB_LINK + if test "$ol_cv_lib_db" != no ; then + ol_cv_berkeley_db=yes + fi + fi +fi ]) - if test $ol_cv_berkeley_db = yes ; then - AC_DEFINE(HAVE_BERKELEY_DB,1, [define if Berkeley DB is available]) - fi -])dnl dnl dnl ==================================================================== dnl Check if GDBM library exists @@ -507,7 +559,7 @@ AC_DEFUN([OL_POSIX_THREAD_VERSION], # include /* this check could be improved */ # ifdef PTHREAD_ONCE_INIT - pthread_version_final + pthread_version_final; # endif ], ol_pthread_final=yes, ol_pthread_final=no) @@ -515,7 +567,7 @@ AC_DEFUN([OL_POSIX_THREAD_VERSION], # include /* this check could be improved */ # ifdef pthread_once_init - pthread_version_draft4 + pthread_version_draft4; # endif ], ol_pthread_draft4=yes, ol_pthread_draft4=no) @@ -547,14 +599,26 @@ AC_DEFUN([OL_PTHREAD_TEST_FUNCTION],[ /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -620,7 +684,7 @@ AC_DEFUN([OL_HEADER_GNU_PTH_PTHREAD_H], [ [AC_EGREP_CPP(__gnu_pth__, [#include #ifdef _POSIX_THREAD_IS_GNU_PTH - __gnu_pth__ + __gnu_pth__; #endif ], [ol_cv_header_gnu_pth_pthread_h=yes], @@ -628,6 +692,19 @@ AC_DEFUN([OL_HEADER_GNU_PTH_PTHREAD_H], [ ]) ])dnl dnl ==================================================================== +dnl Check for NT Threads +AC_DEFUN([OL_NT_THREADS], [ + AC_CACHE_CHECK([for NT Threads], [ol_cv_nt_threads], [ + AC_CHECK_FUNC(_beginthread, + [ol_cv_nt_threads=yes], + [ol_cv_nt_threads=no]) + ]) + + if test $ol_cv_nt_threads = yes ; then + AC_DEFINE(HAVE_NT_THREADS,1,[if you have NT Threads]) + fi +]) +dnl ==================================================================== dnl Check LinuxThreads Header dnl dnl defines ol_cv_header linux_threads to 'yes' or 'no' @@ -740,7 +817,10 @@ AC_DEFUN([OL_SYS_ERRLIST], AC_TRY_COMPILE([ #include #include -#include ], +#include +#ifdef WINNT +#include +#endif ], [char *c = (char *) *sys_errlist], [ol_cv_dcl_sys_errlist=yes ol_cv_have_sys_errlist=yes], @@ -783,7 +863,7 @@ dnl dnl ==================================================================== dnl Look for fetch(3) AC_DEFUN([OL_LIB_FETCH], -[ol=$LIBS +[ol_LIBS=$LIBS LIBS="-lfetch -lcom_err $LIBS" AC_CACHE_CHECK([fetch(3) library],ol_cv_lib_fetch,[ AC_TRY_LINK([ @@ -865,13 +945,31 @@ AC_DEFUN(OL_FUNC_CTIME_R_NARGS, [AC_CACHE_CHECK(number of arguments of ctime_r, ol_cv_func_ctime_r_nargs, [AC_TRY_COMPILE([#include ], [time_t ti; char *buffer; ctime_r(&ti,buffer,32);], - ol_cv_func_ctime_r_nargs=3, - [AC_TRY_COMPILE([#include ], - [time_t ti; char *buffer; ctime_r(&ti,buffer);], - ol_cv_func_ctime_r_nargs=2, - ol_cv_func_ctime_r_nargs=0)])]) + ol_cv_func_ctime_r_nargs3=yes, + ol_cv_func_ctime_r_nargs3=no) + + AC_TRY_COMPILE([#include ], + [time_t ti; char *buffer; ctime_r(&ti,buffer);], + ol_cv_func_ctime_r_nargs2=yes, + ol_cv_func_ctime_r_nargs2=no) + + if test $ol_cv_func_ctime_r_nargs3 = yes -a \ + $ol_cv_func_ctime_r_nargs2 = no ; then + + ol_cv_func_ctime_r_nargs=3 + + elif test $ol_cv_func_ctime_r_nargs3 = no -a \ + $ol_cv_func_ctime_r_nargs2 = yes ; then + + ol_cv_func_ctime_r_nargs=2 + + else + ol_cv_func_ctime_r_nargs=0 + fi + ]) + if test $ol_cv_func_ctime_r_nargs -gt 1 ; then - AC_DEFINE_UNQUOTED(CTIME_R_NARGS, $ol_cv_func_ctime_r_nargs, + AC_DEFINE_UNQUOTED(CTIME_R_NARGS, $ol_cv_func_ctime_r_nargs, [set to the number of arguments ctime_r() expects]) fi ])dnl @@ -902,19 +1000,36 @@ AC_DEFUN(OL_FUNC_GETHOSTBYNAME_R_NARGS, int bufsize=BUFSIZE;int h_errno; (void)gethostbyname_r("segovia.cs.purdue.edu", &hent, buffer, bufsize, &h_errno);], - ol_cv_func_gethostbyname_r_nargs=5, - [AC_TRY_COMPILE([#include + ol_cv_func_gethostbyname_r_nargs5=yes, + ol_cv_func_gethostbyname_r_nargs5=no) + + AC_TRY_COMPILE([#include #include #include #include #define BUFSIZE (sizeof(struct hostent)+10)], - [struct hostent hent;struct hostent *rhent; - char buffer[BUFSIZE]; - int bufsize=BUFSIZE;int h_errno; - (void)gethostbyname_r("localhost", &hent, buffer, bufsize, - &rhent, &h_errno);], - ol_cv_func_gethostbyname_r_nargs=6, - ol_cv_func_gethostbyname_r_nargs=0)])]) + [struct hostent hent;struct hostent *rhent; + char buffer[BUFSIZE]; + int bufsize=BUFSIZE;int h_errno; + (void)gethostbyname_r("localhost", &hent, buffer, bufsize, + &rhent, &h_errno);], + ol_cv_func_gethostbyname_r_nargs6=yes, + ol_cv_func_gethostbyname_r_nargs6=no) + + if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \ + $ol_cv_func_gethostbyname_r_nargs6 = no ; then + + ol_cv_func_gethostbyname_r_nargs=5 + + elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \ + $ol_cv_func_gethostbyname_r_nargs6 = yes ; then + + ol_cv_func_gethostbyname_r_nargs=6 + + else + ol_cv_func_gethostbyname_r_nargs=0 + fi + ]) if test $ol_cv_func_gethostbyname_r_nargs -gt 1 ; then AC_DEFINE_UNQUOTED(GETHOSTBYNAME_R_NARGS, $ol_cv_func_gethostbyname_r_nargs, @@ -937,22 +1052,39 @@ AC_DEFUN(OL_FUNC_GETHOSTBYADDR_R_NARGS, int bufsize=BUFSIZE;int h_errno; (void)gethostbyaddr_r( (void *)&(add.s_addr), alen, AF_INET, &hent, buffer, bufsize, &h_errno);], - ol_cv_func_gethostbyaddr_r_nargs=7, - [AC_TRY_COMPILE([#include + ol_cv_func_gethostbyaddr_r_nargs7=yes, + ol_cv_func_gethostbyaddr_r_nargs7=no) + + AC_TRY_COMPILE([#include #include #include #include #define BUFSIZE (sizeof(struct hostent)+10)], - [struct hostent hent; - struct hostent *rhent; char buffer[BUFSIZE]; - struct in_addr add; - size_t alen=sizeof(struct in_addr); - int bufsize=BUFSIZE;int h_errno; - (void)gethostbyaddr_r( (void *)&(add.s_addr), - alen, AF_INET, &hent, buffer, bufsize, - &rhent, &h_errno);], - ol_cv_func_gethostbyaddr_r_nargs=8, - ol_cv_func_gethostbyaddr_r_nargs=0)])]) + [struct hostent hent; + struct hostent *rhent; char buffer[BUFSIZE]; + struct in_addr add; + size_t alen=sizeof(struct in_addr); + int bufsize=BUFSIZE;int h_errno; + (void)gethostbyaddr_r( (void *)&(add.s_addr), + alen, AF_INET, &hent, buffer, bufsize, + &rhent, &h_errno);], + ol_cv_func_gethostbyaddr_r_nargs8=yes, + ol_cv_func_gethostbyaddr_r_nargs8=no) + + if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes -a \ + $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then + + ol_cv_func_gethostbyaddr_r_nargs=7 + + elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no -a \ + $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then + + ol_cv_func_gethostbyaddr_r_nargs=8 + + else + ol_cv_func_gethostbyaddr_r_nargs=0 + fi + ]) if test $ol_cv_func_gethostbyaddr_r_nargs -gt 1 ; then AC_DEFINE_UNQUOTED(GETHOSTBYADDR_R_NARGS, $ol_cv_func_gethostbyaddr_r_nargs, diff --git a/build/rules.mk b/build/rules.mk index 4f795ff353..0002cd0ac8 100644 --- a/build/rules.mk +++ b/build/rules.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -10,7 +10,8 @@ all-common: $(PROGRAMS) FORCE clean-common: FORCE - $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o *.lo a.out core *.core .libs/* + $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o *.lo a.out core *.core \ + .libs/* *.exe depend-common: FORCE $(MKDEP) $(DEFS) $(DEFINES) $(SRCS) diff --git a/build/srv.mk b/build/srv.mk index ee6d5daa27..cfc51b0954 100644 --- a/build/srv.mk +++ b/build/srv.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation +## Copyright 1998-2000 The OpenLDAP Foundation ## COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory ## of this package for details. ##--------------------------------------------------------------------------- @@ -38,7 +38,7 @@ lint-yes: lint-local-srv FORCE clean-local-srv: clean-srv: clean-local-srv FORCE - $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o a.out core .libs/* + $(RM) $(PROGRAMS) $(XPROGRAMS) $(XSRCS) *.o a.out core .libs/* *.exe depend-local-srv: depend-yes: depend-local-srv FORCE diff --git a/build/top.mk b/build/top.mk index 9dc7dcdce0..98cbf1aadb 100644 --- a/build/top.mk +++ b/build/top.mk @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA +## Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA ## All rights reserved. ## ## Redistribution and use in source and binary forms are permitted only @@ -22,18 +22,18 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ ldap_subdir = @ldap_subdir@ -bindir = $(TMPROOT)@bindir@ -datadir = $(TMPROOT)@datadir@$(ldap_subdir) -includedir = $(TMPROOT)@includedir@ -infodir = $(TMPROOT)@infodir@ -libdir = $(TMPROOT)@libdir@ -libexecdir = $(TMPROOT)@libexecdir@ -localstatedir = $(TMPROOT)@localstatedir@ -mandir = $(TMPROOT)@mandir@ -moduledir = $(TMPROOT)@libexecdir@$(ldap_subdir) -sbindir = $(TMPROOT)@sbindir@ -sharedstatedir = $(TMPROOT)@sharedstatedir@ -sysconfdir = $(TMPROOT)@sysconfdir@$(ldap_subdir) +bindir = @bindir@ +datadir = @datadir@$(ldap_subdir) +includedir = @includedir@ +infodir = @infodir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +moduledir = @libexecdir@$(ldap_subdir) +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@$(ldap_subdir) EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ @@ -54,9 +54,8 @@ MKDEP_CFLAGS = @OL_MKDEP_FLAGS@ MKVERSION = $(top_srcdir)/build/mkversion -v "$(VERSION)" LIBTOOL = @LIBTOOL@ -LIBVERSION = 2:0:0 +LIBVERSION = 0:0:0 LTVERSION = -version-info $(LIBVERSION) -LTLIBLINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LTVERSION) LTLINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) @@ -114,6 +113,7 @@ LDAP_LIBDEPEND = $(LDAP_LIBLDAP_DEPEND) $(LDAP_LIBLBER_DEPEND) \ SLAPD_LIBDEPEND = $(LDAP_LIBDEPEND) $(LDAP_LIBAVL_DEPEND) \ $(LDAP_LIBLDBM_DEPEND) $(LDAP_LIBLTHREAD_DEPEND) +WRAP_LIBS = @WRAP_LIBS@ # AutoConfig generated AC_CC = @CC@ AC_CFLAGS = @CFLAGS@ @@ -121,18 +121,21 @@ AC_DEFS = @CPPFLAGS@ # @DEFS@ AC_LDFLAGS = @LDFLAGS@ AC_LIBS = @LIBS@ -KRB_LIBS = @KRB_LIBS@ +KRB4_LIBS = @KRB4_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +KRB_LIBS = @KRB4_LIBS@ @KRB5_LIBS@ SASL_LIBS = @SASL_LIBS@ TLS_LIBS = @TLS_LIBS@ -SECURITY_LIBS = @SASL_LIBS@ @KRB_LIBS@ @TLS_LIBS@ +AUTH_LIBS = @AUTH_LIBS@ +SECURITY_LIBS = $(SASL_LIBS) $(KRB_LIBS) $(TLS_LIBS) $(AUTH_LIBS) MODULES_CPPFLAGS = @SLAPD_MODULES_CPPFLAGS@ MODULES_LDFLAGS = @SLAPD_MODULES_LDFLAGS@ MODULES_LIBS = @MODULES_LIBS@ -PERL_CPPFLAGS = @SLAPD_PERL_CPPFLAGS@ -PERL_LDFLAGS = @SLAPD_PERL_LDFLAGS@ TERMCAP_LIBS = @TERMCAP_LIBS@ +LINK_BINS_DYNAMIC = @LINK_BINS_DYNAMIC@ +QUIPU_LIBS = @QUIPU_LIBS@ SLAPD_LIBS = @SLAPD_LIBS@ SLURPD_LIBS = @SLURPD_LIBS@ @@ -177,3 +180,4 @@ Makefile: Makefile.in $(top_srcdir)/build/top.mk FORCE: ##--------------------------------------------------------------------------- + diff --git a/build/version b/build/version index 6563d6fcc4..05466500f6 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -2.0-Engineeering +2.0-alpha4 diff --git a/clients/Makefile.in b/clients/Makefile.in index 29f8931285..5bc6b69eb7 100644 --- a/clients/Makefile.in +++ b/clients/Makefile.in @@ -1,7 +1,7 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, See COPYRIGHT file ## ## Clients Makefile.in for OpenLDAP -SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 +SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 maildap diff --git a/clients/fax500/Makefile.in b/clients/fax500/Makefile.in index 4520a63ef6..eefd45123c 100644 --- a/clients/fax500/Makefile.in +++ b/clients/fax500/Makefile.in @@ -1,6 +1,8 @@ # $OpenLDAP$ -PROGRAMS= rp500 fax500 xrpcomp.tmp +UNIX_PRGS = rp500 fax500 +EXEPRGS = $(@PLAT@_PRGS) +PROGRAMS = xrpcomp.tmp $(EXEPRGS) SRCS= main.c faxtotpc.c rp500.c XSRCS=fax5version.c rpversion.c @@ -32,7 +34,12 @@ xrpcomp.tmp: xrpcomp $(SED) -e 's|%LIBEXECDIR%|$(libexecdir)|' $(srcdir)/xrpcomp > xrpcomp.tmp install-local: $(PROGRAMS) FORCE - -$(MKDIR) $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 rp500 $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 fax500 $(libexecdir) - $(INSTALL) $(INSTALLFLAGS) -m 755 xrpcomp.tmp $(libexecdir)/xrpcomp + -$(MKDIR) $(DESTDIR)$(libexecdir) + @( \ + for prg in $(EXEPRGS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + $(INSTALL_SCRIPT) $(INSTALLFLAGS) xrpcomp.tmp \ + $(DESTDIR)$(libexecdir)/xrpcomp diff --git a/clients/fax500/main.c b/clients/fax500/main.c index b94a1a6215..8362a7b520 100644 --- a/clients/fax500/main.c +++ b/clients/fax500/main.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -28,9 +29,6 @@ #include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -191,7 +189,7 @@ main ( int argc, char **argv ) #ifdef LOG_MAIL openlog( myname, OPENLOG_OPTIONS, LOG_MAIL ); -#else +#elif LOG_DEBUG openlog( myname, OPENLOG_OPTIONS ); #endif @@ -832,7 +830,7 @@ add_member( timeout.tv_sec = FAX_TIMEOUT; timeout.tv_usec = 0; - if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "(objectclass=*)", + if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL, attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) { if ( rc == LDAP_NO_SUCH_OBJECT ) { add_error( err, nerr, E_BADMEMBER, dn, NULL ); @@ -1466,7 +1464,7 @@ get_attributes_mail_dn( LDAPMessage *e, char *attr1, char *attr2 ) for ( i = 0; dnlist[i] != NULL; i++ ) { if ( (rc = ldap_search_st( ld, dnlist[i], - LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, + LDAP_SCOPE_BASE, NULL, attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) { if ( rc != LDAP_NO_SUCH_OBJECT ) { unbind_and_exit( EX_TEMPFAIL ); diff --git a/clients/finger/Makefile.in b/clients/finger/Makefile.in index 613bda9e40..5a5d7fc3ea 100644 --- a/clients/finger/Makefile.in +++ b/clients/finger/Makefile.in @@ -3,7 +3,9 @@ SRCS= main.c XSRCS= version.c OBJS= main.o -PROGRAMS= in.xfingerd + +UNIX_PRGS = in.xfingerd +PROGRAMS = $(@PLAT@_PRGS) LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries @@ -19,5 +21,11 @@ version.c: ${OBJS} ${LDAP_LIBDEPEND} $(MKVERSION) in.xfingerd > $@ install-local: $(PROGRAMS) FORCE - -$(MKDIR) $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 in.xfingerd $(libexecdir) + -$(MKDIR) $(DESTDIR)$(libexecdir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + diff --git a/clients/finger/main.c b/clients/finger/main.c index 5e84fe4916..5e8111633e 100644 --- a/clients/finger/main.c +++ b/clients/finger/main.c @@ -130,14 +130,14 @@ main( int argc, char **argv ) if ( dosyslog ) { #ifdef LOG_LOCAL4 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 ); -#else +#elif LOG_DEBUG openlog( myname, OPENLOG_OPTIONS ); #endif } if ( dosyslog && !interactive ) { - hp = gethostbyaddr( (char *) &peername.sin_addr.s_addr, - sizeof(peername.sin_addr.s_addr), AF_INET ); + hp = gethostbyaddr( (char *) &peername.sin_addr, + sizeof(peername.sin_addr), AF_INET ); syslog( LOG_INFO, "connection from %s (%s)", (hp == NULL) ? "unknown" : hp->h_name, inet_ntoa( peername.sin_addr ) ); diff --git a/clients/gopher/Makefile.in b/clients/gopher/Makefile.in index a9d5e4ee94..27e2ba136a 100644 --- a/clients/gopher/Makefile.in +++ b/clients/gopher/Makefile.in @@ -2,9 +2,12 @@ ## ## Makefile for gopher clients ## -PROGRAMS= go500gw go500 + +UNIX_PRGS= go500gw go500 +PROGRAMS = $(@PLAT@_PRGS) SRCS= go500.c go500gw.c + XSRCS= gwversion.c goversion.c GOOBJS = go500.o GWOBJS = go500gw.o @@ -30,8 +33,13 @@ gwversion.c: ${GWOBJS} $(LDAP_LIBDEPEND) $(MKVERSION) go500gw > $@ install-local: $(PROGRAMS) go500gw.help FORCE - -$(MKDIR) $(libexecdir) $(datadir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 go500 $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 go500gw $(libexecdir) - -$(MV) $(datadir)/go500gw.help $(datadir)/go500gw.help- - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/go500gw.help $(datadir) + -$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + -$(MV) $(DESTDIR)$(datadir)/go500gw.help $(DESTDIR)$(datadir)/go500gw.help- + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/go500gw.help $(DESTDIR)$(datadir) + diff --git a/clients/gopher/go500.c b/clients/gopher/go500.c index e8342fc4a6..ca03ce0a98 100644 --- a/clients/gopher/go500.c +++ b/clients/gopher/go500.c @@ -26,12 +26,9 @@ #include #include +#include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -184,7 +181,7 @@ main( int argc, char **argv ) if ( dosyslog ) { #ifdef LOG_LOCAL3 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 ); -#else +#elif LOG_DEBUG openlog( myname, OPENLOG_OPTIONS ); #endif } @@ -203,8 +200,8 @@ main( int argc, char **argv ) fromlen = sizeof(from); if ( getpeername( 0, (struct sockaddr *) &from, &fromlen ) == 0 ) { - hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr), - sizeof(from.sin_addr.s_addr), AF_INET ); + hp = gethostbyaddr( (char *) &(from.sin_addr), + sizeof(from.sin_addr), AF_INET ); Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n", (hp == NULL) ? "unknown" : hp->h_name, inet_ntoa( from.sin_addr ), 0 ); @@ -247,8 +244,8 @@ main( int argc, char **argv ) exit( EXIT_FAILURE ); } - hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr), - sizeof(from.sin_addr.s_addr), AF_INET ); + hp = gethostbyaddr( (char *) &(from.sin_addr), + sizeof(from.sin_addr), AF_INET ); if ( dosyslog ) { syslog( LOG_INFO, "TCP connection from %s (%s)", diff --git a/clients/gopher/go500gw.c b/clients/gopher/go500gw.c index c1c5ab4a9e..dfda607001 100644 --- a/clients/gopher/go500gw.c +++ b/clients/gopher/go500gw.c @@ -26,12 +26,9 @@ #include #include +#include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -207,7 +204,7 @@ main (int argc, char **argv ) if ( dosyslog ) { #ifdef LOG_LOCAL3 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 ); -#else +#elif LOG_DEBUG openlog( myname, OPENLOG_OPTIONS ); #endif } @@ -226,8 +223,8 @@ main (int argc, char **argv ) fromlen = sizeof(from); if ( getpeername( 0, (struct sockaddr *) &from, &fromlen ) == 0 ) { - hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr), - sizeof(from.sin_addr.s_addr), AF_INET ); + hp = gethostbyaddr( (char *) &(from.sin_addr), + sizeof(from.sin_addr), AF_INET ); Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n", (hp == NULL) ? "unknown" : hp->h_name, inet_ntoa( from.sin_addr ), 0 ); @@ -272,8 +269,8 @@ main (int argc, char **argv ) exit( EXIT_FAILURE ); } - hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr), - sizeof(from.sin_addr.s_addr), AF_INET ); + hp = gethostbyaddr( (char *) &(from.sin_addr), + sizeof(from.sin_addr), AF_INET ); if ( dosyslog ) { syslog( LOG_INFO, "TCP connection from %s (%s)", @@ -556,7 +553,7 @@ isnonleaf( LDAP *ld, char **oclist, char *dn ) timeout.tv_usec = 0; ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL, - "(objectClass=*)", attrs, 0, &timeout, &res )) + NULL, attrs, 0, &timeout, &res )) == LDAP_SUCCESS || rc == LDAP_SIZELIMIT_EXCEEDED ) { sizelimit = LDAP_NO_LIMIT; ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); @@ -706,7 +703,7 @@ make_scope( LDAP *ld, char *dn ) timeout.tv_sec = GO500GW_TIMEOUT; timeout.tv_usec = 0; - if ( ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + if ( ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL, attrs, 0, &timeout, &res ) != LDAP_SUCCESS ) { return( -1 ); } diff --git a/clients/mail500/Makefile.in b/clients/mail500/Makefile.in index 38b61fd404..260fefcae9 100644 --- a/clients/mail500/Makefile.in +++ b/clients/mail500/Makefile.in @@ -1,6 +1,7 @@ # $OpenLDAP$ -PROGRAMS= mail500 +UNIX_PRGS = mail500 +PROGRAMS = $(@PLAT@_PRGS) SRCS= main.c XSRCS= version.c @@ -20,5 +21,11 @@ version.c: ${OBJS} $(LDAP_LIBDEPEND) $(MKVERSION) mail500 > $@ install-local: $(PROGRAMS) FORCE - -$(MKDIR) $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 mail500 $(libexecdir) + -$(MKDIR) $(DESTDIR)$(libexecdir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + diff --git a/clients/mail500/README b/clients/mail500/README index 57e7dd1cf8..edd9b2e582 100644 --- a/clients/mail500/README +++ b/clients/mail500/README @@ -38,6 +38,8 @@ R$+%$+<@umich.edu> $>10$1%$2<@> R$+!$+<@umich.edu> $>10$1!$2<@> See the sample sendmail.cf in this directory for more details. +For sendmail 8.9 (and later) users can use MAILER(mail500) if +mail500.m4 is placed within sendmail's cf/mailer directory. The mail500 mailer should be defined similar to this in the sendmail.cf file: @@ -76,11 +78,11 @@ by changing the base array in main.c. For example, the configuration we use at U-M is like this: Base base[] = - { "ou=People, o=University of Michigan, c=US", 0 + { "ou=People, dc=OpenLDAP, dc=org", 0 "uid=%s", "cn=%s", NULL, - "ou=System Groups, ou=Groups, o=University of Michigan, c=US", 1 + "ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org", 1 "(&(cn=%s)(associatedDomain=%h))", NULL, NULL, - "ou=User Groups, ou=Groups, o=University of Michigan, c=US", 1 + "ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org", 1 "(&(cn=%s)(associatedDomain=%h))", NULL, NULL, NULL }; @@ -88,16 +90,16 @@ we use at U-M is like this: which means that in delivering mail to "name" mail500 would do the the following searches, stopping if it found anything at any step: - Search (18) [2]: c=US@o=University of Michigan@ou=People + Search (18) [2]: dc=org@dc=OpenLDAP@ou=People Search subtree (uid=name) - Search (18) [3]: c=US@o=University of Michigan@ou=People + Search (18) [3]: dc=org@dc=OpenLDAP@ou=People Search subtree (cn=name) - Search (18) [4]: c=US@o=University of Michigan@ou=Groups@ou=System Groups - Search subtree & ((cn=name)(associatedDomain=umich.edu)) + Search (18) [4]: dc=org@dc=OpenLDAP@ou=Groups@ou=System Groups + Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org)) - Search (18) [5]: c=US@o=University of Michigan@ou=Groups@ou=User Groups - Search subtree & ((cn=name)(associatedDomain=umich.edu)) + Search (18) [5]: dc=org@dc=OpenLDAP@ou=Groups@ou=User Groups + Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org)) Notice that when specifying a filter %s is replaced by the name, or user portion of the address while %h is replaced by whatever is diff --git a/clients/mail500/mail500.m4 b/clients/mail500/mail500.m4 new file mode 100644 index 0000000000..c5cb36b4d6 --- /dev/null +++ b/clients/mail500/mail500.m4 @@ -0,0 +1,51 @@ +PUSHDIVERT(-1) +## Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA +## All rights reserved. +## +## Redistribution and use in source and binary forms are permitted only +## as authorized by the OpenLDAP Public License. A copy of this +## license is available at http://www.OpenLDAP.org/license.html or +## in file LICENSE in the top-level directory of the distribution. +POPDIVERT + +dnl +dnl mail500 mailer +dnl +dnl This file should be placed in the sendmail's cf/mailer directory. +dnl To include this mailer in your .cf file, use the directive: +dnl MAILER(mail500) +dnl + +ifdef(`MAIL500_HOST', + `define(`MAIL500_HOST_FLAG', `')', + `define(`MAIL500_HOST_FLAG', CONCAT(` -l ', CONCAT(MAIL500_HOST,` ')))') +ifdef(`MAIL500_MAILER_PATH',, + `ifdef(`MAIL500_PATH', + `define(`MAIL500_MAILER_PATH', MAIL500_PATH)', + `define(`MAIL500_MAILER_PATH', /usr/local/libexec/mail500)')') +ifdef(`MAIL500_MAILER_FLAGS',, + `define(`MAIL500_MAILER_FLAGS', `SmnXuh')') +ifdef(`MAIL500_MAILER_ARGS',, + `define(`MAIL500_MAILER_ARGS', + CONCAT(`mail500',CONCAT(MAIL500_HOST_FLAG,`-f $f -h $h -m $n@$w $u')))') +dnl + +MAILER_DEFINITIONS + +######################*****############## +### MAIL500 Mailer specification ### +##################*****################## + +VERSIONID(`$OpenLDAP$') + +Mmail500, P=MAIL500_MAILER_PATH, F=CONCAT(`DFM', MAIL500_MAILER_FLAGS), S=11/31, R=20/40, T=DNS/RFC822/X-Unix, + ifdef(`MAIL500_MAILER_MAX', `M=500_MAILER_MAX, ')A=MAIL500_MAILER_ARGS + +LOCAL_CONFIG +# Mail500 Domains +#CQ foo.com + +PUSHDIVERT(3) +# mail500 additions +R$* < @ $=Q > $* $#mail500 $@ $2 $: <$1> domain handled by mail500 +POPDIVERT diff --git a/clients/mail500/main.c b/clients/mail500/main.c index 064ed64c34..3d0c538a24 100644 --- a/clients/mail500/main.c +++ b/clients/mail500/main.c @@ -10,7 +10,7 @@ * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * - * Copyright 1998,1999 The OpenLDAP Foundation + * Copyright 1998-2000 The OpenLDAP Foundation * COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory * of this package for details. */ @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -32,10 +33,6 @@ #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -64,7 +61,7 @@ LDAP *ld; char *vacationhost = NULL; -char *errorsfrom = MAIL500_BOUNCEFROM; +char *errorsfrom = NULL; char *mailfrom = NULL; char *host = NULL; char *ldaphost = NULL; @@ -98,92 +95,63 @@ typedef struct groupto { char *g_dn; char *g_errorsto; char **g_members; - int g_nmembers; } Group; typedef struct baseinfo { - char *b_url; - int b_m_entries; + char *b_dn; /* dn to start searching at */ char b_rdnpref; /* give rdn's preference when searching? */ int b_search; /* ORed with the type of thing the address */ /* looks like (USER, GROUP_ERRORS, etc.) */ /* to see if this should be searched */ + char *b_filter[3]; /* filter to apply - name substituted for %s */ + /* (up to three of them) */ } Base; -/* - * We should limit the search to objectclass=mailRecipient or - * objectclass=mailGroup. - */ - -/* Base base[] = { - {"dc=StlInter, dc=Net", - 0, 0xff, - {"mail=%s", "mailAlternateAddress=%s", NULL}}, + {"ou=People, dc=OpenLDAP, dc=org", + 0, USER, + {"uid=%s", "cn=%s", NULL}}, + {"ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org", + 1, 0xff, + {"(&(cn=%s)(associatedDomain=%h))", NULL, NULL}}, + {"ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org", + 1, 0xff, + {"(&(cn=%s)(associatedDomain=%h))", NULL, NULL}}, {NULL} }; -*/ - -Base **base = NULL; char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrLDAP", "-odi", "-oi", "-f", NULL, NULL }; -typedef struct attr_semantics { - char *as_name; - int as_m_valued; /* Is multivalued? */ - int as_final; /* If true, no further expansion is tried. */ - int as_syntax; /* How to interpret values */ - int as_m_entries; /* Can resolve to several entries? */ - int as_kind; /* Recipient, sender, etc. */ - char *as_param; /* Extra info for filters and things alike */ -} AttrSemantics; - -#define AS_SYNTAX_UNKNOWN 0 /* Unqualified mailbox name */ -#define AS_SYNTAX_NATIVE_MB 1 /* Unqualified mailbox name */ -#define AS_SYNTAX_RFC822 2 /* RFC822 mail address */ -#define AS_SYNTAX_HOST 3 -#define AS_SYNTAX_DN 4 /* A directory entry */ -#define AS_SYNTAX_RFC822_EXT 5 -#define AS_SYNTAX_URL 6 /* mailto: or ldap: URL */ -#define AS_SYNTAX_BOOL_FILTER 7 /* For joinable, filter in as_param */ - -#define AS_KIND_UNKNOWN 0 -#define AS_KIND_RECIPIENT 1 -#define AS_KIND_ERRORS 2 /* For ErrorsTo and similar */ -#define AS_KIND_REQUEST 3 -#define AS_KIND_OWNER 4 -#define AS_KIND_FORWARD_TO_HOST 5 /* Expand at some other host */ -#define AS_KIND_ALLOWED_SENDER 6 /* Can send to group */ -#define AS_KIND_MODERATOR 7 - -AttrSemantics **attr_semantics = NULL; - -typedef struct subst { - char sub_char; - char *sub_value; -} Subst; - -char **groupclasses = NULL; -char **def_attr = NULL; - -static void load_config( char *filespec ); -static void split_address( char *address, char **localpart, char **domainpart); -static int entry_engine( LDAPMessage *e, char *dn, char *address, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type ); +static char *attrs[] = { "objectClass", "title", "postaladdress", + "telephoneNumber", "mail", "description", "owner", + "errorsTo", "rfc822ErrorsTo", "requestsTo", + "rfc822RequestsTo", "joinable", "cn", "member", + "moderator", "onVacation", "uid", + "suppressNoEmailError", NULL }; + static void do_address( char *name, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type ); +static int do_group( LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr ); +static void do_group_members( LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr ); static void send_message( char **to ); static void send_errors( Error *err, int nerr ); static void do_noemail( FILE *fp, Error *err, int namelen ); static void do_ambiguous( FILE *fp, Error *err, int namelen ); -static int count_values( char **list ); static void add_to( char ***list, int *nlist, char **new ); -static void add_single_to( char ***list, char *new ); static int isgroup( LDAPMessage *e ); static void add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg ); -static void unbind_and_exit( int rc ) LDAP_GCCATTR((noreturn)); +static void add_group( char *dn, Group **list, int *nlist ); +static void unbind_and_exit( int rc ); +static int group_loop( char *dn ); static void send_group( Group *group, int ngroup ); - +static int has_attributes( LDAPMessage *e, char *attr1, char *attr2 ); +static char **get_attributes_mail_dn( LDAPMessage *e, char *attr1, char *attr2 ); +static char *canonical( char *s ); static int connect_to_x500( void ); +static void do_group_errors( LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr ); +static void do_group_request( LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr ); +static void do_group_owner( LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr ); +static void add_member( char *gdn, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, char **suppress ); int main ( int argc, char **argv ) @@ -194,7 +162,6 @@ main ( int argc, char **argv ) Group *togroups; int numto, ngroups, numerr, nargs; int i, j; - char *conffile = NULL; if ( (myname = strrchr( argv[0], '/' )) == NULL ) myname = strdup( argv[0] ); @@ -207,20 +174,16 @@ main ( int argc, char **argv ) #ifdef LOG_MAIL openlog( myname, OPENLOG_OPTIONS, LOG_MAIL ); -#else +#elif LOG_DEBUG openlog( myname, OPENLOG_OPTIONS ); #endif - while ( (i = getopt( argc, argv, "d:C:f:h:l:m:v:" )) != EOF ) { + while ( (i = getopt( argc, argv, "d:f:h:l:m:v:" )) != EOF ) { switch( i ) { case 'd': /* turn on debugging */ debug = atoi( optarg ); break; - case 'C': /* path to configuration file */ - conffile = strdup( optarg ); - break; - case 'f': /* who it's from & where errors should go */ mailfrom = strdup( optarg ); for ( j = 0; sendmailargs[j] != NULL; j++ ) { @@ -263,17 +226,11 @@ main ( int argc, char **argv ) syslog( LOG_ALERT, "required argument -m not present" ); exit( EX_TEMPFAIL ); } -/* if ( host == NULL ) { */ -/* syslog( LOG_ALERT, "required argument -h not present" ); */ -/* exit( EX_TEMPFAIL ); */ -/* } */ - if ( conffile == NULL ) { - syslog( LOG_ALERT, "required argument -C not present" ); + if ( host == NULL ) { + syslog( LOG_ALERT, "required argument -h not present" ); exit( EX_TEMPFAIL ); } - load_config( conffile ); - if ( connect_to_x500() != 0 ) exit( EX_TEMPFAIL ); @@ -303,18 +260,14 @@ main ( int argc, char **argv ) for ( i = optind; i < argc; i++ ) { char *s; int type; - char *localpart, *domainpart; - char address[1024]; -/* TBC: Make this processing optional */ -/* for ( j = 0; argv[i][j] != '\0'; j++ ) { */ -/* if ( argv[i][j] == '.' || argv[i][j] == '_' ) */ -/* argv[i][j] = ' '; */ -/* } */ + for ( j = 0; argv[i][j] != '\0'; j++ ) { + if ( argv[i][j] == '.' || argv[i][j] == '_' ) + argv[i][j] = ' '; + } type = USER; - split_address( argv[i], &localpart, &domainpart ); - if ( (s = strrchr( localpart, '-' )) != NULL ) { + if ( (s = strrchr( argv[i], '-' )) != NULL ) { s++; if ((strcasecmp(s, ERROR) == 0) || @@ -335,15 +288,7 @@ main ( int argc, char **argv ) } } - if ( domainpart ) { - sprintf( address, "%s@%s", localpart, domainpart ); - free( localpart ); - free( domainpart ); - } else { - sprintf( address, "%s@%s", localpart, domainpart ); - free( localpart ); - } - do_address( address, &tolist, &numto, &togroups, &ngroups, + do_address( argv[i], &tolist, &numto, &togroups, &ngroups, &errlist, &numerr, type ); } @@ -411,263 +356,6 @@ main ( int argc, char **argv ) return( EX_OK ); } -static char * -get_config_line( FILE *cf, int *lineno) -{ - static char buf[2048]; - int len; - int pos; - int room; - - pos = 0; - room = sizeof( buf ); - while ( fgets( &buf[pos], room, cf ) ) { - (*lineno)++; - if ( pos > 0 ) { - /* Delete whitespace at the beginning of new data */ - if ( isspace( buf[pos] ) ) { - char *s, *d; - for ( s = buf+pos; isspace(*s); s++ ) - ; - for ( d = buf+pos; *s; s++, d++ ) { - *d = *s; - } - *d = *s; - } - } - len = strlen( buf ); - if ( buf[len-1] != '\n' ) { - syslog( LOG_ALERT, "Definition too long at line %d", - *lineno ); - exit( EX_TEMPFAIL ); - } - if ( buf[0] == '#' ) - continue; - if ( strspn( buf, " \t\n" ) == len ) - continue; - if ( buf[len-2] == '\\' ) { - pos = len - 2; - room = sizeof(buf) - pos; - continue; - } - /* We have a real line, we will exit the loop */ - buf[len-1] = '\0'; - return( buf ); - } - return( NULL ); -} - -static void -add_url ( char *url, int rdnpref, int typemask ) -{ - Base **list_temp; - int size; - Base *b; - - b = calloc(1, sizeof(Base)); - if ( !b ) { - syslog( LOG_ALERT, "Out of memory" ); - exit( EX_TEMPFAIL ); - } - b->b_url = strdup( url ); - b->b_rdnpref = rdnpref; - b->b_search = typemask; - - if ( base == NULL ) { - base = calloc(2, sizeof(LDAPURLDesc *)); - if ( !base ) { - syslog( LOG_ALERT, "Out of memory" ); - exit( EX_TEMPFAIL ); - } - base[0] = b; - } else { - for ( size = 0; base[size]; size++ ) - ; - size += 2; - list_temp = realloc( base, size*sizeof(LDAPURLDesc *) ); - if ( !list_temp ) { - syslog( LOG_ALERT, "Out of memory" ); - exit( EX_TEMPFAIL ); - } - base = list_temp; - base[size-2] = b; - base[size-1] = NULL; - } -} - -static void -add_def_attr( char *s ) -{ - char *p, *q; - - p = s; - while ( *p ) { - p += strspn( p, "\t," ); - q = strpbrk( p, " \t," ); - if ( q ) { - *q = '\0'; - add_single_to( &def_attr, p ); - } else { - add_single_to( &def_attr, p ); - break; - } - p = q + 1; - } -} - -static void -add_attr_semantics( char *s ) -{ - char *p, *q; - AttrSemantics *as; - - as = calloc( 1, sizeof( AttrSemantics ) ); - p = s; - while ( isspace ( *p ) ) - p++; - q = p; - while ( !isspace ( *q ) && *q != '\0' ) - q++; - *q = '\0'; - as->as_name = strdup( p ); - p = q + 1; - - while ( *p ) { - while ( isspace ( *p ) ) - p++; - q = p; - while ( !isspace ( *q ) && *q != '\0' ) - q++; - *q = '\0'; - if ( !strcasecmp( p, "multivalued" ) ) { - as->as_m_valued = 1; - } else if ( !strcasecmp( p, "multiple-entries" ) ) { - as->as_m_entries = 1; - } else if ( !strcasecmp( p, "final" ) ) { - as->as_final = 1; - } else if ( !strcasecmp( p, "local-native-mailbox" ) ) { - as->as_syntax = AS_SYNTAX_NATIVE_MB; - } else if ( !strcasecmp( p, "rfc822" ) ) { - as->as_syntax = AS_SYNTAX_RFC822; - } else if ( !strcasecmp( p, "rfc822-extended" ) ) { - as->as_syntax = AS_SYNTAX_RFC822_EXT; - } else if ( !strcasecmp( p, "dn" ) ) { - as->as_syntax = AS_SYNTAX_DN; - } else if ( !strcasecmp( p, "url" ) ) { - as->as_syntax = AS_SYNTAX_URL; - } else if ( !strncasecmp( p, "search-with-filter=", 19 ) ) { - as->as_syntax = AS_SYNTAX_BOOL_FILTER; - q = strchr( p, '=' ); - if ( q ) { - p = q + 1; - while ( *q && !isspace( *q ) ) { - q++; - } - if ( *q ) { - *q = '\0'; - as->as_param = strdup( p ); - p = q + 1; - } else { - as->as_param = strdup( p ); - p = q; - } - } else { - syslog( LOG_ALERT, - "Missing filter in %s", s ); - exit( EX_TEMPFAIL ); - } - } else if ( !strcasecmp( p, "host" ) ) { - as->as_kind = AS_SYNTAX_HOST; - } else if ( !strcasecmp( p, "forward-to-host" ) ) { - as->as_kind = AS_KIND_FORWARD_TO_HOST; - } else if ( !strcasecmp( p, "recipient" ) ) { - as->as_kind = AS_KIND_RECIPIENT; - } else if ( !strcasecmp( p, "errors" ) ) { - as->as_kind = AS_KIND_ERRORS; - } else if ( !strcasecmp( p, "request" ) ) { - as->as_kind = AS_KIND_REQUEST; - } else if ( !strcasecmp( p, "owner" ) ) { - as->as_kind = AS_KIND_OWNER; - } else { - syslog( LOG_ALERT, - "Unknown semantics word %s", p ); - exit( EX_TEMPFAIL ); - } - p = q + 1; - } - if ( attr_semantics == NULL ) { - attr_semantics = calloc(2, sizeof(AttrSemantics *)); - if ( !attr_semantics ) { - syslog( LOG_ALERT, "Out of memory" ); - exit( EX_TEMPFAIL ); - } - attr_semantics[0] = as; - } else { - int size; - AttrSemantics **list_temp; - for ( size = 0; attr_semantics[size]; size++ ) - ; - size += 2; - list_temp = realloc( attr_semantics, - size*sizeof(AttrSemantics *) ); - if ( !list_temp ) { - syslog( LOG_ALERT, "Out of memory" ); - exit( EX_TEMPFAIL ); - } - attr_semantics = list_temp; - attr_semantics[size-2] = as; - attr_semantics[size-1] = NULL; - } -} - -static void -load_config( char *filespec ) -{ - FILE *cf; - char *line; - int lineno = 0; - char *p; - int rdnpref; - int typemask; - - cf = fopen( filespec, "r" ); - if ( !cf ) { - perror( "Opening config file" ); - exit( EX_TEMPFAIL ); - } - - while ( ( line = get_config_line( cf,&lineno ) ) ) { - p = strpbrk( line, " \t" ); - if ( !p ) { - syslog( LOG_ALERT, - "Missing space at line %d", lineno ); - exit( EX_TEMPFAIL ); - } - if ( !strncmp( line, "search", p-line ) ) { - p += strspn( p, " \t" ); - /* TBC, get these */ - rdnpref = 0; - typemask = 0xFF; - add_url( p, rdnpref, typemask ); - } else if ( !strncmp(line, "attribute", p-line) ) { - p += strspn(p, " \t"); - add_attr_semantics( p ); - } else if ( !strncmp(line, "default-attributes", p-line) ) { - p += strspn(p, " \t"); - add_def_attr( p ); - } else if ( !strncmp(line, "group-classes", p-line) ) { - p += strspn(p, " \t"); - add_single_to( &groupclasses, p ); - } else { - syslog( LOG_ALERT, - "Unparseable config definition at line %d", - lineno ); - exit( EX_TEMPFAIL ); - } - } - fclose( cf ); -} - static int connect_to_x500( void ) { @@ -678,10 +366,8 @@ connect_to_x500( void ) return( -1 ); } - /* TBC: Set this only when it makes sense opt = MAIL500_MAXAMBIGUOUS; ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &opt); - */ opt = LDAP_DEREF_ALWAYS; ldap_set_option(ld, LDAP_OPT_DEREF, &opt); @@ -693,114 +379,33 @@ connect_to_x500( void ) return( 0 ); } -static Group * -new_group( char *dn, Group **list, int *nlist ) -{ - int i; - Group *this_group; - - for ( i = 0; i < *nlist; i++ ) { - if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) { - syslog( LOG_ALERT, "group loop 2 detected (%s)", dn ); - return NULL; - } - } - - if ( *nlist == 0 ) { - *list = (Group *) malloc( sizeof(Group) ); - } else { - *list = (Group *) realloc( *list, (*nlist + 1) * - sizeof(Group) ); - } - - this_group = *list; - - (*list)[*nlist].g_errorsto = NULL; - (*list)[*nlist].g_members = NULL; - (*list)[*nlist].g_nmembers = 0; - /* save the group's dn so we can check for loops above */ - (*list)[*nlist].g_dn = strdup( dn ); - - (*nlist)++; - - return( this_group ); -} - -static void -split_address( - char *address, - char **localpart, - char **domainpart -) -{ - char *p; - - if ( ( p = strrchr( address, '@' ) ) == NULL ) { - *localpart = strdup( address ); - *domainpart = NULL; - } else { - *localpart = malloc( p - address + 1 ); - strncpy( *localpart, address, p - address ); - (*localpart)[p - address] = '\0'; - p++; - *domainpart = strdup( p ); - } -} - static int -dn_search( - char **dnlist, - char *address, - char ***to, - int *nto, - Group **togroups, - int *ngroups, - Error **err, - int *nerr -) +mailcmp( char *a, char *b ) { - int rc; - int i; - int resolved = 0; - LDAPMessage *res, *e; - struct timeval timeout; + int i; - timeout.tv_sec = MAIL500_TIMEOUT; - timeout.tv_usec = 0; - for ( i = 0; dnlist[i]; i++ ) { - if ( (rc = ldap_search_st( ld, dnlist[i], LDAP_SCOPE_BASE, - "(objectclass=*)", def_attr, 0, - &timeout, &res )) != LDAP_SUCCESS ) { - if ( rc == LDAP_NO_SUCH_OBJECT ) { - add_error( err, nerr, E_BADMEMBER, dnlist[i], NULL ); - continue; - } else { - syslog( LOG_ALERT, "member search return 0x%x", rc ); + for ( i = 0; a[i] != '\0'; i++ ) { + if ( a[i] != b[i] ) { + switch ( a[i] ) { + case ' ': + case '.': + case '_': + if ( b[i] == ' ' || b[i] == '.' || b[i] == '_' ) + break; + return( 1 ); - unbind_and_exit( EX_TEMPFAIL ); - } - } else { - if ( (e = ldap_first_entry( ld, res )) == NULL ) { - syslog( LOG_ALERT, "member search error parsing entry" ); - unbind_and_exit( EX_TEMPFAIL ); - } - if ( entry_engine( e, dnlist[i], address, to, nto, - togroups, ngroups, err, nerr, - USER | GROUP_MEMBERS ) ) { - resolved = 1; + default: + return( 1 ); } } } - return( resolved ); + + return( 0 ); } -static int -search_ldap_url( - char *url, - Subst *substs, - char *address, - int rdnpref, - int multi_entry, +static void +do_address( + char *name, char ***to, int *nto, Group **togroups, @@ -810,156 +415,112 @@ search_ldap_url( int type ) { - LDAPURLDesc *ludp; - char *p, *s, *d; - int i; - char filter[1024]; - char realfilter[1024]; + int rc, b, f, match; LDAPMessage *e, *res; - int rc; - char **attrlist; struct timeval timeout; - int match; - int resolved = 0; char *dn; + char filter[1024]; + char realfilter[1024]; + char **mail, **onvacation = NULL, **uid = NULL; + + /* + * Look up the name in X.500, add the appropriate addresses found + * to the to list, or to the err list in case of error. Groups are + * handled by the do_group routine, individuals are handled here. + * When looking up name, we follow the bases hierarchy, looking + * in base[0] first, then base[1], etc. For each base, there is + * a set of search filters to try, in order. If something goes + * wrong here trying to contact X.500, we exit with EX_TEMPFAIL. + * If the b_rdnpref flag is set, then we give preference to entries + * that matched name because it's their rdn, otherwise not. + */ timeout.tv_sec = MAIL500_TIMEOUT; timeout.tv_usec = 0; - - rc = ldap_url_parse( url, &ludp ); - if ( rc ) { - switch ( rc ) { - case LDAP_URL_ERR_NOTLDAP: - syslog( LOG_ALERT, - "Not an LDAP URL: %s", url ); - break; - case LDAP_URL_ERR_BADENCLOSURE: - syslog( LOG_ALERT, - "Bad Enclosure in URL: %s", url ); - break; - case LDAP_URL_ERR_BADURL: - syslog( LOG_ALERT, - "Bad URL: %s", url ); - break; - case LDAP_URL_ERR_BADHOST: - syslog( LOG_ALERT, - "Host is invalid in URL: %s", url ); - break; - case LDAP_URL_ERR_BADATTRS: - syslog( LOG_ALERT, - "Attributes are invalid in URL: %s", url ); - break; - case LDAP_URL_ERR_BADSCOPE: - syslog( LOG_ALERT, - "Scope is invalid in URL: %s", url ); - break; - case LDAP_URL_ERR_BADFILTER: - syslog( LOG_ALERT, - "Filter is invalid in URL: %s", url ); - break; - case LDAP_URL_ERR_BADEXTS: - syslog( LOG_ALERT, - "Extensions are invalid in URL: %s", url ); - break; - case LDAP_URL_ERR_MEM: - syslog( LOG_ALERT, - "Out of memory parsing URL: %s", url ); - break; - case LDAP_URL_ERR_PARAM: - syslog( LOG_ALERT, - "bad parameter parsing URL: %s", url ); - break; - default: - syslog( LOG_ALERT, - "Unknown error %d parsing URL: %s", - rc, url ); - break; + for ( b = 0, match = 0; !match && base[b].b_dn != NULL; b++ ) { + if ( ! (base[b].b_search & type) ) { + continue; } - add_error( err, nerr, E_BADMEMBER, - url, NULL ); - return 0; - } + for ( f = 0; base[b].b_filter[f] != NULL; f++ ) { + char *format, *p, *s, *d; + char *argv[3]; + int argc; - if ( substs ) { - for ( s = ludp->lud_filter, d = filter; *s; s++,d++ ) { - if ( *s == '%' ) { - s++; - if ( *s == '%' ) { - *d = '%'; - continue; - } - for ( i = 0; substs[i].sub_char != '\0'; - i++ ) { - if ( *s == substs[i].sub_char ) { - for ( p = substs[i].sub_value; - *p; p++,d++ ) { - *d = *p; - } - d--; + for ( argc = 0; argc < 3; argc++ ) { + argv[argc] = NULL; + } + + format = strdup( base[b].b_filter[f] ); + for ( argc = 0, p = format; *p; p++ ) { + if ( *p == '%' ) { + switch ( *++p ) { + case 's': /* %s is the name */ + argv[argc] = name; + break; + + case 'h': /* %h is the host */ + *p = 's'; + argv[argc] = host; + break; + + default: + syslog( LOG_ALERT, + "unknown format %c", *p ); break; } + + argc++; } - if ( substs[i].sub_char == '\0' ) { - syslog( LOG_ALERT, - "unknown format %c", *s ); + } + + /* three names ought to do... */ + sprintf( filter, format, argv[0], argv[1], argv[2] ); + free( format ); + for ( s = filter, d = realfilter; *s; s++, d++ ) { + if ( *s == '*' ) { + *d++ = '\\'; } - } else { *d = *s; } - } - *d = *s; - } else { - strncpy( filter, ludp->lud_filter, sizeof( filter ) - 1 ); - filter[ sizeof( filter ) - 1 ] = '\0'; - } + *d = '\0'; + + res = NULL; + rc = ldap_search_st( ld, base[b].b_dn, + LDAP_SCOPE_SUBTREE, realfilter, attrs, 0, &timeout, + &res ); + + /* some other trouble - try again later */ + if ( rc != LDAP_SUCCESS && + rc != LDAP_SIZELIMIT_EXCEEDED ) { + syslog( LOG_ALERT, "return 0x%x from X.500", + rc ); + unbind_and_exit( EX_TEMPFAIL ); + } + + if ( (match = ldap_count_entries( ld, res )) != 0 ) + break; - for ( s = filter, d = realfilter; *s; s++, d++ ) { - if ( *s == '*' ) { - *d++ = '\\'; + ldap_msgfree( res ); } - *d = *s; - } - *d = '\0'; - if ( ludp->lud_attrs ) { - attrlist = ludp->lud_attrs; - } else { - attrlist = def_attr; - } - res = NULL; - /* TBC: we don't read the host, dammit */ - rc = ldap_search_st( ld, ludp->lud_dn, ludp->lud_scope, - realfilter, attrlist, 0, - &timeout, &res ); - - /* some other trouble - try again later */ - if ( rc != LDAP_SUCCESS && - rc != LDAP_SIZELIMIT_EXCEEDED ) { - syslog( LOG_ALERT, "return 0x%x from X.500", - rc ); - unbind_and_exit( EX_TEMPFAIL ); + if ( match ) + break; } - match = ldap_count_entries( ld, res ); - /* trouble - try again later */ if ( match == -1 ) { syslog( LOG_ALERT, "error parsing result from X.500" ); unbind_and_exit( EX_TEMPFAIL ); } - if ( match == 1 || multi_entry ) { - for ( e = ldap_first_entry( ld, res ); e != NULL; - e = ldap_next_entry( ld, e ) ) { - dn = ldap_get_dn( ld, e ); - resolved = entry_engine( e, dn, address, to, nto, - togroups, ngroups, - err, nerr, type ); - if ( !resolved ) { - add_error( err, nerr, E_NOEMAIL, address, res ); - } + /* no matches - bounce with user unknown */ + if ( match == 0 ) { + if ( type == USER ) { + add_error( err, nerr, E_USERUNKNOWN, name, NULL ); + } else { + add_error( err, nerr, E_GROUPUNKNOWN, name, NULL ); } - return ( resolved ); + return; } /* more than one match - bounce with ambiguous user? */ @@ -969,9 +530,9 @@ search_ldap_url( char **xdn; /* not giving rdn preference - bounce with ambiguous user */ - if ( rdnpref == 0 ) { - add_error( err, nerr, E_AMBIGUOUS, address, res ); - return 0; + if ( base[b].b_rdnpref == 0 ) { + add_error( err, nerr, E_AMBIGUOUS, name, res ); + return; } /* @@ -986,7 +547,7 @@ search_ldap_url( xdn = ldap_explode_dn( dn, 1 ); /* XXX bad, but how else can we do it? XXX */ - if ( strcasecmp( xdn[0], address ) == 0 ) { + if ( strcasecmp( xdn[0], name ) == 0 ) { ldap_delete_result_entry( &res, e ); ldap_add_result_entry( &tmpres, e ); } @@ -995,353 +556,503 @@ search_ldap_url( free( dn ); } - /* nothing matched by rdn - go ahead and bounce */ - if ( tmpres == NULL ) { - add_error( err, nerr, E_AMBIGUOUS, address, res ); - return 0; + /* nothing matched by rdn - go ahead and bounce */ + if ( tmpres == NULL ) { + add_error( err, nerr, E_AMBIGUOUS, name, res ); + return; + + /* more than one matched by rdn - bounce with rdn matches */ + } else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) { + add_error( err, nerr, E_AMBIGUOUS, name, tmpres ); + return; + + /* trouble... */ + } else if ( match < 0 ) { + syslog( LOG_ALERT, "error parsing result from X.500" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + /* otherwise one matched by rdn - send to it */ + ldap_msgfree( res ); + res = tmpres; + } + + /* + * if we get this far, it means that we found a single match for + * name. for a user, we deliver to the mail attribute or bounce + * with address and phone if no mail attr. for a group, we + * deliver to all members or bounce to rfc822ErrorsTo if no members. + */ + + /* trouble */ + if ( (e = ldap_first_entry( ld, res )) == NULL ) { + syslog( LOG_ALERT, "error parsing entry from X.500" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + dn = ldap_get_dn( ld, e ); + + if ( type == GROUP_ERRORS ) { + /* sent to group-errors - resend to [rfc822]ErrorsTo attr */ + do_group_errors( e, dn, to, nto, err, nerr ); + + } else if ( type == GROUP_REQUEST ) { + /* sent to group-request - resend to [rfc822]RequestsTo attr */ + do_group_request( e, dn, to, nto, err, nerr ); + + } else if ( type == GROUP_MEMBERS ) { + /* sent to group-members - expand */ + do_group_members( e, dn, to, nto, togroups, ngroups, err, + nerr ); + + } else if ( type == GROUP_OWNER ) { + /* sent to group-owner - resend to owner attr */ + do_group_owner( e, dn, to, nto, err, nerr ); + + } else if ( isgroup( e ) ) { + /* + * sent to group - resend from [rfc822]ErrorsTo if it's there, + * otherwise, expand the group + */ + + do_group( e, dn, to, nto, togroups, ngroups, err, nerr ); + + ldap_msgfree( res ); + + } else { + /* + * sent to user - mail attribute => add it to the to list, + * otherwise bounce + */ + if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) { + char buf[1024]; + char *h; + int i, j; + + /* try to detect simple mail loops */ + sprintf( buf, "%s@%s", name, host ); + for ( i = 0; mail[i] != NULL; i++ ) { + /* + * address is the same as the one we're + * sending to - mail loop. syslog the + * problem, bounce a message back to the + * sender (who else?), and delete the bogus + * addr from the list. + */ + + if ( (h = strchr( mail[i], '@' )) != NULL ) { + h++; + if ( strcasecmp( h, host ) == 0 ) { + syslog( LOG_ALERT, + "potential loop detected (%s)", + mail[i] ); + } + } + + if ( mailcmp( buf, mail[i] ) == 0 ) { + syslog( LOG_ALERT, + "loop detected (%s)", mail[i] ); + + /* remove the bogus address */ + for ( j = i; mail[j] != NULL; j++ ) { + mail[j] = mail[j+1]; + } + } + } + if ( mail[0] != NULL ) { + add_to( to, nto, mail ); + } else { + add_error( err, nerr, E_NOEMAIL, name, res ); + } + + ldap_value_free( mail ); + } else { + add_error( err, nerr, E_NOEMAIL, name, res ); + } + + /* + * If the user is on vacation, send a copy of the mail to + * the vacation server. The address is constructed from + * the vacationhost (set in a command line argument) and + * the uid (XXX this should be more general XXX). + */ + + if ( vacationhost != NULL && (onvacation = ldap_get_values( ld, + e, "onVacation" )) != NULL && strcasecmp( onvacation[0], + "TRUE" ) == 0 ) { + char buf[1024]; + char *vaddr[2]; + + if ( (uid = ldap_get_values( ld, e, "uid" )) != NULL ) { + sprintf( buf, "%s@%s", uid[0], vacationhost ); + + vaddr[0] = buf; + vaddr[1] = NULL; + + add_to( to, nto, vaddr ); + } else { + syslog( LOG_ALERT, + "user without a uid on vacation (%s)", + name ); + } + } + } + + if ( onvacation != NULL ) { + ldap_value_free( onvacation ); + } + if ( uid != NULL ) { + ldap_value_free( uid ); + } + free( dn ); +} + +static int +do_group( + LDAPMessage *e, + char *dn, + char ***to, + int *nto, + Group **togroups, + int *ngroups, + Error **err, + int *nerr +) +{ + int i; + char **moderator; + + /* + * If this group has an rfc822ErrorsTo attribute, we need to + * arrange for errors involving this group to go there, not + * to the sender. Since sendmail only has the concept of a + * single sender, we arrange for errors to go to groupname-errors, + * which we then handle specially when (if) it comes back to us + * by expanding to all the rfc822ErrorsTo addresses. If it has no + * rfc822ErrorsTo attribute, we call do_group_members() to expand + * the group. + */ + + if ( group_loop( dn ) ) { + return( -1 ); + } + + /* + * check for moderated groups - if the group has a moderator + * attribute, we check to see if the from address is one of + * the moderator values. if so, continue on. if not, arrange + * to send the mail to the moderator(s). need to do this before + * we change the from below. + */ + + if ( (moderator = ldap_get_values( ld, e, "moderator" )) != NULL ) { + /* check if it came from any of the group's moderators */ + for ( i = 0; moderator[i] != NULL; i++ ) { + if ( strcasecmp( moderator[i], mailfrom ) == 0 ) + break; + } + + /* not from the moderator? */ + if ( moderator[i] == NULL ) { + add_to( to, nto, moderator ); + ldap_value_free( moderator ); + + return( 0 ); + } + /* else from the moderator - fall through and deliver it */ + } + + if (strcmp(MAIL500_BOUNCEFROM, mailfrom) != 0 && + has_attributes( e, "rfc822ErrorsTo", "errorsTo" ) ) { + add_group( dn, togroups, ngroups ); + + return( 0 ); + } + + do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr ); + + return( 0 ); +} + +/* ARGSUSED */ +static void +do_group_members( + LDAPMessage *e, + char *dn, + char ***to, + int *nto, + Group **togroups, + int *ngroups, + Error **err, + int *nerr +) +{ + int i, rc, anymembers; + char *ndn; + char **mail, **member, **joinable, **suppress; + char filter[1024]; + LDAPMessage *ee, *res; + struct timeval timeout; + int opt; + + /* + * if all has gone according to plan, we've already arranged for + * errors to go to the [rfc822]ErrorsTo attributes (if they exist), + * so all we have to do here is arrange to send to the + * rfc822Mailbox attribute, the member attribute, and anyone who + * has joined the group by setting memberOfGroup equal to the + * group dn. + */ + + /* add members in the group itself - mail attribute */ + anymembers = 0; + if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) { + anymembers = 1; + add_to( to, nto, mail ); + + ldap_value_free( mail ); + } + + /* add members in the group itself - member attribute */ + if ( (member = ldap_get_values( ld, e, "member" )) != NULL ) { + suppress = ldap_get_values( ld, e, "suppressNoEmailError" ); + anymembers = 1; + for ( i = 0; member[i] != NULL; i++ ) { + if ( strcasecmp( dn, member[i] ) == 0 ) { + syslog( LOG_ALERT, "group (%s) contains itself", + dn ); + continue; + } + add_member( dn, member[i], to, nto, togroups, + ngroups, err, nerr, suppress ); + } + + if ( suppress ) { + ldap_value_free( suppress ); + } + ldap_value_free( member ); + } + + /* add members who have joined by setting memberOfGroup */ + if ( (joinable = ldap_get_values( ld, e, "joinable" )) != NULL ) { + if ( strcasecmp( joinable[0], "FALSE" ) == 0 ) { + if ( ! anymembers ) { + add_error( err, nerr, E_NOMEMBERS, dn, + NULL ); + } + + ldap_value_free( joinable ); + return; + } + ldap_value_free( joinable ); + + sprintf( filter, "(memberOfGroup=%s)", dn ); + + timeout.tv_sec = MAIL500_TIMEOUT; + timeout.tv_usec = 0; + + /* for each subtree to look in... */ + opt = MAIL500_MAXAMBIGUOUS; + ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &opt); + for ( i = 0; base[i].b_dn != NULL; i++ ) { + /* find entries that have joined this group... */ + rc = ldap_search_st( ld, base[i].b_dn, + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout, + &res ); + + if ( rc == LDAP_SIZELIMIT_EXCEEDED || + rc == LDAP_TIMELIMIT_EXCEEDED ) { + syslog( LOG_ALERT, + "group search limit exceeded %d", rc ); + unbind_and_exit( EX_TEMPFAIL ); + } + + if ( rc != LDAP_SUCCESS ) { + syslog( LOG_ALERT, "group search return 0x%x", + rc ); + unbind_and_exit( EX_TEMPFAIL ); + } + + /* for each entry that has joined... */ + for ( ee = ldap_first_entry( ld, res ); ee != NULL; + ee = ldap_next_entry( ld, ee ) ) { + anymembers = 1; + if ( isgroup( ee ) ) { + ndn = ldap_get_dn( ld, ee ); + + if ( do_group( e, ndn, to, nto, + togroups, ngroups, err, nerr ) + == -1 ) { + syslog( LOG_ALERT, + "group loop (%s) (%s)", + dn, ndn ); + } + + free( ndn ); + + continue; + } - /* more than one matched by rdn - bounce with rdn matches */ - } else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) { - add_error( err, nerr, E_AMBIGUOUS, address, tmpres ); - return 0; + /* add them to the to list */ + if ( (mail = ldap_get_values( ld, ee, "mail" )) + != NULL ) { + add_to( to, nto, mail ); - /* trouble... */ - } else if ( match < 0 ) { - syslog( LOG_ALERT, "error parsing result from X.500" ); - unbind_and_exit( EX_TEMPFAIL ); - } + ldap_value_free( mail ); - /* otherwise one matched by rdn - send to it */ - ldap_msgfree( res ); - res = tmpres; + /* else generate a bounce */ + } else { + ndn = ldap_get_dn( ld, ee ); - /* trouble */ - if ( (e = ldap_first_entry( ld, res )) == NULL ) { - syslog( LOG_ALERT, "error parsing entry from X.500" ); - unbind_and_exit( EX_TEMPFAIL ); - } + add_error( err, nerr, + E_JOINMEMBERNOEMAIL, ndn, NULL ); - dn = ldap_get_dn( ld, e ); + free( ndn ); + } + } - resolved = entry_engine( e, dn, address, to, nto, - togroups, ngroups, - err, nerr, type ); - if ( !resolved ) { - add_error( err, nerr, E_NOEMAIL, address, res ); - /* Don't free res if we passed it to add_error */ - } else { ldap_msgfree( res ); } + opt = MAIL500_MAXAMBIGUOUS; + ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &opt); + } + + if ( ! anymembers ) { + add_error( err, nerr, E_NOMEMBERS, dn, NULL ); } - return( resolved ); } -static int -url_list_search( - char **urllist, - char *address, - int multi_entry, +static void +add_member( + char *gdn, + char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, - int type + char **suppress ) { - int i; - int resolved = 0; + char *ndn; + char **mail; + int rc; + LDAPMessage *res, *e; + struct timeval timeout; + + timeout.tv_sec = MAIL500_TIMEOUT; + timeout.tv_usec = 0; + if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "(objectclass=*)", + attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) { + if ( rc == LDAP_NO_SUCH_OBJECT ) { + add_error( err, nerr, E_BADMEMBER, dn, NULL ); - for ( i = 0; urllist[i]; i++ ) { + return; + } else { + syslog( LOG_ALERT, "member search return 0x%x", rc ); - if ( !strncasecmp( urllist[i], "mail:", 5 ) ) { - char *vals[2]; + unbind_and_exit( EX_TEMPFAIL ); + } + } - vals[0] = urllist[i] + 5; - vals[1] = NULL; - add_to( to, nto, vals ); - resolved = 1; + if ( (e = ldap_first_entry( ld, res )) == NULL ) { + syslog( LOG_ALERT, "member search error parsing entry" ); - } else if ( ldap_is_ldap_url( urllist[i] ) ) { + unbind_and_exit( EX_TEMPFAIL ); + } + ndn = ldap_get_dn( ld, e ); - resolved = search_ldap_url( urllist[i], NULL, - address, 0, multi_entry, - to, nto, togroups, ngroups, - err, nerr, type ); - } else { - /* Produce some sensible error here */ - resolved = 0; + /* allow groups within groups */ + if ( isgroup( e ) ) { + if ( do_group( e, ndn, to, nto, togroups, ngroups, err, nerr ) + == -1 ) { + syslog( LOG_ALERT, "group loop (%s) (%s)", gdn, ndn ); } + + free( ndn ); + + return; } - return( resolved ); -} -/* - * The entry engine processes an entry. Normally, each entry will resolve - * to one or more values that will be added to the 'to' argument. This - * argument needs not be the global 'to' list, it may be the g_to field - * in a group. Groups have no special treatment, unless they require - * a special sender. - */ + /* send to the member's mail attribute */ + if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) { + add_to( to, nto, mail ); -static int -entry_engine( + ldap_value_free( mail ); + + /* else generate a bounce */ + } else { + if ( suppress == NULL || strcasecmp( suppress[0], "FALSE" ) + == 0 ) { + add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULL ); + } + } + + free( ndn ); +} + +static void +do_group_request( LDAPMessage *e, char *dn, - char *address, char ***to, int *nto, - Group **togroups, - int *ngroups, Error **err, - int *nerr, - int type + int *nerr ) { - char **vals; - int i; - int resolved = 0; - char ***current_to = to; - int *current_nto = nto; - Group *current_group = NULL; - char buf[1024]; - char *localpart, *domainpart; - Subst substs[2]; - - for ( i=0; attr_semantics[i] != NULL; i++ ) { - AttrSemantics *as = attr_semantics[i]; - int nent; - - vals = ldap_get_values( ld, e, as->as_name ); - if ( !vals || vals[0] == NULL ) { - continue; - } - nent = count_values( vals ); - if ( nent > 1 && !as->as_m_valued ) { - add_error( err, nerr, E_AMBIGUOUS, address, e ); - return( 0 ); - } - switch ( as->as_kind ) { - case AS_KIND_RECIPIENT: - if ( ! ( type & ( USER | GROUP_MEMBERS ) ) ) - break; - switch ( as->as_syntax ) { - case AS_SYNTAX_RFC822: - add_to( current_to, current_nto, vals ); - resolved = 1; - break; - case AS_SYNTAX_RFC822_EXT: - add_to( current_to, current_nto, vals ); - resolved = 1; - break; - case AS_SYNTAX_NATIVE_MB: - /* We used to concatenate mailHost if set here */ - /* - * We used to send a copy to the vacation host - * if onVacation to uid@vacationhost - */ - add_to( current_to, current_nto, vals ); - resolved = 1; - break; - - case AS_SYNTAX_DN: - if ( dn_search( vals, address, - current_to, current_nto, - togroups, ngroups, - err, nerr ) ) { - resolved = 1; - } - break; - - case AS_SYNTAX_URL: - if ( url_list_search( vals, address, - as->as_m_entries, - current_to, current_nto, - togroups, ngroups, - err, nerr, type ) ) { - resolved = 1; - } - break; - - case AS_SYNTAX_BOOL_FILTER: - if ( strcasecmp( vals[0], "true" ) ) { - break; - } - substs[0].sub_char = 'D'; - substs[0].sub_value = dn; - substs[1].sub_char = '\0'; - substs[1].sub_value = NULL; - if ( url_list_search( vals, address, - as->as_m_entries, - current_to, current_nto, - togroups, ngroups, - err, nerr, type ) ) { - resolved = 1; - } - break; - - default: - syslog( LOG_ALERT, - "Invalid syntax %d for kind %d", - as->as_syntax, as->as_kind ); - break; - } - break; - - case AS_KIND_ERRORS: - /* This is a group with special processing */ - if ( type & GROUP_ERRORS ) { - switch (as->as_kind) { - case AS_SYNTAX_RFC822: - add_to( current_to, current_nto, vals ); - resolved = 1; - break; - case AS_SYNTAX_URL: - default: - syslog( LOG_ALERT, - "Invalid syntax %d for kind %d", - as->as_syntax, as->as_kind ); - } - } else { - current_group = new_group( dn, togroups, - ngroups ); - current_to = ¤t_group->g_members; - current_nto = ¤t_group->g_nmembers; - split_address( address, - &localpart, &domainpart ); - if ( domainpart ) { - sprintf( buf, "%s-%s@%s", - localpart, ERRORS, - domainpart ); - free( localpart ); - free( domainpart ); - } else { - sprintf( buf, "%s-%s@%s", - localpart, ERRORS, - host ); - free( localpart ); - } - current_group->g_errorsto = strdup( buf ); - } - break; + char **requeststo; - case AS_KIND_REQUEST: - /* This is a group with special processing */ - if ( type & GROUP_REQUEST ) { - add_to( current_to, current_nto, vals ); - resolved = 1; - } - break; - - case AS_KIND_OWNER: - /* This is a group with special processing */ - if ( type & GROUP_REQUEST ) { - add_to( current_to, current_nto, vals ); - resolved = 1; - } - break; + if ( (requeststo = get_attributes_mail_dn( e, "rfc822RequestsTo", + "requestsTo" )) != NULL ) { + add_to( to, nto, requeststo ); - default: - syslog( LOG_ALERT, - "Invalid kind %d", as->as_kind ); - /* Error, TBC */ - } - ldap_value_free( vals ); - if ( as->as_final ) { - return( resolved ); - } + ldap_value_free( requeststo ); + } else { + add_error( err, nerr, E_NOREQUEST, dn, NULL ); } - return( resolved ); } -static int -search_bases( - char *filter, - Subst *substs, - char *name, +static void +do_group_errors( + LDAPMessage *e, + char *dn, char ***to, int *nto, - Group **togroups, - int *ngroups, Error **err, - int *nerr, - int type + int *nerr ) { - int b, resolved = 0; + char **errorsto; - for ( b = 0; base[b] != NULL; b++ ) { + if ( (errorsto = get_attributes_mail_dn( e, "rfc822ErrorsTo", + "errorsTo" )) != NULL ) { + add_to( to, nto, errorsto ); - if ( ! (base[b]->b_search & type) ) { - continue; - } - - resolved = search_ldap_url( base[b]->b_url, substs, name, - base[b]->b_rdnpref, - base[b]->b_m_entries, - to, nto, togroups, ngroups, - err, nerr, type ); - if ( resolved ) - break; + ldap_value_free( errorsto ); + } else { + add_error( err, nerr, E_NOERRORS, dn, NULL ); } - return( resolved ); } static void -do_address( - char *name, +do_group_owner( + LDAPMessage *e, + char *dn, char ***to, int *nto, - Group **togroups, - int *ngroups, Error **err, - int *nerr, - int type + int *nerr ) { - struct timeval timeout; - char *localpart, *domainpart; - int resolved; - Subst substs[5]; - - /* - * Look up the name in X.500, add the appropriate addresses found - * to the to list, or to the err list in case of error. Groups are - * handled by the do_group routine, individuals are handled here. - * When looking up name, we follow the bases hierarchy, looking - * in base[0] first, then base[1], etc. For each base, there is - * a set of search filters to try, in order. If something goes - * wrong here trying to contact X.500, we exit with EX_TEMPFAIL. - * If the b_rdnpref flag is set, then we give preference to entries - * that matched name because it's their rdn, otherwise not. - */ + char **owner; - split_address( name, &localpart, &domainpart ); - timeout.tv_sec = MAIL500_TIMEOUT; - timeout.tv_usec = 0; - substs[0].sub_char = 'm'; - substs[0].sub_value = name; - substs[1].sub_char = 'h'; - substs[1].sub_value = host; - substs[2].sub_char = 'l'; - substs[2].sub_value = localpart; - substs[3].sub_char = 'd'; - substs[3].sub_value = domainpart; - substs[4].sub_char = '\0'; - substs[4].sub_value = NULL; - - resolved = search_bases( NULL, substs, name, - to, nto, togroups, ngroups, - err, nerr, type ); - - if ( !resolved ) { - /* not resolved - bounce with user unknown */ - if ( type == USER ) { - add_error( err, nerr, E_USERUNKNOWN, name, NULL ); - } else { - add_error( err, nerr, E_GROUPUNKNOWN, name, NULL ); - } + if ( (owner = get_attributes_mail_dn( e, "", "owner" )) != NULL ) { + add_to( to, nto, owner ); + ldap_value_free( owner ); + } else { + add_error( err, nerr, E_NOOWNER, dn, NULL ); } } @@ -1707,14 +1418,11 @@ do_ambiguous( FILE *fp, Error *err, int namelen ) } } - /* if ( isgroup( e ) ) { vals = ldap_get_values( ld, e, "description" ); } else { vals = ldap_get_values( ld, e, "title" ); } - */ - vals = ldap_get_values( ld, e, "description" ); fprintf( fp, " %-20s %s\n", rdn, vals ? vals[0] : "" ); for ( i = 1; vals && vals[i] != NULL; i++ ) { @@ -1762,42 +1470,18 @@ add_to( char ***list, int *nlist, char **new ) (*list)[*nlist] = NULL; } -static void -add_single_to( char ***list, char *new ) -{ - int nlist; - - if ( *list == NULL ) { - nlist = 0; - *list = (char **) malloc( 2 * sizeof(char *) ); - } else { - nlist = count_values( *list ); - *list = (char **) realloc( *list, - ( nlist + 2 ) * sizeof(char *) ); - } - - (*list)[nlist] = strdup( new ); - (*list)[nlist+1] = NULL; -} - static int isgroup( LDAPMessage *e ) { - int i, j; + int i; char **oclist; - if ( !groupclasses ) { - return( 0 ); - } - oclist = ldap_get_values( ld, e, "objectClass" ); for ( i = 0; oclist[i] != NULL; i++ ) { - for ( j = 0; groupclasses[j] != NULL; j++ ) { - if ( strcasecmp( oclist[i], groupclasses[j] ) == 0 ) { - ldap_value_free( oclist ); - return( 1 ); - } + if ( strcasecmp( oclist[i], "rfc822MailGroup" ) == 0 ) { + ldap_value_free( oclist ); + return( 1 ); } } ldap_value_free( oclist ); @@ -1820,6 +1504,52 @@ add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg ) (*nerr)++; } +static void +add_group( char *dn, Group **list, int *nlist ) +{ + int i, namelen; + char **ufn; + + for ( i = 0; i < *nlist; i++ ) { + if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) { + syslog( LOG_ALERT, "group loop 2 detected (%s)", dn ); + return; + } + } + + ufn = ldap_explode_dn( dn, 1 ); + namelen = strlen( ufn[0] ); + + if ( *nlist == 0 ) { + *list = (Group *) malloc( sizeof(Group) ); + } else { + *list = (Group *) realloc( *list, (*nlist + 1) * + sizeof(Group) ); + } + + /* send errors to groupname-errors@host */ + (*list)[*nlist].g_errorsto = (char *) malloc( namelen + sizeof(ERRORS) + + hostlen + 2 ); + sprintf( (*list)[*nlist].g_errorsto, "%s-%s@%s", ufn[0], ERRORS, host ); + (void) canonical( (*list)[*nlist].g_errorsto ); + + /* send to groupname-members@host - make it a list for send_group */ + (*list)[*nlist].g_members = (char **) malloc( 2 * sizeof(char *) ); + (*list)[*nlist].g_members[0] = (char *) malloc( namelen + + sizeof(MEMBERS) + hostlen + 2 ); + sprintf( (*list)[*nlist].g_members[0], "%s-%s@%s", ufn[0], MEMBERS, + host ); + (void) canonical( (*list)[*nlist].g_members[0] ); + (*list)[*nlist].g_members[1] = NULL; + + /* save the group's dn so we can check for loops above */ + (*list)[*nlist].g_dn = strdup( dn ); + + (*nlist)++; + + ldap_value_free( ufn ); +} + static void unbind_and_exit( int rc ) { @@ -1830,3 +1560,129 @@ unbind_and_exit( int rc ) exit( rc ); } + +static char * +canonical( char *s ) +{ + char *saves = s; + + for ( ; *s != '\0'; s++ ) { + if ( *s == ' ' ) + *s = '.'; + } + + return( saves ); +} + +static int +group_loop( char *dn ) +{ + int i; + static char **groups; + static int ngroups; + + for ( i = 0; i < ngroups; i++ ) { + if ( strcmp( dn, groups[i] ) == 0 ) + return( 1 ); + } + + if ( ngroups == 0 ) + groups = (char **) malloc( sizeof(char *) ); + else + groups = (char **) realloc( groups, + (ngroups + 1) * sizeof(char *) ); + + groups[ngroups++] = strdup( dn ); + + return( 0 ); +} + +static int +has_attributes( LDAPMessage *e, char *attr1, char *attr2 ) +{ + char **attr; + + if ( (attr = ldap_get_values( ld, e, attr1 )) != NULL ) { + ldap_value_free( attr ); + return( 1 ); + } + + if ( (attr = ldap_get_values( ld, e, attr2 )) != NULL ) { + ldap_value_free( attr ); + return( 1 ); + } + + return( 0 ); +} + +static char ** +get_attributes_mail_dn( + LDAPMessage *e, + char *attr1, + char *attr2 /* this one is dn-valued */ +) +{ + LDAPMessage *ee, *res; + char **vals, **dnlist, **mail, **grname; + char *dn; + int nto = 0, i, rc; + struct timeval timeout; + + dn = ldap_get_dn( ld, e ); + + vals = ldap_get_values( ld, e, attr1 ); + for ( nto = 0; vals != NULL && vals[nto] != NULL; nto++ ) + ; /* NULL */ + + if ( (dnlist = ldap_get_values( ld, e, attr2 )) != NULL ) { + timeout.tv_sec = MAIL500_TIMEOUT; + timeout.tv_usec = 0; + + for ( i = 0; dnlist[i] != NULL; i++ ) { + if ( (rc = ldap_search_st( ld, dnlist[i], + LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, + &timeout, &res )) != LDAP_SUCCESS ) { + if ( rc != LDAP_NO_SUCH_OBJECT ) { + unbind_and_exit( EX_TEMPFAIL ); + } + + syslog( LOG_ALERT, "bad (%s) dn (%s)", attr2, + dnlist[i] ); + + continue; + } + + if ( (ee = ldap_first_entry( ld, res )) == NULL ) { + syslog( LOG_ALERT, "error parsing x500 entry" ); + continue; + } + + if ( isgroup(ee) ) { + char *graddr[2]; + + grname = ldap_explode_dn( dnlist[i], 1 ); + + /* groupname + host + @ + null */ + graddr[0] = (char *) malloc( strlen( grname[0] ) + + strlen( host ) + 2 ); + graddr[1] = NULL; + sprintf( graddr[0], "%s@%s", grname[0], host); + (void) canonical( graddr[0] ); + + add_to( &vals, &nto, graddr ); + + free( graddr[0] ); + ldap_value_free( grname ); + } else if ( (mail = ldap_get_values( ld, ee, "mail" )) + != NULL ) { + add_to( &vals, &nto, mail ); + + ldap_value_free( mail ); + } + + ldap_msgfree( res ); + } + } + + return( vals ); +} diff --git a/clients/mail500/sendmail.cf b/clients/mail500/sendmail.cf index b7ec14d1ce..477162f10b 100644 --- a/clients/mail500/sendmail.cf +++ b/clients/mail500/sendmail.cf @@ -1,3 +1,8 @@ +# +# It's recommended use Sendmail's m4 configuration system to avoid +# mucking directly with .cf files +# + # Mostly rfc1123 compliant sendmail.cf # # Mail sendmail-admins-request@itd.umich.edu to join diff --git a/clients/maildap/Makefile.in b/clients/maildap/Makefile.in new file mode 100644 index 0000000000..5bff81dd2f --- /dev/null +++ b/clients/maildap/Makefile.in @@ -0,0 +1,31 @@ +# $OpenLDAP$ + +UNIX_PRGS = maildap +PROGRAMS = $(@PLAT@_PRGS) + +SRCS= main.c +XSRCS= version.c +OBJS= main.o + +LDAP_INCDIR= ../../include +LDAP_LIBDIR= ../../libraries + +XLIBS = -lldap -llber -llutil +XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) + +maildap : version.o + $(LTLINK) -o $@ version.o $(OBJS) $(LIBS) + +version.c: ${OBJS} $(LDAP_LIBDEPEND) + @-$(RM) $@ + $(MKVERSION) maildap > $@ + +install-local: $(PROGRAMS) FORCE + -$(MKDIR) $(DESTDIR)$(libexecdir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + diff --git a/clients/maildap/README b/clients/maildap/README new file mode 100644 index 0000000000..ef33c14659 --- /dev/null +++ b/clients/maildap/README @@ -0,0 +1,357 @@ + +*** WARNING: Preliminary *** + +This is the README file for maildap, a mailer that does X.500 lookups +via LDAP. It is based on mail500. + +If you are planning to run maildap at your site, you need to create a +configuration file. Previous versions required modifying the source +code for configuration. This is no longer necessary. +there are several + +*** WHAT maildap DOES: *** + +maildap is designed to be invoked as a mailer (e.g., from sendmail), +similar to the way /bin/mail works. It takes a few required arguments +and then a list of addresses to deliver to. It expects to find the +message to deliver on its standard input. It looks up the addresses in +X.500 to figure out where to route the mail, and then execs sendmail to +do the actual delivery. It supports simple aliases, groups, and +mailing lists, the details of which are given below. + +*** HOW IT WORKS (from the sendmail side): *** + +The idea is that you might have a rule like this in your sendmail.cf +file somewhere in rule set 0: + +R$*<@umich.edu>$* $#maildap$@umich.edu$:<$1> + +This rule says that any address that ends in @umich.edu will cause +the maildap mailer to be called to deliver the mail. You probably +also want to do something to prevent addresses like terminator!tim@umich.edu +or tim%terminator.rs.itd.umich.edu@umich.edu from being passed to maildap. +At U-M, we do this by adding rules like this to rule set 9 where we +strip off our local names: + +R<@umich.edu>$*:$* $>10<@>$1:$2 +R$+%$+<@umich.edu> $>10$1%$2<@> +R$+!$+<@umich.edu> $>10$1!$2<@> + +You can also feed complete FQDN addresses to maildap. For instance, +you could define a class containing the list of domains you want to +serve like this: + +FQ/etc/mail/maildapdomains + +and then use a rule in rule set 0 like this: + +R$*<$=Q>$* $#maildap $@$2 $:<$1@$2> + +See the sample sendmail.cf in this directory for more details. +For sendmail 8.9 (and later) users can use MAILER(maildap) if +maildap.m4 is placed within sendmail's cf/mailer directory. + +The maildap mailer should be defined similar to this in the +sendmail.cf file: + +Mmaildap, P=/usr/local/etc/maildap, F=DFMSmnXuh, A=maildap -f $f -h $h -m $n@$w $u + +This defines how maildap will be treated by sendmail and what +arguments it will have when it's called. The various flags specified +by the F=... parameter are explained in your local sendmail book (with +any luck). The arguments to maildap are as follows: + + -f Who the mail is from. This will be used as the address + to which any errors should be sent (unless the address + specifies a mailing list - see below). Normally, sendmail + defines the $f macro to be the sender. + + -h The domain for which the mail is destined. This is passed + in to maildap via the $h macro, which is set by the + $@ metasymbol in the rule added to rule set 0 above. + It's normally used when searching for groups. + + -m The mailer-daemon address. If errors have to be sent, + this is the address they will come from. $n is normally + set to mailer-daemon and $w is normally the local host + name. + +The final argument $u is used to stand for the addresses to which to +deliver the mail. + +*** HOW IT WORKS (from the maildap side): *** + +When maildap gets invoked with one or more names to which to deliver +mail, it searches for each name in X.500. Where it searches, and what +kind(s) of search(es) is controlled by a configuration file. There +are a number of different approaches to handling mail and no general +rules can be given. We will however present some examples of what you +can do. The new maildap is designed to be flexible and able to +accommodate most scenarios. + +For instance, if you are following the mail distribution model that +the old maildap used, you need lines in the configuration file like +these: + +search ldap:///ou=People, dc=OpenLDAP, dc=org??sub?\ + (|(uid=%25l)(cn==%25l)) + +search ldap:///ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\ + (&(cn=%25l)(associatedDomain==%25h)) + +search ldap:///ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\ + (&(cn=%25l)(associatedDomain==%25h)) + +As you can see, searches are described by using LDAP URLs. You can +have as many searches as you want, but the first search that succeeds +completes the processing for a recipient address. You can provide an +attribute list in the URL and it will be honored. Otherwise, the +attribute list will default as explained below. + +Filters can contain substitutions. Actually, they *should* contain +substitutions or the search result would not change with the recipient +address. Since the usual substitution character is % and it has +special meaning in URLs, you have to represent it according to the URL +syntax, that is, %25, 25 being the hex code of %. The filter can be +as complex as you want and you may make as many substitutions as you +want. Known substitutions at this time are: + + %m The recipient address we are considering now, maybe fully + qualified + %h The host, that is, the value of the -h argument to + maildap + %l The local part from %m + %d The domain part from %m + +So, in the above example, if the recipient address were +name@OpenLDAP.org, maildap would do the the following searches, +stopping if it found anything at any step: + + Search (18) [2]: dc=org@dc=OpenLDAP@ou=People + Search subtree (uid=name) + Search (18) [3]: dc=org@dc=OpenLDAP@ou=People + Search subtree (cn=name) + + Search (18) [4]: dc=org@dc=OpenLDAP@ou=Groups@ou=System Groups + Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org)) + + Search (18) [5]: dc=org@dc=OpenLDAP@ou=Groups@ou=User Groups + Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org)) + +[Beware: Currently unimplemented] +You can also specify whether you want search results that matched +because the entry's RDN matched the search to be given preference +or not. At U-M, we only give such preference in the mail group +portion of the searches. Beware with this option: the algorithm +used to decide whether an entry's RDN matched the search is very +simple-minded, and may not always be correct. + +*** HOW IT WORKS (from the X.500 side): *** + +First you need to decide what attributes you will search for and what +attributes will be used to deliver the message. In the classical +maildap, we would search by uid or cn and deliver to the mail +attribute. Another model is to search by the mail attribute and +deliver to something else, such as the uid if determined that the user +has a local account. + +*** THE CONFIGURATION FILE + +The configuration file is composed of lines that prescribe the +operation of maildap. Blank lines are ignored and lines beginning +with # are considered comments and ignored. Outside comments, the +sequence '\', newline, whitespace is ignored so that long lines can be +split for readability. + +Attribute Definitions + +Lines starting with 'attribute' define the semantics of an attribute. +Notice that attributes will be considered in the order they are +defined in the configuration file. This means that the presence of +some can preempt processing of other attributes and that attributes +that simply collect needed information must be defined before others +that use that information. The format is: + +attribute name [multivalued] [final] [multiple-entries] [] [] + +If the attribute is "multivalued", all values will be considered. If +it is not and several values are found the entry is declared in error. + +If the attribute is "final", its presence in an entry prevents further +analysis of the entry. + +If the attribute is "multiple-entries" and it is of an appropriate +syntax that can point to other entries, all such entries are +considered, otherwise the entry is in error. + +The known kinds are: + +recipient The value(s) of this attribute should be + used as the address(es) to deliver the message + to if they are in an appropriate syntax. If + they otherwise point at other entries, they + should be retrieved and expanded as necessary + to complete the resolution of this entry. The + process is recursive and all. + +errors The value(s) of this attribute represent the + entities that should receive error messages + for mail messages directed to this entry. + The presence of an attribute of this kind + force a change in the envelope sender address + of the message. + +The known syntaxes are: + +local-native-mailbox An unqualified mailbox name +rfc822 A fully qualified RFC822 mail address +rfc822-extended Currently identical to rfc822 +dn The Distinguished Name of some other entry +url A URL either of the mailto: or ldap: styles, + others styles, notably file:, could be added. + No substitutions are supported currently. +search-with-filter= Do a search on all known search bases + with the give filter. The only currenty + substitution available is %D, the DN of the + current entry. + +The default attributes to search + +A line starting with "default-attributes" contains a comma-separated +list of attributes to use in searches everytime a specific list is not +known. + +Search bases + +As shown in the example above, lines starting with "search" provide +the search bases to use to initially try to resolve each entry or when +using attributes of syntax "search-with-filter". + +*** EXAMPLES + +A configuration file that approximates the operation of the old +maildap runs as follows: + +attribute errorsTo errors dn +attribute rfc822ErrorsTo errors rfc822 +attribute requestsTo request dn +attribute rfc822RequestsTo request rfc822 +attribute owner owner dn +attribute mail multivalued recipient rfc822 +attribute member multivalued recipient dn +attribute joinable multiple-entries recipient \ + search-with-filter=(memberOfGroup=%D) + +default-attributes objectClass,title,postaladdress,telephoneNumber,\ + mail,description,owner,errorsTo,rfc822ErrorsTo,requestsTo,\ + rfc822RequestsTo,joinable,cn,member,moderator,onVacation,uid,\ + suppressNoEmailError + +# Objectclasses that, when present, identify an entry as a group +group-classes mailGroup + +search ldap:///ou=People, dc=OpenLDAP, dc=org??sub?\ + (|(uid=%25l)(cn==%25l)) + +search ldap:///ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\ + (&(cn=%25l)(associatedDomain==%25h)) + +search ldap:///ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\ + (&(cn=%25l)(associatedDomain==%25h)) + +A configuration that approximates the semantics of the mailRecipient +and mailGroup classes used by Netscape: + +attribute mgrpErrorsTo errors url +attribute rfc822ErrorsTo errors rfc822 +attribute mailRoutingAddress final recipient rfc822 +attribute mailHost final host forward-to-host +attribute uid final recipient local-native-mailbox +attribute uniqueMember multivalued recipient dn +attribute mgrpRFC822MailMember multivalued recipient rfc822-extended +attribute mgrpDeliverTo multivalued multiple-entries recipient url + +default-attributes objetcClass,mailRoutingAddress,mailHost,uid,uniqueMember,\ + mgrpRFC822MailMember,mgrpErrorsTo,rfc822ErrorsTo + +# Objectclasses that, when present, identify an entry as a group +group-classes mailGroup + +search ldap://localhost/dc=OpenLDAP,dc=org?\ + objectClass,mailRoutingAddress,mailHost,uid?\ + sub?\ + (&(|(mail=%25m)(mailAlternateAddress=%25m))(objectClass=mailRecipient)) + +search ldap://localhost/dc=OpenLDAP,dc=org?\ + objectClass,uniqueMember,mgrpRFC822MailMember,mgrpErrorsTo,mgrpDeliverTo,rfc822ErrorsTo?\ + sub?\ + (&(|(mail=%25m)(mailAlternateAddress=%25m))(objectClass=mailGroup)) + +[ The rest is from the original README and I did not rewrite it yet ] + +In X.500, there are several new attribute types and one new object +class defined that maildap makes use of. At its most basic, for normal +entries maildap will deliver to the value(s) listed in the +rfc822Mailbox attribute of the entry. For example, at U-M my entry has +the attribute + + mail= tim@terminator.rs.itd.umich.edu + +So mail sent to tim@umich.edu will be delivered via maildap to that +address. If there were multiple values for the mail attribute, multiple +copies of the mail would be sent. + +A new object class, rfc822MailGroup, and several new attributes have +been defined to handle email groups/mailing lists. To use this, you +will need to add this to your local oidtable.oc: + + # object class for representing rfc 822 mailgroups + rfc822MailGroup: umichObjectClass.2 : \ + top : \ + cn : \ + rfc822Mailbox, member, memberOfGroup, owner, \ + errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo, + joinable, associatedDomain, \ + description, multiLineDescription, \ + userPassword, krbName, \ + telecommunicationAttributeSet, postalAttributeSet + +And you will need to add these to your local oidtable.at: + + # attrs for rfc822mailgroups + multiLineDescription: umichAttributeType.2 : CaseIgnoreList + rfc822ErrorsTo: umichAttributeType.26 : CaseIgnoreIA5String + rfc822RequestsTo: umichAttributeType.27 : CaseIgnoreIA5String + joinable: umichAttributeType.28 : Boolean + memberOfGroup: umichAttributeType.29 : DN + errorsTo: umichAttributeType.30 : DN + requestsTo: umichAttributeType.31 : DN + +The idea was to define a kind of hybrid mail group that could handle +people who were in X.500 or not. So, for example, members of a group +can be specified via the member attribute (for X.500 members) or the +rfc822MailBox attribute (for non-X.500 members). Similarly for the +errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo +attributes. + +To create a real mailing list, with a list maintainer, all you have to +do is create an rfc822MailGroup and fill in the errorsTo or +rfc822ErrorsTo attributes (or both). That will cause any errors +encountered when delivering mail to the group to go to the addresses +listed (or X.500 entry via it's mail attribute). + +If you fill in the requestsTo or rfc822RequestsTo (or both) attributes, +mail sent to groupname-request will be sent to the addresses listed +there. maildap does this automatically, so you don't have to explicitly +add the groupname-request alias to your group. + +To allow users to join a group, there is the joinable flag. If TRUE, +maildap will search for entries that have a memberOfGroup attribute +equal to the DN of the group, using the same algorithm it used to find +the group in the first place (i.e. the DNs and filters listed in the +base array). This allows people to join (or subscribe to) a group +without having to modify the group entry directly. If joinable is +FALSE, the search is not done. + +Finally, keep in mind that this is somewhat experimental at the moment. +We are using it in production at U-M, but your mileage may vary... diff --git a/clients/maildap/maildap.m4 b/clients/maildap/maildap.m4 new file mode 100644 index 0000000000..8e805a7a8a --- /dev/null +++ b/clients/maildap/maildap.m4 @@ -0,0 +1,53 @@ +PUSHDIVERT(-1) +## Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA +## All rights reserved. +## +## Redistribution and use in source and binary forms are permitted only +## as authorized by the OpenLDAP Public License. A copy of this +## license is available at http://www.OpenLDAP.org/license.html or +## in file LICENSE in the top-level directory of the distribution. + +dnl +dnl maildap mailer +dnl +dnl This file should be placed in the sendmail's cf/mailer directory. +dnl To include this mailer in your .cf file, use the directive: +dnl MAILER(maildap) +dnl + +ifdef(`MAILDAP_HOST', + `define(`MAILDAP_HOST_FLAG', CONCAT(` -l ', CONCAT(MAILDAP_HOST,` ')))', + `define(`MAILDAP_HOST_FLAG', `')') +ifdef(`MAILDAP_CONFIG_PATH',, + `define(`MAILDAP_CONFIG_PATH', /etc/mail/maildap.conf)') +ifdef(`MAILDAP_MAILER_PATH',, + `ifdef(`MAILDAP_PATH', + `define(`MAILDAP_MAILER_PATH', MAILDAP_PATH)', + `define(`MAILDAP_MAILER_PATH', /usr/local/libexec/maildap)')') +ifdef(`MAILDAP_MAILER_FLAGS',, + `define(`MAILDAP_MAILER_FLAGS', `SmnXuh')') +ifdef(`MAILDAP_MAILER_ARGS',, + `define(`MAILDAP_MAILER_ARGS', + CONCAT(`maildap',CONCAT(` -C ',MAILDAP_CONFIG_PATH,MAILDAP_HOST_FLAG,`-f $f -m $n@$w $u')))') + +POPDIVERT + +MAILER_DEFINITIONS + +######################*****############## +### MAILDAP Mailer specification ### +##################*****################## + +VERSIONID(`$OpenLDAP$') + +Mmaildap, P=MAILDAP_MAILER_PATH, F=CONCAT(`DFM', MAILDAP_MAILER_FLAGS), S=11/31, R=20/40, T=DNS/RFC822/X-Unix, + ifdef(`MAILDAP_MAILER_MAX', `M=500_MAILER_MAX, ')A=MAILDAP_MAILER_ARGS + +LOCAL_CONFIG +# Maildap Domains +#CQ foo.com + +PUSHDIVERT(3) +# maildap additions +R$* < @ $=Q > $* $#maildap $@ $2 $: <$1@$2> domain handled by maildap +POPDIVERT diff --git a/clients/maildap/main.c b/clients/maildap/main.c new file mode 100644 index 0000000000..d5a258b99b --- /dev/null +++ b/clients/maildap/main.c @@ -0,0 +1,2062 @@ +/* $OpenLDAP$ */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + * + * Copyright 1998-2000 The OpenLDAP Foundation + * COPYING RESTRICTIONS APPLY. See COPYRIGHT File in top level directory + * of this package for details. + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include + +#include "ldap_defaults.h" + +#ifndef MAIL500_BOUNCEFROM +#define MAIL500_BOUNCEFROM "<>" +#endif + +#define USER 0x01 +#define GROUP_ERRORS 0x02 +#define GROUP_REQUEST 0x04 +#define GROUP_MEMBERS 0x08 +#define GROUP_OWNER 0x10 + +#define ERROR "error" +#define ERRORS "errors" +#define REQUEST "request" +#define REQUESTS "requests" +#define MEMBERS "members" +#define OWNER "owner" +#define OWNERS "owners" + +LDAP *ld; +char *vacationhost = NULL; +char *errorsfrom = MAIL500_BOUNCEFROM; +char *mailfrom = NULL; +char *host = NULL; +char *ldaphost = NULL; +int hostlen = 0; +int debug; + +typedef struct errs { + int e_code; +#define E_USERUNKNOWN 1 +#define E_AMBIGUOUS 2 +#define E_NOEMAIL 3 +#define E_NOREQUEST 4 +#define E_NOERRORS 5 +#define E_BADMEMBER 6 +#define E_JOINMEMBERNOEMAIL 7 +#define E_MEMBERNOEMAIL 8 +#define E_LOOP 9 +#define E_NOMEMBERS 10 +#define E_NOOWNER 11 +#define E_GROUPUNKNOWN 12 +#define E_NOOWNADDRESS 13 + char *e_addr; + union e_union_u { + char *e_u_loop; + LDAPMessage *e_u_msg; + } e_union; +#define e_msg e_union.e_u_msg +#define e_loop e_union.e_u_loop +} Error; + +typedef struct groupto { + char *g_dn; + char *g_errorsto; + char **g_members; + int g_nmembers; +} Group; + +typedef struct baseinfo { + char *b_url; + int b_m_entries; + char b_rdnpref; /* give rdn's preference when searching? */ + int b_search; /* ORed with the type of thing the address */ + /* looks like (USER, GROUP_ERRORS, etc.) */ + /* to see if this should be searched */ +} Base; + +Base **base = NULL; + +char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrLDAP", "-odi", "-oi", "-f", NULL, NULL }; + +typedef struct attr_semantics { + char *as_name; + int as_m_valued; /* Is multivalued? */ + int as_priority; /* Priority level of this attribut type */ + int as_syntax; /* How to interpret values */ + int as_m_entries; /* Can resolve to several entries? */ + int as_kind; /* Recipient, sender, etc. */ + char *as_param; /* Extra info for filters and things alike */ +} AttrSemantics; + +#define AS_SYNTAX_UNKNOWN 0 +#define AS_SYNTAX_NATIVE_MB 1 /* Unqualified mailbox name */ +#define AS_SYNTAX_RFC822 2 /* RFC822 mail address */ +#define AS_SYNTAX_HOST 3 +#define AS_SYNTAX_DN 4 /* A directory entry */ +#define AS_SYNTAX_RFC822_EXT 5 +#define AS_SYNTAX_URL 6 /* mailto: or ldap: URL */ +#define AS_SYNTAX_BOOL_FILTER 7 /* For joinable, filter in as_param */ +#define AS_SYNTAX_PRESENT 8 /* Value irrelevant, only presence is + * considered. */ + +#define AS_KIND_UNKNOWN 0 +#define AS_KIND_RECIPIENT 1 +#define AS_KIND_ERRORS 2 /* For ErrorsTo and similar */ +#define AS_KIND_REQUEST 3 +#define AS_KIND_OWNER 4 +#define AS_KIND_ROUTE_TO_HOST 5 /* Expand at some other host */ +#define AS_KIND_ALLOWED_SENDER 6 /* Can send to group */ +#define AS_KIND_MODERATOR 7 +#define AS_KIND_ROUTE_TO_ADDR 8 /* Rewrite recipient address as */ +#define AS_KIND_OWN_ADDR 9 /* RFC822 name of this entry */ +#define AS_KIND_DELIVERY_TYPE 10 /* How to deliver mail to this entry */ + +AttrSemantics **attr_semantics = NULL; +int current_priority = 0; + +typedef struct subst { + char sub_char; + char *sub_value; +} Subst; + +char **groupclasses = NULL; +char **def_attr = NULL; +char **myhosts = NULL; /* FQDNs not to route elsewhere */ +char **mydomains = NULL; /* If an RFC822 address points to one + of these domains, search it in the + directory instead of returning it + to hte MTA */ + +static void load_config( char *filespec ); +static void split_address( char *address, char **localpart, char **domainpart); +static int entry_engine( LDAPMessage *e, char *dn, char *address, char ***to, int *nto, Group ***togroups, int *ngroups, Error **err, int *nerr, int type ); +static void do_address( char *name, char ***to, int *nto, Group ***togroups, int *ngroups, Error **err, int *nerr, int type ); +static void send_message( char **to ); +static void send_errors( Error *err, int nerr ); +static void do_noemail( FILE *fp, Error *err, int namelen ); +static void do_ambiguous( FILE *fp, Error *err, int namelen ); +static int count_values( char **list ); +static void add_to( char ***list, int *nlist, char **new ); +static void add_single_to( char ***list, char *new ); +static int isgroup( LDAPMessage *e ); +static void add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg ); +static void unbind_and_exit( int rc ) LDAP_GCCATTR((noreturn)); +static void send_group( Group **group, int ngroup ); + +static int connect_to_x500( void ); + + +int +main ( int argc, char **argv ) +{ + char *myname; + char **tolist; + Error *errlist; + Group **togroups; + int numto, ngroups, numerr, nargs; + int i, j; + char *conffile = NULL; + + if ( (myname = strrchr( argv[0], '/' )) == NULL ) + myname = strdup( argv[0] ); + else + myname = strdup( myname + 1 ); + +#ifdef SIGPIPE + (void) SIGNAL( SIGPIPE, SIG_IGN ); +#endif + +#ifdef LOG_MAIL + openlog( myname, OPENLOG_OPTIONS, LOG_MAIL ); +#elif LOG_DEBUG + openlog( myname, OPENLOG_OPTIONS ); +#endif + + while ( (i = getopt( argc, argv, "d:C:f:h:l:m:v:" )) != EOF ) { + switch( i ) { + case 'd': /* turn on debugging */ + debug |= atoi( optarg ); + break; + + case 'C': /* path to configuration file */ + conffile = strdup( optarg ); + break; + + case 'f': /* who it's from & where errors should go */ + mailfrom = strdup( optarg ); + for ( j = 0; sendmailargs[j] != NULL; j++ ) { + if ( strcmp( sendmailargs[j], "-f" ) == 0 ) { + sendmailargs[j+1] = mailfrom; + break; + } + } + break; + + case 'h': /* hostname */ + host = strdup( optarg ); + hostlen = strlen(host); + break; + + case 'l': /* ldap host */ + ldaphost = strdup( optarg ); + break; + + /* mailer-daemon address - who we should */ + case 'm': /* say errors come from */ + errorsfrom = strdup( optarg ); + break; + + case 'v': /* vacation host */ + vacationhost = strdup( optarg ); + break; + + default: + syslog( LOG_ALERT, "unknown option" ); + break; + } + } + + if ( mailfrom == NULL ) { + syslog( LOG_ALERT, "required argument -f not present" ); + exit( EX_TEMPFAIL ); + } + if ( errorsfrom == NULL ) { + syslog( LOG_ALERT, "required argument -m not present" ); + exit( EX_TEMPFAIL ); + } +/* if ( host == NULL ) { */ +/* syslog( LOG_ALERT, "required argument -h not present" ); */ +/* exit( EX_TEMPFAIL ); */ +/* } */ + if ( conffile == NULL ) { + syslog( LOG_ALERT, "required argument -C not present" ); + exit( EX_TEMPFAIL ); + } + + load_config( conffile ); + + if ( connect_to_x500() != 0 ) + exit( EX_TEMPFAIL ); + + setuid( geteuid() ); + + if ( debug ) { + char buf[1024]; + int i; + + syslog( LOG_ALERT, "running as %d", geteuid() ); + strcpy( buf, argv[0] ); + for ( i = 1; i < argc; i++ ) { + strcat( buf, " " ); + strcat( buf, argv[i] ); + } + + syslog( LOG_ALERT, "args: (%s)", buf ); + } + + tolist = NULL; + numto = 0; + add_to( &tolist, &numto, sendmailargs ); + nargs = numto; + ngroups = numerr = 0; + togroups = NULL; + errlist = NULL; + for ( i = optind; i < argc; i++ ) { + char *s; + int type; + char *localpart = NULL, *domainpart = NULL; + char address[1024]; + + type = USER; + split_address( argv[i], &localpart, &domainpart ); + if ( (s = strrchr( localpart, '-' )) != NULL ) { + s++; + + if ((strcasecmp(s, ERROR) == 0) || + (strcasecmp(s, ERRORS) == 0)) { + type = GROUP_ERRORS; + *(--s) = '\0'; + } else if ((strcasecmp(s, REQUEST) == 0) || + (strcasecmp(s, REQUESTS) == 0)) { + type = GROUP_REQUEST; + *(--s) = '\0'; + } else if ( strcasecmp( s, MEMBERS ) == 0 ) { + type = GROUP_MEMBERS; + *(--s) = '\0'; + } else if ((strcasecmp(s, OWNER) == 0) || + (strcasecmp(s, OWNERS) == 0)) { + type = GROUP_OWNER; + *(--s) = '\0'; + } + } + + if ( domainpart ) { + sprintf( address, "%s@%s", localpart, domainpart ); + free( localpart ); + free( domainpart ); + } else { + sprintf( address, "%s@%s", localpart, domainpart ); + free( localpart ); + } + do_address( address, &tolist, &numto, &togroups, &ngroups, + &errlist, &numerr, type ); + } + + /* + * If we have both errors and successful deliveries to make or if + * if there are any groups to deliver to, we basically need to read + * the message twice. So, we have to put it in a tmp file. + */ + + if ( numerr > 0 && numto > nargs || ngroups > 0 ) { + FILE *fp; + char buf[BUFSIZ]; + + umask( 077 ); + if ( (fp = tmpfile()) == NULL ) { + syslog( LOG_ALERT, "could not open tmp file" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + /* copy the message to a temp file */ + while ( fgets( buf, sizeof(buf), stdin ) != NULL ) { + if ( fputs( buf, fp ) == EOF ) { + syslog( LOG_ALERT, "error writing tmpfile" ); + unbind_and_exit( EX_TEMPFAIL ); + } + } + + if ( dup2( fileno( fp ), 0 ) == -1 ) { + syslog( LOG_ALERT, "could not dup2 tmpfile" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + fclose( fp ); + } + + /* deal with errors */ + if ( numerr > 0 ) { + if ( debug ) { + syslog( LOG_ALERT, "sending errors" ); + } + (void) rewind( stdin ); + send_errors( errlist, numerr ); + } + + (void) ldap_unbind( ld ); + + /* send to groups with errorsTo */ + if ( ngroups > 0 ) { + if ( debug ) { + syslog( LOG_ALERT, "sending to groups with errorsto" ); + } + (void) rewind( stdin ); + send_group( togroups, ngroups ); + } + + /* send to expanded aliases and groups w/o errorsTo */ + if ( numto > nargs ) { + if ( debug ) { + syslog( LOG_ALERT, "sending to aliases and groups" ); + } + (void) rewind( stdin ); + send_message( tolist ); + } + + return( EX_OK ); +} + +static char * +get_config_line( FILE *cf, int *lineno) +{ + static char buf[2048]; + int len; + int pos; + int room; + + pos = 0; + room = sizeof( buf ); + while ( fgets( &buf[pos], room, cf ) ) { + (*lineno)++; + if ( pos > 0 ) { + /* Delete whitespace at the beginning of new data */ + if ( isspace( buf[pos] ) ) { + char *s, *d; + for ( s = buf+pos; isspace(*s); s++ ) + ; + for ( d = buf+pos; *s; s++, d++ ) { + *d = *s; + } + *d = *s; + } + } + len = strlen( buf ); + if ( buf[len-1] != '\n' ) { + syslog( LOG_ALERT, "Definition too long at line %d", + *lineno ); + exit( EX_TEMPFAIL ); + } + if ( buf[0] == '#' ) + continue; + if ( strspn( buf, " \t\n" ) == len ) + continue; + if ( buf[len-2] == '\\' ) { + pos = len - 2; + room = sizeof(buf) - pos; + continue; + } + /* We have a real line, we will exit the loop */ + buf[len-1] = '\0'; + return( buf ); + } + return( NULL ); +} + +static void +add_url ( char *url, int rdnpref, int typemask ) +{ + Base **list_temp; + int size; + Base *b; + + b = calloc(1, sizeof(Base)); + if ( !b ) { + syslog( LOG_ALERT, "Out of memory" ); + exit( EX_TEMPFAIL ); + } + b->b_url = strdup( url ); + b->b_rdnpref = rdnpref; + b->b_search = typemask; + + if ( base == NULL ) { + base = calloc(2, sizeof(LDAPURLDesc *)); + if ( !base ) { + syslog( LOG_ALERT, "Out of memory" ); + exit( EX_TEMPFAIL ); + } + base[0] = b; + } else { + for ( size = 0; base[size]; size++ ) + ; + size += 2; + list_temp = realloc( base, size*sizeof(LDAPURLDesc *) ); + if ( !list_temp ) { + syslog( LOG_ALERT, "Out of memory" ); + exit( EX_TEMPFAIL ); + } + base = list_temp; + base[size-2] = b; + base[size-1] = NULL; + } +} + +static void +add_def_attr( char *s ) +{ + char *p, *q; + + p = s; + while ( *p ) { + p += strspn( p, "\t," ); + q = strpbrk( p, " \t," ); + if ( q ) { + *q = '\0'; + add_single_to( &def_attr, p ); + } else { + add_single_to( &def_attr, p ); + break; + } + p = q + 1; + } +} + +static void +add_attr_semantics( char *s ) +{ + char *p, *q; + AttrSemantics *as; + + as = calloc( 1, sizeof( AttrSemantics ) ); + as->as_priority = current_priority; + p = s; + while ( isspace ( *p ) ) + p++; + q = p; + while ( !isspace ( *q ) && *q != '\0' ) + q++; + *q = '\0'; + as->as_name = strdup( p ); + p = q + 1; + + while ( *p ) { + while ( isspace ( *p ) ) + p++; + q = p; + while ( !isspace ( *q ) && *q != '\0' ) + q++; + *q = '\0'; + if ( !strcasecmp( p, "multivalued" ) ) { + as->as_m_valued = 1; + } else if ( !strcasecmp( p, "multiple-entries" ) ) { + as->as_m_entries = 1; + } else if ( !strcasecmp( p, "local-native-mailbox" ) ) { + as->as_syntax = AS_SYNTAX_NATIVE_MB; + } else if ( !strcasecmp( p, "rfc822" ) ) { + as->as_syntax = AS_SYNTAX_RFC822; + } else if ( !strcasecmp( p, "rfc822-extended" ) ) { + as->as_syntax = AS_SYNTAX_RFC822_EXT; + } else if ( !strcasecmp( p, "dn" ) ) { + as->as_syntax = AS_SYNTAX_DN; + } else if ( !strcasecmp( p, "url" ) ) { + as->as_syntax = AS_SYNTAX_URL; + } else if ( !strcasecmp( p, "search-with-filter" ) ) { + as->as_syntax = AS_SYNTAX_BOOL_FILTER; + } else if ( !strncasecmp( p, "param=", 6 ) ) { + q = strchr( p, '=' ); + if ( q ) { + p = q + 1; + while ( *q && !isspace( *q ) ) { + q++; + } + if ( *q ) { + *q = '\0'; + as->as_param = strdup( p ); + p = q + 1; + } else { + as->as_param = strdup( p ); + p = q; + } + } + } else if ( !strcasecmp( p, "host" ) ) { + as->as_kind = AS_SYNTAX_HOST; + } else if ( !strcasecmp( p, "present" ) ) { + as->as_kind = AS_SYNTAX_PRESENT; + } else if ( !strcasecmp( p, "route-to-host" ) ) { + as->as_kind = AS_KIND_ROUTE_TO_HOST; + } else if ( !strcasecmp( p, "route-to-address" ) ) { + as->as_kind = AS_KIND_ROUTE_TO_ADDR; + } else if ( !strcasecmp( p, "own-address" ) ) { + as->as_kind = AS_KIND_OWN_ADDR; + } else if ( !strcasecmp( p, "recipient" ) ) { + as->as_kind = AS_KIND_RECIPIENT; + } else if ( !strcasecmp( p, "errors" ) ) { + as->as_kind = AS_KIND_ERRORS; + } else if ( !strcasecmp( p, "request" ) ) { + as->as_kind = AS_KIND_REQUEST; + } else if ( !strcasecmp( p, "owner" ) ) { + as->as_kind = AS_KIND_OWNER; + } else if ( !strcasecmp( p, "delivery-type" ) ) { + as->as_kind = AS_KIND_DELIVERY_TYPE; + } else { + syslog( LOG_ALERT, + "Unknown semantics word %s", p ); + exit( EX_TEMPFAIL ); + } + p = q + 1; + } + if ( attr_semantics == NULL ) { + attr_semantics = calloc(2, sizeof(AttrSemantics *)); + if ( !attr_semantics ) { + syslog( LOG_ALERT, "Out of memory" ); + exit( EX_TEMPFAIL ); + } + attr_semantics[0] = as; + } else { + int size; + AttrSemantics **list_temp; + for ( size = 0; attr_semantics[size]; size++ ) + ; + size += 2; + list_temp = realloc( attr_semantics, + size*sizeof(AttrSemantics *) ); + if ( !list_temp ) { + syslog( LOG_ALERT, "Out of memory" ); + exit( EX_TEMPFAIL ); + } + attr_semantics = list_temp; + attr_semantics[size-2] = as; + attr_semantics[size-1] = NULL; + } +} + +static void +load_config( char *filespec ) +{ + FILE *cf; + char *line; + int lineno = 0; + char *p; + int rdnpref; + int typemask; + + cf = fopen( filespec, "r" ); + if ( !cf ) { + perror( "Opening config file" ); + exit( EX_TEMPFAIL ); + } + + while ( ( line = get_config_line( cf,&lineno ) ) ) { + p = strpbrk( line, " \t" ); + if ( !p ) { + syslog( LOG_ALERT, + "Missing space at line %d", lineno ); + exit( EX_TEMPFAIL ); + } + if ( !strncmp( line, "search", p-line ) ) { + p += strspn( p, " \t" ); + /* TBC, get these */ + rdnpref = 0; + typemask = 0xFF; + add_url( p, rdnpref, typemask ); + } else if ( !strncmp(line, "attribute", p-line) ) { + p += strspn(p, " \t"); + add_attr_semantics( p ); + } else if ( !strncmp(line, "default-attributes", p-line) ) { + p += strspn(p, " \t"); + add_def_attr( p ); + } else if ( !strncmp(line, "group-classes", p-line) ) { + p += strspn(p, " \t"); + add_single_to( &groupclasses, p ); + } else if ( !strncmp(line, "priority", p-line) ) { + p += strspn(p, " \t"); + current_priority = atoi(p); + } else if ( !strncmp(line, "domain", p-line) ) { + p += strspn(p, " \t"); + add_single_to( &mydomains, p ); + } else if ( !strncmp(line, "host", p-line) ) { + p += strspn(p, " \t"); + add_single_to( &myhosts, p ); + } else { + syslog( LOG_ALERT, + "Unparseable config definition at line %d", + lineno ); + exit( EX_TEMPFAIL ); + } + } + fclose( cf ); +} + +static int +connect_to_x500( void ) +{ + int opt; + + if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) { + syslog( LOG_ALERT, "ldap_init failed" ); + return( -1 ); + } + + /* TBC: Set this only when it makes sense + opt = MAIL500_MAXAMBIGUOUS; + ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &opt); + */ + opt = LDAP_DEREF_ALWAYS; + ldap_set_option(ld, LDAP_OPT_DEREF, &opt); + + if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { + syslog( LOG_ALERT, "ldap_simple_bind_s failed" ); + return( -1 ); + } + + return( 0 ); +} + +static Group * +new_group( char *dn, Group ***list, int *nlist ) +{ + int i; + Group *this_group; + + for ( i = 0; i < *nlist; i++ ) { + if ( strcmp( dn, (*list)[i]->g_dn ) == 0 ) { + syslog( LOG_ALERT, "group loop 2 detected (%s)", dn ); + return NULL; + } + } + + this_group = (Group *) malloc( sizeof(Group) ); + + if ( *nlist == 0 ) { + *list = (Group **) malloc( sizeof(Group *) ); + } else { + *list = (Group **) realloc( *list, (*nlist + 1) * + sizeof(Group *) ); + } + + this_group->g_errorsto = NULL; + this_group->g_members = NULL; + this_group->g_nmembers = 0; + /* save the group's dn so we can check for loops above */ + this_group->g_dn = strdup( dn ); + + (*list)[*nlist] = this_group; + (*nlist)++; + + return( this_group ); +} + +static void +split_address( + char *address, + char **localpart, + char **domainpart +) +{ + char *p; + + if ( ( p = strrchr( address, '@' ) ) == NULL ) { + *localpart = strdup( address ); + *domainpart = NULL; + } else { + *localpart = malloc( p - address + 1 ); + strncpy( *localpart, address, p - address ); + (*localpart)[p - address] = '\0'; + p++; + *domainpart = strdup( p ); + } +} + +static int +dn_search( + char **dnlist, + char *address, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr +) +{ + int rc; + int i; + int resolved = 0; + LDAPMessage *res, *e; + struct timeval timeout; + + timeout.tv_sec = MAIL500_TIMEOUT; + timeout.tv_usec = 0; + for ( i = 0; dnlist[i]; i++ ) { + if ( (rc = ldap_search_st( ld, dnlist[i], LDAP_SCOPE_BASE, + NULL, def_attr, 0, + &timeout, &res )) != LDAP_SUCCESS ) { + if ( rc == LDAP_NO_SUCH_OBJECT ) { + add_error( err, nerr, E_BADMEMBER, dnlist[i], NULL ); + continue; + } else { + syslog( LOG_ALERT, "member search return 0x%x", rc ); + + unbind_and_exit( EX_TEMPFAIL ); + } + } else { + if ( (e = ldap_first_entry( ld, res )) == NULL ) { + syslog( LOG_ALERT, "member search error parsing entry" ); + unbind_and_exit( EX_TEMPFAIL ); + } + if ( entry_engine( e, dnlist[i], address, to, nto, + togroups, ngroups, err, nerr, + USER | GROUP_MEMBERS ) ) { + resolved = 1; + } + } + } + return( resolved ); +} + +static int +search_ldap_url( + char *url, + Subst *substs, + char *address, + int rdnpref, + int multi_entry, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + LDAPURLDesc *ludp; + char *p, *s, *d; + int i; + char filter[1024]; + LDAPMessage *e, *res; + int rc; + char **attrlist; + struct timeval timeout; + int match; + int resolved = 0; + char *dn; + + timeout.tv_sec = MAIL500_TIMEOUT; + timeout.tv_usec = 0; + + rc = ldap_url_parse( url, &ludp ); + if ( rc ) { + switch ( rc ) { + case LDAP_URL_ERR_BADSCHEME: + syslog( LOG_ALERT, + "Not an LDAP URL: %s", url ); + break; + case LDAP_URL_ERR_BADENCLOSURE: + syslog( LOG_ALERT, + "Bad Enclosure in URL: %s", url ); + break; + case LDAP_URL_ERR_BADURL: + syslog( LOG_ALERT, + "Bad URL: %s", url ); + break; + case LDAP_URL_ERR_BADHOST: + syslog( LOG_ALERT, + "Host is invalid in URL: %s", url ); + break; + case LDAP_URL_ERR_BADATTRS: + syslog( LOG_ALERT, + "Attributes are invalid in URL: %s", url ); + break; + case LDAP_URL_ERR_BADSCOPE: + syslog( LOG_ALERT, + "Scope is invalid in URL: %s", url ); + break; + case LDAP_URL_ERR_BADFILTER: + syslog( LOG_ALERT, + "Filter is invalid in URL: %s", url ); + break; + case LDAP_URL_ERR_BADEXTS: + syslog( LOG_ALERT, + "Extensions are invalid in URL: %s", url ); + break; + case LDAP_URL_ERR_MEM: + syslog( LOG_ALERT, + "Out of memory parsing URL: %s", url ); + break; + case LDAP_URL_ERR_PARAM: + syslog( LOG_ALERT, + "bad parameter parsing URL: %s", url ); + break; + default: + syslog( LOG_ALERT, + "Unknown error %d parsing URL: %s", + rc, url ); + break; + } + add_error( err, nerr, E_BADMEMBER, + url, NULL ); + return 0; + } + + if ( substs ) { + for ( s = ludp->lud_filter, d = filter; *s; s++,d++ ) { + if ( *s == '%' ) { + s++; + if ( *s == '%' ) { + *d = '%'; + continue; + } + for ( i = 0; substs[i].sub_char != '\0'; + i++ ) { + if ( *s == substs[i].sub_char ) { + for ( p = substs[i].sub_value; + *p; p++,d++ ) { + *d = *p; + } + d--; + break; + } + } + if ( substs[i].sub_char == '\0' ) { + syslog( LOG_ALERT, + "unknown format %c", *s ); + } + } else { + *d = *s; + } + } + *d = *s; + } else { + strncpy( filter, ludp->lud_filter, sizeof( filter ) - 1 ); + filter[ sizeof( filter ) - 1 ] = '\0'; + } + + if ( ludp->lud_attrs ) { + attrlist = ludp->lud_attrs; + } else { + attrlist = def_attr; + } + res = NULL; + /* TBC: we don't read the host, dammit */ + rc = ldap_search_st( ld, ludp->lud_dn, ludp->lud_scope, + filter, attrlist, 0, + &timeout, &res ); + + /* some other trouble - try again later */ + if ( rc != LDAP_SUCCESS && + rc != LDAP_SIZELIMIT_EXCEEDED ) { + syslog( LOG_ALERT, "return 0x%x from X.500", + rc ); + unbind_and_exit( EX_TEMPFAIL ); + } + + match = ldap_count_entries( ld, res ); + + /* trouble - try again later */ + if ( match == -1 ) { + syslog( LOG_ALERT, "error parsing result from X.500" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + if ( match == 1 || multi_entry ) { + for ( e = ldap_first_entry( ld, res ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + dn = ldap_get_dn( ld, e ); + resolved = entry_engine( e, dn, address, to, nto, + togroups, ngroups, + err, nerr, type ); + if ( !resolved ) { + add_error( err, nerr, E_NOEMAIL, address, res ); + } + } + return ( resolved ); + } + + /* more than one match - bounce with ambiguous user? */ + if ( match > 1 ) { + LDAPMessage *next, *tmpres = NULL; + char *dn; + char **xdn; + + /* not giving rdn preference - bounce with ambiguous user */ + if ( rdnpref == 0 ) { + add_error( err, nerr, E_AMBIGUOUS, address, res ); + return 0; + } + + /* + * giving rdn preference - see if any entries were matched + * because of their rdn. If so, collect them to deal with + * later (== 1 we deliver, > 1 we bounce). + */ + + for ( e = ldap_first_entry( ld, res ); e != NULL; e = next ) { + next = ldap_next_entry( ld, e ); + dn = ldap_get_dn( ld, e ); + xdn = ldap_explode_dn( dn, 1 ); + + /* XXX bad, but how else can we do it? XXX */ + if ( strcasecmp( xdn[0], address ) == 0 ) { + ldap_delete_result_entry( &res, e ); + ldap_add_result_entry( &tmpres, e ); + } + + ldap_value_free( xdn ); + free( dn ); + } + + /* nothing matched by rdn - go ahead and bounce */ + if ( tmpres == NULL ) { + add_error( err, nerr, E_AMBIGUOUS, address, res ); + return 0; + + /* more than one matched by rdn - bounce with rdn matches */ + } else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) { + add_error( err, nerr, E_AMBIGUOUS, address, tmpres ); + return 0; + + /* trouble... */ + } else if ( match < 0 ) { + syslog( LOG_ALERT, "error parsing result from X.500" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + /* otherwise one matched by rdn - send to it */ + ldap_msgfree( res ); + res = tmpres; + + /* trouble */ + if ( (e = ldap_first_entry( ld, res )) == NULL ) { + syslog( LOG_ALERT, "error parsing entry from X.500" ); + unbind_and_exit( EX_TEMPFAIL ); + } + + dn = ldap_get_dn( ld, e ); + + resolved = entry_engine( e, dn, address, to, nto, + togroups, ngroups, + err, nerr, type ); + if ( !resolved ) { + add_error( err, nerr, E_NOEMAIL, address, res ); + /* Don't free res if we passed it to add_error */ + } else { + ldap_msgfree( res ); + } + } + return( resolved ); +} + +static int +url_list_search( + char **urllist, + char *address, + int multi_entry, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + int i; + int resolved = 0; + + for ( i = 0; urllist[i]; i++ ) { + + if ( !strncasecmp( urllist[i], "mail:", 5 ) ) { + char *vals[2]; + + vals[0] = urllist[i] + 5; + vals[1] = NULL; + add_to( to, nto, vals ); + resolved = 1; + + } else if ( ldap_is_ldap_url( urllist[i] ) ) { + + resolved = search_ldap_url( urllist[i], NULL, + address, 0, multi_entry, + to, nto, togroups, ngroups, + err, nerr, type ); + } else { + /* Produce some sensible error here */ + resolved = 0; + } + } + return( resolved ); +} + +/* + * We should probably take MX records into account to cover all bases, + * but really, routing belongs in the MTA. + */ +static int +is_my_host( + char * host +) +{ + char **d; + + if ( myhosts == NULL ) + return 0; + for ( d = myhosts; *d; d++ ) { + if ( !strcasecmp(*d,host) ) { + return 1; + } + } + return 0; +} + +static int +is_my_domain( + char * address +) +{ + char **d; + char *p; + + if ( mydomains == NULL ) + return 0; + p = strchr( address, '@' ); + if ( p == NULL) + return 0; + for ( d = mydomains; *d; d++ ) { + if ( !strcasecmp(*d,p+1) ) { + return 1; + } + } + return 0; +} + +static void +do_addresses( + char **addresses, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + int i, j; + int n; + + /* + * Well, this is tricky, every address in my_addresses will be + * removed from the list while we shift the other values down + * and we do it in a single scan of the address list and + * without using additional memory. We are going to be + * modifying the value list in a way that the later + * ldap_value_free works. + */ + j = 0; + for ( i = 0; addresses[i]; i++ ) { + if ( is_my_domain(addresses[i]) ) { + do_address( addresses[i], to, nto, togroups, ngroups, + err, nerr, type ); + ldap_memfree( addresses[i] ); + } else { + if ( j < i ) { + addresses[j] = addresses[i]; + } + j++; + } + } + addresses[j] = NULL; + if ( addresses[0] ) { + add_to( to, nto, addresses ); + } +} + +/* + * The entry engine processes an entry. Normally, each entry will resolve + * to one or more values that will be added to the 'to' argument. This + * argument needs not be the global 'to' list, it may be the g_to field + * in a group. Groups have no special treatment, unless they require + * a special sender. + */ + +static int +entry_engine( + LDAPMessage *e, + char *dn, + char *address, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + char **vals; + int i; + int resolved = 0; + char ***current_to = to; + int *current_nto = nto; + Group *current_group = NULL; + char buf[1024]; + char *localpart = NULL, *domainpart = NULL; + Subst substs[2]; + int cur_priority = 0; + char *route_to_host = NULL; + char *route_to_address = NULL; + int needs_mta_routing = 0; + char **own_addresses = NULL; + int own_addresses_total = 0; + char **delivery_types = NULL; + int delivery_types_total = 0; + char *nvals[2]; + + for ( i=0; attr_semantics[i] != NULL; i++ ) { + AttrSemantics *as = attr_semantics[i]; + int nent; + int j; + + if ( as->as_priority < cur_priority ) { + /* + * We already got higher priority information, + * so no further work to do, ignore the rest. + */ + break; + } + vals = ldap_get_values( ld, e, as->as_name ); + if ( !vals || vals[0] == NULL ) { + continue; + } + nent = count_values( vals ); + if ( nent > 1 && !as->as_m_valued ) { + add_error( err, nerr, E_AMBIGUOUS, address, e ); + return( 0 ); + } + switch ( as->as_kind ) { + case AS_KIND_RECIPIENT: + cur_priority = as->as_priority; + if ( ! ( type & ( USER | GROUP_MEMBERS ) ) ) + break; + switch ( as->as_syntax ) { + case AS_SYNTAX_RFC822: + do_addresses( vals, current_to, current_nto, + togroups, ngroups, err, nerr, + USER ); + resolved = 1; + break; + case AS_SYNTAX_RFC822_EXT: + do_addresses( vals, current_to, current_nto, + togroups, ngroups, err, nerr, + USER ); + resolved = 1; + break; + case AS_SYNTAX_NATIVE_MB: + /* We used to concatenate mailHost if set here */ + /* + * We used to send a copy to the vacation host + * if onVacation to uid@vacationhost + */ + if ( as->as_param ) { + for ( j=0; jas_param, delivery_types[j] ) ) { + add_to( current_to, current_nto, vals ); + resolved = 1; + break; + } + } + } else { + add_to( current_to, current_nto, vals ); + resolved = 1; + } + break; + + case AS_SYNTAX_DN: + if ( dn_search( vals, address, + current_to, current_nto, + togroups, ngroups, + err, nerr ) ) { + resolved = 1; + } + break; + + case AS_SYNTAX_URL: + if ( url_list_search( vals, address, + as->as_m_entries, + current_to, current_nto, + togroups, ngroups, + err, nerr, type ) ) { + resolved = 1; + } + break; + + case AS_SYNTAX_BOOL_FILTER: + if ( strcasecmp( vals[0], "true" ) ) { + break; + } + substs[0].sub_char = 'D'; + substs[0].sub_value = dn; + substs[1].sub_char = '\0'; + substs[1].sub_value = NULL; + if ( url_list_search( vals, address, + as->as_m_entries, + current_to, current_nto, + togroups, ngroups, + err, nerr, type ) ) { + resolved = 1; + } + break; + + default: + syslog( LOG_ALERT, + "Invalid syntax %d for kind %d", + as->as_syntax, as->as_kind ); + break; + } + break; + + case AS_KIND_ERRORS: + cur_priority = as->as_priority; + /* This is a group with special processing */ + if ( type & GROUP_ERRORS ) { + switch (as->as_kind) { + case AS_SYNTAX_RFC822: + add_to( current_to, current_nto, vals ); + resolved = 1; + break; + case AS_SYNTAX_URL: + default: + syslog( LOG_ALERT, + "Invalid syntax %d for kind %d", + as->as_syntax, as->as_kind ); + } + } else { + current_group = new_group( dn, togroups, + ngroups ); + current_to = ¤t_group->g_members; + current_nto = ¤t_group->g_nmembers; + split_address( address, + &localpart, &domainpart ); + if ( domainpart ) { + sprintf( buf, "%s-%s@%s", + localpart, ERRORS, + domainpart ); + free( localpart ); + free( domainpart ); + } else { + sprintf( buf, "%s-%s@%s", + localpart, ERRORS, + host ); + free( localpart ); + } + current_group->g_errorsto = strdup( buf ); + } + break; + + case AS_KIND_REQUEST: + cur_priority = as->as_priority; + /* This is a group with special processing */ + if ( type & GROUP_REQUEST ) { + add_to( current_to, current_nto, vals ); + resolved = 1; + } + break; + + case AS_KIND_OWNER: + cur_priority = as->as_priority; + /* This is a group with special processing */ + if ( type & GROUP_REQUEST ) { + add_to( current_to, current_nto, vals ); + resolved = 1; + } + break; + + case AS_KIND_ROUTE_TO_HOST: + if ( !is_my_host( vals[0] ) ) { + cur_priority = as->as_priority; + if ( as->as_syntax == AS_SYNTAX_PRESENT ) { + needs_mta_routing = 1; + } else { + route_to_host = strdup( vals[0] ); + } + } + break; + + case AS_KIND_ROUTE_TO_ADDR: + for ( j=0; jas_priority; + if ( as->as_syntax == AS_SYNTAX_PRESENT ) { + needs_mta_routing = 1; + } else { + route_to_address = strdup( vals[0] ); + } + } + break; + } + + case AS_KIND_OWN_ADDR: + add_to( &own_addresses, &own_addresses_total, vals ); + cur_priority = as->as_priority; + break; + + case AS_KIND_DELIVERY_TYPE: + add_to( &delivery_types, &delivery_types_total, vals ); + cur_priority = as->as_priority; + break; + + default: + syslog( LOG_ALERT, + "Invalid kind %d", as->as_kind ); + /* Error, TBC */ + } + ldap_value_free( vals ); + } + /* + * Now check if we are dealing with mail routing. We support + * two modes. + * + * The first mode and by far the most robust method is doing + * routing at the MTA. In this case, we just checked if the + * routing attributes were present and did not seem like + * pointing to ourselves. The only thing we have to do here + * is adding to the recipient list any of the RFC822 addresses + * of this entry. That means we needed to retrieve them from + * the entry itself because we might have arrived here through + * some directory search. The address received as argument is + * not the address of the entry we are processing, but rather + * the RFC822 address we are expanding now. Unfortunately, + * this requires an MTA that understands LDAP routing. + * Sendmail 8.10.0 does, if compiled properly. + * + * The second method, that is most emphatically not recommended + * is routing in maildap. This is going to require using the + * percent hack. Moreover, this may occasionally loop. + */ + if ( needs_mta_routing ) { + if ( !own_addresses ) { + add_error( err, nerr, E_NOOWNADDRESS, address, e ); + return( 0 ); + } + nvals[0] = own_addresses[0]; /* Anyone will do */ + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + } else if ( route_to_host ) { + char *p; + if ( !route_to_address ) { + if ( !own_addresses ) { + add_error( err, nerr, E_NOOWNADDRESS, address, e ); + return( 0 ); + } + route_to_address = strdup( own_addresses[0] ); + } + /* This makes use of the percent hack, but there's no choice */ + p = strchr( route_to_address, '@' ); + if ( p ) { + *p = '%'; + } + sprintf( buf, "%s@%s", route_to_address, route_to_host ); + nvals[0] = buf; + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + free( route_to_host ); + free( route_to_address ); + } else if ( route_to_address ) { + nvals[0] = route_to_address; + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + free( route_to_address ); + } + if ( own_addresses ) { + ldap_value_free( own_addresses ); + } + if ( delivery_types ) { + ldap_value_free( delivery_types ); + } + + return( resolved ); +} + +static int +search_bases( + char *filter, + Subst *substs, + char *name, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + int b, resolved = 0; + + for ( b = 0; base[b] != NULL; b++ ) { + + if ( ! (base[b]->b_search & type) ) { + continue; + } + + resolved = search_ldap_url( base[b]->b_url, substs, name, + base[b]->b_rdnpref, + base[b]->b_m_entries, + to, nto, togroups, ngroups, + err, nerr, type ); + if ( resolved ) + break; + } + return( resolved ); +} + +static void +do_address( + char *name, + char ***to, + int *nto, + Group ***togroups, + int *ngroups, + Error **err, + int *nerr, + int type +) +{ + char *localpart = NULL, *domainpart = NULL; + char *synthname = NULL; + int resolved; + int i; + Subst substs[6]; + + /* + * Look up the name in X.500, add the appropriate addresses found + * to the to list, or to the err list in case of error. Groups are + * handled by the do_group routine, individuals are handled here. + * When looking up name, we follow the bases hierarchy, looking + * in base[0] first, then base[1], etc. For each base, there is + * a set of search filters to try, in order. If something goes + * wrong here trying to contact X.500, we exit with EX_TEMPFAIL. + * If the b_rdnpref flag is set, then we give preference to entries + * that matched name because it's their rdn, otherwise not. + */ + + split_address( name, &localpart, &domainpart ); + synthname = strdup( localpart ); + for ( i = 0; synthname[i] != '\0'; i++ ) { + if ( synthname[i] == '.' || synthname[i] == '_' ) + synthname[i] = ' '; + } + substs[0].sub_char = 'm'; + substs[0].sub_value = name; + substs[1].sub_char = 'h'; + substs[1].sub_value = host; + substs[2].sub_char = 'l'; + substs[2].sub_value = localpart; + substs[3].sub_char = 'd'; + substs[3].sub_value = domainpart; + substs[4].sub_char = 's'; + substs[4].sub_value = synthname; + substs[5].sub_char = '\0'; + substs[5].sub_value = NULL; + + resolved = search_bases( NULL, substs, name, + to, nto, togroups, ngroups, + err, nerr, type ); + + if ( localpart ) { + free( localpart ); + } + if ( domainpart ) { + free( domainpart ); + } + if ( synthname ) { + free( synthname ); + } + + if ( !resolved ) { + /* not resolved - bounce with user unknown */ + if ( type == USER ) { + add_error( err, nerr, E_USERUNKNOWN, name, NULL ); + } else { + add_error( err, nerr, E_GROUPUNKNOWN, name, NULL ); + } + } +} + +static void +send_message( char **to ) +{ + int pid; +#ifndef HAVE_WAITPID + WAITSTATUSTYPE status; +#endif + + if ( debug ) { + char buf[1024]; + int i; + + strcpy( buf, to[0] ); + for ( i = 1; to[i] != NULL; i++ ) { + strcat( buf, " " ); + strcat( buf, to[i] ); + } + + syslog( LOG_ALERT, "send_message execing sendmail: (%s)", buf ); + } + + /* parent */ + if ( (pid = fork()) != 0 ) { +#ifdef HAVE_WAITPID + waitpid( pid, (int *) NULL, 0 ); +#else + wait4( pid, &status, WAIT_FLAGS, 0 ); +#endif + /* child */ + } else { + /* to includes sendmailargs */ + execv( MAIL500_SENDMAIL, to ); + + syslog( LOG_ALERT, "execv failed" ); + + exit( EX_TEMPFAIL ); + } +} + +static void +send_group( Group **group, int ngroup ) +{ + int i, pid; + char **argv; + int argc; + char *iargv[7]; +#ifndef HAVE_WAITPID + WAITSTATUSTYPE status; +#endif + + for ( i = 0; i < ngroup; i++ ) { + (void) rewind( stdin ); + + iargv[0] = MAIL500_SENDMAIL; + iargv[1] = "-f"; + iargv[2] = group[i]->g_errorsto; + iargv[3] = "-oMrX.500"; + iargv[4] = "-odi"; + iargv[5] = "-oi"; + iargv[6] = NULL; + + argv = NULL; + argc = 0; + add_to( &argv, &argc, iargv ); + add_to( &argv, &argc, group[i]->g_members ); + + if ( debug ) { + char buf[1024]; + int i; + + strcpy( buf, argv[0] ); + for ( i = 1; i < argc; i++ ) { + strcat( buf, " " ); + strcat( buf, argv[i] ); + } + + syslog( LOG_ALERT, "execing sendmail: (%s)", buf ); + } + + /* parent */ + if ( (pid = fork()) != 0 ) { +#ifdef HAVE_WAITPID + waitpid( pid, (int *) NULL, 0 ); +#else + wait4( pid, &status, WAIT_FLAGS, 0 ); +#endif + /* child */ + } else { + execv( MAIL500_SENDMAIL, argv ); + + syslog( LOG_ALERT, "execv failed" ); + + exit( EX_TEMPFAIL ); + } + } +} + +static void +send_errors( Error *err, int nerr ) +{ + int pid, i, namelen; + FILE *fp; + int fd[2]; + char *argv[8]; + char buf[1024]; +#ifndef HAVE_WAITPID + WAITSTATUSTYPE status; +#endif + + if ( strcmp( MAIL500_BOUNCEFROM, mailfrom ) == 0 ) { + mailfrom = errorsfrom; + } + + argv[0] = MAIL500_SENDMAIL; + argv[1] = "-oMrX.500"; + argv[2] = "-odi"; + argv[3] = "-oi"; + argv[4] = "-f"; + argv[5] = MAIL500_BOUNCEFROM; + argv[6] = mailfrom; + argv[7] = NULL; + + if ( debug ) { + int i; + + strcpy( buf, argv[0] ); + for ( i = 1; argv[i] != NULL; i++ ) { + strcat( buf, " " ); + strcat( buf, argv[i] ); + } + + syslog( LOG_ALERT, "execing sendmail: (%s)", buf ); + } + + if ( pipe( fd ) == -1 ) { + syslog( LOG_ALERT, "cannot create pipe" ); + exit( EX_TEMPFAIL ); + } + + if ( (pid = fork()) != 0 ) { + if ( (fp = fdopen( fd[1], "w" )) == NULL ) { + syslog( LOG_ALERT, "cannot fdopen pipe" ); + exit( EX_TEMPFAIL ); + } + + fprintf( fp, "To: %s\n", mailfrom ); + fprintf( fp, "From: %s\n", errorsfrom ); + fprintf( fp, "Subject: undeliverable mail\n" ); + fprintf( fp, "\n" ); + fprintf( fp, "The following errors occurred when trying to deliver the attached mail:\n" ); + for ( i = 0; i < nerr; i++ ) { + namelen = strlen( err[i].e_addr ); + fprintf( fp, "\n" ); + + switch ( err[i].e_code ) { + case E_USERUNKNOWN: + fprintf( fp, "%s: User unknown\n", err[i].e_addr ); + break; + + case E_GROUPUNKNOWN: + fprintf( fp, "%s: Group unknown\n", err[i].e_addr ); + break; + + case E_BADMEMBER: + fprintf( fp, "%s: Group member does not exist\n", + err[i].e_addr ); + fprintf( fp, "This could be because the distinguished name of the person has changed\n" ); + fprintf( fp, "If this is the case, the problem can be solved by removing and\n" ); + fprintf( fp, "then re-adding the person to the group.\n" ); + break; + + case E_NOREQUEST: + fprintf( fp, "%s: Group exists but has no request address\n", + err[i].e_addr ); + break; + + case E_NOERRORS: + fprintf( fp, "%s: Group exists but has no errors-to address\n", + err[i].e_addr ); + break; + + case E_NOOWNER: + fprintf( fp, "%s: Group exists but has no owner\n", + err[i].e_addr ); + break; + + case E_AMBIGUOUS: + do_ambiguous( fp, &err[i], namelen ); + break; + + case E_NOEMAIL: + do_noemail( fp, &err[i], namelen ); + break; + + case E_MEMBERNOEMAIL: + fprintf( fp, "%s: Group member exists but does not have an email address\n", + err[i].e_addr ); + break; + + case E_JOINMEMBERNOEMAIL: + fprintf( fp, "%s: User has joined group but does not have an email address\n", + err[i].e_addr ); + break; + + case E_LOOP: + fprintf( fp, "%s: User has created a mail loop by adding address %s to their X.500 entry\n", + err[i].e_addr, err[i].e_loop ); + break; + + case E_NOMEMBERS: + fprintf( fp, "%s: Group has no members\n", + err[i].e_addr ); + break; + + case E_NOOWNADDRESS: + fprintf( fp, "%s: Not enough information to perform required routing\n", + err[i].e_addr ); + break; + + default: + syslog( LOG_ALERT, "unknown error %d", err[i].e_code ); + unbind_and_exit( EX_TEMPFAIL ); + break; + } + } + + fprintf( fp, "\n------- The original message sent:\n\n" ); + + while ( fgets( buf, sizeof(buf), stdin ) != NULL ) { + fputs( buf, fp ); + } + fclose( fp ); + +#ifdef HAVE_WAITPID + waitpid( pid, (int *) NULL, 0 ); +#else + wait4( pid, &status, WAIT_FLAGS, 0 ); +#endif + } else { + dup2( fd[0], 0 ); + + execv( MAIL500_SENDMAIL, argv ); + + syslog( LOG_ALERT, "execv failed" ); + + exit( EX_TEMPFAIL ); + } +} + +static void +do_noemail( FILE *fp, Error *err, int namelen ) +{ + int i, last; + char *dn, *rdn; + char **ufn, **vals; + + fprintf(fp, "%s: User has no email address registered.\n", + err->e_addr ); + fprintf( fp, "%*s Name, title, postal address and phone for '%s':\n\n", + namelen, " ", err->e_addr ); + + /* name */ + dn = ldap_get_dn( ld, err->e_msg ); + ufn = ldap_explode_dn( dn, 1 ); + rdn = strdup( ufn[0] ); + if ( strcasecmp( rdn, err->e_addr ) == 0 ) { + if ( (vals = ldap_get_values( ld, err->e_msg, "cn" )) + != NULL ) { + for ( i = 0; vals[i]; i++ ) { + last = strlen( vals[i] ) - 1; + if ( isdigit((unsigned char) vals[i][last]) ) { + rdn = strdup( vals[i] ); + break; + } + } + + ldap_value_free( vals ); + } + } + fprintf( fp, "%*s %s\n", namelen, " ", rdn ); + free( dn ); + free( rdn ); + ldap_value_free( ufn ); + + /* titles or descriptions */ + if ( (vals = ldap_get_values( ld, err->e_msg, "title" )) == NULL && + (vals = ldap_get_values( ld, err->e_msg, "description" )) + == NULL ) { + fprintf( fp, "%*s No title or description registered\n", + namelen, " " ); + } else { + for ( i = 0; vals[i] != NULL; i++ ) { + fprintf( fp, "%*s %s\n", namelen, " ", vals[i] ); + } + + ldap_value_free( vals ); + } + + /* postal address */ + if ( (vals = ldap_get_values( ld, err->e_msg, "postalAddress" )) + == NULL ) { + fprintf( fp, "%*s No postal address registered\n", namelen, + " " ); + } else { + fprintf( fp, "%*s ", namelen, " " ); + for ( i = 0; vals[0][i] != '\0'; i++ ) { + if ( vals[0][i] == '$' ) { + fprintf( fp, "\n%*s ", namelen, " " ); + while ( isspace((unsigned char) vals[0][i+1]) ) + i++; + } else { + fprintf( fp, "%c", vals[0][i] ); + } + } + fprintf( fp, "\n" ); + + ldap_value_free( vals ); + } + + /* telephone number */ + if ( (vals = ldap_get_values( ld, err->e_msg, "telephoneNumber" )) + == NULL ) { + fprintf( fp, "%*s No phone number registered\n", namelen, + " " ); + } else { + for ( i = 0; vals[i] != NULL; i++ ) { + fprintf( fp, "%*s %s\n", namelen, " ", vals[i] ); + } + + ldap_value_free( vals ); + } +} + +/* ARGSUSED */ +static void +do_ambiguous( FILE *fp, Error *err, int namelen ) +{ + int i, last; + char *dn, *rdn; + char **ufn, **vals; + LDAPMessage *e; + + i = ldap_result2error( ld, err->e_msg, 0 ); + + fprintf( fp, "%s: Ambiguous user. %s%d matches found:\n\n", + err->e_addr, i == LDAP_SIZELIMIT_EXCEEDED ? "First " : "", + ldap_count_entries( ld, err->e_msg ) ); + + for ( e = ldap_first_entry( ld, err->e_msg ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + dn = ldap_get_dn( ld, e ); + ufn = ldap_explode_dn( dn, 1 ); + rdn = strdup( ufn[0] ); + if ( strcasecmp( rdn, err->e_addr ) == 0 ) { + if ( (vals = ldap_get_values( ld, e, "cn" )) != NULL ) { + for ( i = 0; vals[i]; i++ ) { + last = strlen( vals[i] ) - 1; + if (isdigit((unsigned char) vals[i][last])) { + rdn = strdup( vals[i] ); + break; + } + } + + ldap_value_free( vals ); + } + } + + /* + if ( isgroup( e ) ) { + vals = ldap_get_values( ld, e, "description" ); + } else { + vals = ldap_get_values( ld, e, "title" ); + } + */ + vals = ldap_get_values( ld, e, "description" ); + + fprintf( fp, " %-20s %s\n", rdn, vals ? vals[0] : "" ); + for ( i = 1; vals && vals[i] != NULL; i++ ) { + fprintf( fp, " %s\n", vals[i] ); + } + + free( dn ); + free( rdn ); + ldap_value_free( ufn ); + if ( vals != NULL ) + ldap_value_free( vals ); + } +} + +static int +count_values( char **list ) +{ + int i; + + for ( i = 0; list && list[i] != NULL; i++ ) + ; /* NULL */ + + return( i ); +} + +static void +add_to( char ***list, int *nlist, char **new ) +{ + int i, nnew, oldnlist; + + nnew = count_values( new ); + + oldnlist = *nlist; + if ( *list == NULL || *nlist == 0 ) { + *list = (char **) malloc( (nnew + 1) * sizeof(char *) ); + *nlist = nnew; + } else { + *list = (char **) realloc( *list, *nlist * sizeof(char *) + + nnew * sizeof(char *) + sizeof(char *) ); + *nlist += nnew; + } + + for ( i = 0; i < nnew; i++ ) + (*list)[i + oldnlist] = strdup( new[i] ); + (*list)[*nlist] = NULL; +} + +static void +add_single_to( char ***list, char *new ) +{ + int nlist; + + if ( *list == NULL ) { + nlist = 0; + *list = (char **) malloc( 2 * sizeof(char *) ); + } else { + nlist = count_values( *list ); + *list = (char **) realloc( *list, + ( nlist + 2 ) * sizeof(char *) ); + } + + (*list)[nlist] = strdup( new ); + (*list)[nlist+1] = NULL; +} + +static int +isgroup( LDAPMessage *e ) +{ + int i, j; + char **oclist; + + if ( !groupclasses ) { + return( 0 ); + } + + oclist = ldap_get_values( ld, e, "objectClass" ); + + for ( i = 0; oclist[i] != NULL; i++ ) { + for ( j = 0; groupclasses[j] != NULL; j++ ) { + if ( strcasecmp( oclist[i], groupclasses[j] ) == 0 ) { + ldap_value_free( oclist ); + return( 1 ); + } + } + } + ldap_value_free( oclist ); + + return( 0 ); +} + +static void +add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg ) +{ + if ( *nerr == 0 ) { + *err = (Error *) malloc( sizeof(Error) ); + } else { + *err = (Error *) realloc( *err, (*nerr + 1) * sizeof(Error) ); + } + + (*err)[*nerr].e_code = code; + (*err)[*nerr].e_addr = strdup( addr ); + (*err)[*nerr].e_msg = msg; + (*nerr)++; +} + +static void +unbind_and_exit( int rc ) +{ + int i; + + if ( (i = ldap_unbind( ld )) != LDAP_SUCCESS ) + syslog( LOG_ALERT, "ldap_unbind failed %d\n", i ); + + exit( rc ); +} diff --git a/clients/rcpt500/Makefile.in b/clients/rcpt500/Makefile.in index 5af6536f91..f0e60b5c0e 100644 --- a/clients/rcpt500/Makefile.in +++ b/clients/rcpt500/Makefile.in @@ -1,6 +1,8 @@ # $OpenLDAP$ -PROGRAMS= rcpt500 +UNIX_PRGS = rcpt500 +PROGRAMS = $(@PLAT@_PRGS) + SRCS= main.c cmds.c help.c query.c XSRCS= version.c OBJS= main.o cmds.o help.o query.o @@ -20,7 +22,13 @@ version.c: ${OBJS} $(LDAP_LIBDEPEND) $(MKVERSION) rcpt500 > $@ install-local: $(PROGRAMS) rcpt500.help FORCE - -$(MKDIR) $(libexecdir) $(datadir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 rcpt500 $(libexecdir) - -$(MV) $(datadir)/rcpt500.help $(datadir)/rcpt500.help- - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/rcpt500.help $(datadir) + -$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(libexecdir); \ + done \ + ) + -$(MV) $(DESTDIR)$(datadir)/rcpt500.help $(DESTDIR)$(datadir)/rcpt500.help- + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/rcpt500.help $(DESTDIR)$(datadir) + diff --git a/clients/rcpt500/cmds.c b/clients/rcpt500/cmds.c index 8e33658a33..d3729ec3f2 100644 --- a/clients/rcpt500/cmds.c +++ b/clients/rcpt500/cmds.c @@ -12,7 +12,7 @@ #include #include "rcpt500.h" -struct command cmds[] = { +struct command rcpt_cmds[] = { "help", help_cmd, /* help must be the first command */ "query for", query_cmd, /* must come before "query for" */ "query", query_cmd, diff --git a/clients/rcpt500/main.c b/clients/rcpt500/main.c index afabd89322..f970476a5e 100644 --- a/clients/rcpt500/main.c +++ b/clients/rcpt500/main.c @@ -126,7 +126,7 @@ main( int argc, char **argv ) */ #ifdef LOG_DAEMON openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON ); -#else +#elif LOG_DEBUG openlog( prog, OPENLOG_OPTIONS ); #endif } @@ -141,7 +141,7 @@ main( int argc, char **argv ) if ( dosyslog ) { syslog( LOG_INFO, "processing command \"%s %s\" from %s", ( msg.msg_command < 0 ) ? "Unknown" : - cmds[ msg.msg_command ].cmd_text, + rcpt_cmds[ msg.msg_command ].cmd_text, ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto ); } @@ -151,10 +151,10 @@ main( int argc, char **argv ) /* sprintf( reply, "Your request was interpreted as: %s %s\n\n", - cmds[ msg.msg_command ].cmd_text, msg.msg_arg ); + rcpt_cmds[ msg.msg_command ].cmd_text, msg.msg_arg ); */ - (*cmds[ msg.msg_command ].cmd_handler)( &msg, reply ); + (*rcpt_cmds[ msg.msg_command ].cmd_handler)( &msg, reply ); if ( send_reply( &msg, reply ) < 0 ) { if ( dosyslog ) { @@ -360,10 +360,10 @@ find_command( char *text, char **argp ) } *s = '\0'; - for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) { - if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL - && isspace( (unsigned char) s[ strlen( cmds[ i ].cmd_text ) ] )) { - strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text )); + for ( i = 0; rcpt_cmds[ i ].cmd_text != NULL; ++i ) { + if (( s = strstr( argbuf, rcpt_cmds[ i ].cmd_text )) != NULL + && isspace( (unsigned char) s[ strlen( rcpt_cmds[ i ].cmd_text ) ] )) { + strcpy( argbuf, text + (s - argbuf) + strlen( rcpt_cmds[ i ].cmd_text )); *argp = argbuf; while ( isspace( (unsigned char) **argp )) { ++(*argp); diff --git a/clients/rcpt500/rcpt500.h b/clients/rcpt500/rcpt500.h index 068af6026b..35194c9c4d 100644 --- a/clients/rcpt500/rcpt500.h +++ b/clients/rcpt500/rcpt500.h @@ -41,7 +41,7 @@ int query_cmd LDAP_P((struct msginfo *msgp, char *reply)); */ /* cmds.c */ -extern struct command cmds[]; +extern struct command rcpt_cmds[]; /* main.c */ extern int dosyslog; #ifdef LDAP_CONNECTIONLESS diff --git a/clients/tools/Makefile.in b/clients/tools/Makefile.in index 11acdd9cff..ed54b4de99 100644 --- a/clients/tools/Makefile.in +++ b/clients/tools/Makefile.in @@ -8,7 +8,10 @@ OBJS = ldapsearch.o ldapmodify.o ldapdelete.o ldapmodrdn.o ldappasswd.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries -XLIBS = -lldif -lldap -llber -llutil +NT_DYN_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_DEFS) + +XLIBS = -llutil -lldif -lldap -llber XXLIBS = $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS) XSRCS = ldsversion.c ldmversion.c lddversion.c ldrversion.c ldpversion.c @@ -55,11 +58,13 @@ ldrversion.c: ldapmodrdn.o $(LDAP_LIBDEPEND) $(MKVERSION) ldapmodrdn > $@ install-local: FORCE - -$(MKDIR) $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapsearch $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapmodify $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapdelete $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldapmodrdn $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ldappasswd $(bindir) - $(RM) $(bindir)/ldapadd$(EXEEXT) - $(LN) $(bindir)/ldapmodify$(EXEEXT) $(bindir)/ldapadd$(EXEEXT) + -$(MKDIR) $(DESTDIR)$(bindir) + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(bindir); \ + done \ + ) + $(RM) $(DESTDIR)$(bindir)/ldapadd$(EXEEXT) + $(LN) $(DESTDIR)$(bindir)/ldapmodify$(EXEEXT) $(DESTDIR)$(bindir)/ldapadd$(EXEEXT) + diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index 54778c42c8..6e06b769e3 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -1,7 +1,7 @@ /* ldapdelete.c - simple program to delete an entry using LDAP */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -20,9 +20,18 @@ #include static char *binddn = NULL; -static char *passwd = NULL; +static struct berval passwd = { 0, NULL}; static char *ldaphost = NULL; static int ldapport = 0; +static int prune = 0; +#ifdef HAVE_CYRUS_SASL +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static int sasl_integrity = 0; +static int sasl_privacy = 0; +#endif +static int use_tls = 0; static int not, verbose, contoper; static LDAP *ld; @@ -30,12 +39,51 @@ static int dodelete LDAP_P(( LDAP *ld, char *dn)); +static int deletechildren LDAP_P(( LDAP *ld, + char *dn )); + +static void +usage( const char *s ) +{ + fprintf( stderr, +"Delete entries from an LDAP server\n\n" +"usage: %s [options] [dn]...\n" +" dn: list of DNs to delete. If not given, it will be readed from stdin\n" +" or from the file specified with \"-f file\".\n" +"options:\n" +" -c\t\tcontinuous operation mode (do not stop on errors)\n" +" -d level\tset LDAP debugging level to `level'\n" +" -D binddn\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -f file\t\tdelete DNs listed in `file'\n" +" -h host\t\tLDAP server\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -k\t\tuse Kerberos authentication\n" +" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" +" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" +" -n\t\tshow what would be done but don't actually delete\n" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" +" -r\t\tdelete recursively\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -w passwd\tbind passwd (for simple authentication)\n" +" -W\t\tprompt for bind passwd\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" +, s ); + + exit( EXIT_FAILURE ); +} + + int main( int argc, char **argv ) { - char *usage = "usage: %s [-n] [-v] [-k] [-W] [-M[M]] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n"; - char buf[ 4096 ]; - FILE *fp; + char buf[ 4096 ]; + FILE *fp; int i, rc, authmethod, want_bindpw, version, debug, manageDSAit; not = verbose = contoper = want_bindpw = debug = manageDSAit = 0; @@ -43,23 +91,21 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "WMnvkKch:P:p:D:w:d:f:" )) != EOF ) { + while (( i = getopt( argc, argv, "cD:d:Ef:h:IKkMnP:p:rU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - fprintf( stderr, usage, argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; case 'K': /* kerberos bind, part one only */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - fprintf( stderr, usage, argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -73,7 +119,7 @@ main( int argc, char **argv ) binddn = strdup( optarg ); break; case 'w': /* password */ - passwd = strdup( optarg ); + passwd.bv_val = strdup( optarg ); { char* p; @@ -81,6 +127,7 @@ main( int argc, char **argv ) *p = '*'; } } + passwd.bv_len = strlen( passwd.bv_val ); break; case 'f': /* read DNs from a file */ if (( fp = fopen( optarg, "r" )) == NULL ) { @@ -97,6 +144,9 @@ main( int argc, char **argv ) case 'n': /* print deletes, don't actually do them */ ++not; break; + case 'r': + prune = 1; + break; case 'v': /* verbose mode */ verbose++; break; @@ -118,16 +168,109 @@ main( int argc, char **argv ) break; default: fprintf( stderr, "protocol version should be 2 or 3\n" ); - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); } break; + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); + } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); } } + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION2; + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION3; + } + + if( manageDSAit ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "manage DSA control requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + + if( use_tls ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "Start TLS requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + if ( fp == NULL ) { if ( optind >= argc ) { fp = stdin; @@ -161,19 +304,71 @@ main( int argc, char **argv ) /* don't chase referrals */ ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); - if (want_bindpw) - passwd = getpass("Enter LDAP Password: "); - if (version != -1 && ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS) { fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); - } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + + if (want_bindpw) + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = strlen( passwd.bv_val ); + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" + "%d\n", maxssf); + return( EXIT_FAILURE ); + } + + rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, + passwd.bv_len ? &passwd : NULL, + NULL, NULL ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } if ( manageDSAit ) { int err; @@ -230,8 +425,12 @@ static int dodelete( if ( not ) { rc = LDAP_SUCCESS; } else { - if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_delete" ); + /* If prune is on, remove a whole subtree. Delete the children of the + * DN recursively, then the DN requested. + */ + if ( prune ) deletechildren( ld, dn ); + if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_delete" ); } else if ( verbose ) { printf( "\tremoved\n" ); } @@ -239,3 +438,59 @@ static int dodelete( return( rc ); } + +/* + * Delete all the children of an entry recursively until leaf nodes are reached. + * + */ +static int deletechildren( LDAP *ld, + char *dn ) +{ + LDAPMessage *res, *e; + int entries; + int rc; + int timeout = 30 * 10000; + + ldap_set_option( ld, LDAP_OPT_TIMEOUT, &timeout ); + if ( verbose ) printf ( "deleting children of: %s\n", dn ); + /* + * Do a one level search at dn for children. For each, delete its children. + */ + if ( ldap_search_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, NULL, 0, &res ) == -1 ) + { + ldap_perror( ld, "ldap_search" ); + ldap_get_option( ld, LDAP_OPT_ERROR_NUMBER, &rc ); + return( rc ); + } + + entries = ldap_count_entries( ld, res ); + if ( entries > 0 ) + { + int i; + + for (e = ldap_first_entry( ld, res ), i = 0; e != NULL; + e = ldap_next_entry( ld, e ), i++ ) + { + if ( (rc = deletechildren( ld, ldap_get_dn( ld, e) )) == -1 ) + { + ldap_perror( ld, "ldap_prune" ); + return rc; + } + if ( verbose ) + { + printf( "\tremoving %s\n", ldap_get_dn( ld, e ) ); + } + if ( ( rc = ldap_delete_s( ld, ldap_get_dn( ld, e ) ) ) == -1 ) + { + ldap_perror( ld, "ldap_delete" ); + return rc; + } + else if ( verbose ) + { + printf( "\t%s removed\n", ldap_get_dn( ld, e ) ); + } + } + } + ldap_msgfree( res ); + return rc; +} diff --git a/clients/tools/ldapdelete.dsp b/clients/tools/ldapdelete.dsp new file mode 100644 index 0000000000..af7b4be030 --- /dev/null +++ b/clients/tools/ldapdelete.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="ldapdelete" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldapdelete - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldapdelete.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldapdelete.mak" CFG="ldapdelete - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldapdelete - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapdelete - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapdelete - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapdelete - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldapdelete - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapdele" +# PROP BASE Intermediate_Dir "ldapdele" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ldapdelete" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ldapdelete - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapdel0" +# PROP BASE Intermediate_Dir "ldapdel0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ldapdelete" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"SRelease/ldapdelete.exe" /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ldapdelete - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapdel1" +# PROP BASE Intermediate_Dir "ldapdel1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ldapdelete" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ldapdelete - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapdel2" +# PROP BASE Intermediate_Dir "ldapdel2" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ldapdelete" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapdelete.exe" /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapdelete.exe" /libpath:"..\..\Release" + +!ENDIF + +# Begin Target + +# Name "ldapdelete - Win32 Single Debug" +# Name "ldapdelete - Win32 Single Release" +# Name "ldapdelete - Win32 Debug" +# Name "ldapdelete - Win32 Release" +# Begin Source File + +SOURCE=.\ldapdelete.c +# End Source File +# End Target +# End Project diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index 043d3bbc3d..d2b453cd1e 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* ldapmodify.c - generic program to modify or add entries using LDAP */ @@ -16,7 +16,9 @@ #include #include +#ifdef HAVE_SYS_STAT_H #include +#endif #ifdef HAVE_SYS_FILE_H #include @@ -33,9 +35,17 @@ static char *prog; static char *binddn = NULL; -static char *passwd = NULL; +static struct berval passwd = { 0, NULL}; static char *ldaphost = NULL; static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static int sasl_integrity = 0; +static int sasl_privacy = 0; +#endif +static int use_tls = 0; static int new, replace, not, verbose, contoper, force, valsfromfiles; static LDAP *ld; @@ -76,23 +86,34 @@ static void usage( const char *prog ) { fprintf( stderr, - "Add or modify entries from an LDAP server\n\n" - "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n" - " [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n" - " a - add values (default%s)\n" - " b - read values from files (for binary attributes)\n" - " c - continuous operation\n" - " D - bind DN\n" - " M - enable Manage DSA IT control (-MM for critical)\n" - " d - debug level\n" - " f - read from file\n" - " F - force all changes records to be used\n" - " h - ldap host\n" - " n - print adds, don't actually do them\n" - " p - LDAP port\n" - " r - replace values\n" - " v - verbose mode\n" - " w - password\n" +"Add or modify entries from an LDAP server\n\n" +"usage: %s [options]\n" +" The list of desired operations are read from stdin or from the file\n" +" specified by \"-f file\".\n" +"options:\n" +" -a\t\tadd values (default%s)\n" +" -b\t\tread values from files (for binary attributes)\n" +" -c\t\tcontinuous operation\n" +" -d level\tset LDAP debugging level to `level'\n" +" -D dn\t\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -f file\t\tperform sequence of operations listed in file\n" +" -F\t\tforce all changes records to be used\n" +" -h host\t\tLDAP server\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -k\t\tuse Kerberos authentication\n" +" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" +" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" +" -n\t\tprint adds, don't actually do them\n" +" -p port\t\tport on LDAP server\n" +" -r\t\treplace values\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\tverbose mode\n" +" -w passwd\tbind password (for Simple authentication)\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") ); exit( EXIT_FAILURE ); } @@ -123,7 +144,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) { + while (( i = getopt( argc, argv, "abcD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'a': /* add */ new = 1; @@ -138,20 +159,18 @@ main( int argc, char **argv ) replace = 1; break; case 'k': /* kerberos bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; case 'K': /* kerberos bind, part 1 only */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -165,7 +184,7 @@ main( int argc, char **argv ) binddn = strdup( optarg ); break; case 'w': /* password */ - passwd = strdup( optarg ); + passwd.bv_val = strdup( optarg ); { char* p; @@ -173,6 +192,7 @@ main( int argc, char **argv ) *p = '*'; } } + passwd.bv_len = strlen( passwd.bv_val ); break; case 'd': debug |= atoi( optarg ); @@ -210,6 +230,67 @@ main( int argc, char **argv ) usage( argv[0] ); } break; + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); + } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage( prog ); } @@ -218,6 +299,38 @@ main( int argc, char **argv ) if ( argc != optind ) usage( prog ); + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION2; + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION3; + } + + if( manageDSAit ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "manage DSA control requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + + if( use_tls ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "Start TLS requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + if ( infile != NULL ) { if (( fp = fopen( infile, "r" )) == NULL ) { perror( infile ); @@ -255,19 +368,72 @@ main( int argc, char **argv ) /* don't chase referrals */ ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); - if (want_bindpw) - passwd = getpass("Enter LDAP Password: "); - if (version != -1 && ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS) { fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION to %d\n", version ); } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } } + + if (want_bindpw) + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = strlen( passwd.bv_val ); + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + + rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, + passwd.bv_len ? &passwd : NULL, + NULL, NULL ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } + } rc = 0; @@ -303,10 +469,14 @@ main( int argc, char **argv ) * has a colon that appears to the left of any equal signs, OR * if the first line consists entirely of digits (an entry id) */ +#ifdef LDAP_LDIF + use_ldif = 1; +#else use_ldif = ( *rbuf == '#' ) || (( p = strchr( rbuf, ':' )) != NULL && ( q = strchr( rbuf, '\n' )) != NULL && p < q && (( q = strchr( rbuf, '=' )) == NULL || p < q )); +#endif start = rbuf; @@ -357,7 +527,7 @@ process_ldif_rec( char *rbuf, int count ) new_entry = new; - rc = got_all = saw_replica = delete_entry = expect_modop = 0; + rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0; expect_deleteoldrdn = expect_newrdn = expect_newsup = 0; expect_sep = expect_ct = 0; linenum = 0; @@ -392,7 +562,7 @@ process_ldif_rec( char *rbuf, int count ) *p++ = '\0'; replicaport = atoi( p ); } - if ( strcasecmp( value, ldaphost ) == 0 && + if ( ldaphost != NULL && strcasecmp( value, ldaphost ) == 0 && replicaport == ldapport ) { use_record = 1; } diff --git a/clients/tools/ldapmodify.dsp b/clients/tools/ldapmodify.dsp new file mode 100644 index 0000000000..9a58a7060f --- /dev/null +++ b/clients/tools/ldapmodify.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="ldapmodify" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldapmodify - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldapmodify.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldapmodify.mak" CFG="ldapmodify - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldapmodify - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodify - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodify - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodify - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldapmodify - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapmodi" +# PROP BASE Intermediate_Dir "ldapmodi" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ldapmodify" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"SDebug/ldapmodify.exe" /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ldapmodify - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapmod0" +# PROP BASE Intermediate_Dir "ldapmod0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ldapmodify" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"SRelease/ldapmodify.exe" /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ldapmodify - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapmod1" +# PROP BASE Intermediate_Dir "ldapmod1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ldapmodify" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Release/ldapmodify.exe" /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/ldapmodify.exe" /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ldapmodify - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapmod2" +# PROP BASE Intermediate_Dir "ldapmod2" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ldapmodify" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapmodify.exe" /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapmodify.exe" /libpath:"..\..\Release" + +!ENDIF + +# Begin Target + +# Name "ldapmodify - Win32 Single Debug" +# Name "ldapmodify - Win32 Single Release" +# Name "ldapmodify - Win32 Debug" +# Name "ldapmodify - Win32 Release" +# Begin Source File + +SOURCE=.\ldapmodify.c +# End Source File +# End Target +# End Project diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index 3bc2e3140d..3aa05b10f0 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP. @@ -32,24 +32,69 @@ #include static char *binddn = NULL; -static char *passwd = NULL; +static struct berval passwd = { 0, NULL}; static char *ldaphost = NULL; static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static int sasl_integrity = 0; +static int sasl_privacy = 0; +#endif +static int use_tls = 0; static int not, verbose, contoper; static LDAP *ld; -static int domodrdn LDAP_P(( +static int domodrdn( LDAP *ld, char *dn, char *rdn, - int remove, /* flag: remove old RDN */ - char *newSuperior)); + char *newSuperior, + int remove ); /* flag: remove old RDN */ + +static void +usage( const char *s ) +{ + fprintf( stderr, +"Rename LDAP entries\n\n" +"usage: %s [options] [dn rdn]\n" +" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n" +" If not given, the list of modifications is read from stdin or\n" +" from the file specified by \"-f file\" (see man page).\n" +"options:\n" +" -c\t\tcontinuous operation mode (do not stop on errors)\n" +" -d level\tset LDAP debugging level to `level'\n" +" -D binddn\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -f file\t\tdo renames listed in `file'\n" +" -h host\t\tLDAP server\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -k\t\tuse Kerberos authentication\n" +" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" +" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" +" -n\t\tshow what would be done but don't actually do it\n" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" +" -r\t\tremove old RDN\n" +" -s newsuperior\tnew superior entry\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -w passwd\tbind passwd (for simple authentication)\n" +" -W\t\tprompt for bind passwd\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" +, s ); + + exit( EXIT_FAILURE ); +} int main(int argc, char **argv) { - char *usage = "usage: %s [-nvkWc] [-M[M]] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n"; - char *myname,*infile, *entrydn, *rdn, buf[ 4096 ]; + char *myname,*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ]; FILE *fp; int rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit; char *newSuperior=NULL; @@ -61,24 +106,24 @@ main(int argc, char **argv) myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname; - while (( i = getopt( argc, argv, "WkKMcnvrh:P:p:D:w:d:f:s:" )) != EOF ) { + while (( i = getopt( argc, argv, "cD:d:Ef:h:IKkMnP:p:rs:U:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif - break; + break; case 'K': /* kerberos bind, part one only */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif - break; + break; case 'c': /* continuous operation mode */ ++contoper; break; @@ -93,7 +138,7 @@ main(int argc, char **argv) version = LDAP_VERSION3; /* This option => force V3 */ break; case 'w': /* password */ - passwd = strdup( optarg ); + passwd.bv_val = strdup( optarg ); { char* p; @@ -101,6 +146,7 @@ main(int argc, char **argv) *p = '*'; } } + passwd.bv_len = strlen( passwd.bv_val ); break; case 'd': debug |= atoi( optarg ); @@ -138,26 +184,117 @@ main(int argc, char **argv) break; default: fprintf( stderr, "protocol version should be 2 or 3\n" ); - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); + } + break; + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif break; default: - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } } + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION2; + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION3; + } + + if( manageDSAit ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "manage DSA control requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + + if( use_tls ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "Start TLS requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + if (newSuperior != NULL) { if (version == LDAP_VERSION2) { fprintf( stderr, "%s: version conflict!, -s newSuperior requires LDAPv3\n", myname); - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } - - /* promote to LDAPv3 */ version = LDAP_VERSION3; } @@ -174,7 +311,7 @@ main(int argc, char **argv) ++havedn; } else if ( argc - optind != 0 ) { fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname); - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } @@ -214,19 +351,71 @@ main(int argc, char **argv) ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); - if (want_bindpw) - passwd = getpass("Enter LDAP Password: "); - if (version != -1 && ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS) { fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); - } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + + if (want_bindpw) + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = strlen( passwd.bv_val ); + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" + "%d\n", maxssf); + return( EXIT_FAILURE ); + } + + rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, + passwd.bv_len ? &passwd : NULL, + NULL, NULL ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } if ( manageDSAit ) { int err; @@ -252,7 +441,7 @@ main(int argc, char **argv) rc = 0; if (havedn) - rc = domodrdn(ld, entrydn, rdn, remove, newSuperior); + rc = domodrdn( ld, entrydn, rdn, newSuperior, remove ); else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { if ( *buf != '\0' ) { /* blank lines optional, skip */ buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ @@ -262,7 +451,7 @@ main(int argc, char **argv) perror( "strdup" ); return( EXIT_FAILURE ); } - rc = domodrdn(ld, entrydn, rdn, remove, newSuperior); + rc = domodrdn(ld, entrydn, rdn, newSuperior, remove ); havedn = 0; } else if ( !havedn ) { /* don't have DN yet */ if (( entrydn = strdup( buf )) == NULL ) { @@ -284,8 +473,8 @@ static int domodrdn( LDAP *ld, char *dn, char *rdn, - int remove, /* flag: remove old RDN */ - char *newSuperior) + char *newSuperior, + int remove ) /* flag: remove old RDN */ { int i; @@ -299,7 +488,7 @@ static int domodrdn( } if ( !not ) { - i = ldap_rename2_s( ld, dn, rdn, remove, newSuperior ); + i = ldap_rename2_s( ld, dn, rdn, newSuperior, remove ); if ( i != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_rename2_s" ); } else if ( verbose ) { diff --git a/clients/tools/ldapmodrdn.dsp b/clients/tools/ldapmodrdn.dsp new file mode 100644 index 0000000000..bcf0cc01cc --- /dev/null +++ b/clients/tools/ldapmodrdn.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="ldapmodrdn" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldapmodrdn - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldapmodrdn.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldapmodrdn.mak" CFG="ldapmodrdn - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldapmodrdn - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodrdn - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodrdn - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapmodrdn - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldapmodrdn - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapmodr" +# PROP BASE Intermediate_Dir "ldapmodr" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ldapmodrdn" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ldapmodrdn - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapmod0" +# PROP BASE Intermediate_Dir "ldapmod0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ldapmodrdn" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapmodrdn.exe" /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ldapmodrdn - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapmod1" +# PROP BASE Intermediate_Dir "ldapmod1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ldapmodrdn" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ldapmodrdn - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapmod2" +# PROP BASE Intermediate_Dir "ldapmod2" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ldapmodrdn" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapmodrdn.exe" /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapmodrdn.exe" /libpath:"..\..\Release" + +!ENDIF + +# Begin Target + +# Name "ldapmodrdn - Win32 Single Debug" +# Name "ldapmodrdn - Win32 Single Release" +# Name "ldapmodrdn - Win32 Debug" +# Name "ldapmodrdn - Win32 Release" +# Begin Source File + +SOURCE=.\ldapmodrdn.c +# End Source File +# End Target +# End Project diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 98aa570fed..18b19c2d61 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -1,22 +1,8 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ -/* - * Copyright 1998, David E. Storey, All rights reserved. - * This software is not subject to any license of The Murphy Group, Inc. - * or George Mason University. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - * - * ldappasswd.c - program to modify passwords in an LDAP tree - * - * Author: David E. Storey - */ #include "portable.h" @@ -31,381 +17,102 @@ #include #include -#include #include -#include -#include -#include #include "ldap_defaults.h" -/* local macros */ -#define CEILING(x) ((double)(x) > (int)(x) ? (int)(x) + 1 : (int)(x)) - -#define LDAP_PASSWD_ATTRIB "userPassword" -#define LDAP_PASSWD_CONF LDAP_SYSCONFDIR LDAP_DIRSEP "passwd.conf" - -#define HS_NONE 0 -#define HS_PLAIN 1 -#define HS_CONV 2 - -typedef enum -{ - HASHTYPE_NONE, - HASHTYPE_CRYPT, - HASHTYPE_MD5, - HASHTYPE_SMD5, - HASHTYPE_SHA1, - HASHTYPE_SSHA1 -} -HashTypes; - -typedef struct salt_t -{ - unsigned char *salt; - unsigned int len; -} -Salt; - -typedef struct hash_t -{ - const char *name; - unsigned int namesz; - char *(*func) (const char *, Salt *); - unsigned char takes_salt; - HashTypes type; - HashTypes type_salted; - unsigned int default_salt_len; -} -Hash; - -static int noupdates = 0; static int verbose = 0; -static int want_entryhash = 0; -static int auto_gen_pw = 0; - -/*** functions ***/ - -/* - * pw_encode() essentially base64 encodes a password and its salt - */ - -static char * -pw_encode (unsigned char *passwd, Salt * salt, unsigned int len) -{ - int salted = salt && salt->salt && salt->len; - int b64_len = 0; - char *base64digest = NULL; - unsigned char *npasswd = passwd; - - if (salted) - { - npasswd = (unsigned char *)malloc (len + salt->len); - memcpy (npasswd, passwd, len); - memcpy (&npasswd[len], salt->salt, salt->len); - len += salt->len; - } - - b64_len = CEILING (len / 3) * 4 + 1; - base64digest = (char *)malloc (b64_len); - if (lutil_b64_ntop (npasswd, len, base64digest, b64_len) < 0) - { - free (base64digest); - base64digest = NULL; - } - - if (salted) - free (npasswd); - - return (base64digest); -} - -/* - * if you'd like to write a better salt generator, please, be my guest. - */ static void -make_salt (Salt * salt, unsigned int len) -{ - - if (!salt) - return; - - salt->len = len; - salt->salt = (unsigned char *)malloc (len); - - for (len = 0; len < salt->len; len++) - salt->salt[len] = rand () & 0xff; -} - -/* - * password generator - */ - -static char * -gen_pass (unsigned int len) -{ - static const unsigned char autogen[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,"; - unsigned int i; - Salt salt; - - salt.salt = NULL; - salt.len = 0; - - make_salt (&salt, len); - for (i = 0; i < len; i++) - salt.salt[i] = autogen[salt.salt[i] % (sizeof (autogen) - 1)]; - - return ((char *)salt.salt); -} - -#ifdef SLAPD_CLEARTEXT -static char * -hash_none (const char *pw_in, Salt * salt) -{ - return (strdup (pw_in)); -} -#endif - -#ifdef SLAPD_CRYPT -static char * -hash_crypt (const char *pw_in, Salt * salt) -{ - static const unsigned char crypt64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; - char *crypted_pw = NULL; - Salt lsalt; - - if (salt && salt->salt && strlen ((char *)salt->salt) >= 2) - { - /* sanity check */ - if (!(isalnum(salt->salt[0]) || salt->salt[0] == '.' || salt->salt[0] == '/')) - salt->salt[0] = crypt64[salt->salt[0] % (sizeof (crypt64) - 1)]; - if (!(isalnum(salt->salt[1]) || salt->salt[1] == '.' || salt->salt[1] == '/')) - salt->salt[1] = crypt64[salt->salt[1] % (sizeof (crypt64) - 1)]; - - crypted_pw = crypt (pw_in, (char *)salt->salt); - } - else - { - make_salt (&lsalt, 2); - lsalt.salt[0] = crypt64[lsalt.salt[0] % (sizeof (crypt64) - 1)]; - lsalt.salt[1] = crypt64[lsalt.salt[1] % (sizeof (crypt64) - 1)]; - crypted_pw = crypt (pw_in, (char *)lsalt.salt); - free (lsalt.salt); - } - return (strdup (crypted_pw)); -} -#endif - -static char * -hash_md5 (const char *pw_in, Salt * salt) -{ - lutil_MD5_CTX MD5context; - unsigned char MD5digest[16]; - - lutil_MD5Init (&MD5context); - lutil_MD5Update (&MD5context, - (const unsigned char *)pw_in, strlen(pw_in)); - if (salt && salt->salt && salt->len) - lutil_MD5Update (&MD5context, salt->salt, salt->len); - lutil_MD5Final (MD5digest, &MD5context); - - return (pw_encode (MD5digest, salt, sizeof (MD5digest))); -} - -static char * -hash_sha1 (const char *pw_in, Salt * salt) +usage(const char *s) { - lutil_SHA1_CTX SHA1context; - unsigned char SHA1digest[20]; - - lutil_SHA1Init (&SHA1context); - lutil_SHA1Update (&SHA1context, - (const unsigned char *)pw_in, strlen(pw_in)); - if (salt && salt->salt && salt->len) - lutil_SHA1Update (&SHA1context, salt->salt, salt->len); - lutil_SHA1Final (SHA1digest, &SHA1context); + fprintf(stderr, +"Change the password of an LDAP entry\n\n" +"usage: %s [options] dn\n" +" dn: the DN of the entry whose password must be changed\n" +"options:\n" +" -a secret\told password\n" +" -A\t\tprompt for old password\n" +" -d level\tdebugging level\n" +" -D binddn\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -h host\t\tLDAP server (default: localhost)\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -n\t\tmake no modifications\n" +" -p port\t\tport on LDAP server\n" +" -S\t\tprompt for new password\n" +" -s secret\tnew password\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\tverbose mode\n" +" -w passwd\tbind password (for simple authentication)\n" +" -W\t\tprompt for bind password\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" + , s ); - return (pw_encode (SHA1digest, salt, sizeof (SHA1digest))); + exit( EXIT_FAILURE ); } -static const Hash hashes[] = -{ -#ifdef SLAPD_CLEARTEXT - {"none", 4, hash_none, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0}, -#endif -#ifdef SLAPD_CRYPT - {"crypt", 5, hash_crypt, 1, HASHTYPE_CRYPT, HASHTYPE_CRYPT, 2}, -#endif - {"md5", 3, hash_md5, 0, HASHTYPE_MD5, HASHTYPE_SMD5, 0}, - {"smd5", 4, hash_md5, 1, HASHTYPE_SMD5, HASHTYPE_SMD5, 4}, - {"sha", 3, hash_sha1, 0, HASHTYPE_SHA1, HASHTYPE_SSHA1, 0}, - {"ssha", 4, hash_sha1, 1, HASHTYPE_SSHA1, HASHTYPE_SSHA1, 4}, - {NULL, 0, NULL, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0} -}; - -static int -modify_dn (LDAP * ld, char *targetdn, char *pwattr, char *oldpw, - char *newpw, HashTypes htype, Salt * salt) +int +main( int argc, char *argv[] ) { - int ret = 0; - int salted = salt->salt ? 1 : 0; - int want_salt = salt->len && !salted; - char *buf = NULL; - char *hashed_pw = NULL; - char *strvals[2]; - LDAPMod mod, *mods[2]; - - if (!ld || !targetdn || !newpw) - return (1); - - /* auto-generate password */ - if (auto_gen_pw) - newpw = gen_pass (auto_gen_pw); - - /* handle salt */ - if (want_salt) - { - make_salt (salt, salt->len); - htype = hashes[htype].type_salted; - } - else if (hashes[htype].default_salt_len) - { - /* user chose a salted hash and needs a salt */ - if (!salted) - { - want_salt++; - salt->len = hashes[htype].default_salt_len; - make_salt (salt, salt->len); - } - } - - /* hash password */ - hashed_pw = hashes[htype].func (newpw, salt->len ? salt : NULL); - - /* return salt back to its original state */ - if (want_salt) - { - free (salt->salt); - salt->salt = NULL; - } - - buf = (char *)malloc (hashes[htype].namesz + 3 + strlen (hashed_pw)); - if (htype) - sprintf (buf, "{%s}%s", hashes[htype].name, hashed_pw); - else - sprintf (buf, "%s", hashed_pw); - - if (verbose > 0) - { - printf ("%s", targetdn); - if (verbose > 1) - { - printf (":%s", buf); - if (verbose > 2) - printf (":%s", newpw); - } - printf ("\n"); - } + int rc; + char *ldaphost = NULL; - strvals[0] = buf; - strvals[1] = NULL; - mod.mod_values = strvals; - mod.mod_type = pwattr; - mod.mod_op = LDAP_MOD_REPLACE; - mods[0] = &mod; - mods[1] =NULL; + char *dn = NULL; + char *binddn = NULL; - if (!noupdates && (ret = ldap_modify_s (ld, targetdn, mods)) != LDAP_SUCCESS) - ldap_perror (ld, "ldap_modify"); + struct berval passwd = { 0, NULL}; + char *newpw = NULL; + char *oldpw = NULL; - free (hashed_pw); - free (buf); - return (ret); -} - -static void -usage(const char *s) -{ - fprintf (stderr, "Usage: %s [options] [filter]\n", s); - fprintf (stderr, " -a attrib\tpassword attribute (default: " LDAP_PASSWD_ATTRIB ")\n"); - fprintf (stderr, " -b basedn\tbasedn to perform searches\n"); -/* fprintf (stderr, " -C\t\tuse entry's current hash mechanism\n"); */ - fprintf (stderr, " -D binddn\tbind dn\n"); - fprintf (stderr, " -d level\tdebugging level\n"); - fprintf (stderr, " -E\t\tprompt for new password\n"); - fprintf (stderr, " -e passwd\tnew password\n"); - fprintf (stderr, " -g passlen\tauto-generate passwords with length pwlen\n"); - fprintf (stderr, " -H hash\thash type (default: crypt)\n"); - fprintf (stderr, " -h host\tldap server (default: localhost)\n"); -#ifdef HAVE_KERBEROS - fprintf (stderr, " -K\t\tuse Kerberos step 1\n"); - fprintf (stderr, " -k\t\tuse Kerberos\n"); -#endif - fprintf (stderr, " -l time\ttime limit\n"); - fprintf (stderr, " -n\t\tmake no modifications\n"); - fprintf (stderr, " -P version\tprotocol version (2 or 3)\n"); - fprintf (stderr, " -p port\tldap port\n"); - fprintf (stderr, " -s scope\tsearch scope: base, one, sub (default: sub)\n"); - fprintf (stderr, " -t targetdn\tdn to change password\n"); - fprintf (stderr, " -v\t\tverbose (more v's, more verbose)\n"); - fprintf (stderr, " -W\t\tprompt for bind password\n"); - fprintf (stderr, " -w passwd\tbind password (for simple authentication)\n"); - fprintf (stderr, " -Y saltlen\tsalt length to use\n"); -/* fprintf (stderr, " -y salt\tsalt to use\n"); */ - fprintf (stderr, " -z size\tsize limit\n"); - exit( EXIT_FAILURE ); -} + int want_bindpw = 0; + int want_newpw = 0; + int want_oldpw = 0; -int -main (int argc, char *argv[]) -{ - char *base = NULL; - char *binddn = NULL; - char *bindpw = NULL; - char *filtpattern = NULL; - char *ldaphost = NULL; - char *targetdn = NULL; - char *pwattr = LDAP_PASSWD_ATTRIB; - char *newpw = NULL; - int authmethod = LDAP_AUTH_SIMPLE; - int hashtype = HASHTYPE_CRYPT; - int i, j; + int noupdates = 0; + int i; int ldapport = 0; int debug = 0; - int scope = LDAP_SCOPE_SUBTREE; - int sizelimit = -1; - int timelimit = -1; int version = -1; - int want_bindpw = 0; - int want_newpw = 0; + int authmethod = LDAP_AUTH_SIMPLE; +#ifdef HAVE_CYRUS_SASL + char *sasl_authc_id = NULL; + char *sasl_authz_id = NULL; + char *sasl_mech = NULL; + int sasl_integrity = 0; + int sasl_privacy = 0; +#endif + int use_tls = 0; LDAP *ld; - Salt salt; + struct berval *bv = NULL; - salt.salt = NULL; - salt.len = 0; + char *retoid; + struct berval *retdata; if (argc == 1) usage (argv[0]); - while ((i = getopt (argc, argv, "a:b:C:D:d:Ee:g:H:h:Kkl:nP:p:s:t:vWw:Y:y:z:")) != EOF) + while( (i = getopt( argc, argv, + "Aa:D:d:EIh:np:Ss:U:vWw:X:Y:Z" )) != EOF ) { - switch (i) - { - case 'a': /* password attribute */ - pwattr = strdup (optarg); + switch (i) { + case 'A': /* prompt for oldr password */ + want_oldpw++; break; + case 'a': /* old password (secret) */ + oldpw = strdup (optarg); - case 'b': /* base search dn */ - base = strdup (optarg); - break; + { + char* p; - case 'C': - want_entryhash++; + for( p = optarg; *p == '\0'; p++ ) { + *p = '*'; + } + } break; - case 'D': /* bind distinguished name */ binddn = strdup (optarg); break; @@ -414,111 +121,44 @@ main (int argc, char *argv[]) debug |= atoi (optarg); break; - case 'E': /* prompt for new password */ - want_newpw++; - break; - - case 'e': /* new password */ - newpw = strdup (optarg); - break; - - case 'g': - auto_gen_pw = strtol (optarg, NULL, 10); - break; - - case 'H': /* hashes */ - for (j = 0; hashes[j].name; j++) - { - if (!strncasecmp (optarg, hashes[j].name, hashes[j].namesz)) - { - hashtype = hashes[j].type; - break; - } - } - - if (!hashes[j].name) - { - fprintf (stderr, "hash type: %s is unknown\n", optarg); - usage (argv[0]); - } - break; - case 'h': /* ldap host */ ldaphost = strdup (optarg); break; - case 'K': /* use kerberos bind, 1st part only */ -#ifdef HAVE_KERBEROS - authmethod = LDAP_AUTH_KRBV41; -#else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage (argv[0]); -#endif - break; - - case 'k': /* use kerberos bind */ -#ifdef HAVE_KERBEROS - authmethod = LDAP_AUTH_KRBV4; -#else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage (argv[0]); -#endif - break; - - case 'l': /* time limit */ - timelimit = strtol (optarg, NULL, 10); - break; - case 'n': /* don't update entry(s) */ noupdates++; break; - case 'P': - switch( atoi( optarg ) ) { - case 2: - version = LDAP_VERSION2; - break; - case 3: - version = LDAP_VERSION3; - break; - default: - fprintf( stderr, "protocol version should be 2 or 3\n" ); - usage( argv[0] ); - } + case 'p': /* ldap port */ + ldapport = strtol( optarg, NULL, 10 ); break; - case 'p': /* ldap port */ - ldapport = strtol (optarg, NULL, 10); + case 'S': /* prompt for user password */ + want_newpw++; break; - case 's': /* scope */ - if (strcasecmp (optarg, "base") == 0) - scope = LDAP_SCOPE_BASE; - else if (strcasecmp (optarg, "one") == 0) - scope = LDAP_SCOPE_ONELEVEL; - else if (strcasecmp (optarg, "sub") == 0) - scope = LDAP_SCOPE_SUBTREE; - else + case 's': /* new password (secret) */ + newpw = strdup (optarg); + { - fprintf (stderr, "scope should be base, one, or sub\n"); - usage (argv[0]); - } - break; + char* p; - case 't': /* target dn */ - targetdn = strdup (optarg); + for( p = optarg; *p == '\0'; p++ ) { + *p = '*'; + } + } break; case 'v': /* verbose */ verbose++; break; - case 'W': /* promt for bind password */ + case 'W': /* prompt for bind password */ want_bindpw++; break; case 'w': /* bind password */ - bindpw = strdup (optarg); + passwd.bv_val = strdup (optarg); { char* p; @@ -526,19 +166,70 @@ main (int argc, char *argv[]) *p = '*'; } } + passwd.bv_len = strlen( passwd.bv_val ); break; - case 'Y': /* salt length */ - salt.len = strtol (optarg, NULL, 10); + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif break; - - case 'y': /* user specified salt */ - salt.len = strlen (optarg); - salt.salt = (unsigned char *)strdup (optarg); + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif break; - - case 'z': /* time limit */ - sizelimit = strtol (optarg, NULL, 10); + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && + strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); + } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif break; default: @@ -546,32 +237,53 @@ main (int argc, char *argv[]) } } - /* grab filter */ - if (!(argc - optind < 1)) - filtpattern = strdup (argv[optind]); + if( argc - optind != 1 ) { + usage( argv[0] ); + } - /* check for target(s) */ - if (!filtpattern && !targetdn) - targetdn = binddn; + dn = strdup( argv[optind] ); - /* handle bind password */ - if (want_bindpw) - bindpw = strdup (getpass ("Enter LDAP password: ")); + if( want_oldpw && oldpw == NULL ) { + /* prompt for old password */ + char *ckoldpw; + newpw = strdup(getpassphrase("Old password: ")); + ckoldpw = getpassphrase("Re-enter old password: "); - /* handle new password */ - if (!newpw) - { + if( strncmp( oldpw, ckoldpw, strlen(oldpw) )) { + fprintf( stderr, "passwords do not match\n" ); + return EXIT_FAILURE; + } + } + + if( want_newpw && newpw == NULL ) { + /* prompt for new password */ char *cknewpw; - newpw = strdup (getpass ("New password: ")); - cknewpw = getpass ("Re-enter new password: "); + newpw = strdup(getpassphrase("New password: ")); + cknewpw = getpassphrase("Re-enter new password: "); + + if( strncmp( newpw, cknewpw, strlen(newpw) )) { + fprintf( stderr, "passwords do not match\n" ); + return EXIT_FAILURE; + } + } - if (strncmp (newpw, cknewpw, strlen (newpw))) - { - fprintf (stderr, "passwords do not match\n"); - return ( EXIT_FAILURE ); + if( binddn == NULL && dn != NULL ) { + binddn = dn; + dn = NULL; + + if( passwd.bv_val == NULL ) { + passwd.bv_val = oldpw; + passwd.bv_len = oldpw == NULL ? 0 : strlen( oldpw ); } } + if (want_bindpw && passwd.bv_val == NULL ) { + /* handle bind password */ + fprintf( stderr, "Bind DN: %s\n", binddn ); + passwd.bv_val = strdup( getpassphrase("Enter bind password: ")); + passwd.bv_len = strlen( passwd.bv_val ); + } + if ( debug ) { if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); @@ -584,107 +296,165 @@ main (int argc, char *argv[]) #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, SIG_IGN ); #endif - /* seed random number generator */ - -#ifdef HAVE_GETTIMEOFDAY - /* this is of questionable value - * gettimeofday may not provide much usec - */ - { - struct timeval tv; - gettimeofday (&tv, NULL); - srand(tv.tv_sec * (tv.tv_usec + 1)); - } -#else - /* The traditional seed */ - srand((unsigned)time( NULL )); -#endif /* connect to server */ - if ((ld = ldap_init (ldaphost, ldapport)) == NULL) - { - perror ("ldap_init"); - return ( EXIT_FAILURE ); + if ((ld = ldap_init( ldaphost, ldapport )) == NULL) { + perror("ldap_init"); + return EXIT_FAILURE; } - /* set options */ - if (timelimit != -1 && - ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS ) - { - fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit ); - } - if (sizelimit != -1 && - ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS ) - { - fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit ); - } - - /* this seems prudent */ - { - int deref = LDAP_DEREF_NEVER; - ldap_set_option( ld, LDAP_OPT_DEREF, &deref); - } /* don't chase referrals */ ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); - if (version != -1 && - ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS ) - { + /* LDAPv3 only */ + version = 3; + rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + + if(rc != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } - /* authenticate to server */ - if (ldap_bind_s (ld, binddn, bindpw, authmethod) != LDAP_SUCCESS) - { - ldap_perror (ld, "ldap_bind"); - return ( EXIT_FAILURE ); + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } } - if (targetdn) - { - if (want_entryhash) - { - /* insert code here =) */ + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" + "%d\n", maxssf); + return( EXIT_FAILURE ); + } + + rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, + passwd.bv_len ? &passwd : NULL, + NULL, NULL ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); } - else - modify_dn (ld, targetdn, pwattr, NULL, newpw, hashtype, &salt); } - if (filtpattern) - { - char filter[BUFSIZ]; - LDAPMessage *result = NULL, *e; - char *attrs[2]; - attrs[0] = pwattr; - attrs[1] = NULL; - - /* search */ - sprintf (filter, "%s", filtpattern); - i = ldap_search_s (ld, base, scope, filter, attrs, 0, &result); - if (i != LDAP_SUCCESS && - i != LDAP_TIMELIMIT_EXCEEDED && - i != LDAP_SIZELIMIT_EXCEEDED) - { - ldap_perror (ld, "ldap_search"); - return ( EXIT_FAILURE ); + if( dn != NULL || oldpw != NULL || newpw != NULL ) { + /* build change password control */ + BerElement *ber = ber_alloc_t( LBER_USE_DER ); + + if( ber == NULL ) { + perror( "ber_alloc_t" ); + ldap_unbind( ld ); + return EXIT_FAILURE; } - for (e = ldap_first_entry (ld, result); e; e = ldap_next_entry (ld, e)) - { - char *dn = ldap_get_dn (ld, e); - if (dn) - { - struct berval **pw_vals = ldap_get_values_len (ld, e, pwattr); - modify_dn (ld, dn, pwattr, pw_vals ? pw_vals[0]->bv_val : NULL, newpw, hashtype, &salt); - if (pw_vals) - ldap_value_free_len (pw_vals); - free (dn); - } + ber_printf( ber, "{" /*}*/ ); + + if( dn != NULL ) { + ber_printf( ber, "ts", + LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn ); + free(dn); + } + + if( oldpw != NULL ) { + ber_printf( ber, "ts", + LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw ); + free(oldpw); + } + + if( newpw != NULL ) { + ber_printf( ber, "ts", + LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw ); + free(newpw); + } + + ber_printf( ber, /*{*/ "}" ); + + rc = ber_flatten( ber, &bv ); + + if( rc < 0 ) { + perror( "ber_flatten" ); + ldap_unbind( ld ); + return EXIT_FAILURE; } + + ber_free( ber, 1 ); + } + + rc = ldap_extended_operation_s( ld, + LDAP_EXOP_X_MODIFY_PASSWD, bv, + NULL, NULL, + &retoid, &retdata ); + + ber_bvfree( bv ); + + if( retdata != NULL ) { + ber_tag_t tag; + char *s; + BerElement *ber = ber_init( retdata ); + + if( ber == NULL ) { + perror( "ber_init" ); + ldap_unbind( ld ); + return EXIT_FAILURE; + } + + /* we should check the tag */ + tag = ber_scanf( ber, "{a}", &s); + + if( tag == LBER_ERROR ) { + perror( "ber_scanf" ); + } else { + printf("New password: %s\n", s); + free( s ); + } + + ber_free( ber, 1 ); } + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_extended_operation" ); + ldap_unbind( ld ); + return EXIT_FAILURE; + } + + ldap_memfree( retoid ); + ber_bvfree( retdata ); + /* disconnect from server */ ldap_unbind (ld); - return ( EXIT_SUCCESS ); + return EXIT_SUCCESS; } diff --git a/clients/tools/ldappasswd.dsp b/clients/tools/ldappasswd.dsp new file mode 100644 index 0000000000..df406dfe5f --- /dev/null +++ b/clients/tools/ldappasswd.dsp @@ -0,0 +1,145 @@ +# Microsoft Developer Studio Project File - Name="ldappasswd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldappasswd - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldappasswd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldappasswd.mak" CFG="ldappasswd - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldappasswd - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldappasswd - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldappasswd - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldappasswd - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldappasswd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldappass" +# PROP BASE Intermediate_Dir "ldappass" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ldappasswd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "ldappasswd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldappas0" +# PROP BASE Intermediate_Dir "ldappas0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ldappasswd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ldappasswd - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Single Debug" +# PROP BASE Intermediate_Dir "Single Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ldappasswd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ldappasswd - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Single Release" +# PROP BASE Intermediate_Dir "Single Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ldappasswd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "ldappasswd - Win32 Release" +# Name "ldappasswd - Win32 Debug" +# Name "ldappasswd - Win32 Single Debug" +# Name "ldappasswd - Win32 Single Release" +# Begin Source File + +SOURCE=.\ldappasswd.c +# End Source File +# End Target +# End Project diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index 1eba56399a..0bae49a3e1 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -1,8 +1,9 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ + #include "portable.h" #include @@ -13,12 +14,25 @@ #include #include #include +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif #include #include "ldif.h" #include "ldap_defaults.h" +#undef DEPSEP #define DEFSEP "=" static void @@ -33,38 +47,48 @@ usage( const char *s ) "\t\t+ -- all operational attributes\n" "\t\tempty list -- all non-operational attributes\n" "options:\n" -" -n\t\tshow what would be done but don't actually search\n" -" -v\t\trun in verbose mode (diagnostics to standard output)\n" -" -t\t\twrite binary values to files in TMPDIR\n" -" -tt\t\twrite all values to files in TMPDIR\n" -" -T path\twrite files to directory specified by path (default: \"/tmp\")\n" -" -V prefix\tURL prefix for files (default: \"file://tmp/\"\n" -" -u\t\tinclude User Friendly entry names in the output\n" +" -a deref\tone of `never', `always', `search', or `find' (alias\n" +" \tdereferencing)\n" " -A\t\tretrieve attribute names only (no values)\n" +" -b basedn\tbase dn for search\n" " -B\t\tdo not suppress printing of binary values\n" -" -F sep\tprint `sep' instead of `=' between attribute names and values\n" +" -d level\tset LDAP debugging level to `level'\n" +" -D binddn\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -f file\t\tperform sequence of searches listed in `file'\n" +" -F sep\t\tprint `sep' instead of `=' between attribute names and\n" +" \tvalues\n" +" -h host\t\tLDAP server\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -k\t\tuse Kerberos authentication\n" +" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" +" -l limit\ttime limit (in seconds) for search\n" " -L\t\tprint entries in LDIF format (implies -B)\n" " -LL\t\tprint entries in LDIF format without comments\n" -" -LLL\t\tprint entries in LDIF format without comments and version\n" +" -LLL\t\tprint entries in LDIF format without comments and\n" +" \tversion\n" " -M\t\tenable Manage DSA IT control (-MM to make critical)\n" +" -n\t\tshow what would be done but don't actually search\n" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" " -R\t\tdo not automatically follow referrals\n" -" -S attr\tsort the results by attribute `attr'\n" -" -d level\tset LDAP debugging level to `level'\n" -" -f file\tperform sequence of searches listed in `file'\n" -" -b basedn\tbase dn for search\n" " -s scope\tone of base, one, or sub (search scope)\n" -" -a deref\tone of never, always, search, or find (alias dereferencing)\n" -" -l limit\ttime limit (in seconds) for search\n" -" -z limit\tsize limit (in entries) for search\n" -" -D binddn\tbind dn\n" +" -S attr\t\tsort the results by attribute `attr'\n" +" -t\t\twrite binary values to files in TMPDIR\n" +" -tt\t\twrite all values to files in TMPDIR\n" +" -T path\t\twrite files to directory specified by path (default:\n" +" \t\"/tmp\")\n" +" -u\t\tinclude User Friendly entry names in the output\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -V prefix\tURL prefix for files (default: \"file://tmp/\")\n" " -w passwd\tbind passwd (for simple authentication)\n" " -W\t\tprompt for bind passwd\n" -#ifdef HAVE_KERBEROS -" -k\t\tuse Kerberos instead of Simple Password authentication\n" -#endif -" -h host\tldap server\n" -" -p port\tport on ldap server\n" -" -P version\tprocotol version (2 or 3)\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -z limit\tsize limit (in entries) for search\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , s ); exit( EXIT_FAILURE ); @@ -97,10 +121,18 @@ static char *tmpdir = NULL; static char *urlpre = NULL; static char *binddn = NULL; -static char *passwd = NULL; +static struct berval passwd = { 0, NULL }; static char *base = NULL; static char *ldaphost = NULL; static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static int sasl_integrity = 0; +static int sasl_privacy = 0; +#endif +static int use_tls = 0; static char *sep = DEFSEP; static char *sortattr = NULL; static int skipsortattr = 0; @@ -110,7 +142,7 @@ int main( int argc, char **argv ) { char *infile, *filtpattern, **attrs, line[ BUFSIZ ]; - FILE *fp; + FILE *fp = NULL; int rc, i, first, scope, deref, attrsonly, manageDSAit; int referrals, timelimit, sizelimit, debug; int authmethod, version, want_bindpw; @@ -120,13 +152,16 @@ main( int argc, char **argv ) debug = verbose = binary = not = vals2tmp = attrsonly = manageDSAit = ldif = want_bindpw = 0; - deref = referrals = sizelimit = timelimit = version = -1; + deref = sizelimit = timelimit = version = -1; + + /* default should be off */ + referrals = 1; scope = LDAP_SCOPE_SUBTREE; authmethod = LDAP_AUTH_SIMPLE; while (( i = getopt( argc, argv, - "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:T:V:")) != EOF ) + "Aa:Bb:D:d:EF:f:h:IKkLl:MnP:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF ) { switch( i ) { case 'n': /* do Not do any searches */ @@ -139,19 +174,22 @@ main( int argc, char **argv ) debug |= atoi( optarg ); break; case 'k': /* use kerberos bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); + return( EXIT_FAILURE ); #endif break; case 'K': /* use kerberos bind, 1st part only */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); + return( EXIT_FAILURE ); #endif break; + break; case 'u': /* include UFN */ ++includeufn; break; @@ -163,7 +201,7 @@ main( int argc, char **argv ) manageDSAit++; break; case 'R': /* don't automatically chase referrals */ - referrals = (int) LDAP_OPT_OFF; + referrals = 0; break; case 'A': /* retrieve attribute names only -- no values */ ++attrsonly; @@ -229,7 +267,7 @@ main( int argc, char **argv ) ldapport = atoi( optarg ); break; case 'w': /* bind password */ - passwd = strdup( optarg ); + passwd.bv_val = strdup( optarg ); { char* p; @@ -237,6 +275,7 @@ main( int argc, char **argv ) *p = '*'; } } + passwd.bv_len = strlen( passwd.bv_val ); break; case 'l': /* time limit */ timelimit = atoi( optarg ); @@ -264,11 +303,109 @@ main( int argc, char **argv ) usage( argv[0] ); } break; + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); + } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage( argv[0] ); } } +#ifdef LDAP_LDIF + /* no alternative format */ + if( ldif < 1 ) ldif = 1; +#endif + + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION2; + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION3; + } + + if( manageDSAit ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "manage DSA control requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + + if( use_tls ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "Start TLS requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + if ( argc - optind < 1 ) { usage( argv[ 0 ] ); } @@ -312,7 +449,7 @@ main( int argc, char **argv ) } if( urlpre == NULL ) { - urlpre = malloc( sizeof("file:///") + strlen(tmpdir) ); + urlpre = malloc( sizeof("file:////") + strlen(tmpdir) ); if( urlpre == NULL ) { perror( "malloc" ); @@ -380,13 +517,65 @@ main( int argc, char **argv ) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } - if (want_bindpw) { - passwd = getpass("Enter LDAP Password: "); + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); + if (want_bindpw) { + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = strlen( passwd.bv_val ); + } + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" + "%d\n", maxssf); + return( EXIT_FAILURE ); + } + + rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, + passwd.bv_len ? &passwd : NULL, + NULL, NULL ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } } if ( manageDSAit ) { @@ -622,6 +811,7 @@ print_entry( if ( vals2tmp > 1 || ( vals2tmp && ldif_is_not_printable( bvals[i]->bv_val, bvals[i]->bv_len ) )) { + int tmpfd; /* write value to file */ sprintf( tmpfname, "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX", tmpdir, a ); @@ -632,7 +822,12 @@ print_entry( continue; } - if (( tmpfp = fopen( tmpfname, "w")) == NULL ) { + if (( tmpfd = open( tmpfname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) == -1 ) { + perror( tmpfname ); + continue; + } + + if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) { perror( tmpfname ); continue; } diff --git a/clients/tools/ldapsearch.dsp b/clients/tools/ldapsearch.dsp new file mode 100644 index 0000000000..d3918c8e45 --- /dev/null +++ b/clients/tools/ldapsearch.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="ldapsearch" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ldapsearch - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ldapsearch.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ldapsearch.mak" CFG="ldapsearch - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ldapsearch - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapsearch - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapsearch - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ldapsearch - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ldapsearch - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ldapsear" +# PROP BASE Intermediate_Dir "ldapsear" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ldapsearch" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ldapsearch - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapsea0" +# PROP BASE Intermediate_Dir "ldapsea0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ldapsearch" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ldapsearch - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapsea1" +# PROP BASE Intermediate_Dir "ldapsea1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ldapsearch" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapsearch.exe" /libpath:"..\..\libraries\SRelease" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "ldapsearch - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ldapsea2" +# PROP BASE Intermediate_Dir "ldapsea2" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ldapsearch" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W2 /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/ldapsearch.exe" /libpath:"..\..\libraries\SRelease" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /debug /machine:I386 /libpath:"..\..\Debug" + +!ENDIF + +# Begin Target + +# Name "ldapsearch - Win32 Single Debug" +# Name "ldapsearch - Win32 Single Release" +# Name "ldapsearch - Win32 Release" +# Name "ldapsearch - Win32 Debug" +# Begin Source File + +SOURCE=.\ldapsearch.c +# End Source File +# End Target +# End Project diff --git a/clients/ud/Makefile.in b/clients/ud/Makefile.in index 54c16e29e1..7c22affb6b 100644 --- a/clients/ud/Makefile.in +++ b/clients/ud/Makefile.in @@ -11,7 +11,10 @@ PROGRAMS= ud LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries -XLIBS = -lldif -lldap -llber -llutil +NT_DYN_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_DEFS) + +XLIBS = -llutil -lldif -lldap -llber XXLIBS = $(TERMCAP_LIBS) $(SECURITY_LIBS) $(LUTIL_LIBS) ud : version.o @@ -22,6 +25,12 @@ version.c: ${OBJS} $(LDAP_LIBDEPEND) $(MKVERSION) -s -c -n Version UserDirectory > $@ install-local: FORCE - -$(MKDIR) $(bindir) - -mv -f $(bindir)/ud $(bindir)/ud- - $(LTINSTALL) $(INSTALLFLAGS) -m 755 ud $(bindir) + -$(MKDIR) $(DESTDIR)$(bindir) + -mv -f $(DESTDIR)$(bindir)/ud $(DESTDIR)$(bindir)/ud- + @( \ + for prg in $(PROGRAMS); do \ + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \ + $(DESTDIR)$(bindir); \ + done \ + ) + diff --git a/clients/ud/auth.c b/clients/ud/auth.c index b757d78169..5ae44ef154 100644 --- a/clients/ud/auth.c +++ b/clients/ud/auth.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1991, 1992 Regents of the University of Michigan. * All rights reserved. @@ -33,7 +37,7 @@ #include "ldap_defaults.h" #include "ud.h" -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND static char tktpath[20]; /* ticket file path */ static int kinit(); static int valid_tgt(); @@ -46,7 +50,7 @@ int auth( char *who, int implicit ) { int rc; /* return code from ldap_bind() */ - char *passwd = NULL; /* returned by getpass() */ + char *passwd = NULL; /* returned by getpassphrase() */ char **rdns; /* for fiddling with the DN */ int authmethod; int name_provided; /* was a name passed in? */ @@ -56,7 +60,7 @@ auth( char *who, int implicit ) char *user; #endif char uidname[20]; -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char **krbnames; /* for kerberos names */ int kinited, ikrb; char buf[5]; @@ -144,7 +148,7 @@ auth( char *who, int implicit ) rdns = ldap_explode_dn(Entry.DN, TRUE); printf(" Authenticating to the directory as \"%s\"...\n", *rdns ); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND /* * First, if the user has a choice of auth methods, ask which * one they want to use. if they want kerberos, ask which @@ -237,13 +241,13 @@ auth( char *who, int implicit ) authmethod = LDAP_AUTH_SIMPLE; sprintf(prompt, " Enter your LDAP password: "); do { - passwd = getpass(prompt); + passwd = getpassphrase(prompt); } while (passwd != NULL && *passwd == '\0'); if (passwd == NULL) { (void) ldap_value_free(rdns); return(0); } -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND } (void) ldap_value_free(krbnames); #endif @@ -255,13 +259,13 @@ auth( char *who, int implicit ) if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE) fprintf(stderr, " Entry has no password\n"); else if (ld_errno == LDAP_INVALID_CREDENTIALS) -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND if ( authmethod == LDAP_AUTH_KRBV4 ) { fprintf(stderr, " The Kerberos credentials are invalid.\n"); } else { #endif fprintf(stderr, " The password you provided is incorrect.\n"); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND } #endif else @@ -290,7 +294,7 @@ auth( char *who, int implicit ) return(0); } -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND #define FIVEMINS ( 5 * 60 ) #define TGT "krbtgt" @@ -334,6 +338,8 @@ valid_tgt( char **names ) static char *kauth_name; +#ifndef HAVE_KTH_KERBEROS + /*ARGSUSED*/ int krbgetpass( char *user, char *inst, char *realm, char *pw, C_Block key ) @@ -346,7 +352,7 @@ krbgetpass( char *user, char *inst, char *realm, char *pw, C_Block key ) sprintf(prompt, " Enter Kerberos password for %s: ", kauth_name ); #endif do { - passwd = getpass(prompt); + passwd = getpassphrase(prompt); } while (passwd != NULL && *passwd == '\0'); if (passwd == NULL) { return(-1); @@ -365,6 +371,7 @@ krbgetpass( char *user, char *inst, char *realm, char *pw, C_Block key ) return( 0 ); } +#endif /* HAVE_KTH_KERBEROS */ static int kinit( char *kname ) @@ -382,14 +389,18 @@ kinit( char *kname ) } #ifdef HAVE_AFS_KERBEROS - /* - * realm must be uppercase for krb_ routines - */ + /* realm must be uppercase for AFS krb_ routines */ ldap_pvt_str2upper( realm ); #endif /* HAVE_AFS_KERBEROS */ +#ifdef HAVE_KTH_KERBEROS + /* Kth kerberos knows how to do both string to keys */ + rc = krb_get_pw_in_tkt( name, inst, realm, TGT, realm, + DEFAULT_TKT_LIFE, 0 ); +#else rc = krb_get_in_tkt( name, inst, realm, TGT, realm, DEFAULT_TKT_LIFE, krbgetpass, NULL, NULL ); +#endif if ( rc != KSUCCESS ) { switch ( rc ) { diff --git a/clients/ud/edit.c b/clients/ud/edit.c index 67f2ed9a86..de640dc380 100644 --- a/clients/ud/edit.c +++ b/clients/ud/edit.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1994 Regents of the University of Michigan. * All rights reserved. @@ -14,6 +18,7 @@ #include "portable.h" #include +#include #include @@ -24,6 +29,12 @@ #include #include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -31,6 +42,10 @@ #include #endif +#ifdef HAVE_IO_H +#include +#endif + #include #include @@ -43,7 +58,7 @@ static int print_attrs_and_values( FILE *fp, struct attribute *attrs, short fla static int ovalues( char *attr ); static void write_entry( void ); -static char *entry_temp_file; +static char entry_temp_file[L_tmpnam]; void @@ -116,7 +131,7 @@ load_editor( void ) { FILE *fp; char *cp, *editor = UD_DEFAULT_EDITOR; - static char template[MED_BUF_SIZE]; + int tmpfd; #ifndef HAVE_SPAWNLP int pid; int status; @@ -129,13 +144,16 @@ load_editor( void ) #endif /* write the entry into a temp file */ - (void) strcpy(template, "/tmp/udEdit.XXXXXX"); - if ((entry_temp_file = mktemp(template)) == NULL) { - perror("mktemp"); - return(-1); + if (tmpnam(entry_temp_file) == NULL) { + perror("tmpnam"); + return -1; } - if ((fp = fopen(entry_temp_file, "w")) == NULL) { - perror("fopen"); + if ((tmpfd = open(entry_temp_file, O_WRONLY|O_CREAT|O_EXCL, 0600)) == -1) { + perror(entry_temp_file); + return -1; + } + if ((fp = fdopen(tmpfd, "w")) == NULL) { + perror("fdopen"); return(-1); } fprintf(fp, "## Directory entry of %s\n", Entry.name); diff --git a/clients/ud/find.c b/clients/ud/find.c index 5e8b865603..f247fcc5bf 100644 --- a/clients/ud/find.c +++ b/clients/ud/find.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1991, 1992, 1993 * Regents of the University of Michigan. All rights reserved. @@ -32,8 +36,8 @@ static int num_picked = 0; /* used when user picks entry at More prompt */ int vrfy( char *dn ) { - LDAPMessage *results; - static char *attrs[2] = { "objectClass", NULL }; + LDAPMessage *results = NULL; + static char *attrs[2] = { "1.1", NULL }; int ld_errno = 0; #ifdef DEBUG @@ -41,7 +45,7 @@ vrfy( char *dn ) printf("->vrfy(%s)\n", dn); #endif /* verify that this DN exists in the directory */ - (void) ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", attrs, TRUE, &results); + (void) ldap_search_s(ld, dn, LDAP_SCOPE_BASE, NULL, attrs, TRUE, &results); (void) ldap_msgfree(results); ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); @@ -65,7 +69,7 @@ disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who ) char *namelist[MAX_NUM_NAMES]; /* names found */ char response[SMALL_BUF_SIZE]; /* results from user */ char *name = NULL; /* DN to lookup */ - LDAPMessage *mp; + LDAPMessage *mp = NULL; int ld_errno = 0; #ifdef DEBUG @@ -92,7 +96,7 @@ disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who ) for (;;) { printf(" Do you wish to see a list of names? "); fflush(stdout); - (void) memset(response, 0, sizeof(response)); + (void) memset(response, '\0', sizeof(response)); fetch_buffer(response, sizeof(response), stdin); switch (response[0]) { case 'n' : @@ -129,7 +133,7 @@ disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who ) printf(" ld = 0x%x\n", ld); printf(" search base = %s\n", name); printf(" scope = LDAP_SCOPE_BASE\n"); - printf(" filter = objectClass=*\n"); + printf(" filter = (objectClass=*)\n"); for (i = 0; read_attrs[i] != NULL; i++) printf(" read_attrs[%d] = %s\n", i, read_attrs[i]); printf(" read_attrs[%d] = NULL\n", i); @@ -137,7 +141,7 @@ disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who ) printf(" &mp = 0x%x\n", &mp); } #endif - if (ldap_search_s(ld, name, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &mp) != LDAP_SUCCESS) { + if (ldap_search_s(ld, name, LDAP_SCOPE_BASE, NULL, read_attrs, FALSE, &mp) != LDAP_SUCCESS) { ldap_perror(ld, "ldap_search_s"); Free(name); ldap_msgfree(mp); @@ -224,15 +228,10 @@ find( char *who, int quiet ) return(NULL); } else if (matches == 1) { dn = ldap_get_dn(ld, ldap_first_entry(ld, res)); - rc = ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &res); + rc = ldap_search_s(ld, dn, LDAP_SCOPE_BASE, NULL, read_attrs, FALSE, &res); ldap_memfree(dn); if (rc != LDAP_SUCCESS) { - int ld_errno = 0; - ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); - if (ld_errno == LDAP_UNAVAILABLE) - printf(" Could not contact the LDAP server to find \"%s\".\n", who); - else - ldap_perror(ld, "ldap_search_s"); + ldap_perror(ld, "ldap_search_s"); return(NULL); } ldap_set_option(ld, LDAP_OPT_DEREF, &savederef); @@ -303,7 +302,7 @@ find( char *who, int quiet ) printf(" ld = 0x%x\n", ld); printf(" dn = %s\n", dn); printf(" scope = LDAP_SCOPE_BASE\n"); - printf(" filter = %s\n", "objectClass=*"); + printf(" filter = %s\n", "(objectClass=*)"); for (i = 0; read_attrs[i] != NULL; i++) printf(" read_attrs[%d] = %s\n", i, read_attrs[i]); printf(" read_attrs[%d] = NULL\n", i); @@ -311,7 +310,7 @@ find( char *who, int quiet ) printf(" &results = 0x%x\n", &res); } #endif - if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &res) != LDAP_SUCCESS) { + if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE, NULL, read_attrs, FALSE, &res) != LDAP_SUCCESS) { ldap_perror(ld, "ldap_search_s"); ldap_msgfree(res); res = NULL; @@ -462,7 +461,7 @@ fetch_boolean_value( char *who, struct attribute attr ) printf("->fetch_boolean_value(%s, %s)\n", who, attr.quipu_name); #endif attributes[0] = attr.quipu_name; - if (ldap_search_s(ld, who, LDAP_SCOPE_BASE, "objectClass=*", attributes, FALSE, &result) != LDAP_SUCCESS) { + if (ldap_search_s(ld, who, LDAP_SCOPE_BASE, NULL, attributes, FALSE, &result) != LDAP_SUCCESS) { int ld_errno = 0; ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE) diff --git a/clients/ud/globals.c b/clients/ud/globals.c index 5927351c5b..3531c75a76 100644 --- a/clients/ud/globals.c +++ b/clients/ud/globals.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1992, 1993, 1994 Regents of the University of Michigan. * All rights reserved. @@ -14,8 +18,7 @@ #include "portable.h" #include -#include /* portable.h+ldap.h needs time_t */ -#include +#include /* ldap.h needs time_t */ #include #include "ud.h" @@ -41,7 +44,7 @@ struct attribute attrlist[] = { #ifdef UOFM { "multiLineDescription", "Description", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD | ATTR_FLAG_IS_MULTILINE }, #endif -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND { "krbName", "Kerberos name", 0, ATTR_FLAG_PERSON | ATTR_FLAG_READ }, #endif { "description", "Brief description", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ }, @@ -66,5 +69,9 @@ struct attribute attrlist[] = { { "drink", "Favorite Beverage", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD }, { "lastModifiedBy", "Last modified by", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ }, { "lastModifiedTime", "Last modified at", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE }, + { "modifiersname", "Modifier's Name", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ }, + { "modifytimestamp", "Modify Timestamp", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE }, + { "creatorsname", "Creator's Name", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ }, + { "createtimestamp", "Create Timestamp", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE }, { NULL, NULL, 0, ATTR_FLAG_NONE } }; diff --git a/clients/ud/group.c b/clients/ud/group.c index 950631d765..fd73738e77 100644 --- a/clients/ud/group.c +++ b/clients/ud/group.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1993, 1994 Regents of the University of Michigan. * All rights reserved. @@ -215,9 +219,9 @@ remove_group( char *name ) if ((dn = bind_and_fetch(name)) == NULL) return; - printf("\n The group '%s' will be permanently removed from\n", - name); - printf(" the Directory. Are you absolutely sure that you want to\n" ); printf(" remove this entire group? "); + printf("\n The entry\n '%s'\n will be permanently removed from", dn); + printf(" the Directory.\n Are you absolutely sure that you want to" ); + printf(" remove this entire group? "); fflush(stdout); fetch_buffer(tmp, sizeof(tmp), stdin); if (!(tmp[0] == 'y' || tmp[0] == 'Y')) @@ -230,7 +234,7 @@ remove_group( char *name ) int ld_errno = 0; ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); if (ld_errno == LDAP_INSUFFICIENT_ACCESS) - printf(" You do not own the group \"%s\".\n", name); + printf(" You do not own the entry\n\t\"%s\".\n", dn); else ldap_perror(ld, " ldap_delete_s"); printf(" Group not removed.\n"); @@ -239,10 +243,12 @@ remove_group( char *name ) } ldap_uncache_entry(ld, dn); if (verbose) + { if (name == NULL) printf(" The group has been removed.\n"); else printf(" The group \"%s\" has been removed.\n", name); + } Free(dn); return; } diff --git a/clients/ud/help.c b/clients/ud/help.c index 027e168e41..0fb0590bf2 100644 --- a/clients/ud/help.c +++ b/clients/ud/help.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1992, 1993 Regents of the University of Michigan. * All rights reserved. diff --git a/clients/ud/main.c b/clients/ud/main.c index 7f0d4baa3d..e830c85238 100644 --- a/clients/ud/main.c +++ b/clients/ud/main.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -280,7 +280,7 @@ do_commands( void ) printf(" Thank you!\n"); ldap_unbind(ld); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND destroy_tickets(); #endif exit( EXIT_SUCCESS ); @@ -353,7 +353,7 @@ change_base( int type, char **base, char *s ) /* * If s is NULL we need to prompt the user for an argument. */ - while (s == NULL) { + if (s == NULL) { if (verbose) { printf(" You need to specify how the base is to be changed. Valid choices are:\n"); printf(" ? - list the choices immediately below this level\n"); @@ -367,6 +367,8 @@ change_base( int type, char **base, char *s ) fetch_buffer(buf, sizeof(buf), stdin); if ((buf != NULL) && (buf[0] != '\0')) s = buf; + else + return; } /* set the output string */ @@ -433,7 +435,7 @@ change_base( int type, char **base, char *s ) * the user if they want to see more. They can also just * type a number at that point too. */ - if (ldap_search_s(ld, *base, LDAP_SCOPE_ONELEVEL, "(|(objectClass=quipuNonLeafObject)(objectClass=externalNonLeafObject))", attrs, FALSE, &mp) != LDAP_SUCCESS) { + if (ldap_search_s(ld, *base, LDAP_SCOPE_ONELEVEL, NULL, attrs, FALSE, &mp) != LDAP_SUCCESS) { int ld_errno = 0; ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); if ((ld_errno == LDAP_TIMELIMIT_EXCEEDED) || @@ -658,12 +660,7 @@ initialize_client( void ) } if (ldap_bind_s(ld, (char *) default_bind_object, NULL, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) { - int ld_errno = 0; - ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); - - fprintf(stderr, " The LDAP Directory is temporarily unavailable. Please try again later.\n"); - if (ld_errno != LDAP_UNAVAILABLE) - ldap_perror(ld, " ldap_bind_s"); + ldap_perror(ld, " ldap_bind_s"); exit( EXIT_FAILURE ); /* NOTREACHED */ } diff --git a/clients/ud/mod.c b/clients/ud/mod.c index 40eea36316..1a13a967f2 100644 --- a/clients/ud/mod.c +++ b/clients/ud/mod.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1991,1993 Regents of the University of Michigan. * All rights reserved. @@ -393,7 +397,7 @@ get_value( char *id, char *prompt ) * Other attributes may not. */ count = 1; - (void) memset(buffer, 0, sizeof(buffer)); + (void) memset(buffer, '\0', sizeof(buffer)); #ifdef UOFM if (!strcmp(id, "postalAddress") || !strcmp(id, "homePostalAddress") || !strcmp(id, "multiLineDescription") || !strcmp(id, "vacationMessage")) #else @@ -784,23 +788,22 @@ check_URL( char *url ) void mod_perror( LDAP *ld ) { - int ld_errno = 0; + int ld_errno = LDAP_SUCCESS; + char *ld_errtext = NULL; - if(ld != NULL) { - ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); - } + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno ); - if (( ld == NULL ) || ( ld_errno != LDAP_UNAVAILABLE && - ld_errno != LDAP_UNWILLING_TO_PERFORM )) - { - ldap_perror( ld, "modify" ); - return; - } + if( ld_errno != LDAP_SUCCESS ) { + ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_errtext ); + } + + fprintf( stderr, " modify failed: %s (%d)\n", + ldap_err2string( ld_errno ), ld_errno ); - fprintf( stderr, "\n modify: failed because part of the online directory is not able\n" ); - fprintf( stderr, " to be modified right now" ); - if ( ld_errno == LDAP_UNAVAILABLE ) { - fprintf( stderr, " or is temporarily unavailable" ); + if( ld_errtext != NULL ) { + fprintf( stderr, " additional information: %s\n", + ld_errtext ); } - fprintf( stderr, ".\n Please try again later.\n" ); + + fprintf( stderr, " Please try again later.\n" ); } diff --git a/clients/ud/print.c b/clients/ud/print.c index 8cb5c133dc..914b3e3d1b 100644 --- a/clients/ud/print.c +++ b/clients/ud/print.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1991, 1993 * Regents of the University of Michigan. All rights reserved. @@ -52,6 +56,8 @@ static char *person_attr_print_order[] = { "memberOfGroup", "lastModifiedBy", "lastModifiedTime", + "modifiersname", + "modifytimestamp", NULL }; @@ -74,6 +80,10 @@ static char *group_attr_print_order[] = { "labeledURL", "lastModifiedBy", "lastModifiedTime", + "modifiersname", + "modifytimestamp", + "creatorsname", + "createtimestamp", NULL }; @@ -195,6 +205,12 @@ print_an_entry( void ) if (debug & D_TRACE) printf("->print_an_entry()\n"); #endif + + if( Entry.name == NULL ) { + printf(" No Entry found.\n"); + return; + } + printf(" \"%s\"\n", Entry.name); /* @@ -559,7 +575,7 @@ time2text( char *ldtimestr, int dateonly ) return( fmterr ); } - memset( (char *)&t, 0, sizeof( struct tm )); + memset( (char *)&t, '\0', sizeof( struct tm )); p = ldtimestr; @@ -568,8 +584,10 @@ time2text( char *ldtimestr, int dateonly ) /* POSIX says tm_year should be year - 1900 */ t.tm_year = 100 * GET2BYTENUM( p ) - 1900; p += 2; + } else { + t.tm_year = 0; } - t.tm_year = GET2BYTENUM( p ); p += 2; + t.tm_year += GET2BYTENUM( p ); p += 2; t.tm_mon = GET2BYTENUM( p ) - 1; p += 2; t.tm_mday = GET2BYTENUM( p ); p += 2; diff --git a/clients/ud/string_to_key.c b/clients/ud/string_to_key.c index 8a6a5ae70f..120cde80cf 100644 --- a/clients/ud/string_to_key.c +++ b/clients/ud/string_to_key.c @@ -1,11 +1,12 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" -#if defined(HAVE_KERBEROS) && !defined(openbsd) +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) && !defined(openbsd) /* - * $Source: /repo/OpenLDAP/pkg/ldap/clients/ud/string_to_key.c,v $ - * $Author: hallvard $ - * * Copyright 1985, 1986, 1987, 1988, 1989 by the Massachusetts Institute * of Technology. * @@ -66,7 +67,7 @@ des_string_to_key( char *str, register des_cblock *key ) length = strlen(str); /* init key array for bits */ - memset(k_char, 0, sizeof(k_char)); + memset(k_char, '\0', sizeof(k_char)); #ifdef USE_DES_DEBUG if (des_debug) @@ -115,7 +116,7 @@ des_string_to_key( char *str, register des_cblock *key ) (void) des_key_sched(key,key_sked); (void) des_cbc_cksum((des_cblock *)in_str,key,length,key_sked,key); /* erase key_sked */ - memset((char *)key_sked, 0, sizeof(key_sked)); + memset((char *)key_sked, '\0', sizeof(key_sked)); /* now fix up key parity again */ des_fixup_key_parity(key); @@ -159,8 +160,8 @@ Andrew_StringToKey( int i; int passlen; - memset(key, 0, sizeof(des_cblock)); - memset(password, 0, sizeof(password)); + memset(key, '\0', sizeof(des_cblock)); + memset(password, '\0', sizeof(password)); strncpy (password, cell, 8); passlen = strlen (str); diff --git a/clients/ud/ud.dsp b/clients/ud/ud.dsp new file mode 100644 index 0000000000..2513226ad6 --- /dev/null +++ b/clients/ud/ud.dsp @@ -0,0 +1,188 @@ +# Microsoft Developer Studio Project File - Name="ud" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ud - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ud.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ud.mak" CFG="ud - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ud - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ud - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ud - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ud - Win32 Single Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ud - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ud" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "ud - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ud" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ud - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ud___Wi0" +# PROP BASE Intermediate_Dir "ud___Wi0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ud" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib hs_regex.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release" +# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ud - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ud___Wi1" +# PROP BASE Intermediate_Dir "ud___Wi1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ud" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib hs_regex.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug" +# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ENDIF + +# Begin Target + +# Name "ud - Win32 Release" +# Name "ud - Win32 Debug" +# Name "ud - Win32 Single Release" +# Name "ud - Win32 Single Debug" +# Begin Source File + +SOURCE=.\auth.c +# End Source File +# Begin Source File + +SOURCE=.\edit.c +# End Source File +# Begin Source File + +SOURCE=.\find.c +# End Source File +# Begin Source File + +SOURCE=.\globals.c +# End Source File +# Begin Source File + +SOURCE=.\group.c +# End Source File +# Begin Source File + +SOURCE=.\help.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\mod.c +# End Source File +# Begin Source File + +SOURCE=.\print.c +# End Source File +# Begin Source File + +SOURCE=.\string_to_key.c +# End Source File +# Begin Source File + +SOURCE=.\ud.h +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Target +# End Project diff --git a/clients/ud/ud.h b/clients/ud/ud.h index fa07c3531d..6f6d1b461a 100644 --- a/clients/ud/ud.h +++ b/clients/ud/ud.h @@ -1,12 +1,7 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* * Copyright (c) 1991, 1992, 1993 @@ -90,7 +85,7 @@ /* * Authentication method we will be using. */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND #define UD_AUTH_METHOD LDAP_AUTH_KRBV4 #else #define UD_AUTH_METHOD LDAP_AUTH_SIMPLE @@ -198,7 +193,7 @@ extern char Version[]; /* in auth.c: */ int auth LDAP_P(( char *who, int implicit )); -#if defined(HAVE_KERBEROS) && defined(_AC_KRB_H) +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) && defined(_AC_KRB_H) int krbgetpass LDAP_P(( char *u, char *in, char *re, char *pw, C_Block key )); void destroy_tickets LDAP_P(( void )); #endif @@ -269,7 +264,7 @@ void print_URL LDAP_P(( struct attribute A )); void print_one_URL LDAP_P(( char *s, int l_lead, char *tag, int u_lead )); /* in string_to_key.c: */ -#if defined(HAVE_KERBEROS) && !defined(openbsd) && defined(_AC_KRB_H) +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) && !defined(openbsd) && defined(_AC_KRB_H) #if defined(HAVE_AFS_KERBEROS) || !defined(HAVE_KERBEROS_V) void des_string_to_key LDAP_P(( char *str, des_cblock *key )); #endif diff --git a/clients/ud/util.c b/clients/ud/util.c index 27023de759..3cc445e2df 100644 --- a/clients/ud/util.c +++ b/clients/ud/util.c @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1992, 1993 Regents of the University of Michigan. * All rights reserved. @@ -100,7 +104,7 @@ fatal( char *s ) { if (errno != 0) perror(s); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND destroy_tickets(); #endif exit( EXIT_FAILURE ); @@ -405,15 +409,19 @@ isadn( char *s ) char * my_ldap_dn2ufn( char *s ) { +#ifdef UD_BASE register char **cpp; static char short_DN[BUFSIZ]; - if (strstr(s, NULL) == NULL) + if (strstr(s, UD_BASE) == NULL) return(ldap_dn2ufn(s)); cpp = ldap_explode_dn(s, TRUE); sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1)); ldap_value_free(cpp); return(short_DN); +#else + return(ldap_dn2ufn(s)); +#endif } /* return TRUE if this attribute should be printed as a URL */ diff --git a/configure b/configure index 618b873411..151a0952b3 100755 --- a/configure +++ b/configure @@ -1,14 +1,17 @@ #! /bin/sh # $OpenLDAP$ -# from OpenLDAP: pkg/ldap/configure.in,v 1.223.2.3 1999/09/10 20:25:17 kdz Exp +# from OpenLDAP: pkg/ldap/configure.in,v 1.314 2000/06/09 21:09:52 kurt Exp -# Copyright 1998,1999 The OpenLDAP Foundation. All Rights Reserved. +# Copyright 1998-2000 The OpenLDAP Foundation. All Rights Reserved. # # Redistribution and use in source and binary forms are permitted only # as authorized by the OpenLDAP Public License. A copy of this # license is available at http://www.OpenLDAP.org/license.html or # in file LICENSE in the top-level directory of the distribution. +echo "Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved." +echo "Copying restrictions apply, see COPYRIGHT file." + # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13.1 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. @@ -31,22 +34,24 @@ ac_help="$ac_help --enable-proctitle enable proctitle support (yes)" ac_help="$ac_help --enable-cache enable caching (yes)" -ac_help="$ac_help - --enable-dns enable V2 DX Referrals extension (no)" ac_help="$ac_help --enable-referrals enable V2 Referrals extension (yes)" +ac_help="$ac_help + --enable-kbind enable V2 Kerberos IV bind (auto)" ac_help="$ac_help --enable-cldap enable connectionless ldap (no)" ac_help="$ac_help - --enable-x-compile enable cross compiling (no)" + --enable-ipv6 enable IPv6 support (auto)" ac_help="$ac_help - --enable-dmalloc enable debug malloc support (no)" + --enable-unix enable UNIX domain socket support (auto)" +ac_help="$ac_help + --enable-x-compile enable cross compiling (no)" ac_help="$ac_help --with-cyrus-sasl with Cyrus SASL support (auto)" ac_help="$ac_help --with-fetch with fetch URL support (auto)" ac_help="$ac_help - --with-kerberos with Kerberos support (auto)" + --with-kerberos with support (auto)" ac_help="$ac_help --with-readline with readline support (auto)" ac_help="$ac_help @@ -63,6 +68,10 @@ ac_help="$ac_help --enable-cleartext enable cleartext passwords (yes)" ac_help="$ac_help --enable-crypt enable crypt(3) passwords (auto)" +ac_help="$ac_help + --enable-kpasswd enable kerberos password verification (no)" +ac_help="$ac_help + --enable-spasswd enable (Cyrus) SASL password verification (no)" ac_help="$ac_help --enable-modules enable dynamic module support (no)" ac_help="$ac_help @@ -75,14 +84,14 @@ ac_help="$ac_help --enable-rlookups enable reverse lookups (auto)" ac_help="$ac_help --enable-aci enable per-object ACIs (no)" -ac_help="$ac_help - --enable-discreteaci enable discrete rights in ACIs (no)" ac_help="$ac_help --enable-wrappers enable tcp wrapper support (no)" ac_help="$ac_help - --enable-bdb2 enable bdb2 backend (no)" + --enable-dynamic enable linking built binaries with dynamic libs (no)" +ac_help="$ac_help + --enable-dnssrv enable dnssrv backend (no)" ac_help="$ac_help - --with-bdb2-module module type (static)" + --with-dnssrv-module module type (static)" ac_help="$ac_help --enable-ldap enable ldap backend (no)" ac_help="$ac_help @@ -99,18 +108,10 @@ ac_help="$ac_help --enable-passwd enable passwd backend (no)" ac_help="$ac_help --with-passwd-module module type (static)" -ac_help="$ac_help - --enable-perl enable perl backend (no)" -ac_help="$ac_help - --with-perl-module module type (static)" ac_help="$ac_help --enable-shell enable shell backend (no)" ac_help="$ac_help --with-shell-module module type (static)" -ac_help="$ac_help - --enable-tcl enable tcl backend (no)" -ac_help="$ac_help - --with-tcl-module module type (static)" ac_help="$ac_help SLURPD (Replication Daemon) Options:" ac_help="$ac_help @@ -629,6 +630,16 @@ else ac_n= ac_c='\c' ac_t= fi + +# set unset (borrowed from autoconf 2.14a) +if (unset FOO) >/dev/null 2>&1; then + ol_unset=unset +else + ol_unset=false +fi +# unset CDPATH +$ol_unset CDPATH || test "${CDPATH+set}" != set || CDPATH=: && export CDPATH + ac_aux_dir= for ac_dir in build $srcdir/build; do if test -f $ac_dir/install-sh; then @@ -639,6 +650,10 @@ for ac_dir in build $srcdir/build; do ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break fi done if test -z "$ac_aux_dir"; then @@ -653,9 +668,11 @@ if test -z "$OL_VERSION"; then { echo "configure: error: could not determine version" 1>&2; exit 1; } fi +echo "Configuring OpenLDAP $OL_VERSION ..." + echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:659: checking host system type" >&5 +echo "configure:676: checking host system type" >&5 if test "x$ac_cv_host" = "x" || (test "x$host" != "xNONE" && test "x$host" != "x$ac_cv_host_alias"); then # Make sure we can run config.sub. @@ -696,7 +713,7 @@ host_os=$ac_cv_host_os echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:700: checking target system type" >&5 +echo "configure:717: checking target system type" >&5 if test "x$ac_cv_target" = "x" || (test "x$target" != "xNONE" && test "x$target" != "x$ac_cv_target_alias"); then # Make sure we can run config.sub. @@ -736,7 +753,7 @@ target_os=$ac_cv_target_os echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:740: checking build system type" >&5 +echo "configure:757: checking build system type" >&5 if test "x$ac_cv_build" = "x" || (test "x$build" != "xNONE" && test "x$build" != "x$ac_cv_build_alias"); then # Make sure we can run config.sub. @@ -813,7 +830,7 @@ test "$host_alias" != "$target_alias" && # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:817: checking for a BSD compatible install" >&5 +echo "configure:834: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"\${ac_cv_path_install+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -870,7 +887,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:874: checking whether build environment is sane" >&5 +echo "configure:891: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile @@ -931,7 +948,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:935: checking for $ac_word" >&5 +echo "configure:952: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -961,7 +978,7 @@ test -n "$AWK" && break done echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:965: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:982: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1001,7 +1018,7 @@ fi missing_dir=`cd $ac_aux_dir && pwd` echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 -echo "configure:1005: checking for working aclocal" >&5 +echo "configure:1022: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -1014,7 +1031,7 @@ else fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 -echo "configure:1018: checking for working autoconf" >&5 +echo "configure:1035: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -1027,7 +1044,7 @@ else fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 -echo "configure:1031: checking for working automake" >&5 +echo "configure:1048: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -1040,7 +1057,7 @@ else fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 -echo "configure:1044: checking for working autoheader" >&5 +echo "configure:1061: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -1053,7 +1070,7 @@ else fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 -echo "configure:1057: checking for working makeinfo" >&5 +echo "configure:1074: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. @@ -1073,7 +1090,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1077: checking for $ac_word" >&5 +echo "configure:1094: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_AMTAR+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1124,7 +1141,7 @@ EOF echo $ac_n "checking configure arguments""... $ac_c" 1>&6 -echo "configure:1128: checking configure arguments" >&5 +echo "configure:1145: checking configure arguments" >&5 top_builddir=`pwd` @@ -1230,10 +1247,10 @@ else ol_enable_cache="yes" fi # end --enable-cache -# OpenLDAP --enable-dns - # Check whether --enable-dns or --disable-dns was given. -if test "${enable_dns+set}" = set; then - enableval="$enable_dns" +# OpenLDAP --enable-referrals + # Check whether --enable-referrals or --disable-referrals was given. +if test "${enable_referrals+set}" = set; then + enableval="$enable_referrals" ol_arg=invalid for ol_val in auto yes no ; do @@ -1242,18 +1259,18 @@ if test "${enable_dns+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-dns" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-referrals" 1>&2; exit 1; } fi - ol_enable_dns="$ol_arg" + ol_enable_referrals="$ol_arg" else - ol_enable_dns="no" + ol_enable_referrals="yes" fi -# end --enable-dns -# OpenLDAP --enable-referrals - # Check whether --enable-referrals or --disable-referrals was given. -if test "${enable_referrals+set}" = set; then - enableval="$enable_referrals" +# end --enable-referrals +# OpenLDAP --enable-kbind + # Check whether --enable-kbind or --disable-kbind was given. +if test "${enable_kbind+set}" = set; then + enableval="$enable_kbind" ol_arg=invalid for ol_val in auto yes no ; do @@ -1262,14 +1279,14 @@ if test "${enable_referrals+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-referrals" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-kbind" 1>&2; exit 1; } fi - ol_enable_referrals="$ol_arg" + ol_enable_kbind="$ol_arg" else - ol_enable_referrals="yes" + ol_enable_kbind="auto" fi -# end --enable-referrals +# end --enable-kbind # OpenLDAP --enable-cldap # Check whether --enable-cldap or --disable-cldap was given. if test "${enable_cldap+set}" = set; then @@ -1290,31 +1307,30 @@ else ol_enable_cldap="no" fi # end --enable-cldap -# OpenLDAP --enable-x_compile - # Check whether --enable-x_compile or --disable-x_compile was given. -if test "${enable_x_compile+set}" = set; then - enableval="$enable_x_compile" +# OpenLDAP --enable-ipv6 + # Check whether --enable-ipv6 or --disable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval="$enable_ipv6" ol_arg=invalid - for ol_val in yes no ; do + for ol_val in auto yes no ; do if test "$enableval" = "$ol_val" ; then ol_arg="$ol_val" fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-x_compile" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-ipv6" 1>&2; exit 1; } fi - ol_enable_x_compile="$ol_arg" + ol_enable_ipv6="$ol_arg" else - ol_enable_x_compile="no" + ol_enable_ipv6="auto" fi -# end --enable-x_compile - -# OpenLDAP --enable-dmalloc - # Check whether --enable-dmalloc or --disable-dmalloc was given. -if test "${enable_dmalloc+set}" = set; then - enableval="$enable_dmalloc" +# end --enable-ipv6 +# OpenLDAP --enable-unix + # Check whether --enable-unix or --disable-unix was given. +if test "${enable_unix+set}" = set; then + enableval="$enable_unix" ol_arg=invalid for ol_val in auto yes no ; do @@ -1323,14 +1339,35 @@ if test "${enable_dmalloc+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-dmalloc" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-unix" 1>&2; exit 1; } + fi + ol_enable_unix="$ol_arg" + +else + ol_enable_unix="auto" +fi +# end --enable-unix +# OpenLDAP --enable-x_compile + # Check whether --enable-x_compile or --disable-x_compile was given. +if test "${enable_x_compile+set}" = set; then + enableval="$enable_x_compile" + + ol_arg=invalid + for ol_val in yes no ; do + if test "$enableval" = "$ol_val" ; then + ol_arg="$ol_val" + fi + done + if test "$ol_arg" = "invalid" ; then + { echo "configure: error: bad value $enableval for --enable-x_compile" 1>&2; exit 1; } fi - ol_enable_dmalloc="$ol_arg" + ol_enable_x_compile="$ol_arg" else - ol_enable_dmalloc="no" + ol_enable_x_compile="no" fi -# end --enable-dmalloc +# end --enable-x_compile + # OpenLDAP --with-cyrus_sasl # Check whether --with-cyrus_sasl or --without-cyrus_sasl was given. @@ -1380,7 +1417,7 @@ if test "${with_kerberos+set}" = set; then withval="$with_kerberos" ol_arg=invalid - for ol_val in auto k5 k4 afs yes no ; do + for ol_val in auto k5 k5only k425 kth k4 afs yes no ; do if test "$withval" = "$ol_val" ; then ol_arg="$ol_val" fi @@ -1422,7 +1459,7 @@ if test "${with_threads+set}" = set; then withval="$with_threads" ol_arg=invalid - for ol_val in auto posix mach pth lwp yes no manual ; do + for ol_val in auto nt posix mach pth lwp yes no manual ; do if test "$withval" = "$ol_val" ; then ol_arg="$ol_val" fi @@ -1547,6 +1584,46 @@ else ol_enable_crypt="auto" fi # end --enable-crypt +# OpenLDAP --enable-kpasswd + # Check whether --enable-kpasswd or --disable-kpasswd was given. +if test "${enable_kpasswd+set}" = set; then + enableval="$enable_kpasswd" + + ol_arg=invalid + for ol_val in auto yes no ; do + if test "$enableval" = "$ol_val" ; then + ol_arg="$ol_val" + fi + done + if test "$ol_arg" = "invalid" ; then + { echo "configure: error: bad value $enableval for --enable-kpasswd" 1>&2; exit 1; } + fi + ol_enable_kpasswd="$ol_arg" + +else + ol_enable_kpasswd="no" +fi +# end --enable-kpasswd +# OpenLDAP --enable-spasswd + # Check whether --enable-spasswd or --disable-spasswd was given. +if test "${enable_spasswd+set}" = set; then + enableval="$enable_spasswd" + + ol_arg=invalid + for ol_val in auto yes no ; do + if test "$enableval" = "$ol_val" ; then + ol_arg="$ol_val" + fi + done + if test "$ol_arg" = "invalid" ; then + { echo "configure: error: bad value $enableval for --enable-spasswd" 1>&2; exit 1; } + fi + ol_enable_spasswd="$ol_arg" + +else + ol_enable_spasswd="no" +fi +# end --enable-spasswd # OpenLDAP --enable-modules # Check whether --enable-modules or --disable-modules was given. if test "${enable_modules+set}" = set; then @@ -1667,10 +1744,10 @@ else ol_enable_aci="no" fi # end --enable-aci -# OpenLDAP --enable-discreteaci - # Check whether --enable-discreteaci or --disable-discreteaci was given. -if test "${enable_discreteaci+set}" = set; then - enableval="$enable_discreteaci" +# OpenLDAP --enable-wrappers + # Check whether --enable-wrappers or --disable-wrappers was given. +if test "${enable_wrappers+set}" = set; then + enableval="$enable_wrappers" ol_arg=invalid for ol_val in auto yes no ; do @@ -1679,18 +1756,18 @@ if test "${enable_discreteaci+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-discreteaci" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-wrappers" 1>&2; exit 1; } fi - ol_enable_discreteaci="$ol_arg" + ol_enable_wrappers="$ol_arg" else - ol_enable_discreteaci="no" + ol_enable_wrappers="no" fi -# end --enable-discreteaci -# OpenLDAP --enable-wrappers - # Check whether --enable-wrappers or --disable-wrappers was given. -if test "${enable_wrappers+set}" = set; then - enableval="$enable_wrappers" +# end --enable-wrappers +# OpenLDAP --enable-dynamic + # Check whether --enable-dynamic or --disable-dynamic was given. +if test "${enable_dynamic+set}" = set; then + enableval="$enable_dynamic" ol_arg=invalid for ol_val in auto yes no ; do @@ -1699,19 +1776,19 @@ if test "${enable_wrappers+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-wrappers" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-dynamic" 1>&2; exit 1; } fi - ol_enable_wrappers="$ol_arg" + ol_enable_dynamic="$ol_arg" else - ol_enable_wrappers="no" + ol_enable_dynamic="no" fi -# end --enable-wrappers +# end --enable-dynamic -# OpenLDAP --enable-bdb2 - # Check whether --enable-bdb2 or --disable-bdb2 was given. -if test "${enable_bdb2+set}" = set; then - enableval="$enable_bdb2" +# OpenLDAP --enable-dnssrv + # Check whether --enable-dnssrv or --disable-dnssrv was given. +if test "${enable_dnssrv+set}" = set; then + enableval="$enable_dnssrv" ol_arg=invalid for ol_val in auto yes no ; do @@ -1720,18 +1797,18 @@ if test "${enable_bdb2+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-bdb2" 1>&2; exit 1; } + { echo "configure: error: bad value $enableval for --enable-dnssrv" 1>&2; exit 1; } fi - ol_enable_bdb2="$ol_arg" + ol_enable_dnssrv="$ol_arg" else - ol_enable_bdb2="no" + ol_enable_dnssrv="no" fi -# end --enable-bdb2 -# OpenLDAP --with-bdb2_module - # Check whether --with-bdb2_module or --without-bdb2_module was given. -if test "${with_bdb2_module+set}" = set; then - withval="$with_bdb2_module" +# end --enable-dnssrv +# OpenLDAP --with-dnssrv_module + # Check whether --with-dnssrv_module or --without-dnssrv_module was given. +if test "${with_dnssrv_module+set}" = set; then + withval="$with_dnssrv_module" ol_arg=invalid for ol_val in static dynamic ; do @@ -1740,14 +1817,14 @@ if test "${with_bdb2_module+set}" = set; then fi done if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $withval for --with-bdb2_module" 1>&2; exit 1; } + { echo "configure: error: bad value $withval for --with-dnssrv_module" 1>&2; exit 1; } fi - ol_with_bdb2_module="$ol_arg" + ol_with_dnssrv_module="$ol_arg" else - ol_with_bdb2_module="static" + ol_with_dnssrv_module="static" fi -# end --with-bdb2_module +# end --with-dnssrv_module # OpenLDAP --enable-ldap # Check whether --enable-ldap or --disable-ldap was given. @@ -1816,7 +1893,7 @@ if test "${with_ldbm_api+set}" = set; then withval="$with_ldbm_api" ol_arg=invalid - for ol_val in auto db2 db mdbm gdbm ndbm manual ; do + for ol_val in auto berkeley bcompat mdbm gdbm ; do if test "$withval" = "$ol_val" ; then ol_arg="$ol_val" fi @@ -1873,7 +1950,6 @@ else fi # end --with-ldbm_type - # OpenLDAP --enable-passwd # Check whether --enable-passwd or --disable-passwd was given. if test "${enable_passwd+set}" = set; then @@ -1915,47 +1991,6 @@ else fi # end --with-passwd_module -# OpenLDAP --enable-perl - # Check whether --enable-perl or --disable-perl was given. -if test "${enable_perl+set}" = set; then - enableval="$enable_perl" - - ol_arg=invalid - for ol_val in auto yes no ; do - if test "$enableval" = "$ol_val" ; then - ol_arg="$ol_val" - fi - done - if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-perl" 1>&2; exit 1; } - fi - ol_enable_perl="$ol_arg" - -else - ol_enable_perl="no" -fi -# end --enable-perl -# OpenLDAP --with-perl_module - # Check whether --with-perl_module or --without-perl_module was given. -if test "${with_perl_module+set}" = set; then - withval="$with_perl_module" - - ol_arg=invalid - for ol_val in static dynamic ; do - if test "$withval" = "$ol_val" ; then - ol_arg="$ol_val" - fi - done - if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $withval for --with-perl_module" 1>&2; exit 1; } - fi - ol_with_perl_module="$ol_arg" - -else - ol_with_perl_module="static" -fi -# end --with-perl_module - # OpenLDAP --enable-shell # Check whether --enable-shell or --disable-shell was given. if test "${enable_shell+set}" = set; then @@ -1997,47 +2032,6 @@ else fi # end --with-shell_module -# OpenLDAP --enable-tcl - # Check whether --enable-tcl or --disable-tcl was given. -if test "${enable_tcl+set}" = set; then - enableval="$enable_tcl" - - ol_arg=invalid - for ol_val in auto yes no ; do - if test "$enableval" = "$ol_val" ; then - ol_arg="$ol_val" - fi - done - if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $enableval for --enable-tcl" 1>&2; exit 1; } - fi - ol_enable_tcl="$ol_arg" - -else - ol_enable_tcl="no" -fi -# end --enable-tcl -# OpenLDAP --with-tcl_module - # Check whether --with-tcl_module or --without-tcl_module was given. -if test "${with_tcl_module+set}" = set; then - withval="$with_tcl_module" - - ol_arg=invalid - for ol_val in static dynamic ; do - if test "$withval" = "$ol_val" ; then - ol_arg="$ol_val" - fi - done - if test "$ol_arg" = "invalid" ; then - { echo "configure: error: bad value $withval for --with-tcl_module" 1>&2; exit 1; } - fi - ol_with_tcl_module="$ol_arg" - -else - ol_with_tcl_module="static" -fi -# end --with-tcl_module - # Check whether --with-xxslurpdoptions or --without-xxslurpdoptions was given. if test "${with_xxslurpdoptions+set}" = set; then @@ -2119,20 +2113,11 @@ else fi -# validate options -if test $ol_enable_dns = yes ; then - if test $ol_enable_referrals = no ; then - { echo "configure: error: DNS requires --enable-referrals" 1>&2; exit 1; } - fi - if test $ol_enable_referrals = auto ; then - echo "configure: warning: DNS requires referrals, adding --enable-referrals" 1>&2 - ol_enable_referrals=yes - fi -fi +# validate options if test $ol_enable_slapd = no ; then - if test $ol_enable_bdb2 = yes ; then - echo "configure: warning: slapd disabled, ignoring --enable-bdb2 argument" 1>&2 + if test $ol_enable_dnssrv = yes ; then + echo "configure: warning: slapd disabled, ignoring --enable-dnssrv argument" 1>&2 fi if test $ol_enable_ldap = yes ; then echo "configure: warning: slapd disabled, ignoring --enable-ldap argument" 1>&2 @@ -2143,15 +2128,9 @@ if test $ol_enable_slapd = no ; then if test $ol_enable_passwd = yes ; then echo "configure: warning: slapd disabled, ignoring --enable-passwd argument" 1>&2 fi - if test $ol_enable_perl = yes ; then - echo "configure: warning: slapd disabled, ignoring --enable-perl argument" 1>&2 - fi if test $ol_enable_shell = yes ; then echo "configure: warning: slapd disabled, ignoring --enable-shell argument" 1>&2 fi - if test $ol_enable_tcl = yes ; then - echo "configure: warning: slapd disabled, ignoring --enable-tcl argument" 1>&2 - fi if test $ol_enable_modules = yes ; then echo "configure: warning: slapd disabled, ignoring --enable-modules argument" 1>&2 fi @@ -2173,17 +2152,14 @@ if test $ol_enable_slapd = no ; then if test $ol_enable_aci = yes ; then echo "configure: warning: slapd disabled, ignoring --enable-aci argument" 1>&2 fi - if test $ol_enable_discreteaci = yes ; then - echo "configure: warning: slapd disabled, ignoring --enable-discreteaci argument" 1>&2 - fi if test $ol_with_ldbm_api != auto ; then echo "configure: warning: slapd disabled, ignoring --with-ldbm-api argument" 1>&2 fi if test $ol_with_ldbm_type != auto ; then echo "configure: warning: slapd disabled, ignoring --with-ldbm-type argument" 1>&2 fi - if test $ol_with_bdb2_module != static ; then - echo "configure: warning: slapd disabled, ignoring --with-bdb2-module argument" 1>&2 + if test $ol_with_dnssrv_module != static ; then + echo "configure: warning: slapd disabled, ignoring --with-dnssrv-module argument" 1>&2 fi if test $ol_with_ldap_module != static ; then echo "configure: warning: slapd disabled, ignoring --with-ldap-module argument" 1>&2 @@ -2194,27 +2170,19 @@ if test $ol_enable_slapd = no ; then if test $ol_with_passwd_module != static ; then echo "configure: warning: slapd disabled, ignoring --with-passwd-module argument" 1>&2 fi - if test $ol_with_perl_module != static ; then - echo "configure: warning: slapd disabled, ignoring --with-perl-module argument" 1>&2 - fi if test $ol_with_shell_module != static ; then echo "configure: warning: slapd disabled, ignoring --with-shell-module argument" 1>&2 fi - if test $ol_with_tcl_module != static ; then - echo "configure: warning: slapd disabled, ignoring --with-tcl-module argument" 1>&2 - fi if test $ol_enable_slurpd = yes ; then { echo "configure: error: slurpd requires slapd" 1>&2; exit 1; } fi # force settings to no - ol_enable_bdb2=no + ol_enable_dnssrv=no ol_enable_ldap=no ol_enable_ldbm=no ol_enable_passwd=no - ol_enable_perl=no ol_enable_shell=no - ol_enable_tcl=no ol_enable_modules=no ol_enable_multimaster=no @@ -2222,19 +2190,17 @@ if test $ol_enable_slapd = no ; then ol_enable_quipu=no ol_enable_rlookups=no ol_enable_aci=no - ol_enable_discreteaci=no ol_enable_wrappers=no + ol_enable_dynamic=no ol_with_ldbm_api=no ol_with_ldbm_type=no - ol_with_bdb2_module=static + ol_with_dnssrv_module=static ol_with_ldap_module=static ol_with_ldbm_module=static ol_with_passwd_module=static - ol_with_perl_module=static ol_with_shell_module=static - ol_with_tcl_module=static ol_enable_slurpd=no @@ -2252,16 +2218,11 @@ elif test $ol_enable_ldbm = no ; then echo "configure: warning: LDBM disabled, ignoring --with-ldbm-module argument" 1>&2 fi - if test $ol_enable_bdb2 = yes ; then - { echo "configure: error: BDB2 requires --enable-ldbm" 1>&2; exit 1; } - fi - if test $ol_enable_modules != yes -a \ + $ol_enable_dnssrv = no -a \ $ol_enable_ldap = no -a \ $ol_enable_passwd = no -a \ - $ol_enable_perl = no -a \ - $ol_enable_shell = no -a \ - $ol_enable_tcl = no ; then + $ol_enable_shell = no ; then { echo "configure: error: slapd requires a backend" 1>&2; exit 1; } fi @@ -2269,26 +2230,8 @@ elif test $ol_enable_ldbm = no ; then ol_with_ldbm_type=no ol_with_ldbm_module=static -elif test $ol_enable_bdb2 = yes ; then - - if test $ol_with_ldbm_api != auto -a \ - $ol_with_ldbm_api != db2 ; then - { echo "configure: error: BDB2 requires LDBM API DB2" 1>&2; exit 1; } - fi - - ol_with_ldbm_api=db2 - else - - if test $ol_enable_bdb2 != no ; then - if test $ol_with_ldbm_api != auto -a \ - $ol_with_ldbm_api != db2 ; then - echo "configure: warning: BDB2 requires LDBM api db2 or auto" 1>&2 - ol_enable_bdb2=no - fi - fi - - if test $ol_with_ldbm_api = gdbm -a \ + if test $ol_with_ldbm_api = gdbm -a \ $ol_with_ldbm_type = btree ; then { echo "configure: error: GDBM only supports LDBM type hash" 1>&2; exit 1; } fi @@ -2308,52 +2251,67 @@ if test $ol_enable_slurpd = yes ; then fi fi +if test $ol_enable_kbind = yes -o $ol_enable_kpasswd = yes ; then + if test $ol_with_kerberos = no ; then + { echo "configure: error: options require --with-kerberos" 1>&2; exit 1; } + fi +elif test $ol_enable_kbind = no -o $ol_enable_kpasswd = no ; then + if test $ol_with_kerberos != auto ; then + echo "configure: warning: Kerberos detection enabled unnecessarily" 1>&2; + else + ol_with_kerberos=no + fi +fi + +if test $ol_enable_spasswd = yes ; then + if test $ol_with_cyrus_sasl = no ; then + { echo "configure: error: options require --with-cyrus-sasl" 1>&2; exit 1; } + fi + ol_link_spasswd=yes +fi + echo "$ac_t""done" 1>&6 -## Initialize vars LDAP_LIBS= LDIF_LIBS= LDBM_LIBS= LTHREAD_LIBS= LUTIL_LIBS= +QUIPU_LIBS= SLAPD_LIBS= SLURPD_LIBS= BUILD_SLAPD=no BUILD_SLURPD=no -BUILD_BDB2=no +BUILD_QUIPU=no +BUILD_THREAD=no + +BUILD_DNSSRV=no BUILD_LDAP=no BUILD_LDBM=no BUILD_PASSWD=no -BUILD_PERL=no -BUILD_QUIPU=no BUILD_SHELL=no -BUILD_TCL=no -BUILD_THREAD=no -BUILD_BDB2_DYNAMIC=static +BUILD_DNSSRV_DYNAMIC=static BUILD_LDAP_DYNAMIC=static BUILD_LDBM_DYNAMIC=static BUILD_PASSWD_DYNAMIC=static -BUILD_PERL_DYNAMIC=static BUILD_SHELL_DYNAMIC=static -BUILD_TCL_DYNAMIC=static SLAPD_MODULES_LDFLAGS= SLAPD_MODULES_CPPFLAGS= SLAPD_MODULES_LIST= -SLAPD_PERL_LDFLAGS= -SLAPD_PERL_CPPFLAGS= - -KRB_LIBS= +KRB4_LIBS= +KRB5_LIBS= READLINE_LIBS= SASL_LIBS= TERMCAP_LIBS= TLS_LIBS= MODULES_LIBS= +AUTH_LIBS= @@ -2381,7 +2339,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2385: checking for $ac_word" >&5 +echo "configure:2343: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2433,7 +2391,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2437: checking for $ac_word" >&5 +echo "configure:2395: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2466,6 +2424,7 @@ fi + # Check whether --enable-fast-install or --disable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval="$enable_fast_install" @@ -2492,7 +2451,7 @@ fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2496: checking for $ac_word" >&5 +echo "configure:2455: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_RANLIB+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2522,7 +2481,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2526: checking for $ac_word" >&5 +echo "configure:2485: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2552,7 +2511,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2556: checking for $ac_word" >&5 +echo "configure:2515: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2603,7 +2562,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2607: checking for $ac_word" >&5 +echo "configure:2566: checking for $ac_word" >&5 if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2635,7 +2594,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2639: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5 +echo "configure:2598: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -2646,12 +2605,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 2650 "configure" +#line 2609 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:2655: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2614: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -2677,12 +2636,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2681: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2640: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2686: checking whether we are using GNU C" >&5 +echo "configure:2645: checking whether we are using GNU C" >&5 if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2691,7 +2650,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2695: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2654: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -2710,7 +2669,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2714: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2673: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2753,7 +2712,7 @@ ac_prog=ld if test "$ac_cv_prog_gcc" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 -echo "configure:2757: checking for ld used by GCC" >&5 +echo "configure:2716: checking for ld used by GCC" >&5 ac_prog=`($CC -print-prog-name=ld) 2>&5` case "$ac_prog" in # Accept absolute paths. @@ -2777,10 +2736,10 @@ echo "configure:2757: checking for ld used by GCC" >&5 esac elif test "$with_gnu_ld" = yes; then echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 -echo "configure:2781: checking for GNU ld" >&5 +echo "configure:2740: checking for GNU ld" >&5 else echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 -echo "configure:2784: checking for non-GNU ld" >&5 +echo "configure:2743: checking for non-GNU ld" >&5 fi if eval "test \"\${ac_cv_path_LD+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2814,9 +2773,8 @@ else echo "$ac_t""no" 1>&6 fi test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } - echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 -echo "configure:2820: checking if the linker ($LD) is GNU ld" >&5 +echo "configure:2778: checking if the linker ($LD) is GNU ld" >&5 if eval "test \"\${ac_cv_prog_gnu_ld+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2832,7 +2790,7 @@ echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 -echo "configure:2836: checking for BSD-compatible nm" >&5 +echo "configure:2794: checking for BSD-compatible nm" >&5 if eval "test \"\${ac_cv_path_NM+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2867,9 +2825,8 @@ fi NM="$ac_cv_path_NM" echo "$ac_t""$NM" 1>&6 - echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:2873: checking whether ln -s works" >&5 +echo "configure:2830: checking whether ln -s works" >&5 if eval "test \"\${ac_cv_prog_LN_S+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2889,6 +2846,17 @@ else echo "$ac_t""no" 1>&6 fi +if test $host != $build; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi + + +case "$target" in +NONE) lt_target="$host" ;; +*) lt_target="$target" ;; +esac # Check for any special flags to pass to ltconfig. libtool_flags="--cache-file=$cache_file" @@ -2898,7 +2866,7 @@ test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" libtool_flags="$libtool_flags --enable-dlopen" - +libtool_flags="$libtool_flags --enable-win32-dll" # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" @@ -2910,11 +2878,11 @@ test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" # Some flags need to be propagated to the compiler or linker for good # libtool support. -case "$host" in +case "$lt_target" in *-*-irix6*) # Find out which ABI we are using. - echo '#line 2917 "configure"' > conftest.$ac_ext - if { (eval echo configure:2918: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + echo '#line 2885 "configure"' > conftest.$ac_ext + if { (eval echo configure:2886: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case "`/usr/bin/file conftest.o`" in *32-bit*) LD="${LD-ld} -32" @@ -2935,19 +2903,19 @@ case "$host" in SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 -echo "configure:2939: checking whether the C compiler needs -belf" >&5 +echo "configure:2907: checking whether the C compiler needs -belf" >&5 if eval "test \"\${lt_cv_cc_needs_belf+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* lt_cv_cc_needs_belf=yes else @@ -2966,83 +2934,286 @@ echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 fi ;; - -esac - - -# Save cache, so that ltconfig can load it - - -# Actually configure libtool. ac_aux_dir is where install-sh is found. -CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ -LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ -LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ -DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ -${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ -$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ -|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } - -# Reload cache, that may have been modified by ltconfig - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - -# Redirect the config.log output again, so that the ltconfig log is not -# clobbered by the next message. -exec 5>>./config.log - - -for ac_prog in mawk gawk nawk awk -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 +*-*-cygwin* | *-*-mingw*) + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3005: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then +echo "configure:2942: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_DLLTOOL+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then - ac_cv_prog_AWK="$ac_prog" + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" break fi done IFS="$ac_save_ifs" fi fi -AWK="$ac_cv_prog_AWK" -if test -n "$AWK"; then - echo "$ac_t""$AWK" 1>&6 +DLLTOOL="$ac_cv_prog_DLLTOOL" +if test -n "$DLLTOOL"; then + echo "$ac_t""$DLLTOOL" 1>&6 else echo "$ac_t""no" 1>&6 fi -test -n "$AWK" && break -done -# test for ln hardlink support -echo $ac_n "checking whether ln works""... $ac_c" 1>&6 -echo "configure:3036: checking whether ln works" >&5 -if eval "test \"\${ol_cv_prog_LN_H+set}\" = set"; then +if test -z "$ac_cv_prog_DLLTOOL"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2974: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_DLLTOOL+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - rm -f conftest.src conftest.dst -echo "conftest" > conftest.src -if ln conftest.src conftest.dst 2>/dev/null -then - ol_cv_prog_LN_H="ln" + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else - ol_cv_prog_LN_H="cp" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_DLLTOOL="dlltool" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="false" +fi +fi +DLLTOOL="$ac_cv_prog_DLLTOOL" +if test -n "$DLLTOOL"; then + echo "$ac_t""$DLLTOOL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + DLLTOOL="false" +fi +fi + + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3009: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_AS+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AS="${ac_tool_prefix}as" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AS="$ac_cv_prog_AS" +if test -n "$AS"; then + echo "$ac_t""$AS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$ac_cv_prog_AS"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3041: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_AS+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AS="as" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="false" +fi +fi +AS="$ac_cv_prog_AS" +if test -n "$AS"; then + echo "$ac_t""$AS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + AS="false" +fi +fi + + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3076: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_OBJDUMP+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +OBJDUMP="$ac_cv_prog_OBJDUMP" +if test -n "$OBJDUMP"; then + echo "$ac_t""$OBJDUMP" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$ac_cv_prog_OBJDUMP"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3108: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_OBJDUMP+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_OBJDUMP="objdump" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_OBJDUMP" && ac_cv_prog_OBJDUMP="false" +fi +fi +OBJDUMP="$ac_cv_prog_OBJDUMP" +if test -n "$OBJDUMP"; then + echo "$ac_t""$OBJDUMP" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + OBJDUMP="false" +fi +fi + + ;; + +esac + + +# Save cache, so that ltconfig can load it + + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + +# Reload cache, that may have been modified by ltconfig + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log + + +for ac_prog in mawk gawk nawk awk +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3176: checking for $ac_word" >&5 +if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AWK="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AWK" && break +done + +# test for ln hardlink support +echo $ac_n "checking whether ln works""... $ac_c" 1>&6 +echo "configure:3207: checking whether ln works" >&5 +if eval "test \"\${ol_cv_prog_LN_H+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftest.src conftest.dst +echo "conftest" > conftest.src +if ln conftest.src conftest.dst 2>/dev/null +then + ol_cv_prog_LN_H="ln" +else + ol_cv_prog_LN_H="cp" fi rm -f conftest.src conftest.dst @@ -3055,7 +3226,7 @@ else fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:3059: checking whether ln -s works" >&5 +echo "configure:3230: checking whether ln -s works" >&5 if eval "test \"\${ac_cv_prog_LN_S+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3083,7 +3254,7 @@ fi # Extract the first word of "sendmail", so it can be a program name with args. set dummy sendmail; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3087: checking for $ac_word" >&5 +echo "configure:3258: checking for $ac_word" >&5 if eval "test \"\${ac_cv_path_SENDMAIL+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3091,7 +3262,7 @@ else /*) ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a path. ;; - ?:/*) + ?:/*) ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a dos path. ;; *) @@ -3119,7 +3290,7 @@ fi # Extract the first word of "vi", so it can be a program name with args. set dummy vi; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3123: checking for $ac_word" >&5 +echo "configure:3294: checking for $ac_word" >&5 if eval "test \"\${ac_cv_path_EDITOR+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3127,7 +3298,7 @@ else /*) ac_cv_path_EDITOR="$EDITOR" # Let the user override the test with a path. ;; - ?:/*) + ?:/*) ac_cv_path_EDITOR="$EDITOR" # Let the user override the test with a dos path. ;; *) @@ -3155,7 +3326,7 @@ fi # Extract the first word of "finger", so it can be a program name with args. set dummy finger; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3159: checking for $ac_word" >&5 +echo "configure:3330: checking for $ac_word" >&5 if eval "test \"\${ac_cv_path_FINGER+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3163,7 +3334,7 @@ else /*) ac_cv_path_FINGER="$FINGER" # Let the user override the test with a path. ;; - ?:/*) + ?:/*) ac_cv_path_FINGER="$FINGER" # Let the user override the test with a dos path. ;; *) @@ -3189,60 +3360,8 @@ else fi -ol_link_perl=no -if test $ol_enable_perl != no ; then - # Extract the first word of "perl", so it can be a program name with args. -set dummy perl; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3198: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_path_PERLBIN+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - case "$PERLBIN" in - /*) - ac_cv_path_PERLBIN="$PERLBIN" # Let the user override the test with a path. - ;; - ?:/*) - ac_cv_path_PERLBIN="$PERLBIN" # Let the user override the test with a dos path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_path_PERLBIN="$ac_dir/$ac_word" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_PERLBIN" && ac_cv_path_PERLBIN="/usr/bin/perl" - ;; -esac -fi -PERLBIN="$ac_cv_path_PERLBIN" -if test -n "$PERLBIN"; then - echo "$ac_t""$PERLBIN" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - - if test "no$PERLBIN" = "no" ; then - if test $ol_enable_perl = yes ; then - { echo "configure: error: could not locate perl" 1>&2; exit 1; } - fi - - else - SLAPD_PERL_LDFLAGS="`$PERLBIN -MExtUtils::Embed -e ldopts|sed -e s/-lc//`" - SLAPD_PERL_CPPFLAGS="`$PERLBIN -MExtUtils::Embed -e ccopts`" - - ol_link_perl=yes - fi -fi - echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:3246: checking how to run the C preprocessor" >&5 +echo "configure:3365: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -3257,13 +3376,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3267: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3386: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3274,13 +3393,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3403: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3291,13 +3410,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3301: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3420: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3335,9 +3454,9 @@ elif test $cross_compiling = yes -a $ol_enable_x_compile = no; then fi echo $ac_n "checking for AIX""... $ac_c" 1>&6 -echo "configure:3339: checking for AIX" >&5 +echo "configure:3458: checking for AIX" >&5 cat > conftest.$ac_ext <&6 -echo "configure:3363: checking for POSIXized ISC" >&5 +echo "configure:3482: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then @@ -3381,17 +3500,17 @@ fi ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 -echo "configure:3385: checking for minix/config.h" >&5 +echo "configure:3504: checking for minix/config.h" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3395: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3514: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3430,12 +3549,12 @@ fi echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 -echo "configure:3434: checking for Cygwin environment" >&5 +echo "configure:3553: checking for Cygwin environment" >&5 if eval "test \"\${ac_cv_cygwin+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3569: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else @@ -3462,19 +3581,19 @@ echo "$ac_t""$ac_cv_cygwin" 1>&6 CYGWIN= test "$ac_cv_cygwin" = yes && CYGWIN=yes echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 -echo "configure:3466: checking for mingw32 environment" >&5 +echo "configure:3585: checking for mingw32 environment" >&5 if eval "test \"\${ac_cv_mingw32+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else @@ -3490,19 +3609,19 @@ echo "$ac_t""$ac_cv_mingw32" 1>&6 MINGW32= test "$ac_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking for EMX OS/2 environment""... $ac_c" 1>&6 -echo "configure:3494: checking for EMX OS/2 environment" >&5 +echo "configure:3613: checking for EMX OS/2 environment" >&5 if eval "test \"\${ac_cv_emxos2+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_emxos2=yes else @@ -3521,7 +3640,7 @@ test "$ac_cv_emxos2" = yes && EMXOS2=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:3525: checking for executable suffix" >&5 +echo "configure:3644: checking for executable suffix" >&5 if eval "test \"\${ac_cv_exeext+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3531,7 +3650,7 @@ else rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= - if { (eval echo configure:3535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + if { (eval echo configure:3654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.C | *.o | *.obj | *.xcoff) ;; @@ -3552,13 +3671,13 @@ echo "$ac_t""${ac_cv_exeext}" 1>&6 ac_exeext=$EXEEXT echo $ac_n "checking for object suffix""... $ac_c" 1>&6 -echo "configure:3556: checking for object suffix" >&5 +echo "configure:3675: checking for object suffix" >&5 if eval "test \"\${ac_cv_objext+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftest* echo 'int i = 1;' > conftest.$ac_ext -if { (eval echo configure:3562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3681: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; @@ -3582,7 +3701,7 @@ EOF echo $ac_n "checking for be_app in -lbe""... $ac_c" 1>&6 -echo "configure:3586: checking for be_app in -lbe" >&5 +echo "configure:3705: checking for be_app in -lbe" >&5 ac_lib_var=`echo be'_'be_app | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3590,7 +3709,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lbe -lroot -lnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3627,7 +3746,7 @@ fi echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6 -echo "configure:3631: checking for ${CC-cc} option to accept ANSI C" >&5 +echo "configure:3750: checking for ${CC-cc} option to accept ANSI C" >&5 if eval "test \"\${am_cv_prog_cc_stdc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3644,7 +3763,7 @@ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIO do CC="$ac_save_CC $ac_arg" cat > conftest.$ac_ext < #include @@ -3681,7 +3800,7 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } EOF -if { (eval echo configure:3685: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3804: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_prog_cc_stdc="$ac_arg"; break else @@ -3715,7 +3834,7 @@ if test -z "${MKDEP}"; then OL_MKDEP="${CC-cc}" if test -z "${MKDEP_FLAGS}"; then echo $ac_n "checking for ${OL_MKDEP} depend flag""... $ac_c" 1>&6 -echo "configure:3719: checking for ${OL_MKDEP} depend flag" >&5 +echo "configure:3838: checking for ${OL_MKDEP} depend flag" >&5 if eval "test \"\${ol_cv_mkdep+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3725,7 +3844,7 @@ else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } \ + if { ac_try='$OL_MKDEP $flag conftest.c'; { (eval echo configure:3848: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \ | egrep '^conftest\.'"${ac_objext}" >/dev/null 2>&1 then if test ! -f conftest."${ac_object}" ; then @@ -3757,64 +3876,224 @@ if test "${ol_cv_mkdep}" = no ; then echo "configure: warning: do not know how to generate dependencies" 1>&2 fi -ol_link_modules=no -if test $ol_enable_modules != no ; then - for ac_hdr in ltdl.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3767: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo $ac_n "checking for afopen in -ls""... $ac_c" 1>&6 +echo "configure:3881: checking for afopen in -ls" >&5 +ac_lib_var=`echo s'_'afopen | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - cat > conftest.$ac_ext < conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char afopen(); + +int main() { +afopen() +; return 0; } EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then +if { (eval echo configure:3900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" + eval "ac_cv_lib_$ac_lib_var=yes" else - echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" + eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* +LIBS="$ac_save_LIBS" + fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <> confdefs.h <<\EOF +#define HAVE_AIX_SECURITY 1 EOF - + + else echo "$ac_t""no" 1>&6 fi -done - if test $ac_cv_header_ltdl_h = no ; then - { echo "configure: error: could not locate libtool ltdl.h" 1>&2; exit 1; } - - fi - echo $ac_n "checking for lt_dlinit in -lltdl""... $ac_c" 1>&6 -echo "configure:3810: checking for lt_dlinit in -lltdl" >&5 -ac_lib_var=`echo ltdl'_'lt_dlinit | sed 'y%./+-:%__p__%'` +for ac_func in getaddrinfo +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3931: checking for $ac_func" >&5 +if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +f = $ac_func; +#endif + +; return 0; } +EOF +if { (eval echo configure:3960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +if test $ac_cv_func_getaddrinfo = no ; then + if test $ol_enable_ipv6 = yes ; then + { echo "configure: error: IPv6 support requires getaddrinfo()" 1>&2; exit 1; } + fi + ol_enable_ipv6=no +fi + +if test $ol_enable_unix != no ; then + for ac_hdr in sys/un.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3997: checking for $ac_hdr" >&5 +if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4007: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + if test $ol_enable_unix = auto ; then + ol_enable_unix=$ac_cv_header_sys_un_h + elif test $ac_cv_header_sys_un_h = no ; then + { echo "configure: error: UNIX domain support requires sys/un.h" 1>&2; exit 1; } + fi +fi + +ol_link_modules=no +if test $ol_enable_modules != no ; then + for ac_hdr in ltdl.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4047: checking for $ac_hdr" >&5 +if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4057: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + if test $ac_cv_header_ltdl_h = no ; then + { echo "configure: error: could not locate libtool ltdl.h" 1>&2; exit 1; } + fi + + echo $ac_n "checking for lt_dlinit in -lltdl""... $ac_c" 1>&6 +echo "configure:4089: checking for lt_dlinit in -lltdl" >&5 +ac_lib_var=`echo ltdl'_'lt_dlinit | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lltdl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3840,41 +4119,39 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo ltdl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <> confdefs.h <<\EOF +#define HAVE_LIBLTDL 1 EOF - LIBS="-lltdl $LIBS" - + else echo "$ac_t""no" 1>&6 fi + if test "$ac_cv_lib_ltdl_lt_dlinit" = no ; then { echo "configure: error: could not locate libtool -lltdl" 1>&2; exit 1; } fi ol_link_modules=yes else - ol_with_bdb2_module=static + ol_with_dnssrv_module=static ol_with_ldap_module=static ol_with_ldbm_module=static ol_with_passwd_module=static - ol_with_perl_module=static ol_with_shell_module=static - ol_with_tcl_module=static fi # test for EBCDIC echo $ac_n "checking for EBCDIC""... $ac_c" 1>&6 -echo "configure:3872: checking for EBCDIC" >&5 +echo "configure:4149: checking for EBCDIC" >&5 if eval "test \"\${ol_cv_cpp_ebcdic+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4164: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3907,12 +4184,12 @@ EOF fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:3911: checking for ANSI C header files" >&5 +echo "configure:4188: checking for ANSI C header files" >&5 if eval "test \"\${ol_cv_header_stdc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -3920,7 +4197,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3924: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4201: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3937,7 +4214,7 @@ rm -f conftest* if test $ol_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -3955,7 +4232,7 @@ fi if test $ol_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -3976,7 +4253,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #ifndef HAVE_EBCDIC @@ -3994,7 +4271,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:3998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4275: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -4028,12 +4305,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:4032: checking for $ac_hdr that defines DIR" >&5 +echo "configure:4309: checking for $ac_hdr that defines DIR" >&5 if eval "test \"\${ac_cv_header_dirent_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -4041,7 +4318,7 @@ int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:4045: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4322: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -4066,7 +4343,7 @@ done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:4070: checking for opendir in -ldir" >&5 +echo "configure:4347: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4074,7 +4351,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4107,7 +4384,7 @@ fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:4111: checking for opendir in -lx" >&5 +echo "configure:4388: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4115,7 +4392,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4149,12 +4426,12 @@ fi fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:4153: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:4430: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"\${ac_cv_header_sys_wait_h+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -4170,7 +4447,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:4174: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4451: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -4191,12 +4468,12 @@ EOF fi echo $ac_n "checking POSIX termios""... $ac_c" 1>&6 -echo "configure:4195: checking POSIX termios" >&5 +echo "configure:4472: checking POSIX termios" >&5 if eval "test \"\${am_cv_sys_posix_termios+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -4206,7 +4483,7 @@ int main() { tcgetattr(0, 0); ; return 0; } EOF -if { (eval echo configure:4210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_sys_posix_termios=yes else @@ -4222,7 +4499,7 @@ echo "$ac_t""$am_cv_sys_posix_termios" 1>&6 echo $ac_n "checking whether use of TIOCGWINSZ requires sys/ioctl.h""... $ac_c" 1>&6 -echo "configure:4226: checking whether use of TIOCGWINSZ requires sys/ioctl.h" >&5 +echo "configure:4503: checking whether use of TIOCGWINSZ requires sys/ioctl.h" >&5 if eval "test \"\${am_cv_sys_tiocgwinsz_needs_sys_ioctl_h+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4231,7 +4508,7 @@ else gwinsz_in_termios_h=no if test $am_cv_sys_posix_termios = yes; then cat > conftest.$ac_ext < # include @@ -4251,7 +4528,7 @@ rm -f conftest* if test $gwinsz_in_termios_h = no; then cat > conftest.$ac_ext < # include @@ -4290,12 +4567,15 @@ for ac_hdr in \ arpa/inet.h \ arpa/nameser.h \ assert.h \ + conio.h \ crypt.h \ + direct.h \ errno.h \ fcntl.h \ filio.h \ getopt.h \ grp.h \ + io.h \ libutil.h \ limits.h \ locale.h \ @@ -4304,6 +4584,7 @@ for ac_hdr in \ memory.h \ psap.h \ pwd.h \ + process.h \ resolv.h \ sgtty.h \ shadow.h \ @@ -4325,21 +4606,22 @@ for ac_hdr in \ syslog.h \ termios.h \ unistd.h \ + winsock.h \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4333: checking for $ac_hdr" >&5 +echo "configure:4615: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4343: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4625: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4368,13 +4650,107 @@ done +echo $ac_n "checking for sigset in -lV3""... $ac_c" 1>&6 +echo "configure:4655: checking for sigset in -lV3" >&5 +ac_lib_var=`echo V3'_'sigset | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lV3 $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo V3 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + +if test $ac_cv_header_winsock_h = yes; then + echo $ac_n "checking for winsock""... $ac_c" 1>&6 +echo "configure:4704: checking for winsock" >&5 +if eval "test \"\${ol_cv_winsock+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + + socket(0,0,0); + select(0,NULL,NULL,NULL,NULL); + closesocket(0); + gethostname(NULL,0); + +; return 0; } +EOF +if { (eval echo configure:4721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_winsock=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_winsock=no +fi +rm -f conftest*] +fi + +echo "$ac_t""$ol_cv_winsock" 1>&6 + + if test $ol_cv_winsock = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_WINSOCK 1 +EOF + + ac_cv_func_socket=yes + ac_cv_func_select=yes + ac_cv_func_closesocket=yes + ac_cv_func_gethostname=yes + fi +fi + + echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:4373: checking for socket" >&5 +echo "configure:4749: checking for socket" >&5 if eval "test \"\${ac_cv_func_socket+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4778: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -4417,7 +4793,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6 -echo "configure:4421: checking for main in -lsocket" >&5 +echo "configure:4797: checking for main in -lsocket" >&5 ac_lib_var=`echo socket'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4425,14 +4801,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4460,7 +4836,7 @@ else fi echo $ac_n "checking for main in -lnet""... $ac_c" 1>&6 -echo "configure:4464: checking for main in -lnet" >&5 +echo "configure:4840: checking for main in -lnet" >&5 ac_lib_var=`echo net'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4468,14 +4844,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4502,27 +4878,23 @@ else echo "$ac_t""no" 1>&6 fi - echo $ac_n "checking for socket in -lnet""... $ac_c" 1>&6 -echo "configure:4507: checking for socket in -lnet" >&5 -ac_lib_var=`echo net'_'socket | sed 'y%./+-:%__p__%'` + echo $ac_n "checking for main in -lnsl_s""... $ac_c" 1>&6 +echo "configure:4883: checking for main in -lnsl_s" >&5 +ac_lib_var=`echo nsl_s'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lnet $LIBS" +LIBS="-lnsl_s $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4898: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4537,35 +4909,35 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo net | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + ac_tr_lib=HAVE_LIB`echo nsl_s | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi - echo $ac_n "checking for main in -lnsl_s""... $ac_c" 1>&6 -echo "configure:4554: checking for main in -lnsl_s" >&5 -ac_lib_var=`echo nsl_s'_'main | sed 'y%./+-:%__p__%'` + echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 +echo "configure:4926: checking for main in -lnsl" >&5 +ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lnsl_s $LIBS" +LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4580,35 +4952,39 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo nsl_s | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi - echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 -echo "configure:4597: checking for main in -lnsl" >&5 -ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'` + echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6 +echo "configure:4969: checking for socket in -linet" >&5 +ac_lib_var=`echo inet'_'socket | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lnsl $LIBS" +LIBS="-linet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4988: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4623,54 +4999,7 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&6 -fi - - echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6 -echo "configure:4640: checking for socket in -linet" >&5 -ac_lib_var=`echo inet'_'socket | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-linet $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo inet | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + ac_tr_lib=HAVE_LIB`echo inet | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 -echo "configure:4687: checking for main in -lgen" >&5 +echo "configure:5016: checking for main in -lgen" >&5 ac_lib_var=`echo gen'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4691,14 +5020,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lgen $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4730,12 +5059,12 @@ fi echo $ac_n "checking for select""... $ac_c" 1>&6 -echo "configure:4734: checking for select" >&5 +echo "configure:5063: checking for select" >&5 if eval "test \"\${ac_cv_func_select+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5092: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_select=yes" else @@ -4780,8 +5109,9 @@ else fi -echo $ac_n "checking types of arguments for select()""... $ac_c" 1>&6 -echo "configure:4785: checking types of arguments for select()" >&5 +if test "${ac_cv_header_winsock_h}" != yes; then + echo $ac_n "checking types of arguments for select()""... $ac_c" 1>&6 +echo "configure:5115: checking types of arguments for select()" >&5 if eval "test \"\${ac_cv_func_select_arg234+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4795,7 +5125,7 @@ else for ac_cv_func_select_arg1 in 'int' 'size_t' 'unsigned long' 'unsigned'; do for ac_cv_func_select_arg5 in 'struct timeval *' 'const struct timeval *'; do cat > conftest.$ac_ext < @@ -4814,7 +5144,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:4818: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5148: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_not_found=no ; break 3 else @@ -4852,23 +5182,24 @@ EOF EOF +fi for ac_hdr in regex.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4862: checking for $ac_hdr" >&5 +echo "configure:5193: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4872: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5203: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4898,12 +5229,12 @@ if test "$ac_cv_header_regex_h" != yes ; then { echo "configure: error: POSIX regex.h required." 1>&2; exit 1; } fi echo $ac_n "checking for regfree""... $ac_c" 1>&6 -echo "configure:4902: checking for regfree" >&5 +echo "configure:5233: checking for regfree" >&5 if eval "test \"\${ac_cv_func_regfree+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5262: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_regfree=yes" else @@ -4950,7 +5281,7 @@ fi echo $ac_n "checking for compatible POSIX regex""... $ac_c" 1>&6 -echo "configure:4954: checking for compatible POSIX regex" >&5 +echo "configure:5285: checking for compatible POSIX regex" >&5 if eval "test \"\${ol_cv_c_posix_regex+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4959,7 +5290,7 @@ else ol_cv_c_posix_regex=cross else cat > conftest.$ac_ext < @@ -4985,7 +5316,7 @@ main() return rc; } EOF -if { (eval echo configure:4989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_c_posix_regex=yes else @@ -5005,69 +5336,22 @@ if test "$ol_cv_c_posix_regex" = no ; then { echo "configure: error: broken POSIX regex!" 1>&2; exit 1; } fi -echo $ac_n "checking for sigset in -lV3""... $ac_c" 1>&6 -echo "configure:5010: checking for sigset in -lV3" >&5 -ac_lib_var=`echo V3'_'sigset | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lV3 $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo V3 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&6 -fi - - -echo $ac_n "checking for res_search""... $ac_c" 1>&6 -echo "configure:5058: checking for res_search" >&5 -if eval "test \"\${ac_cv_func_res_search+set}\" = set"; then +ol_link_dnssrv=no +echo $ac_n "checking for res_query""... $ac_c" 1>&6 +echo "configure:5342: checking for res_query" >&5 +if eval "test \"\${ac_cv_func_res_query+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ -char res_search(); +char res_query(); char (*f)(); int main() { @@ -5075,55 +5359,55 @@ int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ -#if defined (__stub_res_search) || defined (__stub___res_search) +#if defined (__stub_res_query) || defined (__stub___res_query) choke me #else -f = res_search; +f = res_query; #endif ; return 0; } EOF -if { (eval echo configure:5087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5371: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_func_res_search=yes" + eval "ac_cv_func_res_query=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_func_res_search=no" + eval "ac_cv_func_res_query=no" fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_func_'res_search`\" = yes"; then +if eval "test \"`echo '$ac_cv_func_'res_query`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 fi -if test $ac_cv_func_res_search = no ; then - echo $ac_n "checking for res_search in -lbind""... $ac_c" 1>&6 -echo "configure:5108: checking for res_search in -lbind" >&5 -ac_lib_var=`echo bind'_'res_search | sed 'y%./+-:%__p__%'` +if test $ac_cv_func_res_query = no ; then + echo $ac_n "checking for res_query in -lbind""... $ac_c" 1>&6 +echo "configure:5392: checking for res_query in -lbind" >&5 +ac_lib_var=`echo bind'_'res_query | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lbind $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5150,31 +5434,31 @@ else echo "$ac_t""no" 1>&6 fi - ac_cv_func_res_search=$ac_cv_lib_bind_res_search + ac_cv_func_res_query=$ac_cv_lib_bind_res_query fi -if test $ac_cv_func_res_search = no ; then - echo $ac_n "checking for __res_search in -lbind""... $ac_c" 1>&6 -echo "configure:5159: checking for __res_search in -lbind" >&5 -ac_lib_var=`echo bind'_'__res_search | sed 'y%./+-:%__p__%'` +if test $ac_cv_func_res_query = no ; then + echo $ac_n "checking for __res_query in -lbind""... $ac_c" 1>&6 +echo "configure:5443: checking for __res_query in -lbind" >&5 +ac_lib_var=`echo bind'_'__res_query | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lbind $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5201,31 +5485,31 @@ else echo "$ac_t""no" 1>&6 fi - ac_cv_func_res_search=$ac_cv_lib_bind___res_search + ac_cv_func_res_query=$ac_cv_lib_bind___res_query fi -if test $ac_cv_func_res_search = no ; then - echo $ac_n "checking for res_search in -lresolv""... $ac_c" 1>&6 -echo "configure:5210: checking for res_search in -lresolv" >&5 -ac_lib_var=`echo resolv'_'res_search | sed 'y%./+-:%__p__%'` +if test $ac_cv_func_res_query = no ; then + echo $ac_n "checking for res_query in -lresolv""... $ac_c" 1>&6 +echo "configure:5494: checking for res_query in -lresolv" >&5 +ac_lib_var=`echo resolv'_'res_query | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5252,38 +5536,40 @@ else echo "$ac_t""no" 1>&6 fi - ac_cv_func_res_search=$ac_cv_lib_resolv_res_search + ac_cv_func_res_query=$ac_cv_lib_resolv_res_query fi -if test "$ac_cv_func_res_search" = yes ; then +if test "$ac_cv_func_res_query" = yes ; then cat >> confdefs.h <<\EOF -#define HAVE_RES_SEARCH 1 +#define HAVE_RES_QUERY 1 EOF -elif test $ol_enable_dns = yes ; then - { echo "configure: error: --enable-dns requires res_search" 1>&2; exit 1; } -elif test $ol_enable_dns != no ; then - echo "configure: warning: no res_search, disabling DNS support" 1>&2 + + if test $ol_enable_dnssrv != no ; then + ol_link_dnssrv=yes + fi fi +if test "$ol_enable_dnssrv" = yes -a "$ol_link_dnssrv" = no ; then + { echo "configure: error: DNSSRV requires res_query()" 1>&2; exit 1; } +fi -# QUIPU if test $ol_enable_quipu != no ; then for ac_hdr in quipu/commonarg.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5277: checking for $ac_hdr" >&5 +echo "configure:5563: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5573: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5319,24 +5605,29 @@ done fi fi -ol_link_kerberos=no +ol_link_kbind=no +ol_link_kpasswd=no +ol_link_krb5=no +ol_link_krb4=no -if test $ol_with_kerberos = auto -o $ol_with_kerberos = k5 ; then - for ac_hdr in kerberosIV/krb.h kerberosIV/des.h +if test $ol_with_kerberos = auto -o $ol_with_kerberos = k5 \ + -o $ol_with_kerberos = k5only -o $ol_with_kerberos = k425 ; then + + for ac_hdr in krb5.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5330: checking for $ac_hdr" >&5 +echo "configure:5621: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5340: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5363,163 +5654,111 @@ fi done - if test $ac_cv_header_kerberosIV_krb_h = yes ; then - echo $ac_n "checking for main in -lkrb4""... $ac_c" 1>&6 -echo "configure:5369: checking for main in -lkrb4" >&5 -ac_lib_var=`echo krb4'_'main | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + if test $ac_cv_header_krb5_h = yes ; then + for ac_hdr in heim_err.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:5663: checking for $ac_hdr" >&5 +if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - ac_save_LIBS="$LIBS" -LIBS="-lkrb4 -lkrb5 -ldes425 $LIBS" -cat > conftest.$ac_ext < conftest.$ac_ext < EOF -if { (eval echo configure:5384: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:5673: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + eval "ac_cv_header_$ac_safe=yes" else + echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* -LIBS="$ac_save_LIBS" - fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 - have_k5=yes + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 -have_k5=no fi +done + if test $ac_cv_header_heim_err_h = yes ; then + krb5_impl=heimdal + else + krb5_impl=mit + fi - if test $have_k5 = yes ; then - ol_with_kerberos=found - ol_link_kerberos=yes - - KRB_LIBS="-lkrb4 -lkrb5 -ldes425" - - LIBS="$KRB_LIBS $LIBS" - - echo $ac_n "checking for des_debug in Kerberos libraries""... $ac_c" 1>&6 -echo "configure:5415: checking for des_debug in Kerberos libraries" >&5 -if eval "test \"\${ol_cv_var_des_debug+set}\" = set"; then + if test $krb5_impl = mit; then + echo $ac_n "checking for main in -lkrb5""... $ac_c" 1>&6 +echo "configure:5707: checking for main in -lkrb5" >&5 +ac_lib_var=`echo krb5'_'main | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - - save_LIBS="$LIBS" - LIBS="$KRB_LIBS $LIBS" - cat > conftest.$ac_ext < conftest.$ac_ext < -#include -extern int des_debug; - int main() { - -des_debug = 1; - +main() ; return 0; } EOF -if { (eval echo configure:5436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5722: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - ol_cv_var_des_debug=yes + eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - ol_cv_var_des_debug=no + eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* - LIBS="$save_LIBS" - -fi - -echo "$ac_t""$ol_cv_var_des_debug" 1>&6 - - if test $ol_cv_var_des_debug = yes ; then - cat >> confdefs.h <<\EOF -#define HAVE_DES_DEBUG 1 -EOF - - fi - - LIBS="$save_LIBS" - fi - fi -fi +LIBS="$ac_save_LIBS" -if test $ol_with_kerberos = auto -o $ol_with_kerberos = k4 ; then - for ac_hdr in krb.h des.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5469: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5479: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 +have_krb5=no fi -done - if test $ac_cv_header_krb_h = yes ; then - echo $ac_n "checking for main in -lkrb""... $ac_c" 1>&6 -echo "configure:5508: checking for main in -lkrb" >&5 -ac_lib_var=`echo krb'_'main | sed 'y%./+-:%__p__%'` + elif test $krb5_impl = heimdal; then + echo $ac_n "checking for main in -lkrb5""... $ac_c" 1>&6 +echo "configure:5747: checking for main in -lkrb5" >&5 +ac_lib_var=`echo krb5'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lkrb -ldes $LIBS" +LIBS="-lkrb5 -ldes -lasn1 -lroken -lcom_err $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5762: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5534,47 +5773,64 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - have_k4=yes + have_krb5=yes + KRB5_LIBS="-lkrb5 -ldes -lasn1 -lroken -lcom_err" else echo "$ac_t""no" 1>&6 -have_k4=no +have_krb5=no fi - if test $have_k4 = yes ; then - ol_with_kerberos=found - ol_link_kerberos=yes + cat >> confdefs.h <<\EOF +#define HAVE_HEIMDAL_KERBEROS 1 +EOF - KRB_LIBS="-lkrb -ldes" + else + have_krb5=no + echo "configure: warning: Unrecongized Kerberos5 Implementation" 1>&2 fi - fi -fi -if test $ol_link_kerberos = yes ; then - cat >> confdefs.h <<\EOF -#define HAVE_KERBEROS 1 + if test $have_krb5 = yes ; then + ol_link_krb5=yes + + cat >> confdefs.h <<\EOF +#define HAVE_KRB5 1 EOF + + if test $ol_enable_kpasswd != no ; then + ol_link_kpasswd=yes; + fi + + if test $ol_with_kerberos = k5only ; then + ol_with_kerberos=found + fi + + elif test $ol_with_kerberos != auto ; then + { echo "configure: error: Required Kerberos 5 support not available" 1>&2; exit 1; } + fi + + fi fi -ol_link_tls=no -if test $ol_with_tls != no ; then - - for ac_hdr in openssl/ssl.h ssl.h +if test $ol_link_krb5 = yes -a \ + \( $ol_with_kerberos = auto -o $ol_with_kerberos = k425 \) ; then + + for ac_hdr in kerberosIV/krb.h kerberosIV/des.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5568: checking for $ac_hdr" >&5 +echo "configure:5824: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5578: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5834: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5600,29 +5856,26 @@ else fi done - - if test $ac_cv_header_openssl_ssl_h = yes -o $ac_cv_header_ssl_h = yes ; then - echo $ac_n "checking for SSLeay_add_ssl_algorithms in -lssl""... $ac_c" 1>&6 -echo "configure:5607: checking for SSLeay_add_ssl_algorithms in -lssl" >&5 -ac_lib_var=`echo ssl'_'SSLeay_add_ssl_algorithms | sed 'y%./+-:%__p__%'` + + if test $ac_cv_header_kerberosIV_krb_h = yes ; then + if test $krb5_impl = mit; then + echo $ac_n "checking for main in -lkrb4""... $ac_c" 1>&6 +echo "configure:5864: checking for main in -lkrb4" >&5 +ac_lib_var=`echo krb4'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lssl -lcrypto $LIBS" +LIBS="-lkrb4 -ldes425 -lkrb5 -lcrypto -lcom_err $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5637,36 +5890,32 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - have_ssleay=yes - need_rsaref=no + have_k425=yes + KRB4_LIBS="-lkrb4 -ldes425" else echo "$ac_t""no" 1>&6 -have_ssleay=no +have_k425=no fi - - if test $have_ssleay = no ; then - echo $ac_n "checking for SSL_library_init in -lssl""... $ac_c" 1>&6 -echo "configure:5651: checking for SSL_library_init in -lssl" >&5 -ac_lib_var=`echo ssl'_'SSL_library_init | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + + elif test $krb5_impl = heimdal; then + echo $ac_n "checking for main in -lkrb4""... $ac_c" 1>&6 +echo "configure:5904: checking for main in -lkrb4" >&5 +ac_lib_var=`echo krb4'_'main | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lssl -lcrypto $LIBS" +LIBS="-lkrb4 -lkrb5 -ldes -lasn1 -lroken -lcom_err $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5681,37 +5930,148 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - have_ssleay=yes - need_rsaref=no + have_k425=yes + KRB4_LIBS="-lkrb4" else echo "$ac_t""no" 1>&6 -have_ssleay=no +have_k425=no fi + + else + have_425=no + echo "configure: warning: Unrecongized Kerberos5 Implementation" 1>&2 fi - if test $have_ssleay = no ; then - echo $ac_n "checking for ssl3_accept in -lssl""... $ac_c" 1>&6 -echo "configure:5696: checking for ssl3_accept in -lssl" >&5 -ac_lib_var=`echo ssl'_'ssl3_accept | sed 'y%./+-:%__p__%'` + if test $have_k425 = yes ; then + ol_with_kerberos=found + ol_link_krb4=yes + + cat >> confdefs.h <<\EOF +#define HAVE_KRB425 1 +EOF + + cat >> confdefs.h <<\EOF +#define HAVE_KRB4 1 +EOF + + + echo $ac_n "checking for des_debug in Kerberos libraries""... $ac_c" 1>&6 +echo "configure:5961: checking for des_debug in Kerberos libraries" >&5 +if eval "test \"\${ol_cv_var_des_debug+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + save_LIBS="$LIBS" + LIBS="$KRB4_LIBS $KRB5_LIBS $LIBS" + cat > conftest.$ac_ext < +#include +extern int des_debug; + +int main() { + +des_debug = 1; + +; return 0; } +EOF +if { (eval echo configure:5982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_var_des_debug=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_var_des_debug=no +fi +rm -f conftest* + LIBS="$save_LIBS" + +fi + +echo "$ac_t""$ol_cv_var_des_debug" 1>&6 + + if test $ol_cv_var_des_debug = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_DES_DEBUG 1 +EOF + + fi + + LIBS="$save_LIBS" + fi + fi +fi + +if test $ol_link_krb5 = yes ; then + ol_with_kerberos=found +fi + +if test $ol_with_kerberos = auto -o $ol_with_kerberos = k4 \ + -o $ol_with_kerberos = kth ; then + + for ac_hdr in krb.h des.h krb-archaeology.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:6021: checking for $ac_hdr" >&5 +if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:6031: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + if test $ac_cv_header_krb_h = yes ; then + echo $ac_n "checking for main in -lkrb""... $ac_c" 1>&6 +echo "configure:6060: checking for main in -lkrb" >&5 +ac_lib_var=`echo krb'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" -LIBS="-lssl -lcrypto -lRSAglue -lrsaref $LIBS" +LIBS="-lkrb -ldes $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6075: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5726,97 +6086,84 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - have_ssleay=yes - need_rsaref=yes + have_k4=yes else echo "$ac_t""no" 1>&6 -have_ssleay=no +have_k4=no fi - fi - if test $have_ssleay = yes ; then - ol_with_tls=found - ol_link_tls=yes + if test $have_k4 = yes ; then + ol_with_kerberos=found + ol_link_krb4=yes cat >> confdefs.h <<\EOF -#define HAVE_SSLEAY 1 +#define HAVE_KRB4 1 EOF - if test $need_rsaref = yes; then + KRB4_LIBS="-lkrb -ldes" + + if test $ac_cv_header_krb_archaeology_h = yes ; then cat >> confdefs.h <<\EOF -#define HAVE_RSAREF 1 +#define HAVE_KTH_KERBEROS 1 EOF - - TLS_LIBS="-lssl -lcrypto -lRSAglue -lrsaref" - else - TLS_LIBS="-lssl -lcrypto" fi fi fi fi -if test $ol_link_tls = yes ; then +if test $ol_link_krb4 = yes -a $ol_enable_kpasswd != no ; then + ol_link_kpasswd=yes; +fi + +if test $ol_link_krb4 = yes -o $ol_link_krb5 = yes ; then cat >> confdefs.h <<\EOF -#define HAVE_TLS 1 +#define HAVE_KERBEROS 1 EOF -fi -for ac_func in \ - ctime_r \ - gethostbyname_r gethostbyaddr_r \ +elif test $ol_with_kerberos != auto -a $ol_with_kerberos != no ; then + { echo "configure: error: Kerberos detection failed." 1>&2; exit 1; } +fi +ol_link_tls=no +if test $ol_with_tls != no ; then + + for ac_hdr in openssl/ssl.h ssl.h do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5775: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:6139: checking for $ac_hdr" >&5 +if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func(); -char (*f)(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -f = $ac_func; -#endif - -; return 0; } +#include <$ac_hdr> EOF -if { (eval echo configure:5804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:6149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then rm -rf conftest* - eval "ac_cv_func_$ac_func=yes" + eval "ac_cv_header_$ac_safe=yes" else + echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_func_$ac_func=no" + eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi - -if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 -echo "configure:5833: checking number of arguments of ctime_r" >&5 -if eval "test \"\${ol_cv_func_ctime_r_nargs+set}\" = set"; then + + if test $ac_cv_header_openssl_ssl_h = yes -o $ac_cv_header_ssl_h = yes ; then + echo $ac_n "checking for SSLeay_add_ssl_algorithms in -lssl""... $ac_c" 1>&6 +echo "configure:6178: checking for SSLeay_add_ssl_algorithms in -lssl" >&5 +ac_lib_var=`echo ssl'_'SSLeay_add_ssl_algorithms | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - cat > conftest.$ac_ext < -int main() { -time_t ti; char *buffer; ctime_r(&ti,buffer,32); -; return 0; } -EOF -if { (eval echo configure:5845: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - ol_cv_func_ctime_r_nargs=3 -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - cat > conftest.$ac_ext < conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char SSLeay_add_ssl_algorithms(); + int main() { -time_t ti; char *buffer; ctime_r(&ti,buffer); +SSLeay_add_ssl_algorithms() ; return 0; } EOF -if { (eval echo configure:5860: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - ol_cv_func_ctime_r_nargs=2 + eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - ol_cv_func_ctime_r_nargs=0 -fi -rm -f conftest* + eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* -fi - -echo "$ac_t""$ol_cv_func_ctime_r_nargs" 1>&6 - if test $ol_cv_func_ctime_r_nargs -gt 1 ; then - cat >> confdefs.h <&6 + have_ssleay=yes + need_rsaref=no +else + echo "$ac_t""no" 1>&6 +have_ssleay=no +fi + + + if test $have_ssleay = no ; then + echo $ac_n "checking for SSL_library_init in -lssl""... $ac_c" 1>&6 +echo "configure:6222: checking for SSL_library_init in -lssl" >&5 +ac_lib_var=`echo ssl'_'SSL_library_init | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lssl -lcrypto $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + have_ssleay=yes + need_rsaref=no +else + echo "$ac_t""no" 1>&6 +have_ssleay=no +fi + + fi + + if test $have_ssleay = no ; then + echo $ac_n "checking for ssl3_accept in -lssl""... $ac_c" 1>&6 +echo "configure:6267: checking for ssl3_accept in -lssl" >&5 +ac_lib_var=`echo ssl'_'ssl3_accept | sed 'y%./+-:%__p__%'` +if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lssl -lcrypto -lRSAglue -lrsaref $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + have_ssleay=yes + need_rsaref=yes +else + echo "$ac_t""no" 1>&6 +have_ssleay=no +fi + + fi + + if test $have_ssleay = yes ; then + ol_with_tls=found + ol_link_tls=yes + + cat >> confdefs.h <<\EOF +#define HAVE_SSLEAY 1 +EOF + + + if test $need_rsaref = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_RSAREF 1 +EOF + + + TLS_LIBS="-lssl -lcrypto -lRSAglue -lrsaref" + else + TLS_LIBS="-lssl -lcrypto" + fi + fi + fi +fi + +if test $ol_link_tls = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_TLS 1 +EOF + +fi + +for ac_func in \ + ctime_r \ + gethostbyname_r gethostbyaddr_r \ + +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:6346: checking for $ac_func" >&5 +if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +f = $ac_func; +#endif + +; return 0; } +EOF +if { (eval echo configure:6375: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +if test "$ac_cv_func_ctime_r" = no ; then + ol_cv_func_ctime_r_nargs=0 +else + echo $ac_n "checking number of arguments of ctime_r""... $ac_c" 1>&6 +echo "configure:6404: checking number of arguments of ctime_r" >&5 +if eval "test \"\${ol_cv_func_ctime_r_nargs+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +time_t ti; char *buffer; ctime_r(&ti,buffer,32); +; return 0; } +EOF +if { (eval echo configure:6416: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ol_cv_func_ctime_r_nargs3=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_func_ctime_r_nargs3=no +fi +rm -f conftest* + + cat > conftest.$ac_ext < +int main() { +time_t ti; char *buffer; ctime_r(&ti,buffer); +; return 0; } +EOF +if { (eval echo configure:6435: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ol_cv_func_ctime_r_nargs2=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_func_ctime_r_nargs2=no +fi +rm -f conftest* + + if test $ol_cv_func_ctime_r_nargs3 = yes -a \ + $ol_cv_func_ctime_r_nargs2 = no ; then + + ol_cv_func_ctime_r_nargs=3 + + elif test $ol_cv_func_ctime_r_nargs3 = no -a \ + $ol_cv_func_ctime_r_nargs2 = yes ; then + + ol_cv_func_ctime_r_nargs=2 + + else + ol_cv_func_ctime_r_nargs=0 + fi + +fi + +echo "$ac_t""$ol_cv_func_ctime_r_nargs" 1>&6 + + if test $ol_cv_func_ctime_r_nargs -gt 1 ; then + cat >> confdefs.h <&6 -echo "configure:5886: checking number of arguments of gethostbyname_r" >&5 +echo "configure:6475: checking number of arguments of gethostbyname_r" >&5 if eval "test \"\${ol_cv_func_gethostbyname_r_nargs+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5901,15 +6490,19 @@ struct hostent hent; char buffer[BUFSIZE]; buffer, bufsize, &h_errno); ; return 0; } EOF -if { (eval echo configure:5905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6494: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - ol_cv_func_gethostbyname_r_nargs=5 + ol_cv_func_gethostbyname_r_nargs5=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - cat > conftest.$ac_ext < conftest.$ac_ext < #include @@ -5918,24 +6511,37 @@ else #define BUFSIZE (sizeof(struct hostent)+10) int main() { struct hostent hent;struct hostent *rhent; - char buffer[BUFSIZE]; - int bufsize=BUFSIZE;int h_errno; - (void)gethostbyname_r("localhost", &hent, buffer, bufsize, - &rhent, &h_errno); + char buffer[BUFSIZE]; + int bufsize=BUFSIZE;int h_errno; + (void)gethostbyname_r("localhost", &hent, buffer, bufsize, + &rhent, &h_errno); ; return 0; } EOF -if { (eval echo configure:5928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6521: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - ol_cv_func_gethostbyname_r_nargs=6 + ol_cv_func_gethostbyname_r_nargs6=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - ol_cv_func_gethostbyname_r_nargs=0 -fi -rm -f conftest* + ol_cv_func_gethostbyname_r_nargs6=no fi rm -f conftest* + + if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \ + $ol_cv_func_gethostbyname_r_nargs6 = no ; then + + ol_cv_func_gethostbyname_r_nargs=5 + + elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \ + $ol_cv_func_gethostbyname_r_nargs6 = yes ; then + + ol_cv_func_gethostbyname_r_nargs=6 + + else + ol_cv_func_gethostbyname_r_nargs=0 + fi + fi echo "$ac_t""$ol_cv_func_gethostbyname_r_nargs" 1>&6 @@ -5952,12 +6558,12 @@ fi if test "$ac_cv_func_gethostbyaddr_r" = yes ; then echo $ac_n "checking number of arguments of gethostbyaddr_r""... $ac_c" 1>&6 -echo "configure:5956: checking number of arguments of gethostbyaddr_r" >&5 +echo "configure:6562: checking number of arguments of gethostbyaddr_r" >&5 if eval "test \"\${ol_cv_func_gethostbyaddr_r_nargs+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5973,15 +6579,19 @@ struct hostent hent; char buffer[BUFSIZE]; alen, AF_INET, &hent, buffer, bufsize, &h_errno); ; return 0; } EOF -if { (eval echo configure:5977: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6583: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - ol_cv_func_gethostbyaddr_r_nargs=7 + ol_cv_func_gethostbyaddr_r_nargs7=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - cat > conftest.$ac_ext < conftest.$ac_ext < #include @@ -5990,30 +6600,43 @@ else #define BUFSIZE (sizeof(struct hostent)+10) int main() { struct hostent hent; - struct hostent *rhent; char buffer[BUFSIZE]; - struct in_addr add; - size_t alen=sizeof(struct in_addr); - int bufsize=BUFSIZE;int h_errno; - (void)gethostbyaddr_r( (void *)&(add.s_addr), - alen, AF_INET, &hent, buffer, bufsize, - &rhent, &h_errno); + struct hostent *rhent; char buffer[BUFSIZE]; + struct in_addr add; + size_t alen=sizeof(struct in_addr); + int bufsize=BUFSIZE;int h_errno; + (void)gethostbyaddr_r( (void *)&(add.s_addr), + alen, AF_INET, &hent, buffer, bufsize, + &rhent, &h_errno); ; return 0; } EOF -if { (eval echo configure:6003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6613: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - ol_cv_func_gethostbyaddr_r_nargs=8 + ol_cv_func_gethostbyaddr_r_nargs8=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - ol_cv_func_gethostbyaddr_r_nargs=0 + ol_cv_func_gethostbyaddr_r_nargs8=no fi rm -f conftest* -fi -rm -f conftest* -fi -echo "$ac_t""$ol_cv_func_gethostbyaddr_r_nargs" 1>&6 + if test $ol_cv_func_gethostbyaddr_r_nargs7 = yes -a \ + $ol_cv_func_gethostbyaddr_r_nargs8 = no ; then + + ol_cv_func_gethostbyaddr_r_nargs=7 + + elif test $ol_cv_func_gethostbyaddr_r_nargs7 = no -a \ + $ol_cv_func_gethostbyaddr_r_nargs8 = yes ; then + + ol_cv_func_gethostbyaddr_r_nargs=8 + + else + ol_cv_func_gethostbyaddr_r_nargs=0 + fi + +fi + +echo "$ac_t""$ol_cv_func_gethostbyaddr_r_nargs" 1>&6 if test $ol_cv_func_gethostbyaddr_r_nargs -gt 1 ; then cat >> confdefs.h <&6 +echo "configure:6676: checking for NT Threads" >&5 +if eval "test \"\${ol_cv_nt_threads+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + echo $ac_n "checking for _beginthread""... $ac_c" 1>&6 +echo "configure:6682: checking for _beginthread" >&5 +if eval "test \"\${ac_cv_func__beginthread+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _beginthread(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__beginthread) || defined (__stub____beginthread) +choke me +#else +f = _beginthread; +#endif + +; return 0; } +EOF +if { (eval echo configure:6711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func__beginthread=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__beginthread=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_beginthread`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ol_cv_nt_threads=yes +else + echo "$ac_t""no" 1>&6 +ol_cv_nt_threads=no +fi + + +fi + +echo "$ac_t""$ol_cv_nt_threads" 1>&6 + + if test $ol_cv_nt_threads = yes ; then + cat >> confdefs.h <<\EOF +#define HAVE_NT_THREADS 1 +EOF + + fi + + + if test "$ol_cv_nt_threads" = yes ; then + ol_link_threads=nt + ol_with_threads=found + ol_with_yielding_select=yes + + cat >> confdefs.h <<\EOF +#define HAVE_NT_SERVICE_MANAGER 1 +EOF + + cat >> confdefs.h <<\EOF +#define HAVE_NT_EVENT_LOG 1 +EOF + + fi + + if test $ol_with_threads = nt ; then + { echo "configure: error: could not locate NT Threads" 1>&2; exit 1; } + fi +fi + if test $ol_with_threads = auto -o $ol_with_threads = yes \ -o $ol_with_threads = posix ; then @@ -6050,17 +6767,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:6054: checking for $ac_hdr" >&5 +echo "configure:6771: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6064: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6781: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6089,19 +6806,19 @@ done if test $ac_cv_header_pthread_h = yes ; then echo $ac_n "checking POSIX thread version""... $ac_c" 1>&6 -echo "configure:6093: checking POSIX thread version" >&5 +echo "configure:6810: checking POSIX thread version" >&5 if eval "test \"\${ol_cv_pthread_version+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* this check could be improved */ # ifdef PTHREAD_ONCE_INIT - pthread_version_final + pthread_version_final; # endif EOF @@ -6117,13 +6834,13 @@ rm -f conftest* cat > conftest.$ac_ext < /* this check could be improved */ # ifdef pthread_once_init - pthread_version_draft4 + pthread_version_draft4; # endif EOF @@ -6170,12 +6887,12 @@ EOF echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6 -echo "configure:6174: checking for LinuxThreads pthread.h" >&5 +echo "configure:6891: checking for LinuxThreads pthread.h" >&5 if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -6202,16 +6919,16 @@ EOF echo $ac_n "checking for GNU Pth pthread.h""... $ac_c" 1>&6 -echo "configure:6206: checking for GNU Pth pthread.h" >&5 +echo "configure:6923: checking for GNU Pth pthread.h" >&5 if eval "test \"\${ol_cv_header_gnu_pth_pthread_h+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #ifdef _POSIX_THREAD_IS_GNU_PTH - __gnu_pth__ + __gnu_pth__; #endif EOF @@ -6236,17 +6953,17 @@ echo "$ac_t""$ol_cv_header_gnu_pth_pthread_h" 1>&6 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:6240: checking for $ac_hdr" >&5 +echo "configure:6957: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6250: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6967: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6276,14 +6993,14 @@ done echo $ac_n "checking for pthread_create in default libraries""... $ac_c" 1>&6 -echo "configure:6280: checking for pthread_create in default libraries" >&5 +echo "configure:6997: checking for pthread_create in default libraries" >&5 if eval "test \"\${ol_cv_pthread_create+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -6302,14 +7019,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6327,7 +7056,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_create=yes else @@ -6339,7 +7068,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -6362,14 +7091,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6388,7 +7129,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:6392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7133: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_create=yes else @@ -6413,7 +7154,7 @@ echo "$ac_t""$ol_cv_pthread_create" 1>&6 if test "$ol_link_threads" = no ; then # try -kthread echo $ac_n "checking for pthread link with -kthread""... $ac_c" 1>&6 -echo "configure:6417: checking for pthread link with -kthread" >&5 +echo "configure:7158: checking for pthread link with -kthread" >&5 if eval "test \"\${ol_cv_pthread_kthread+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6424,7 +7165,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -6443,14 +7184,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6468,7 +7221,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7225: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_kthread=yes else @@ -6480,7 +7233,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -6503,14 +7256,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6529,7 +7294,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:6533: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7298: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_kthread=yes else @@ -6559,7 +7324,7 @@ fi if test "$ol_link_threads" = no ; then # try -pthread echo $ac_n "checking for pthread link with -pthread""... $ac_c" 1>&6 -echo "configure:6563: checking for pthread link with -pthread" >&5 +echo "configure:7328: checking for pthread link with -pthread" >&5 if eval "test \"\${ol_cv_pthread_pthread+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6570,7 +7335,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -6589,14 +7354,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6614,7 +7391,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7395: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_pthread=yes else @@ -6626,7 +7403,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -6649,14 +7426,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6675,7 +7464,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:6679: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_pthread=yes else @@ -6705,7 +7494,7 @@ fi if test "$ol_link_threads" = no ; then # try -pthreads echo $ac_n "checking for pthread link with -pthreads""... $ac_c" 1>&6 -echo "configure:6709: checking for pthread link with -pthreads" >&5 +echo "configure:7498: checking for pthread link with -pthreads" >&5 if eval "test \"\${ol_cv_pthread_pthreads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6716,7 +7505,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -6735,14 +7524,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6760,7 +7561,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7565: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_pthreads=yes else @@ -6772,7 +7573,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -6795,14 +7596,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6821,7 +7634,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:6825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_pthreads=yes else @@ -6851,7 +7664,7 @@ fi if test "$ol_link_threads" = no ; then # try -mthreads echo $ac_n "checking for pthread link with -mthreads""... $ac_c" 1>&6 -echo "configure:6855: checking for pthread link with -mthreads" >&5 +echo "configure:7668: checking for pthread link with -mthreads" >&5 if eval "test \"\${ol_cv_pthread_mthreads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6862,7 +7675,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -6881,14 +7694,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6906,7 +7731,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_mthreads=yes else @@ -6918,7 +7743,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -6941,14 +7766,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -6967,7 +7804,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:6971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_mthreads=yes else @@ -6997,7 +7834,7 @@ fi if test "$ol_link_threads" = no ; then # try -thread echo $ac_n "checking for pthread link with -thread""... $ac_c" 1>&6 -echo "configure:7001: checking for pthread link with -thread" >&5 +echo "configure:7838: checking for pthread link with -thread" >&5 if eval "test \"\${ol_cv_pthread_thread+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7008,7 +7845,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7027,14 +7864,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7052,7 +7901,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7056: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7905: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_thread=yes else @@ -7064,7 +7913,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7087,14 +7936,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7113,7 +7974,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_thread=yes else @@ -7144,7 +8005,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthread -lmach -lexc -lc_r echo $ac_n "checking for pthread link with -lpthread -lmach -lexc -lc_r""... $ac_c" 1>&6 -echo "configure:7148: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5 +echo "configure:8009: checking for pthread link with -lpthread -lmach -lexc -lc_r" >&5 if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc_lc_r+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7155,7 +8016,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7174,14 +8035,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7199,7 +8072,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8076: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes else @@ -7211,7 +8084,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7234,14 +8107,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7260,7 +8145,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthread_lmach_lexc_lc_r=yes else @@ -7290,7 +8175,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthread -lmach -lexc echo $ac_n "checking for pthread link with -lpthread -lmach -lexc""... $ac_c" 1>&6 -echo "configure:7294: checking for pthread link with -lpthread -lmach -lexc" >&5 +echo "configure:8179: checking for pthread link with -lpthread -lmach -lexc" >&5 if eval "test \"\${ol_cv_pthread_lpthread_lmach_lexc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7301,7 +8186,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7320,14 +8205,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7345,7 +8242,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthread_lmach_lexc=yes else @@ -7357,7 +8254,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7380,14 +8277,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7406,7 +8315,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7410: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthread_lmach_lexc=yes else @@ -7437,7 +8346,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthread -Wl,-woff,85 echo $ac_n "checking for pthread link with -lpthread -Wl,-woff,85""... $ac_c" 1>&6 -echo "configure:7441: checking for pthread link with -lpthread -Wl,-woff,85" >&5 +echo "configure:8350: checking for pthread link with -lpthread -Wl,-woff,85" >&5 if eval "test \"\${ol_cv_pthread_lib_lpthread_woff+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7448,7 +8357,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7467,14 +8376,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7492,7 +8413,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8417: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lib_lpthread_woff=yes else @@ -7504,7 +8425,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7527,14 +8448,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7553,7 +8486,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7557: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8490: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lib_lpthread_woff=yes else @@ -7584,7 +8517,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthread echo $ac_n "checking for pthread link with -lpthread""... $ac_c" 1>&6 -echo "configure:7588: checking for pthread link with -lpthread" >&5 +echo "configure:8521: checking for pthread link with -lpthread" >&5 if eval "test \"\${ol_cv_pthread_lpthread+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7595,7 +8528,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7614,14 +8547,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7639,7 +8584,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthread=yes else @@ -7651,7 +8596,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7674,17 +8619,29 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ -#if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); -#else - status = pthread_create(&t, NULL, task, NULL); -#endif + status = pthread_attr_init(&attr); + if( status ) exit( status ); + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); if( status ) exit( status ); - /* make sure pthread_detach() isn't just a stub */ +#define ATTR &attr +#else +#if HAVE_PTHREADS_D4 +#define ATTR pthread_attr_default +#else +#define ATTR NULL +#endif +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); + if( status ) exit( status ); + + /* make sure pthread_detach() isn't just a stub */ #if HAVE_PTHREADS_D4 status = pthread_detach( &t ); #else @@ -7700,7 +8657,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthread=yes else @@ -7730,7 +8687,7 @@ fi if test "$ol_link_threads" = no ; then # try -lc_r echo $ac_n "checking for pthread link with -lc_r""... $ac_c" 1>&6 -echo "configure:7734: checking for pthread link with -lc_r" >&5 +echo "configure:8691: checking for pthread link with -lc_r" >&5 if eval "test \"\${ol_cv_pthread_lc_r+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7741,7 +8698,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7760,14 +8717,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7785,7 +8754,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7789: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lc_r=yes else @@ -7797,7 +8766,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7820,14 +8789,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7846,7 +8827,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7850: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lc_r=yes else @@ -7877,7 +8858,7 @@ fi if test "$ol_link_threads" = no ; then # try -threads echo $ac_n "checking for pthread link with -threads""... $ac_c" 1>&6 -echo "configure:7881: checking for pthread link with -threads" >&5 +echo "configure:8862: checking for pthread link with -threads" >&5 if eval "test \"\${ol_cv_pthread_threads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7888,7 +8869,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -7907,14 +8888,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7932,7 +8925,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:7936: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8929: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_threads=yes else @@ -7944,7 +8937,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -7967,14 +8960,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -7993,7 +8998,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:7997: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:9002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_threads=yes else @@ -8024,7 +9029,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthreads -lmach -lexc -lc_r echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc -lc_r""... $ac_c" 1>&6 -echo "configure:8028: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5 +echo "configure:9033: checking for pthread link with -lpthreads -lmach -lexc -lc_r" >&5 if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc_lc_r+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8035,7 +9040,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -8054,14 +9059,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8079,7 +9096,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:8083: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9100: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes else @@ -8091,7 +9108,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -8114,14 +9131,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8140,7 +9169,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:8144: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:9173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthreads_lmach_lexc_lc_r=yes else @@ -8170,7 +9199,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthreads -lmach -lexc echo $ac_n "checking for pthread link with -lpthreads -lmach -lexc""... $ac_c" 1>&6 -echo "configure:8174: checking for pthread link with -lpthreads -lmach -lexc" >&5 +echo "configure:9203: checking for pthread link with -lpthreads -lmach -lexc" >&5 if eval "test \"\${ol_cv_pthread_lpthreads_lmach_lexc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8181,7 +9210,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -8200,14 +9229,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8225,7 +9266,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:8229: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthreads_lmach_lexc=yes else @@ -8237,7 +9278,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -8260,14 +9301,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8286,7 +9339,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:8290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:9343: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthreads_lmach_lexc=yes else @@ -8316,7 +9369,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthreads -lexc echo $ac_n "checking for pthread link with -lpthreads -lexc""... $ac_c" 1>&6 -echo "configure:8320: checking for pthread link with -lpthreads -lexc" >&5 +echo "configure:9373: checking for pthread link with -lpthreads -lexc" >&5 if eval "test \"\${ol_cv_pthread_lpthreads_lexc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8327,7 +9380,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -8346,14 +9399,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8371,7 +9436,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:8375: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9440: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lpthreads_lexc=yes else @@ -8383,7 +9448,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -8406,14 +9471,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8432,7 +9509,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:8436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:9513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lpthreads_lexc=yes else @@ -8463,7 +9540,7 @@ fi if test "$ol_link_threads" = no ; then # try -lpthreads echo $ac_n "checking for pthread link with -lpthreads""... $ac_c" 1>&6 -echo "configure:8467: checking for pthread link with -lpthreads" >&5 +echo "configure:9544: checking for pthread link with -lpthreads" >&5 if eval "test \"\${ol_cv_pthread_lib_lpthreads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8474,7 +9551,7 @@ else if test "$cross_compiling" = yes; then cat > conftest.$ac_ext < @@ -8493,14 +9570,26 @@ int main() { /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8518,7 +9607,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:8522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_pthread_lib_lpthreads=yes else @@ -8530,7 +9619,7 @@ fi rm -f conftest* else cat > conftest.$ac_ext < @@ -8553,14 +9642,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -8579,7 +9680,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:8583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:9684: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_lib_lpthreads=yes else @@ -8621,12 +9722,12 @@ EOF for ac_func in sched_yield pthread_yield do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8625: checking for $ac_func" >&5 +echo "configure:9726: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9755: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8678,7 +9779,7 @@ done if test $ac_cv_func_sched_yield = no -a \ $ac_cv_func_pthread_yield = no ; then echo $ac_n "checking for sched_yield in -lrt""... $ac_c" 1>&6 -echo "configure:8682: checking for sched_yield in -lrt" >&5 +echo "configure:9783: checking for sched_yield in -lrt" >&5 ac_lib_var=`echo rt'_'sched_yield | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8686,7 +9787,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lrt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -8729,12 +9830,12 @@ fi for ac_func in thr_yield do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8733: checking for $ac_func" >&5 +echo "configure:9834: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8789,15 +9890,15 @@ done echo "configure: warning: could not locate sched_yield() or pthread_yield()" 1>&2 fi - for ac_func in pthread_kill + for ac_func in pthread_kill pthread_rwlock_destroy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8796: checking for $ac_func" >&5 +echo "configure:9897: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9926: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8847,13 +9948,13 @@ done echo $ac_n "checking for pthread_detach with ""... $ac_c" 1>&6 -echo "configure:8851: checking for pthread_detach with " >&5 +echo "configure:9952: checking for pthread_detach with " >&5 if eval "test \"\${ol_cv_func_pthread_detach+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -8865,7 +9966,7 @@ int main() { pthread_detach(NULL); ; return 0; } EOF -if { (eval echo configure:8869: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9970: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_func_pthread_detach=yes else @@ -8897,12 +9998,12 @@ EOF do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8901: checking for $ac_func" >&5 +echo "configure:10002: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8953,12 +10054,12 @@ done echo $ac_n "checking for pthread_kill_other_threads_np""... $ac_c" 1>&6 -echo "configure:8957: checking for pthread_kill_other_threads_np" >&5 +echo "configure:10058: checking for pthread_kill_other_threads_np" >&5 if eval "test \"\${ac_cv_func_pthread_kill_other_threads_np+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_pthread_kill_other_threads_np=yes" else @@ -9002,7 +10103,7 @@ else fi echo $ac_n "checking for LinuxThreads implementation""... $ac_c" 1>&6 -echo "configure:9006: checking for LinuxThreads implementation" >&5 +echo "configure:10107: checking for LinuxThreads implementation" >&5 if eval "test \"\${ol_cv_sys_linux_threads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -9015,7 +10116,7 @@ echo "$ac_t""$ol_cv_sys_linux_threads" 1>&6 echo $ac_n "checking for LinuxThreads consistency""... $ac_c" 1>&6 -echo "configure:9019: checking for LinuxThreads consistency" >&5 +echo "configure:10120: checking for LinuxThreads consistency" >&5 if eval "test \"\${ol_cv_linux_threads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -9040,7 +10141,7 @@ echo "$ac_t""$ol_cv_linux_threads" 1>&6 fi echo $ac_n "checking if pthread_create() works""... $ac_c" 1>&6 -echo "configure:9044: checking if pthread_create() works" >&5 +echo "configure:10145: checking if pthread_create() works" >&5 if eval "test \"\${ol_cv_pthread_create_works+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -9049,7 +10150,7 @@ else ol_cv_pthread_create_works=yes else cat > conftest.$ac_ext < @@ -9072,14 +10173,26 @@ int main(argc, argv) /* pthread test function */ pthread_t t; int status; +#if HAVE_PTHREADS_FINAL && defined(PTHREAD_CREATE_UNDETACHED) + /* This system (e.g. AIX) defaults detached; must override */ + pthread_attr_t attr; - /* make sure pthread_create() isn't just a stub */ + status = pthread_attr_init(&attr); + if( status ) exit( status ); + + status = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); + if( status ) exit( status ); + +#define ATTR &attr +#else #if HAVE_PTHREADS_D4 - status = pthread_create(&t, pthread_attr_default, task, NULL); +#define ATTR pthread_attr_default #else - status = pthread_create(&t, NULL, task, NULL); +#define ATTR NULL #endif - +#endif + /* make sure pthread_create() isn't just a stub */ + status = pthread_create(&t, ATTR, task, NULL); if( status ) exit( status ); /* make sure pthread_detach() isn't just a stub */ @@ -9098,7 +10211,7 @@ int main(argc, argv) } EOF -if { (eval echo configure:9102: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:10215: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_create_works=yes else @@ -9120,7 +10233,7 @@ echo "$ac_t""$ol_cv_pthread_create_works" 1>&6 if test $ol_with_yielding_select = auto ; then echo $ac_n "checking if select yields when using pthreads""... $ac_c" 1>&6 -echo "configure:9124: checking if select yields when using pthreads" >&5 +echo "configure:10237: checking if select yields when using pthreads" >&5 if eval "test \"\${ol_cv_pthread_select_yields+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -9129,7 +10242,7 @@ else ol_cv_pthread_select_yields=cross else cat > conftest.$ac_ext < @@ -9205,7 +10318,7 @@ int main(argc, argv) exit(2); } EOF -if { (eval echo configure:9209: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:10322: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_pthread_select_yields=no else @@ -9249,17 +10362,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9253: checking for $ac_hdr" >&5 +echo "configure:10366: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9263: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10376: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9289,12 +10402,12 @@ done ol_with_threads=found echo $ac_n "checking for cthread_fork""... $ac_c" 1>&6 -echo "configure:9293: checking for cthread_fork" >&5 +echo "configure:10406: checking for cthread_fork" >&5 if eval "test \"\${ac_cv_func_cthread_fork+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_cthread_fork=yes" else @@ -9340,7 +10453,7 @@ fi if test $ol_link_threads = no ; then echo $ac_n "checking for cthread_fork with -all_load""... $ac_c" 1>&6 -echo "configure:9344: checking for cthread_fork with -all_load" >&5 +echo "configure:10457: checking for cthread_fork with -all_load" >&5 if eval "test \"\${ol_cv_cthread_all_load+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -9348,7 +10461,7 @@ else save_LIBS="$LIBS" LIBS="-all_load $LIBS" cat > conftest.$ac_ext < int main() { @@ -9357,7 +10470,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:9361: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10474: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_cthread_all_load=yes else @@ -9402,17 +10515,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9406: checking for $ac_hdr" >&5 +echo "configure:10519: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9416: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10529: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9441,7 +10554,7 @@ done if test $ac_cv_header_pth_h = yes ; then echo $ac_n "checking for pth_version in -lpth""... $ac_c" 1>&6 -echo "configure:9445: checking for pth_version in -lpth" >&5 +echo "configure:10558: checking for pth_version in -lpth" >&5 ac_lib_var=`echo pth'_'pth_version | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9449,7 +10562,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpth $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9504,17 +10617,17 @@ if test $ol_with_threads = auto -o $ol_with_threads = yes \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9508: checking for $ac_hdr" >&5 +echo "configure:10621: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9518: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9542,7 +10655,7 @@ done if test $ac_cv_header_thread_h = yes -a $ac_cv_header_synch_h = yes ; then echo $ac_n "checking for thr_create in -lthread""... $ac_c" 1>&6 -echo "configure:9546: checking for thr_create in -lthread" >&5 +echo "configure:10659: checking for thr_create in -lthread" >&5 ac_lib_var=`echo thread'_'thr_create | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9550,7 +10663,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lthread $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10678: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9601,12 +10714,12 @@ EOF do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:9605: checking for $ac_func" >&5 +echo "configure:10718: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -9661,17 +10774,17 @@ done do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9665: checking for $ac_hdr" >&5 +echo "configure:10778: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9675: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10788: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9699,7 +10812,7 @@ done if test $ac_cv_header_lwp_lwp_h = yes ; then echo $ac_n "checking for lwp_create in -llwp""... $ac_c" 1>&6 -echo "configure:9703: checking for lwp_create in -llwp" >&5 +echo "configure:10816: checking for lwp_create in -llwp" >&5 ac_lib_var=`echo lwp'_'lwp_create | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9707,7 +10820,7 @@ else ac_save_LIBS="$LIBS" LIBS="-llwp $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9771,17 +10884,17 @@ if test $ol_with_threads = manual ; then do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9775: checking for $ac_hdr" >&5 +echo "configure:10888: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10898: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9810,12 +10923,12 @@ done for ac_func in sched_yield pthread_yield do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:9814: checking for $ac_func" >&5 +echo "configure:10927: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10956: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -9865,12 +10978,12 @@ done echo $ac_n "checking for LinuxThreads pthread.h""... $ac_c" 1>&6 -echo "configure:9869: checking for LinuxThreads pthread.h" >&5 +echo "configure:10982: checking for LinuxThreads pthread.h" >&5 if eval "test \"\${ol_cv_header_linux_threads+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -9900,17 +11013,17 @@ EOF do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9904: checking for $ac_hdr" >&5 +echo "configure:11017: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9914: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9940,17 +11053,17 @@ done do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9944: checking for $ac_hdr" >&5 +echo "configure:11057: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9954: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11067: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9980,17 +11093,17 @@ done do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:9984: checking for $ac_hdr" >&5 +echo "configure:11097: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9994: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11107: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10018,7 +11131,7 @@ done fi -if test $ol_link_threads != no ; then +if test $ol_link_threads != no -a $ol_link_threads != nt ; then cat >> confdefs.h <<\EOF #define REENTRANT 1 EOF @@ -10049,20 +11162,20 @@ EOF echo $ac_n "checking for thread specific errno""... $ac_c" 1>&6 -echo "configure:10053: checking for thread specific errno" >&5 +echo "configure:11166: checking for thread specific errno" >&5 if eval "test \"\${ol_cv_errno_thread_specific+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { errno = 0; ; return 0; } EOF -if { (eval echo configure:10066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11179: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_errno_thread_specific=yes else @@ -10078,20 +11191,20 @@ fi echo "$ac_t""$ol_cv_errno_thread_specific" 1>&6 echo $ac_n "checking for thread specific h_errno""... $ac_c" 1>&6 -echo "configure:10082: checking for thread specific h_errno" >&5 +echo "configure:11195: checking for thread specific h_errno" >&5 if eval "test \"\${ol_cv_h_errno_thread_specific+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { h_errno = 0; ; return 0; } EOF -if { (eval echo configure:10095: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11208: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_h_errno_thread_specific=yes else @@ -10138,77 +11251,29 @@ EOF fi - ol_link_ldbm=no -if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db2 ; then - echo $ac_n "checking for DB2 library""... $ac_c" 1>&6 -echo "configure:10146: checking for DB2 library" >&5 -if eval "test \"\${ol_cv_lib_db2+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ol_LIBS="$LIBS" - echo $ac_n "checking for db_open in -ldb""... $ac_c" 1>&6 -echo "configure:10152: checking for db_open in -ldb" >&5 -ac_lib_var=`echo db'_'db_open | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldb $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ol_cv_lib_db2=-ldb -else - echo "$ac_t""no" 1>&6 -ol_cv_lib_db2=no -fi - LIBS="$ol_LIBS" - -fi - -echo "$ac_t""$ol_cv_lib_db2" 1>&6 +if test $ol_with_ldbm_api = auto \ + -o $ol_with_ldbm_api = berkeley \ + -o $ol_with_ldbm_api = bcompat ; then -for ac_hdr in db.h + if test $ol_with_ldbm_api = bcompat; then \ + ol_cv_berkeley_db=no +for ac_hdr in db_185.h db.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:10202: checking for $ac_hdr" >&5 +echo "configure:11267: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11277: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10234,299 +11299,388 @@ else fi done -if test $ac_cv_header_db_h = yes ; then - echo $ac_n "checking if db.h is DB2""... $ac_c" 1>&6 -echo "configure:10240: checking if db.h is DB2" >&5 -if eval "test \"\${ol_cv_header_db2+set}\" = set"; then +if test $ac_cv_header_db_185_h = yes -o $ac_cv_header_db_h = yes; then + echo $ac_n "checking if Berkeley DB header compatibility""... $ac_c" 1>&6 +echo "configure:11305: checking if Berkeley DB header compatibility" >&5 +if eval "test \"\${ol_cv_header_db1+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < - /* this check could be improved */ -# ifdef DB_VERSION_MAJOR -# if DB_VERSION_MAJOR == 2 - __db_version_2 -# endif -# endif - +#if HAVE_DB_185_H +# include +#else +# include +#endif + + /* this check could be improved */ +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#if DB_VERSION_MAJOR == 1 + __db_version_1 +#endif + EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "__db_version_2" >/dev/null 2>&1; then + egrep "__db_version_1" >/dev/null 2>&1; then rm -rf conftest* - ol_cv_header_db2=yes + ol_cv_header_db1=yes else rm -rf conftest* - ol_cv_header_db2=no + ol_cv_header_db1=no fi rm -f conftest* fi -echo "$ac_t""$ol_cv_header_db2" 1>&6 -else - ol_cv_header_db2=no -fi - +echo "$ac_t""$ol_cv_header_db1" 1>&6 - - echo $ac_n "checking for Berkeley DB2""... $ac_c" 1>&6 -echo "configure:10278: checking for Berkeley DB2" >&5 -if eval "test \"\${ol_cv_berkeley_db2+set}\" = set"; then + if test ol_cv_header_db1=yes ; then + ol_cv_lib_db=no +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (default)""... $ac_c" 1>&6 +echo "configure:11348: checking for Berkeley DB link (default)" >&5 +if eval "test \"\${ol_cv_db_none+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test "$ol_cv_lib_db2" = no -o "$ol_cv_header_db2" = no ; then - ol_cv_berkeley_db2=no - else - ol_cv_berkeley_db2=yes - fi + ol_DB_LIB= + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" -fi + cat > conftest.$ac_ext <&6 - if test $ol_cv_berkeley_db2 = yes ; then - cat >> confdefs.h <<\EOF -#define HAVE_BERKELEY_DB2 1 -EOF +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif - fi +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif +#ifndef NULL +#define NULL ((void*)0) +#endif - if test $ol_cv_berkeley_db2 = yes ; then - ol_link_ldbm=db2 - ol_with_ldbm_api=db2 +int main() { - if test $ol_with_ldbm_type = hash ; then - cat >> confdefs.h <<\EOF -#define LDBM_USE_DBHASH 1 -EOF +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif - else - cat >> confdefs.h <<\EOF -#define LDBM_USE_DBBTREE 1 +; return 0; } EOF +if { (eval echo configure:11387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_db_none=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_db_none=no +fi +rm -f conftest* - fi + LIBS="$ol_LIBS" - if test $ol_cv_lib_db2 != yes ; then - LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db2" - fi - fi fi -ol_link_bdb2=no -if test $ol_link_ldbm = db2 -a $ol_enable_bdb2 != no ; then - ol_link_bdb2=yes +echo "$ac_t""$ol_cv_db_none" 1>&6 + + if test $ol_cv_db_none = yes ; then + ol_cv_lib_db=yes + fi fi -if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db ; then - echo $ac_n "checking for Berkeley DB library""... $ac_c" 1>&6 -echo "configure:10329: checking for Berkeley DB library" >&5 -if eval "test \"\${ol_cv_lib_db+set}\" = set"; then +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb)""... $ac_c" 1>&6 +echo "configure:11411: checking for Berkeley DB link (-ldb)" >&5 +if eval "test \"\${ol_cv_db_db+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - for ac_hdr in db1/db.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:10338: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < conftest.$ac_ext < + +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +int main() { + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10348: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then +if { (eval echo configure:11450: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" + ol_cv_db_db=yes else - echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" + ol_cv_db_db=no fi rm -f conftest* + + LIBS="$ol_LIBS" + fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 + +echo "$ac_t""$ol_cv_db_db" 1>&6 + + if test $ol_cv_db_db = yes ; then + ol_cv_lib_db=-ldb + fi fi -done - ol_LIBS="$LIBS" - echo $ac_n "checking for dbopen""... $ac_c" 1>&6 -echo "configure:10376: checking for dbopen" >&5 -if eval "test \"\${ac_cv_func_dbopen+set}\" = set"; then +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb3)""... $ac_c" 1>&6 +echo "configure:11474: checking for Berkeley DB link (-ldb3)" >&5 +if eval "test \"\${ol_cv_db_db3+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - cat > conftest.$ac_ext < conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dbopen(); -char (*f)(); + +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif int main() { -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dbopen) || defined (__stub___dbopen) -choke me +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); #else -f = dbopen; + (void) dbopen( NULL, 0, 0, 0, NULL); #endif ; return 0; } EOF -if { (eval echo configure:10405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_func_dbopen=yes" + ol_cv_db_db3=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_func_dbopen=no" + ol_cv_db_db3=no fi rm -f conftest* + + LIBS="$ol_LIBS" + fi -if eval "test \"`echo '$ac_cv_func_'dbopen`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ol_cv_lib_db=yes -else - echo "$ac_t""no" 1>&6 +echo "$ac_t""$ol_cv_db_db3" 1>&6 - echo $ac_n "checking for dbopen in -ldb1""... $ac_c" 1>&6 -echo "configure:10424: checking for dbopen in -ldb1" >&5 -ac_lib_var=`echo db1'_'dbopen | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then + if test $ol_cv_db_db3 = yes ; then + ol_cv_lib_db=-ldb3 + fi +fi + +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb2)""... $ac_c" 1>&6 +echo "configure:11537: checking for Berkeley DB link (-ldb2)" >&5 +if eval "test \"\${ol_cv_db_db2+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - ac_save_LIBS="$LIBS" -LIBS="-ldb1 $LIBS" -cat > conftest.$ac_ext < conftest.$ac_ext < +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif int main() { -dbopen() + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + ; return 0; } EOF -if { (eval echo configure:10443: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + ol_cv_db_db2=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ol_cv_db_db2=no fi rm -f conftest* -LIBS="$ac_save_LIBS" + + LIBS="$ol_LIBS" fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ol_cv_lib_db=-ldb1 -else - echo "$ac_t""no" 1>&6 - echo $ac_n "checking for dbopen in -ldb""... $ac_c" 1>&6 -echo "configure:10463: checking for dbopen in -ldb" >&5 -ac_lib_var=`echo db'_'dbopen | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "$ac_t""$ol_cv_db_db2" 1>&6 + + if test $ol_cv_db_db2 = yes ; then + ol_cv_lib_db=-ldb2 + fi +fi + +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb1)""... $ac_c" 1>&6 +echo "configure:11600: checking for Berkeley DB link (-ldb1)" >&5 +if eval "test \"\${ol_cv_db_db1+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - ac_save_LIBS="$LIBS" -LIBS="-ldb $LIBS" -cat > conftest.$ac_ext < conftest.$ac_ext < +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif int main() { -dbopen() + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + ; return 0; } EOF -if { (eval echo configure:10482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11639: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + ol_cv_db_db1=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ol_cv_db_db1=no fi rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ol_cv_lib_db=-ldb -else - echo "$ac_t""no" 1>&6 -ol_cv_lib_db=no -fi - -fi + LIBS="$ol_LIBS" - fi - LIBS="$ol_LIBS" +echo "$ac_t""$ol_cv_db_db1" 1>&6 + if test $ol_cv_db_db1 = yes ; then + ol_cv_lib_db=-ldb1 + fi fi -echo "$ac_t""$ol_cv_lib_db" 1>&6 + if test "$ol_cv_lib_db" != no ; then + ol_cv_berkeley_db=yes + fi + fi +fi -for ac_hdr in db_185.h + else + ol_cv_berkeley_db=no +for ac_hdr in db.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:10520: checking for $ac_hdr" >&5 +echo "configure:11674: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10530: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10552,105 +11706,436 @@ else fi done -if test "$ol_cv_header_db2" = yes ; then - - ol_cv_header_db=$ac_cv_header_db_185_h +if test $ac_cv_header_db_h = yes; then + ol_cv_lib_db=no +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (default)""... $ac_c" 1>&6 +echo "configure:11714: checking for Berkeley DB link (default)" >&5 +if eval "test \"\${ol_cv_db_none+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 else - ol_cv_header_db=$ac_cv_header_db_h + + ol_DB_LIB= + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" + + cat > conftest.$ac_ext < +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +int main() { + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } +EOF +if { (eval echo configure:11753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_db_none=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_db_none=no fi +rm -f conftest* + LIBS="$ol_LIBS" - - echo $ac_n "checking for Berkeley DB""... $ac_c" 1>&6 -echo "configure:10566: checking for Berkeley DB" >&5 -if eval "test \"\${ol_cv_berkeley_db+set}\" = set"; then +fi + +echo "$ac_t""$ol_cv_db_none" 1>&6 + + if test $ol_cv_db_none = yes ; then + ol_cv_lib_db=yes + fi +fi + +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb)""... $ac_c" 1>&6 +echo "configure:11777: checking for Berkeley DB link (-ldb)" >&5 +if eval "test \"\${ol_cv_db_db+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test "$ol_cv_lib_db" = no -o "$ol_cv_header_db" = no ; then - ol_cv_berkeley_db=no - else - ol_cv_berkeley_db=yes - fi + ol_DB_LIB=-ldb + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" -fi + cat > conftest.$ac_ext <&6 - if test $ol_cv_berkeley_db = yes ; then - cat >> confdefs.h <<\EOF -#define HAVE_BERKELEY_DB 1 -EOF +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif - fi +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif +#ifndef NULL +#define NULL ((void*)0) +#endif - if test $ol_cv_berkeley_db = yes ; then - ol_link_ldbm=db - ol_with_ldbm_api=db +int main() { - if test $ol_with_ldbm_type = hash ; then - cat >> confdefs.h <<\EOF -#define LDBM_USE_DBHASH 1 +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } EOF +if { (eval echo configure:11816: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_db_db=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_db_db=no +fi +rm -f conftest* - else - cat >> confdefs.h <<\EOF -#define LDBM_USE_DBBTREE 1 + LIBS="$ol_LIBS" + +fi + +echo "$ac_t""$ol_cv_db_db" 1>&6 + + if test $ol_cv_db_db = yes ; then + ol_cv_lib_db=-ldb + fi +fi + +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb3)""... $ac_c" 1>&6 +echo "configure:11840: checking for Berkeley DB link (-ldb3)" >&5 +if eval "test \"\${ol_cv_db_db3+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + ol_DB_LIB=-ldb3 + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" + + cat > conftest.$ac_ext < +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +int main() { + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } EOF +if { (eval echo configure:11879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_db_db3=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_db_db3=no +fi +rm -f conftest* - fi + LIBS="$ol_LIBS" - if test $ol_cv_lib_db != yes ; then - LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db" - fi +fi + +echo "$ac_t""$ol_cv_db_db3" 1>&6 + + if test $ol_cv_db_db3 = yes ; then + ol_cv_lib_db=-ldb3 fi fi -if test $ol_with_ldbm_api = manual ; then - ol_link_ldbm=yes +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb2)""... $ac_c" 1>&6 +echo "configure:11903: checking for Berkeley DB link (-ldb2)" >&5 +if eval "test \"\${ol_cv_db_db2+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + ol_DB_LIB=-ldb2 + ol_LIBS=$LIBS + LIBS="$ol_DB_LIB $LIBS" - echo "configure: warning: LDBM defines and link options must be set manually" 1>&2 + cat > conftest.$ac_ext <&6 -echo "configure:10619: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +int main() { + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } +EOF +if { (eval echo configure:11942: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ol_cv_db_db2=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_db_db2=no +fi +rm -f conftest* + + LIBS="$ol_LIBS" + +fi + +echo "$ac_t""$ol_cv_db_db2" 1>&6 + + if test $ol_cv_db_db2 = yes ; then + ol_cv_lib_db=-ldb2 + fi +fi + +if test $ol_cv_lib_db = no ; then + echo $ac_n "checking for Berkeley DB link (-ldb1)""... $ac_c" 1>&6 +echo "configure:11966: checking for Berkeley DB link (-ldb1)" >&5 +if eval "test \"\${ol_cv_db_db1+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - cat > conftest.$ac_ext < conftest.$ac_ext < + +#ifdef HAVE_DB_185_H +# include +#else +# include +#endif + +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +int main() { + +#if DB_VERSION_MAJOR > 2 + db_env_create( NULL, 0 ); +#elif DB_VERSION_MAJOR > 1 + db_appexit( NULL ); +#else + (void) dbopen( NULL, 0, 0, 0, NULL); +#endif + +; return 0; } EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10629: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then +if { (eval echo configure:12005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" + ol_cv_db_db1=yes else - echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" + ol_cv_db_db1=no fi rm -f conftest* + + LIBS="$ol_LIBS" + fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 + + if test $ol_cv_db_db1 = yes ; then + ol_cv_lib_db=-ldb1 + fi +fi + + + if test "$ol_cv_lib_db" != no ; then + ol_cv_berkeley_db=yes + echo $ac_n "checking for Berkeley DB thread support""... $ac_c" 1>&6 +echo "configure:12031: checking for Berkeley DB thread support" >&5 +if eval "test \"\${ol_cv_berkeley_db_thread+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + ol_LIBS="$LIBS" + if test $ol_cv_lib_db != yes ; then + LIBS="$ol_cv_lib_db" + fi + + if test "$cross_compiling" = yes; then + ol_cv_berkeley_db_thread=cross +else + cat > conftest.$ac_ext < +#endif +#ifndef NULL +#define NULL ((void *)0) +#endif +main() +{ + int rc; + u_int32_t flags = DB_CREATE | DB_THREAD; + + +#if DB_VERSION_MAJOR > 2 + DB_ENV *env = NULL; + + rc = db_env_create( &env, 0 ); + + if( rc == 0 ) { + rc = env->open( env, NULL, NULL, flags, 0 ); + } + +#else + DB_ENV env; + memset( &env, '\0', sizeof(env) ); + + rc = db_appinit( NULL, NULL, &env, flags ); + + if( rc == 0 ) { + db_appexit( &env ); + } +#endif + + return rc; +} +EOF +if { (eval echo configure:12085: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ol_cv_berkeley_db_thread=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ol_cv_berkeley_db_thread=no +fi +rm -fr conftest* +fi + + + LIBS="$ol_LIBS" + + if test $ol_cv_berkeley_db_thread != no ; then + cat >> confdefs.h <<\EOF +#define HAVE_BERKELEY_DB_THREAD 1 +EOF + + fi + +fi + +echo "$ac_t""$ol_cv_berkeley_db_thread" 1>&6 + fi +fi + + fi + + if test $ol_cv_berkeley_db != no ; then + cat >> confdefs.h <<\EOF +#define HAVE_BERKELEY_DB 1 +EOF + + + ol_link_ldbm=berkeley + ol_with_ldbm_api=db + + if test $ol_with_ldbm_type = hash ; then + cat >> confdefs.h <<\EOF +#define LDBM_USE_DBHASH 1 EOF - -else - echo "$ac_t""no" 1>&6 -fi -done + else + cat >> confdefs.h <<\EOF +#define LDBM_USE_DBBTREE 1 +EOF + + fi + + if test $ol_cv_lib_db != yes ; then + LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db" + fi + fi fi if test $ol_link_ldbm = no -a $ol_with_ldbm_type = btree ; then @@ -10660,18 +12145,18 @@ fi if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = mdbm ; then echo $ac_n "checking for MDBM library""... $ac_c" 1>&6 -echo "configure:10664: checking for MDBM library" >&5 +echo "configure:12149: checking for MDBM library" >&5 if eval "test \"\${ol_cv_lib_mdbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ol_LIBS="$LIBS" echo $ac_n "checking for mdbm_set_chain""... $ac_c" 1>&6 -echo "configure:10670: checking for mdbm_set_chain" >&5 +echo "configure:12155: checking for mdbm_set_chain" >&5 if eval "test \"\${ac_cv_func_mdbm_set_chain+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12184: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_mdbm_set_chain=yes" else @@ -10714,7 +12199,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for mdbm_set_chain in -lmdbm""... $ac_c" 1>&6 -echo "configure:10718: checking for mdbm_set_chain in -lmdbm" >&5 +echo "configure:12203: checking for mdbm_set_chain in -lmdbm" >&5 ac_lib_var=`echo mdbm'_'mdbm_set_chain | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -10722,7 +12207,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lmdbm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10768,17 +12253,17 @@ echo "$ac_t""$ol_cv_lib_mdbm" 1>&6 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:10772: checking for $ac_hdr" >&5 +echo "configure:12257: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12267: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10805,7 +12290,7 @@ fi done echo $ac_n "checking for db""... $ac_c" 1>&6 -echo "configure:10809: checking for db" >&5 +echo "configure:12294: checking for db" >&5 if eval "test \"\${ol_cv_mdbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -10838,18 +12323,18 @@ fi if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = gdbm ; then echo $ac_n "checking for GDBM library""... $ac_c" 1>&6 -echo "configure:10842: checking for GDBM library" >&5 +echo "configure:12327: checking for GDBM library" >&5 if eval "test \"\${ol_cv_lib_gdbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ol_LIBS="$LIBS" echo $ac_n "checking for gdbm_open""... $ac_c" 1>&6 -echo "configure:10848: checking for gdbm_open" >&5 +echo "configure:12333: checking for gdbm_open" >&5 if eval "test \"\${ac_cv_func_gdbm_open+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12362: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gdbm_open=yes" else @@ -10892,7 +12377,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gdbm_open in -lgdbm""... $ac_c" 1>&6 -echo "configure:10896: checking for gdbm_open in -lgdbm" >&5 +echo "configure:12381: checking for gdbm_open in -lgdbm" >&5 ac_lib_var=`echo gdbm'_'gdbm_open | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -10900,7 +12385,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lgdbm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10946,17 +12431,17 @@ echo "$ac_t""$ol_cv_lib_gdbm" 1>&6 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:10950: checking for $ac_hdr" >&5 +echo "configure:12435: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10960: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12445: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10983,7 +12468,7 @@ fi done echo $ac_n "checking for db""... $ac_c" 1>&6 -echo "configure:10987: checking for db" >&5 +echo "configure:12472: checking for db" >&5 if eval "test \"\${ol_cv_gdbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -11015,22 +12500,20 @@ EOF fi fi -if test $ol_with_ldbm_api = auto ; then - echo "configure: warning: skipping automatic checking for NDBM, must be manually enabled." 1>&2 -elif test $ol_with_ldbm_api = ndbm ; then +if test $ol_with_ldbm_api = ndbm ; then echo $ac_n "checking for NDBM library""... $ac_c" 1>&6 -echo "configure:11023: checking for NDBM library" >&5 +echo "configure:12506: checking for NDBM library" >&5 if eval "test \"\${ol_cv_lib_ndbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ol_LIBS="$LIBS" echo $ac_n "checking for dbm_open""... $ac_c" 1>&6 -echo "configure:11029: checking for dbm_open" >&5 +echo "configure:12512: checking for dbm_open" >&5 if eval "test \"\${ac_cv_func_dbm_open+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_dbm_open=yes" else @@ -11073,7 +12556,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dbm_open in -lndbm""... $ac_c" 1>&6 -echo "configure:11077: checking for dbm_open in -lndbm" >&5 +echo "configure:12560: checking for dbm_open in -lndbm" >&5 ac_lib_var=`echo ndbm'_'dbm_open | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11081,7 +12564,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lndbm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12579: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11112,7 +12595,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dbm_open in -ldbm""... $ac_c" 1>&6 -echo "configure:11116: checking for dbm_open in -ldbm" >&5 +echo "configure:12599: checking for dbm_open in -ldbm" >&5 ac_lib_var=`echo dbm'_'dbm_open | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11120,7 +12603,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldbm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11168,17 +12651,17 @@ echo "$ac_t""$ol_cv_lib_ndbm" 1>&6 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11172: checking for $ac_hdr" >&5 +echo "configure:12655: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11182: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12665: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11205,7 +12688,7 @@ fi done echo $ac_n "checking for db""... $ac_c" 1>&6 -echo "configure:11209: checking for db" >&5 +echo "configure:12692: checking for db" >&5 if eval "test \"\${ol_cv_ndbm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -11247,22 +12730,28 @@ if test $ol_link_ldbm = no -a $ol_enable_ldbm != no ; then ol_enable_ldbm=no fi +if test $ol_enable_dynamic = yes -a $enable_shared = yes ; then + LINK_BINS_DYNAMIC="yes" +else + LINK_BINS_DYNAMIC="no" +fi + if test $ol_enable_wrappers != no ; then for ac_hdr in tcpd.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11256: checking for $ac_hdr" >&5 +echo "configure:12745: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11266: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11292,43 +12781,27 @@ done if test $ac_cv_header_tcpd_h != yes ; then have_wrappers=no else - echo $ac_n "checking for main in -lwrap""... $ac_c" 1>&6 -echo "configure:11297: checking for main in -lwrap" >&5 -ac_lib_var=`echo wrap'_'main | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lwrap $LIBS" -cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12796: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + have_wrappers=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + have_wrappers=no fi rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - have_wrappers=yes -else - echo "$ac_t""no" 1>&6 -have_wrappers=no -fi - fi if test $have_wrappers = yes ; then @@ -11336,10 +12809,10 @@ fi #define HAVE_TCPD 1 EOF - SLAPD_LIBS="$SLAPD_LIBS -lwrap" + WRAP_LIBS="-lwrap" echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 -echo "configure:11343: checking for main in -lnsl" >&5 +echo "configure:12816: checking for main in -lnsl" >&5 ac_lib_var=`echo nsl'_'main | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11347,14 +12820,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11389,17 +12862,18 @@ fi echo "configure: warning: disabling wrappers support" 1>&2 ol_enable_wrappers=no + WRAP_LIBS="" fi fi if test $ol_enable_syslog != no ; then echo $ac_n "checking for openlog""... $ac_c" 1>&6 -echo "configure:11398: checking for openlog" >&5 +echo "configure:12872: checking for openlog" >&5 if eval "test \"\${ac_cv_func_openlog+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_openlog=yes" else @@ -11445,290 +12919,25 @@ fi if test $ac_cv_func_openlog = no -a $ol_enable_syslog = yes; then { echo "configure: error: could not find syslog" 1>&2; exit 1; } fi - ol_enable_syslog=$ac_cv_func_openlog -fi - -if test $ol_enable_dmalloc != no ; then - for ac_hdr in dmalloc.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11457: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11467: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 -fi -done - - echo $ac_n "checking for dmalloc_shutdown in -ldmalloc""... $ac_c" 1>&6 -echo "configure:11494: checking for dmalloc_shutdown in -ldmalloc" >&5 -ac_lib_var=`echo dmalloc'_'dmalloc_shutdown | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldmalloc $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo dmalloc | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&6 -fi - -fi - -if test $ol_enable_tcl != no ; then - for ac_hdr in tcl.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11547: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11557: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 -fi -done - - - if test $ac_cv_header_tcl_h != yes ; then - have_tcl=no - else - echo $ac_n "checking for main in -ltcl""... $ac_c" 1>&6 -echo "configure:11588: checking for main in -ltcl" >&5 -ac_lib_var=`echo tcl'_'main | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ltcl $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl" -else - echo "$ac_t""no" 1>&6 -have_tcl=no -fi - - - if test $have_tcl != yes; then - echo $ac_n "checking for main in -ltcl7.6""... $ac_c" 1>&6 -echo "configure:11627: checking for main in -ltcl7.6" >&5 -ac_lib_var=`echo tcl7.6'_'main | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ltcl7.6 $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl7.6" -else - echo "$ac_t""no" 1>&6 -have_tcl=no -fi - - fi - - if test $have_tcl != yes; then - echo $ac_n "checking for main in -ltcl8.0""... $ac_c" 1>&6 -echo "configure:11667: checking for main in -ltcl8.0" >&5 -ac_lib_var=`echo tcl8.0'_'main | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ltcl8.0 $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl8.0" -else - echo "$ac_t""no" 1>&6 -have_tcl=no -fi - - fi - fi - - if test $have_tcl != yes ; then - echo "configure: warning: could not find -ltcl" 1>&2 - if test $ol_enable_tcl = yes ; then - { echo "configure: error: could not find tcl, select appropriate options or disable" 1>&2; exit 1; } - fi - - ol_enable_tcl=no - fi + ol_enable_syslog=$ac_cv_func_openlog fi -# ud needs termcap (should insert check here) ol_link_termcap=no for ac_hdr in termcap.h ncurses.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11722: checking for $ac_hdr" >&5 +echo "configure:12931: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11732: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12941: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11757,7 +12966,7 @@ done if test $ol_link_termcap = no ; then echo $ac_n "checking for tputs in -ltermcap""... $ac_c" 1>&6 -echo "configure:11761: checking for tputs in -ltermcap" >&5 +echo "configure:12970: checking for tputs in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tputs | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11765,7 +12974,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ltermcap $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11809,7 +13018,7 @@ fi if test $ol_link_termcap = no ; then echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6 -echo "configure:11813: checking for initscr in -lncurses" >&5 +echo "configure:13022: checking for initscr in -lncurses" >&5 ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11817,7 +13026,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13041: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11868,20 +13077,21 @@ EOF fi ol_link_sasl=no +ol_link_spasswd=no if test $ol_with_cyrus_sasl != no ; then ac_safe=`echo "sasl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sasl.h""... $ac_c" 1>&6 -echo "configure:11875: checking for sasl.h" >&5 +echo "configure:13085: checking for sasl.h" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11885: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:13095: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11905,7 +13115,7 @@ fi if test $ac_cv_header_sasl_h = yes ; then echo $ac_n "checking for sasl_client_init in -lsasl""... $ac_c" 1>&6 -echo "configure:11909: checking for sasl_client_init in -lsasl" >&5 +echo "configure:13119: checking for sasl_client_init in -lsasl" >&5 ac_lib_var=`echo sasl'_'sasl_client_init | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -11913,7 +13123,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsasl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13138: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11961,18 +13171,40 @@ EOF fi fi +if test $cross_compiling != yes ; then + dev=no + if test -r /dev/urandom ; then + dev="/dev/urandom"; + elif test -r /idev/urandom ; then + dev="/idev/urandom"; + elif test -r /dev/srandom ; then + dev="/dev/srandom"; + elif test -r /dev/random ; then + dev="/dev/random"; + elif test -r /idev/random ; then + dev="/idev/random"; + fi + + if test $dev != no ; then + cat >> confdefs.h <&6 -echo "configure:11970: checking fetch(3) library" >&5 +echo "configure:13202: checking fetch(3) library" >&5 if eval "test \"\${ol_cv_lib_fetch+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -11982,7 +13214,7 @@ int main() { struct url *u = fetchParseURL("file:///"); ; return 0; } EOF -if { (eval echo configure:11986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13218: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_lib_fetch=yes else @@ -12020,17 +13252,17 @@ if test $ol_with_readline != no ; then do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12024: checking for $ac_hdr" >&5 +echo "configure:13256: checking for $ac_hdr" >&5 if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12034: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:13266: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12061,7 +13293,7 @@ done save_LIBS="$LIBS" LIBS="$TERMCAP_LIBS $LIBS" echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6 -echo "configure:12065: checking for readline in -lreadline" >&5 +echo "configure:13297: checking for readline in -lreadline" >&5 ac_lib_var=`echo readline'_'readline | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -12069,7 +13301,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lreadline $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13316: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12120,15 +13352,14 @@ EOF fi -# FreeBSD (and others) have crypt(3) in -lcrypt if test $ol_enable_crypt != no ; then echo $ac_n "checking for crypt""... $ac_c" 1>&6 -echo "configure:12127: checking for crypt" >&5 +echo "configure:13358: checking for crypt" >&5 if eval "test \"\${ac_cv_func_crypt+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_crypt=yes" else @@ -12171,7 +13402,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:12175: checking for crypt in -lcrypt" >&5 +echo "configure:13406: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -12179,7 +13410,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcrypt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12231,15 +13462,14 @@ EOF fi fi -# FreeBSD (and others) have setproctitle(3) in -lutil if test $ol_enable_proctitle != no ; then echo $ac_n "checking for setproctitle""... $ac_c" 1>&6 -echo "configure:12238: checking for setproctitle" >&5 +echo "configure:13468: checking for setproctitle" >&5 if eval "test \"\${ac_cv_func_setproctitle+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_setproctitle=yes" else @@ -12282,7 +13512,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for setproctitle in -lutil""... $ac_c" 1>&6 -echo "configure:12286: checking for setproctitle in -lutil" >&5 +echo "configure:13516: checking for setproctitle in -lutil" >&5 ac_lib_var=`echo util'_'setproctitle | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -12290,7 +13520,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lutil $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12322,6 +13552,7 @@ else echo "$ac_t""no" 1>&6 have_setproctitle=no LIBOBJS="$LIBOBJS setproctitle.o" + LIBSRCS="$LIBSRCS setproctitle.c" fi fi @@ -12335,117 +13566,13 @@ EOF fi fi -echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:12340: checking for uid_t in sys/types.h" >&5 -if eval "test \"\${ac_cv_type_uid_t+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "uid_t" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_uid_t=yes -else - rm -rf conftest* - ac_cv_type_uid_t=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_type_uid_t" 1>&6 -if test $ac_cv_type_uid_t = no; then - cat >> confdefs.h <<\EOF -#define uid_t int -EOF - - cat >> confdefs.h <<\EOF -#define gid_t int -EOF - -fi - -echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 -echo "configure:12374: checking type of array argument to getgroups" >&5 -if eval "test \"\${ac_cv_type_getgroups+set}\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_type_getgroups=cross -else - cat > conftest.$ac_ext < -#define NGID 256 -#undef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -main() -{ - gid_t gidset[NGID]; - int i, n; - union { gid_t gval; long lval; } val; - - val.lval = -1; - for (i = 0; i < NGID; i++) - gidset[i] = val.gval; - n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, - gidset); - /* Exit non-zero if getgroups seems to require an array of ints. This - happens when gid_t is short but getgroups modifies an array of ints. */ - exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); -} - -EOF -if { (eval echo configure:12407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_type_getgroups=gid_t -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_type_getgroups=int -fi -rm -fr conftest* -fi - -if test $ac_cv_type_getgroups = cross; then - cat > conftest.$ac_ext < -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_getgroups=gid_t -else - rm -rf conftest* - ac_cv_type_getgroups=int -fi -rm -f conftest* - -fi -fi - -echo "$ac_t""$ac_cv_type_getgroups" 1>&6 -cat >> confdefs.h <&6 -echo "configure:12444: checking for ANSI C header files" >&5 +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:13571: checking for ANSI C header files" >&5 if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12453,7 +13580,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12457: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:13584: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12470,7 +13597,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -12488,7 +13615,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -12509,18 +13636,25 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < +#if ((' ' & 0x0FF) == 0x020) #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +#define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +#define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:12524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:13658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -12544,18 +13678,19 @@ EOF fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:12548: checking for mode_t" >&5 +echo "configure:13682: checking for mode_t" >&5 if eval "test \"\${ac_cv_type_mode_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif + EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then @@ -12579,18 +13714,19 @@ EOF fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:12583: checking for off_t" >&5 +echo "configure:13718: checking for off_t" >&5 if eval "test \"\${ac_cv_type_off_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif + EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then @@ -12614,18 +13750,19 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:12618: checking for pid_t" >&5 +echo "configure:13754: checking for pid_t" >&5 if eval "test \"\${ac_cv_type_pid_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif + EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then @@ -12649,19 +13786,19 @@ EOF fi echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6 -echo "configure:12653: checking for ptrdiff_t" >&5 +echo "configure:13790: checking for ptrdiff_t" >&5 if eval "test \"\${am_cv_type_ptrdiff_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { ptrdiff_t p ; return 0; } EOF -if { (eval echo configure:12665: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_type_ptrdiff_t=yes else @@ -12682,12 +13819,12 @@ EOF fi echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:12686: checking return type of signal handlers" >&5 +echo "configure:13823: checking return type of signal handlers" >&5 if eval "test \"\${ac_cv_type_signal+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12704,7 +13841,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:12708: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13845: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -12722,81 +13859,123 @@ cat >> confdefs.h <&6 -echo "configure:12727: checking for sig_atomic_t" >&5 -if eval "test \"\${ol_cv_type_sig_atomic_t+set}\" = set"; then +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:13864: checking for size_t" >&5 +if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < -int main() { -sig_atomic_t atomic; -; return 0; } +#include +#if STDC_HEADERS +#include +#include +#endif + EOF -if { (eval echo configure:12739: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - ol_cv_type_sig_atomic_t=yes + eval "ac_cv_type_size_t=yes" else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 rm -rf conftest* - ol_cv_type_sig_atomic_t=no + eval "ac_cv_type_size_t=no" fi rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_type_'size_t`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 + cat >> confdefs.h <&6 - if test $ol_cv_type_sig_atomic_t = no; then - cat >> confdefs.h <<\EOF -#define sig_atomic_t int + +echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 +echo "configure:13901: checking for ssize_t" >&5 +if eval "test \"\${ac_cv_type_ssize_t+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif + EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])ssize_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + eval "ac_cv_type_ssize_t=yes" +else + rm -rf conftest* + eval "ac_cv_type_ssize_t=no" +fi +rm -f conftest* - fi - -echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:12760: checking for size_t" >&5 -if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then +fi +if eval "test \"`echo '$ac_cv_type_'ssize_t`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 + cat >> confdefs.h <&6 +echo "configure:13937: checking for caddr_t" >&5 +if eval "test \"\${ac_cv_type_caddr_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif + EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + egrep "(^|[^a-zA-Z_0-9])caddr_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - eval "ac_cv_type_size_t=yes" + eval "ac_cv_type_caddr_t=yes" else rm -rf conftest* - eval "ac_cv_type_size_t=no" + eval "ac_cv_type_caddr_t=no" fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_type_'size_t`\" = yes"; then +if eval "test \"`echo '$ac_cv_type_'caddr_t`\" = yes"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 cat >> confdefs.h <&6 -echo "configure:12795: checking for socklen_t" >&5 +echo "configure:13974: checking for socklen_t" >&5 if eval "test \"\${ol_cv_type_socklen_t+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13993: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ol_cv_type_socklen_t=yes else @@ -12831,12 +14010,12 @@ EOF fi echo $ac_n "checking for member st_blksize in aggregate type struct stat""... $ac_c" 1>&6 -echo "configure:12835: checking for member st_blksize in aggregate type struct stat" >&5 +echo "configure:14014: checking for member st_blksize in aggregate type struct stat" >&5 if eval "test \"\${ac_cv_c_struct_member_st_blksize+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12844,7 +14023,7 @@ int main() { struct stat foo; foo.st_blksize; ; return 0; } EOF -if { (eval echo configure:12848: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14027: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_struct_member_st_blksize=yes else @@ -12866,12 +14045,12 @@ EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:12870: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:14049: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"\${ac_cv_header_time+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12880,7 +14059,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:12884: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14063: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -12901,12 +14080,12 @@ EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:12905: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:14084: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"\${ac_cv_struct_tm+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12914,7 +14093,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:12918: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14097: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -12934,15 +14113,84 @@ EOF fi +echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:14118: checking for uid_t in sys/types.h" >&5 +if eval "test \"\${ac_cv_type_uid_t+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "uid_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_uid_t=yes +else + rm -rf conftest* + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_uid_t" 1>&6 +if test $ac_cv_type_uid_t = no; then + cat >> confdefs.h <<\EOF +#define uid_t int +EOF + + cat >> confdefs.h <<\EOF +#define gid_t int +EOF + +fi + +echo $ac_n "checking for sig_atomic_t""... $ac_c" 1>&6 +echo "configure:14152: checking for sig_atomic_t" >&5 +if eval "test \"\${ol_cv_type_sig_atomic_t+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +sig_atomic_t atomic; +; return 0; } +EOF +if { (eval echo configure:14164: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ol_cv_type_sig_atomic_t=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ol_cv_type_sig_atomic_t=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ol_cv_type_sig_atomic_t" 1>&6 + if test $ol_cv_type_sig_atomic_t = no; then + cat >> confdefs.h <<\EOF +#define sig_atomic_t int +EOF + + fi + + + # test for pw_gecos in struct passwd echo $ac_n "checking struct passwd for pw_gecos""... $ac_c" 1>&6 -echo "configure:12940: checking struct passwd for pw_gecos" >&5 +echo "configure:14188: checking struct passwd for pw_gecos" >&5 if eval "test \"\${ol_cv_struct_passwd_pw_gecos+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -12952,7 +14200,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:12956: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ol_cv_struct_passwd_pw_gecos=yes else @@ -12974,13 +14222,13 @@ fi # test for pw_passwd in struct passwd echo $ac_n "checking struct passwd for pw_passwd""... $ac_c" 1>&6 -echo "configure:12978: checking struct passwd for pw_passwd" >&5 +echo "configure:14226: checking struct passwd for pw_passwd" >&5 if eval "test \"\${ol_cv_struct_passwd_pw_passwd+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -12990,7 +14238,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:12994: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14242: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ol_cv_struct_passwd_pw_passwd=yes else @@ -13012,7 +14260,7 @@ fi echo $ac_n "checking if toupper() requires islower()""... $ac_c" 1>&6 -echo "configure:13016: checking if toupper() requires islower()" >&5 +echo "configure:14264: checking if toupper() requires islower()" >&5 if eval "test \"\${ol_cv_c_upper_lower+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13021,7 +14269,7 @@ else ol_cv_c_upper_lower=safe else cat > conftest.$ac_ext < @@ -13033,7 +14281,7 @@ main() exit(1); } EOF -if { (eval echo configure:13037: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:14285: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ol_cv_c_upper_lower=no else @@ -13056,12 +14304,12 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:13060: checking for working const" >&5 +echo "configure:14308: checking for working const" >&5 if eval "test \"\${ac_cv_c_const+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14362: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -13131,12 +14379,12 @@ EOF fi echo $ac_n "checking if compiler understands volatile""... $ac_c" 1>&6 -echo "configure:13135: checking if compiler understands volatile" >&5 +echo "configure:14383: checking if compiler understands volatile" >&5 if eval "test \"\${ol_cv_c_volatile+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ol_cv_c_volatile=yes else @@ -13173,30 +14421,16 @@ if test $cross_compiling = yes ; then #define CROSS_COMPILING 1 EOF - - cat >> confdefs.h <<\EOF -#define LBER_INT_T long -EOF - - cat >> confdefs.h <<\EOF -#define LBER_TAG_T long -EOF - - cat >> confdefs.h <<\EOF -#define LBER_SOCKET_T int -EOF - - else echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:13193: checking whether byte ordering is bigendian" >&5 +echo "configure:14427: checking whether byte ordering is bigendian" >&5 if eval "test \"\${ac_cv_c_bigendian+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -13207,11 +14441,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:13211: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14445: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -13222,7 +14456,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:13226: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14460: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -13242,7 +14476,7 @@ if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:14493: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -13278,162 +14512,155 @@ EOF fi - echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:13283: checking size of short" >&5 +fi + +echo $ac_n "checking size of short""... $ac_c" 1>&6 +echo "configure:14519: checking size of short" >&5 if eval "test \"\${ac_cv_sizeof_short+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } -else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext < -main() -{ - FILE *f=fopen("conftestval", "w"); - if (!f) exit(1); - fprintf(f, "%d\n", sizeof(short)); - exit(0); -} +#include "confdefs.h" +#include + + +int main() { +switch (0) case 0: case (sizeof (short) == $ac_size):; +; return 0; } EOF -if { (eval echo configure:13302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_sizeof_short=`cat conftestval` +if { (eval echo configure:14535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_short=$ac_size else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_sizeof_short=0 -fi -rm -fr conftest* fi +rm -f conftest* + if test x$ac_cv_sizeof_short != x ; then break; fi +done fi -echo "$ac_t""$ac_cv_sizeof_short" 1>&6 + +if test x$ac_cv_sizeof_short = x ; then + { echo "configure: error: cannot determine a size for short" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_short" 1>&6 cat >> confdefs.h <&6 -echo "configure:13322: checking size of int" >&5 + +echo $ac_n "checking size of int""... $ac_c" 1>&6 +echo "configure:14558: checking size of int" >&5 if eval "test \"\${ac_cv_sizeof_int+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } -else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext < -main() -{ - FILE *f=fopen("conftestval", "w"); - if (!f) exit(1); - fprintf(f, "%d\n", sizeof(int)); - exit(0); -} +#include "confdefs.h" +#include + + +int main() { +switch (0) case 0: case (sizeof (int) == $ac_size):; +; return 0; } EOF -if { (eval echo configure:13341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_sizeof_int=`cat conftestval` +if { (eval echo configure:14574: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_int=$ac_size else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_sizeof_int=0 -fi -rm -fr conftest* fi +rm -f conftest* + if test x$ac_cv_sizeof_int != x ; then break; fi +done fi -echo "$ac_t""$ac_cv_sizeof_int" 1>&6 + +if test x$ac_cv_sizeof_int = x ; then + { echo "configure: error: cannot determine a size for int" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 cat >> confdefs.h <&6 -echo "configure:13361: checking size of long" >&5 + +echo $ac_n "checking size of long""... $ac_c" 1>&6 +echo "configure:14597: checking size of long" >&5 if eval "test \"\${ac_cv_sizeof_long+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } -else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext < -main() -{ - FILE *f=fopen("conftestval", "w"); - if (!f) exit(1); - fprintf(f, "%d\n", sizeof(long)); - exit(0); -} +#include "confdefs.h" +#include + + +int main() { +switch (0) case 0: case (sizeof (long) == $ac_size):; +; return 0; } EOF -if { (eval echo configure:13380: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_sizeof_long=`cat conftestval` +if { (eval echo configure:14613: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_long=$ac_size else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_sizeof_long=0 -fi -rm -fr conftest* fi +rm -f conftest* + if test x$ac_cv_sizeof_long != x ; then break; fi +done fi -echo "$ac_t""$ac_cv_sizeof_long" 1>&6 + +if test x$ac_cv_sizeof_long = x ; then + { echo "configure: error: cannot determine a size for long" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 cat >> confdefs.h <&2 - if test "$ac_cv_sizeof_int" -lt 4 ; then - echo "configure: warning: OpenLDAP requires 'int' to be 32 bits or greater." 1>&2 - - cat >> confdefs.h <<\EOF + cat >> confdefs.h <<\EOF #define LBER_INT_T long EOF - cat >> confdefs.h <<\EOF -#define LBER_TAG_T long -EOF - - cat >> confdefs.h <<\EOF -#define LBER_SOCKET_T int -EOF - - else - cat >> confdefs.h <<\EOF +else + cat >> confdefs.h <<\EOF #define LBER_INT_T int EOF - cat >> confdefs.h <<\EOF -#define LBER_TAG_T long +fi + +cat >> confdefs.h <<\EOF +#define LBER_LEN_T long EOF - cat >> confdefs.h <<\EOF +cat >> confdefs.h <<\EOF #define LBER_SOCKET_T int EOF - fi -fi - cat >> confdefs.h <<\EOF -#define LBER_LEN_T long +#define LBER_TAG_T long EOF echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 -echo "configure:13437: checking for 8-bit clean memcmp" >&5 +echo "configure:14664: checking for 8-bit clean memcmp" >&5 if eval "test \"\${ac_cv_func_memcmp_clean+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13441,7 +14668,7 @@ else ac_cv_func_memcmp_clean=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:14682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_memcmp_clean=yes else @@ -13469,12 +14696,12 @@ echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" echo $ac_n "checking for strftime""... $ac_c" 1>&6 -echo "configure:13473: checking for strftime" >&5 +echo "configure:14700: checking for strftime" >&5 if eval "test \"\${ac_cv_func_strftime+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strftime=yes" else @@ -13520,7 +14747,7 @@ else echo "$ac_t""no" 1>&6 # strftime is in -lintl on SCO UNIX. echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 -echo "configure:13524: checking for strftime in -lintl" >&5 +echo "configure:14751: checking for strftime in -lintl" >&5 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-:%__p__%'` if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -13528,7 +14755,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -13567,12 +14794,12 @@ fi echo $ac_n "checking for inet_aton()""... $ac_c" 1>&6 -echo "configure:13571: checking for inet_aton()" >&5 +echo "configure:14798: checking for inet_aton()" >&5 if eval "test \"\${ol_cv_func_inet_aton+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_func_inet_aton=yes else @@ -13615,13 +14842,176 @@ EOF fi +echo $ac_n "checking for _spawnlp""... $ac_c" 1>&6 +echo "configure:14847: checking for _spawnlp" >&5 +if eval "test \"\${ac_cv_func__spawnlp+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _spawnlp(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__spawnlp) || defined (__stub____spawnlp) +choke me +#else +f = _spawnlp; +#endif + +; return 0; } +EOF +if { (eval echo configure:14876: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func__spawnlp=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__spawnlp=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_spawnlp`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SPAWNLP 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking for _snprintf""... $ac_c" 1>&6 +echo "configure:14900: checking for _snprintf" >&5 +if eval "test \"\${ac_cv_func__snprintf+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _snprintf(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__snprintf) || defined (__stub____snprintf) +choke me +#else +f = _snprintf; +#endif + +; return 0; } +EOF +if { (eval echo configure:14929: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func__snprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__snprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_snprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_cv_func_snprintf=yes + cat >> confdefs.h <<\EOF +#define snprintf _snprintf +EOF + + +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking for _vsnprintf""... $ac_c" 1>&6 +echo "configure:14955: checking for _vsnprintf" >&5 +if eval "test \"\${ac_cv_func__vsnprintf+set}\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char _vsnprintf(); +char (*f)(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__vsnprintf) || defined (__stub____vsnprintf) +choke me +#else +f = _vsnprintf; +#endif + +; return 0; } +EOF +if { (eval echo configure:14984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func__vsnprintf=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func__vsnprintf=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'_vsnprintf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_cv_func_vsnprintf=yes + cat >> confdefs.h <<\EOF +#define vsnprintf _vsnprintf +EOF + + +else + echo "$ac_t""no" 1>&6 +fi + + echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:13620: checking for vprintf" >&5 +echo "configure:15010: checking for vprintf" >&5 if eval "test \"\${ac_cv_func_vprintf+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else @@ -13669,12 +15059,12 @@ fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:13673: checking for _doprnt" >&5 +echo "configure:15063: checking for _doprnt" >&5 if eval "test \"\${ac_cv_func__doprnt+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15092: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else @@ -13727,12 +15117,12 @@ if test $ac_cv_func_vprintf = yes ; then for ac_func in vsnprintf vsprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:13731: checking for $ac_func" >&5 +echo "configure:15121: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15150: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -13785,6 +15175,7 @@ fi for ac_func in \ bcopy \ closesocket \ + chroot \ endgrent \ endpwent \ flock \ @@ -13792,6 +15183,7 @@ for ac_func in \ getgrgid \ gethostname \ getpass \ + getpassphrase \ getpwuid \ getpwnam \ getspnam \ @@ -13833,12 +15225,12 @@ for ac_func in \ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:13837: checking for $ac_func" >&5 +echo "configure:15229: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -13890,12 +15282,12 @@ done for ac_func in getopt tempnam do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:13894: checking for $ac_func" >&5 +echo "configure:15286: checking for $ac_func" >&5 if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -13946,25 +15338,36 @@ done +if test "$ac_cv_func_getopt" != yes; then + LIBSRCS="$LIBSRCS getopt.c" +fi + +if test "$ac_cv_func_tempnam" != yes; then + LIBSRCS="$LIBSRCS tempnam.c" +fi + # Check Configuration echo $ac_n "checking declaration of sys_errlist""... $ac_c" 1>&6 -echo "configure:13952: checking declaration of sys_errlist" >&5 +echo "configure:15352: checking declaration of sys_errlist" >&5 if eval "test \"\${ol_cv_dcl_sys_errlist+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -#include +#include +#ifdef WINNT +#include +#endif int main() { char *c = (char *) *sys_errlist ; return 0; } EOF -if { (eval echo configure:13968: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15371: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ol_cv_dcl_sys_errlist=yes ol_cv_have_sys_errlist=yes @@ -13987,20 +15390,20 @@ EOF echo $ac_n "checking existence of sys_errlist""... $ac_c" 1>&6 -echo "configure:13991: checking existence of sys_errlist" >&5 +echo "configure:15394: checking existence of sys_errlist" >&5 if eval "test \"\${ol_cv_have_sys_errlist+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *c = (char *) *sys_errlist ; return 0; } EOF -if { (eval echo configure:14004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ol_cv_have_sys_errlist=yes else @@ -14047,9 +15450,9 @@ if test "$ol_enable_cache" = no ; then EOF fi -if test "$ol_enable_dns" != no ; then +if test "$ol_link_kbind" != no ; then cat >> confdefs.h <<\EOF -#define LDAP_API_FEATURE_X_OPENLDAP_V2_DNS LDAP_VENDOR_VERSION +#define LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND LDAP_VENDOR_VERSION EOF fi @@ -14071,10 +15474,15 @@ if test "$ol_enable_cldap" != no ; then EOF fi +if test "$ol_enable_unix" != no; then + cat >> confdefs.h <<\EOF +#define LDAP_PF_UNIX 1 +EOF -if test "$ol_enable_crypt" != no ; then +fi +if test "$ol_enable_ipv6" != no; then cat >> confdefs.h <<\EOF -#define SLAPD_CRYPT 1 +#define LDAP_PF_INET6 1 EOF fi @@ -14083,6 +15491,24 @@ if test "$ol_enable_cleartext" != no ; then #define SLAPD_CLEARTEXT 1 EOF +fi +if test "$ol_enable_crypt" != no ; then + cat >> confdefs.h <<\EOF +#define SLAPD_CRYPT 1 +EOF + +fi +if test "$ol_link_kpasswd" != no ; then + cat >> confdefs.h <<\EOF +#define SLAPD_KPASSWD 1 +EOF + +fi +if test "$ol_link_spasswd" != no ; then + cat >> confdefs.h <<\EOF +#define SLAPD_SPASSWD 1 +EOF + fi if test "$ol_enable_multimaster" != no ; then cat >> confdefs.h <<\EOF @@ -14107,12 +15533,6 @@ if test "$ol_enable_aci" != no ; then #define SLAPD_ACI_ENABLED 1 EOF -fi -if test "$ol_enable_discreteaci" != no ; then - cat >> confdefs.h <<\EOF -#define SLAPD_ACI_DISCRETE_RIGHTS 1 -EOF - fi if test "$ol_link_modules" != no ; then @@ -14121,25 +15541,24 @@ if test "$ol_link_modules" != no ; then EOF BUILD_SLAPD=yes - MODULES_LIBS=-lltdl SLAPD_MODULES_LDFLAGS="-dlopen self" fi -if test "$ol_link_bdb2" != no ; then +if test "$ol_link_dnssrv" != no ; then cat >> confdefs.h <<\EOF -#define SLAPD_BDB2 1 +#define SLAPD_DNSSRV 1 EOF BUILD_SLAPD=yes - BUILD_BDB2=yes - if test "$ol_with_bdb2_module" != static ; then + BUILD_DNSSRV=yes + if test "$ol_with_dnssrv_module" != static ; then cat >> confdefs.h <<\EOF -#define SLAPD_BDB2_DYNAMIC 1 +#define SLAPD_DNSSRV_DYNAMIC 1 EOF - BUILD_BDB2=mod - BUILD_BDB2_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-bdb2/back_bdb2.la" + BUILD_DNSSRV=mod + BUILD_DNSSRV_DYNAMIC=shared + SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-dnssrv/back_dnssrv.la" fi fi @@ -14197,24 +15616,6 @@ EOF fi fi -if test "$ol_link_perl" != no ; then - cat >> confdefs.h <<\EOF -#define SLAPD_PERL 1 -EOF - - BUILD_SLAPD=yes - BUILD_PERL=yes - if test "$ol_with_perl_module" != static ; then - cat >> confdefs.h <<\EOF -#define SLAPD_PERL_DYNAMIC 1 -EOF - - BUILD_PERL=mod - BUILD_PERL_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-perl/back_perl.la" - fi -fi - if test "$ol_enable_shell" != no ; then cat >> confdefs.h <<\EOF #define SLAPD_SHELL 1 @@ -14233,31 +15634,36 @@ EOF fi fi -if test "$ol_enable_tcl" != no ; then - cat >> confdefs.h <<\EOF -#define SLAPD_TCL 1 -EOF +if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \ + $BUILD_SLAPD = yes ; then + BUILD_SLURPD=yes +fi - BUILD_SLAPD=yes - BUILD_TCL=yes - if test "$ol_with_tcl_module" != static; then - cat >> confdefs.h <<\EOF -#define SLAPD_TCL_DYNAMIC 1 -EOF - BUILD_TCL=mod - BUILD_TCL_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-tcl/back_tcl.la" - fi +if test "$LINK_BINS_DYNAMIC" = yes; then + LIB_LINKAGE=DYN + LT_LIB_LINKAGE=shared +else + LIB_LINKAGE=STAT + LT_LIB_LINKAGE=static fi -if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \ - $BUILD_SLAPD = yes ; then - BUILD_SLURPD=yes +if test "$ac_cv_mingw32" = yes ; then + PLAT=NT + DYN_EXT=dll +else + PLAT=UNIX + DYN_EXT=so fi + + + + + + @@ -14269,10 +15675,8 @@ fi - - - - + + @@ -14368,6 +15772,7 @@ clients/gopher/Makefile:build/top.mk:clients/gopher/Makefile.in:build/rules.mk \ clients/mail500/Makefile:build/top.mk:clients/mail500/Makefile.in:build/rules.mk \ clients/rcpt500/Makefile:build/top.mk:clients/rcpt500/Makefile.in:build/rules.mk \ clients/ud/Makefile:build/top.mk:clients/ud/Makefile.in:build/rules.mk \ +clients/maildap/Makefile:build/top.mk:clients/maildap/Makefile.in:build/rules.mk \ clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk \ include/Makefile:build/top.mk:include/Makefile.in \ libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk \ @@ -14377,16 +15782,15 @@ libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib. libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk \ libraries/libldbm/Makefile:build/top.mk:libraries/libldbm/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/libldif/Makefile:build/top.mk:libraries/libldif/Makefile.in:build/lib.mk:build/lib-static.mk \ +libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \ servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \ servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \ -servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \ +servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk \ servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \ servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \ servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \ -servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \ servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \ -servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \ servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \ servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \ servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \ @@ -14461,56 +15865,60 @@ s%@top_builddir@%$top_builddir%g s%@ldap_subdir@%$ldap_subdir%g s%@CC@%$CC%g s%@RANLIB@%$RANLIB%g -s%@LD@%$LD%g -s%@NM@%$NM%g s%@LN_S@%$LN_S%g +s%@DLLTOOL@%$DLLTOOL%g +s%@AS@%$AS%g +s%@OBJDUMP@%$OBJDUMP%g s%@LIBTOOL@%$LIBTOOL%g s%@LN_H@%$LN_H%g s%@SENDMAIL@%$SENDMAIL%g s%@EDITOR@%$EDITOR%g s%@FINGER@%$FINGER%g -s%@PERLBIN@%$PERLBIN%g s%@CPP@%$CPP%g s%@EXEEXT@%$EXEEXT%g s%@OBJEXT@%$OBJEXT%g s%@OL_MKDEP@%$OL_MKDEP%g s%@OL_MKDEP_FLAGS@%$OL_MKDEP_FLAGS%g s%@LIBOBJS@%$LIBOBJS%g +s%@LIBSRCS@%$LIBSRCS%g +s%@PLAT@%$PLAT%g +s%@LIB_LINKAGE@%$LIB_LINKAGE%g +s%@LT_LIB_LINKAGE@%$LT_LIB_LINKAGE%g +s%@DYN_EXT@%$DYN_EXT%g s%@BUILD_SLAPD@%$BUILD_SLAPD%g -s%@BUILD_BDB2@%$BUILD_BDB2%g +s%@BUILD_DNSSRV@%$BUILD_DNSSRV%g s%@BUILD_LDAP@%$BUILD_LDAP%g s%@BUILD_LDBM@%$BUILD_LDBM%g s%@BUILD_PASSWD@%$BUILD_PASSWD%g -s%@BUILD_PERL@%$BUILD_PERL%g s%@BUILD_QUIPU@%$BUILD_QUIPU%g s%@BUILD_SHELL@%$BUILD_SHELL%g -s%@BUILD_TCL@%$BUILD_TCL%g -s%@BUILD_BDB2_DYNAMIC@%$BUILD_BDB2_DYNAMIC%g +s%@BUILD_DNSSRV_DYNAMIC@%$BUILD_DNSSRV_DYNAMIC%g s%@BUILD_LDAP_DYNAMIC@%$BUILD_LDAP_DYNAMIC%g s%@BUILD_LDBM_DYNAMIC@%$BUILD_LDBM_DYNAMIC%g s%@BUILD_PASSWD_DYNAMIC@%$BUILD_PASSWD_DYNAMIC%g -s%@BUILD_PERL_DYNAMIC@%$BUILD_PERL_DYNAMIC%g s%@BUILD_SHELL_DYNAMIC@%$BUILD_SHELL_DYNAMIC%g -s%@BUILD_TCL_DYNAMIC@%$BUILD_TCL_DYNAMIC%g s%@BUILD_SLURPD@%$BUILD_SLURPD%g s%@LDAP_LIBS@%$LDAP_LIBS%g s%@LDIF_LIBS@%$LDIF_LIBS%g s%@SLAPD_LIBS@%$SLAPD_LIBS%g +s%@QUIPU_LIBS@%$QUIPU_LIBS%g s%@SLURPD_LIBS@%$SLURPD_LIBS%g s%@LDBM_LIBS@%$LDBM_LIBS%g s%@LTHREAD_LIBS@%$LTHREAD_LIBS%g s%@LUTIL_LIBS@%$LUTIL_LIBS%g +s%@WRAP_LIBS@%$WRAP_LIBS%g +s%@LINK_BINS_DYNAMIC@%$LINK_BINS_DYNAMIC%g s%@SLAPD_MODULES_CPPFLAGS@%$SLAPD_MODULES_CPPFLAGS%g s%@SLAPD_MODULES_LDFLAGS@%$SLAPD_MODULES_LDFLAGS%g s%@SLAPD_MODULES_LIST@%$SLAPD_MODULES_LIST%g -s%@SLAPD_PERL_CPPFLAGS@%$SLAPD_PERL_CPPFLAGS%g -s%@SLAPD_PERL_LDFLAGS@%$SLAPD_PERL_LDFLAGS%g -s%@KRB_LIBS@%$KRB_LIBS%g +s%@KRB4_LIBS@%$KRB4_LIBS%g +s%@KRB5_LIBS@%$KRB5_LIBS%g s%@READLINE_LIBS@%$READLINE_LIBS%g s%@SASL_LIBS@%$SASL_LIBS%g s%@TERMCAP_LIBS@%$TERMCAP_LIBS%g s%@TLS_LIBS@%$TLS_LIBS%g s%@MODULES_LIBS@%$MODULES_LIBS%g +s%@AUTH_LIBS@%$AUTH_LIBS%g CEOF EOF @@ -14567,6 +15975,7 @@ clients/gopher/Makefile:build/top.mk:clients/gopher/Makefile.in:build/rules.mk \ clients/mail500/Makefile:build/top.mk:clients/mail500/Makefile.in:build/rules.mk \ clients/rcpt500/Makefile:build/top.mk:clients/rcpt500/Makefile.in:build/rules.mk \ clients/ud/Makefile:build/top.mk:clients/ud/Makefile.in:build/rules.mk \ +clients/maildap/Makefile:build/top.mk:clients/maildap/Makefile.in:build/rules.mk \ clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk \ include/Makefile:build/top.mk:include/Makefile.in \ libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk \ @@ -14576,16 +15985,15 @@ libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib. libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk \ libraries/libldbm/Makefile:build/top.mk:libraries/libldbm/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/libldif/Makefile:build/top.mk:libraries/libldif/Makefile.in:build/lib.mk:build/lib-static.mk \ +libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \ servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \ servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \ -servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \ +servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk \ servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \ servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \ servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \ -servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \ servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \ -servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \ servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \ servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \ servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \ @@ -14638,7 +16046,7 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in - *Makefile*) ac_comsub="1i\\ + *[Mm]akefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac diff --git a/configure.in b/configure.in index 307ee53902..4697b764cd 100644 --- a/configure.in +++ b/configure.in @@ -1,31 +1,47 @@ dnl $OpenLDAP$ dnl -dnl Copyright 1998,1999 The OpenLDAP Foundation. All Rights Reserved. +dnl Copyright 1998-2000 The OpenLDAP Foundation. All Rights Reserved. dnl dnl Redistribution and use in source and binary forms are permitted only dnl as authorized by the OpenLDAP Public License. A copy of this dnl license is available at http://www.OpenLDAP.org/license.html or dnl in file LICENSE in the top-level directory of the distribution. dnl +dnl ---------------------------------------------------------------- +dnl Redefine AC_INIT_BINSH to provide RCS IDs and copyright notice +dnl at top of generated configure script. Prints simple copyright. define([AC_INIT_BINSH], [[#! /bin/sh # $]OpenLDAP[$ # from] translit([$OpenLDAP$], $")] [ -# Copyright 1998,1999 The OpenLDAP Foundation. All Rights Reserved. +# Copyright 1998-2000 The OpenLDAP Foundation. All Rights Reserved. # # Redistribution and use in source and binary forms are permitted only # as authorized by the OpenLDAP Public License. A copy of this # license is available at http://www.OpenLDAP.org/license.html or # in file LICENSE in the top-level directory of the distribution. -])dnl +echo "Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved." +echo "Copying restrictions apply, see COPYRIGHT file." +])dnl +dnl ---------------------------------------------------------------- dnl Disable config.cache! define([AC_CACHE_LOAD], )dnl define([AC_CACHE_SAVE], )dnl - +dnl ================================================================ dnl Configure.in for OpenLDAP AC_INIT(build/version)dnl + +# set unset (borrowed from autoconf 2.14a) +if (unset FOO) >/dev/null 2>&1; then + ol_unset=unset +else + ol_unset=false +fi +# unset CDPATH +$ol_unset CDPATH || test "${CDPATH+set}" != set || CDPATH=: && export CDPATH + AC_CONFIG_AUX_DIR(build)dnl OL_VERSION=`cat $ac_aux_dir/version` @@ -33,7 +49,8 @@ if test -z "$OL_VERSION"; then AC_MSG_ERROR([could not determine version]) fi -dnl ---------------------------------------------------------------- +echo "Configuring OpenLDAP $OL_VERSION ..." + dnl Determine host platform dnl we try not to use this for much AC_CANONICAL_SYSTEM @@ -44,15 +61,14 @@ AC_SUBST(VERSION) AC_DEFINE_UNQUOTED(OPENLDAP_PACKAGE,"$PACKAGE",Package) AC_DEFINE_UNQUOTED(OPENLDAP_VERSION,"$VERSION",Version) -dnl require: dnl autoconf 2.13.1 -dnl also: +dnl We use autoconf features new to 2.13. dnl aclocal.m4 should be built using aclocal from automake 1.4 dnl libtool 1.3.3 should be installed. -AC_PREREQ(2.13.1)dnl Required Autoconf version +AC_PREREQ(2.13)dnl Required Autoconf version AC_CONFIG_HEADER(include/portable.h include/ldap_features.h include/lber_types.h)dnl -dnl ---------------------------------------------------------------- +dnl ================================================================ dnl Start Args AC_MSG_CHECKING(configure arguments) AC_PREFIX_DEFAULT(/usr/local) @@ -60,6 +76,8 @@ AC_PREFIX_DEFAULT(/usr/local) top_builddir=`pwd` AC_SUBST(top_builddir)dnl +dnl ---------------------------------------------------------------- +dnl --with-subdir ldap_subdir="/openldap" AC_ARG_WITH(subdir, @@ -80,104 +98,100 @@ esac AC_SUBST(ldap_subdir)dnl +dnl ---------------------------------------------------------------- +dnl General "enable" options OL_ARG_ENABLE(debug,[ --enable-debug enable debugging], yes)dnl -dnl ol_enable_syslog=no OL_ARG_ENABLE(syslog,[ --enable-syslog enable syslog support], auto)dnl OL_ARG_ENABLE(proctitle,[ --enable-proctitle enable proctitle support], yes)dnl OL_ARG_ENABLE(cache,[ --enable-cache enable caching], yes)dnl -OL_ARG_ENABLE(dns,[ --enable-dns enable V2 DX Referrals extension], no)dnl OL_ARG_ENABLE(referrals,[ --enable-referrals enable V2 Referrals extension], yes)dnl +OL_ARG_ENABLE(kbind,[ --enable-kbind enable V2 Kerberos IV bind], auto)dnl OL_ARG_ENABLE(cldap,[ --enable-cldap enable connectionless ldap], no)dnl +OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl +OL_ARG_ENABLE(unix,[ --enable-unix enable UNIX domain socket support], auto)dnl OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling], no, [yes no])dnl +dnl ---------------------------------------------------------------- dnl General "with" options -OL_ARG_ENABLE(dmalloc,[ --enable-dmalloc enable debug malloc support], no)dnl +dnl OL_ARG_ENABLE(dmalloc,[ --enable-dmalloc enable debug malloc support], no)dnl OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support], auto, [auto yes no] ) OL_ARG_WITH(fetch,[ --with-fetch with fetch URL support], auto, [auto yes no] ) -OL_ARG_WITH(kerberos,[ --with-kerberos with Kerberos support], - auto, [auto k5 k4 afs yes no]) +OL_ARG_WITH(kerberos,[ --with-kerberos with support], + auto, [auto k5 k5only k425 kth k4 afs yes no]) OL_ARG_WITH(readline,[ --with-readline with readline support], auto, [auto yes no] ) OL_ARG_WITH(threads,[ --with-threads use threads], - auto, [auto posix mach pth lwp yes no manual] ) + auto, [auto nt posix mach pth lwp yes no manual] ) OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support], auto, [auto ssleay openssl yes no] ) OL_ARG_WITH(yielding_select,[ --with-yielding-select with implicitly yielding select], auto, [auto yes no manual] ) +dnl ---------------------------------------------------------------- dnl Server options +dnl ---------------------------------------------------------------- +dnl ---------------------------------------------------------------- dnl SLAPD OPTIONS AC_ARG_WITH(xxslapdoptions,[SLAPD (Standalone LDAP Daemon) Options:]) OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], auto)dnl +OL_ARG_ENABLE(kpasswd,[ --enable-kpasswd enable kerberos password verification], no)dnl +OL_ARG_ENABLE(spasswd,[ --enable-spasswd enable (Cyrus) SASL password verification], no)dnl OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl OL_ARG_ENABLE(multimaster,[ --enable-multimaster enable multimaster replication], no)dnl OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl OL_ARG_ENABLE(quipu,[ --enable-quipu build quipu migration tools], no)dnl OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs], no)dnl -OL_ARG_ENABLE(discreteaci,[ --enable-discreteaci enable discrete rights in ACIs], no)dnl OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl +OL_ARG_ENABLE(dynamic,[ --enable-dynamic enable linking built binaries with dynamic libs], no)dnl dnl SLAPD Backend options -OL_ARG_ENABLE(bdb2,[ --enable-bdb2 enable bdb2 backend], no)dnl -OL_ARG_WITH(bdb2_module,[ --with-bdb2-module module type], static, +OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend], no)dnl +OL_ARG_WITH(dnssrv_module,[ --with-dnssrv-module module type], static, [static dynamic]) OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend], no)dnl OL_ARG_WITH(ldap_module,[ --with-ldap-module module type], static, [static dynamic]) OL_ARG_ENABLE(ldbm,[ --enable-ldbm enable ldbm backend], yes)dnl OL_ARG_WITH(ldbm_api,[ --with-ldbm-api use LDBM API], auto, - [auto db2 db mdbm gdbm ndbm manual]) + [auto berkeley bcompat mdbm gdbm]) OL_ARG_WITH(ldbm_module,[ --with-ldbm-module module type], static, [static dynamic]) OL_ARG_WITH(ldbm_type,[ --with-ldbm-type use LDBM type], auto, [auto btree hash]) - OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend], no)dnl OL_ARG_WITH(passwd_module,[ --with-passwd-module module type], static, [static dynamic]) -OL_ARG_ENABLE(perl,[ --enable-perl enable perl backend], no)dnl -OL_ARG_WITH(perl_module,[ --with-perl-module module type], static, - [static dynamic]) OL_ARG_ENABLE(shell,[ --enable-shell enable shell backend], no)dnl OL_ARG_WITH(shell_module,[ --with-shell-module module type], static, [static dynamic]) -OL_ARG_ENABLE(tcl,[ --enable-tcl enable tcl backend], no)dnl -OL_ARG_WITH(tcl_module,[ --with-tcl-module module type], static, - [static dynamic]) +dnl ---------------------------------------------------------------- dnl SLURPD OPTIONS AC_ARG_WITH(xxslurpdoptions,[SLURPD (Replication Daemon) Options:]) OL_ARG_ENABLE(slurpd,[ --enable-slurpd enable building slurpd], auto)dnl +dnl ---------------------------------------------------------------- AC_ARG_WITH(xxliboptions,[Library Generation & Linking Options]) AC_ENABLE_STATIC dnl AC_DISABLE_SHARED AC_ENABLE_SHARED +dnl ---------------------------------------------------------------- + dnl General "enable" options # validate options -if test $ol_enable_dns = yes ; then - if test $ol_enable_referrals = no ; then - AC_MSG_ERROR([DNS requires --enable-referrals]) - fi - if test $ol_enable_referrals = auto ; then - AC_MSG_WARN([DNS requires referrals, adding --enable-referrals]) - ol_enable_referrals=yes - fi -fi - if test $ol_enable_slapd = no ; then dnl SLAPD was specificallly disabled - if test $ol_enable_bdb2 = yes ; then - AC_MSG_WARN([slapd disabled, ignoring --enable-bdb2 argument]) + if test $ol_enable_dnssrv = yes ; then + AC_MSG_WARN([slapd disabled, ignoring --enable-dnssrv argument]) fi if test $ol_enable_ldap = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-ldap argument]) @@ -188,15 +202,9 @@ if test $ol_enable_slapd = no ; then if test $ol_enable_passwd = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-passwd argument]) fi - if test $ol_enable_perl = yes ; then - AC_MSG_WARN([slapd disabled, ignoring --enable-perl argument]) - fi if test $ol_enable_shell = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-shell argument]) fi - if test $ol_enable_tcl = yes ; then - AC_MSG_WARN([slapd disabled, ignoring --enable-tcl argument]) - fi if test $ol_enable_modules = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-modules argument]) fi @@ -218,17 +226,14 @@ if test $ol_enable_slapd = no ; then if test $ol_enable_aci = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-aci argument]) fi - if test $ol_enable_discreteaci = yes ; then - AC_MSG_WARN([slapd disabled, ignoring --enable-discreteaci argument]) - fi if test $ol_with_ldbm_api != auto ; then AC_MSG_WARN([slapd disabled, ignoring --with-ldbm-api argument]) fi if test $ol_with_ldbm_type != auto ; then AC_MSG_WARN([slapd disabled, ignoring --with-ldbm-type argument]) fi - if test $ol_with_bdb2_module != static ; then - AC_MSG_WARN([slapd disabled, ignoring --with-bdb2-module argument]) + if test $ol_with_dnssrv_module != static ; then + AC_MSG_WARN([slapd disabled, ignoring --with-dnssrv-module argument]) fi if test $ol_with_ldap_module != static ; then AC_MSG_WARN([slapd disabled, ignoring --with-ldap-module argument]) @@ -239,27 +244,19 @@ if test $ol_enable_slapd = no ; then if test $ol_with_passwd_module != static ; then AC_MSG_WARN([slapd disabled, ignoring --with-passwd-module argument]) fi - if test $ol_with_perl_module != static ; then - AC_MSG_WARN([slapd disabled, ignoring --with-perl-module argument]) - fi if test $ol_with_shell_module != static ; then AC_MSG_WARN([slapd disabled, ignoring --with-shell-module argument]) fi - if test $ol_with_tcl_module != static ; then - AC_MSG_WARN([slapd disabled, ignoring --with-tcl-module argument]) - fi if test $ol_enable_slurpd = yes ; then AC_MSG_ERROR([slurpd requires slapd]) fi # force settings to no - ol_enable_bdb2=no + ol_enable_dnssrv=no ol_enable_ldap=no ol_enable_ldbm=no ol_enable_passwd=no - ol_enable_perl=no ol_enable_shell=no - ol_enable_tcl=no ol_enable_modules=no ol_enable_multimaster=no @@ -267,19 +264,17 @@ if test $ol_enable_slapd = no ; then ol_enable_quipu=no ol_enable_rlookups=no ol_enable_aci=no - ol_enable_discreteaci=no ol_enable_wrappers=no + ol_enable_dynamic=no ol_with_ldbm_api=no ol_with_ldbm_type=no - ol_with_bdb2_module=static + ol_with_dnssrv_module=static ol_with_ldap_module=static ol_with_ldbm_module=static ol_with_passwd_module=static - ol_with_perl_module=static ol_with_shell_module=static - ol_with_tcl_module=static ol_enable_slurpd=no @@ -298,16 +293,11 @@ elif test $ol_enable_ldbm = no ; then AC_MSG_WARN([LDBM disabled, ignoring --with-ldbm-module argument]) fi - if test $ol_enable_bdb2 = yes ; then - AC_MSG_ERROR([BDB2 requires --enable-ldbm]) - fi - if test $ol_enable_modules != yes -a \ + $ol_enable_dnssrv = no -a \ $ol_enable_ldap = no -a \ $ol_enable_passwd = no -a \ - $ol_enable_perl = no -a \ - $ol_enable_shell = no -a \ - $ol_enable_tcl = no ; then + $ol_enable_shell = no ; then AC_MSG_ERROR([slapd requires a backend]) fi @@ -315,27 +305,8 @@ elif test $ol_enable_ldbm = no ; then ol_with_ldbm_type=no ol_with_ldbm_module=static -elif test $ol_enable_bdb2 = yes ; then - dnl SLAPD with BDB2 - - if test $ol_with_ldbm_api != auto -a \ - $ol_with_ldbm_api != db2 ; then - AC_MSG_ERROR([BDB2 requires LDBM API DB2]) - fi - - ol_with_ldbm_api=db2 - else dnl SLAPD with LDBM - - if test $ol_enable_bdb2 != no ; then - if test $ol_with_ldbm_api != auto -a \ - $ol_with_ldbm_api != db2 ; then - AC_MSG_WARN([BDB2 requires LDBM api db2 or auto]) - ol_enable_bdb2=no - fi - fi - if test $ol_with_ldbm_api = gdbm -a \ $ol_with_ldbm_type = btree ; then AC_MSG_ERROR([GDBM only supports LDBM type hash]) @@ -357,60 +328,78 @@ if test $ol_enable_slurpd = yes ; then fi fi +if test $ol_enable_kbind = yes -o $ol_enable_kpasswd = yes ; then + if test $ol_with_kerberos = no ; then + AC_MSG_ERROR([options require --with-kerberos]) + fi +elif test $ol_enable_kbind = no -o $ol_enable_kpasswd = no ; then + if test $ol_with_kerberos != auto ; then + AC_MSG_WARN([Kerberos detection enabled unnecessarily]); + else + ol_with_kerberos=no + fi +fi + +if test $ol_enable_spasswd = yes ; then + if test $ol_with_cyrus_sasl = no ; then + AC_MSG_ERROR([options require --with-cyrus-sasl]) + fi + ol_link_spasswd=yes +fi + AC_MSG_RESULT(done) -## Initialize vars +dnl ---------------------------------------------------------------- +dnl Initialize vars LDAP_LIBS= LDIF_LIBS= LDBM_LIBS= LTHREAD_LIBS= LUTIL_LIBS= +QUIPU_LIBS= SLAPD_LIBS= SLURPD_LIBS= BUILD_SLAPD=no BUILD_SLURPD=no -BUILD_BDB2=no +BUILD_QUIPU=no +BUILD_THREAD=no + +BUILD_DNSSRV=no BUILD_LDAP=no BUILD_LDBM=no BUILD_PASSWD=no -BUILD_PERL=no -BUILD_QUIPU=no BUILD_SHELL=no -BUILD_TCL=no -BUILD_THREAD=no -BUILD_BDB2_DYNAMIC=static +BUILD_DNSSRV_DYNAMIC=static BUILD_LDAP_DYNAMIC=static BUILD_LDBM_DYNAMIC=static BUILD_PASSWD_DYNAMIC=static -BUILD_PERL_DYNAMIC=static BUILD_SHELL_DYNAMIC=static -BUILD_TCL_DYNAMIC=static SLAPD_MODULES_LDFLAGS= SLAPD_MODULES_CPPFLAGS= SLAPD_MODULES_LIST= -SLAPD_PERL_LDFLAGS= -SLAPD_PERL_CPPFLAGS= - -KRB_LIBS= +KRB4_LIBS= +KRB5_LIBS= READLINE_LIBS= SASL_LIBS= TERMCAP_LIBS= TLS_LIBS= MODULES_LIBS= +AUTH_LIBS= -dnl ---------------------------------------------------------------- +dnl ================================================================ dnl Checks for programs dnl AC_PROG_INSTALL AC_DEFINE(HAVE_MKVERSION, 1, [define this if you have mkversion]) +dnl ---------------------------------------------------------------- dnl dnl Determine which C translator to use dnl @@ -464,9 +453,9 @@ dnl The default CFLAGS is empty NOT whatever AC_PROG_CC sets. dnl (for now, let autoconf sort this out) dnl CFLAGS=${CFLAGS-""} +AC_LIBTOOL_WIN32_DLL AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL -dnl AC_PROG_MAKE_SET AC_PROG_AWK OL_PROG_LN_H @@ -481,26 +470,10 @@ AC_PATH_PROG(SENDMAIL, sendmail, /usr/lib/sendmail, AC_PATH_PROG(EDITOR, vi, /usr/ucb/vi, $PATH:/usr/ucb) AC_PATH_PROG(FINGER, finger, /usr/ucb/finger, $PATH:/usr/ucb) -ol_link_perl=no -if test $ol_enable_perl != no ; then - AC_PATH_PROG(PERLBIN, perl, /usr/bin/perl) - - if test "no$PERLBIN" = "no" ; then - if test $ol_enable_perl = yes ; then - AC_MSG_ERROR([could not locate perl]) - fi - - else - SLAPD_PERL_LDFLAGS="`$PERLBIN -MExtUtils::Embed -e ldopts|sed -e s/-lc//`" - SLAPD_PERL_CPPFLAGS="`$PERLBIN -MExtUtils::Embed -e ccopts`" - - dnl should check perl version - ol_link_perl=yes - fi -fi - AC_PROG_CPP +dnl ---------------------------------------------------------------- +dnl Cross compiling checks if test $cross_compiling = yes -a $ol_enable_x_compile = yes; then AC_MSG_WARN([cross compiling.... some functionality will be removed.]) @@ -513,11 +486,13 @@ elif test $cross_compiling = yes -a $ol_enable_x_compile = no; then AC_MSG_ERROR([ if cross compiling, add --enable-x-compile.]) fi +dnl ---------------------------------------------------------------- dnl Checks for UNIX Variants AC_AIX AC_ISC_POSIX AC_MINIX +dnl ---------------------------------------------------------------- dnl Checks for system services AC_CYGWIN AC_MINGW32 @@ -526,15 +501,18 @@ AC_OBJEXT AC_DEFINE_UNQUOTED( EXEEXT, "${EXEEXT}", [defined to be the EXE extension]) +dnl ---------------------------------------------------------------- dnl BeOS requires -lbe -lroot -lnet AC_CHECK_LIB(be, be_app, [LIBS="$LIBS -lbe -lroot -lnet"], :, [-lroot -lnet]) +dnl ---------------------------------------------------------------- dnl OpenLDAP requires STDC features AM_PROG_CC_STDC if test "X${am_cv_prog_cc_stdc}" = "Xno" ; then AC_MSG_ERROR([OpenLDAP requires compiler to support STDC constructs.]) fi +dnl ---------------------------------------------------------------- dnl Check cc depend flags OL_MKDEPEND if test "${ol_cv_mkdep}" = no ; then @@ -542,31 +520,61 @@ if test "${ol_cv_mkdep}" = no ; then AC_MSG_WARN([do not know how to generate dependencies]) fi -dnl +dnl ---------------------------------------------------------------- +dnl Check for AIX security library +AC_CHECK_LIB(s, afopen, [ + AUTH_LIBS=-ls + AC_DEFINE(HAVE_AIX_SECURITY,1,[define if you have AIX security lib]) +]) + + +dnl ---------------------------------------------------------------- +dnl PF_INET6 support requires getaddrinfo +dnl PF_UNIX may use getaddrinfo in available +AC_CHECK_FUNCS( getaddrinfo ) + +if test $ac_cv_func_getaddrinfo = no ; then + if test $ol_enable_ipv6 = yes ; then + AC_MSG_ERROR([IPv6 support requires getaddrinfo()]) + fi + ol_enable_ipv6=no +fi + +if test $ol_enable_unix != no ; then + AC_CHECK_HEADERS( sys/un.h ) + + if test $ol_enable_unix = auto ; then + ol_enable_unix=$ac_cv_header_sys_un_h + elif test $ac_cv_header_sys_un_h = no ; then + AC_MSG_ERROR([UNIX domain support requires sys/un.h]) + fi +fi + +dnl ---------------------------------------------------------------- dnl Check for module support -dnl ol_link_modules=no if test $ol_enable_modules != no ; then AC_CHECK_HEADERS(ltdl.h) if test $ac_cv_header_ltdl_h = no ; then AC_MSG_ERROR([could not locate libtool ltdl.h]) - fi - AC_CHECK_LIB(ltdl, lt_dlinit) + AC_CHECK_LIB(ltdl, lt_dlinit, [ + MODULES_LIBS=-lltdl + AC_DEFINE(HAVE_LIBLTDL,1,[define if you have libtool -ltdl]) + ]) + if test "$ac_cv_lib_ltdl_lt_dlinit" = no ; then AC_MSG_ERROR([could not locate libtool -lltdl]) fi ol_link_modules=yes else - ol_with_bdb2_module=static + ol_with_dnssrv_module=static ol_with_ldap_module=static ol_with_ldbm_module=static ol_with_passwd_module=static - ol_with_perl_module=static ol_with_shell_module=static - ol_with_tcl_module=static fi dnl ---------------------------------------------------------------- @@ -589,12 +597,15 @@ AC_CHECK_HEADERS( \ arpa/inet.h \ arpa/nameser.h \ assert.h \ + conio.h \ crypt.h \ + direct.h \ errno.h \ fcntl.h \ filio.h \ getopt.h \ grp.h \ + io.h \ libutil.h \ limits.h \ locale.h \ @@ -603,6 +614,7 @@ AC_CHECK_HEADERS( \ memory.h \ psap.h \ pwd.h \ + process.h \ resolv.h \ sgtty.h \ shadow.h \ @@ -624,11 +636,35 @@ AC_CHECK_HEADERS( \ syslog.h \ termios.h \ unistd.h \ + winsock.h \ ) + dnl ---------------------------------------------------------------- dnl Checks for libraries +dnl HP-UX requires -lV3 +AC_CHECK_LIB(V3, sigset) + +dnl Gotta check for winsock manually +if test $ac_cv_header_winsock_h = yes; then + AC_CACHE_CHECK([for winsock], [ol_cv_winsock], + AC_TRY_LINK([#include ],[ + socket(0,0,0); + select(0,NULL,NULL,NULL,NULL); + closesocket(0); + gethostname(NULL,0); + ],[ol_cv_winsock=yes],[ol_cv_winsock=no])]) + + if test $ol_cv_winsock = yes ; then + AC_DEFINE(HAVE_WINSOCK,1,[define if you have winsock]) + ac_cv_func_socket=yes + ac_cv_func_select=yes + ac_cv_func_closesocket=yes + ac_cv_func_gethostname=yes + fi +fi + dnl Find socket() dnl Likely combinations: dnl -lsocket [ -lnsl_s | -lnsl ] @@ -638,7 +674,6 @@ AC_CHECK_FUNC(socket, :, [ dnl hopefully we won't include too many libraries AC_CHECK_LIB(socket, main) AC_CHECK_LIB(net, main) - AC_CHECK_LIB(net, socket) AC_CHECK_LIB(nsl_s, main) AC_CHECK_LIB(nsl, main) AC_CHECK_LIB(inet, socket) @@ -647,16 +682,18 @@ dnl hopefully we won't include too many libraries dnl require select AC_CHECK_FUNC(select, :, AC_MSG_ERROR([select() required.])) -dnl AC_CHECK_FUNCS(socketpair) -dnl Select arg types -dnl (if this detection becomes permenent, it and the select() detection -dnl should be done before the yielding select test) -AC_FUNC_SELECT_ARGTYPES +if test "${ac_cv_header_winsock_h}" != yes; then + dnl Select arg types + dnl (if this detection becomes permenent, it and the select() detection + dnl should be done before the yielding select test) + AC_FUNC_SELECT_ARGTYPES +fi dnl check to see if system call automatically restart dnl AC_SYS_RESTARTABLE_SYSCALLS +dnl ---------------------------------------------------------------- dnl require POSIX regex AC_CHECK_HEADERS( regex.h ) if test "$ac_cv_header_regex_h" != yes ; then @@ -669,37 +706,40 @@ if test "$ol_cv_c_posix_regex" = no ; then AC_MSG_ERROR([broken POSIX regex!]) fi -dnl HP-UX requires -lV3 -AC_CHECK_LIB(V3, sigset) - +dnl ---------------------------------------------------------------- dnl Check for resolver routines -AC_CHECK_FUNC(res_search,:) -if test $ac_cv_func_res_search = no ; then - AC_CHECK_LIB(bind, res_search) - ac_cv_func_res_search=$ac_cv_lib_bind_res_search +ol_link_dnssrv=no +AC_CHECK_FUNC(res_query,:) +if test $ac_cv_func_res_query = no ; then + AC_CHECK_LIB(bind, res_query) + ac_cv_func_res_query=$ac_cv_lib_bind_res_query fi -if test $ac_cv_func_res_search = no ; then - AC_CHECK_LIB(bind, __res_search) - ac_cv_func_res_search=$ac_cv_lib_bind___res_search +if test $ac_cv_func_res_query = no ; then + AC_CHECK_LIB(bind, __res_query) + ac_cv_func_res_query=$ac_cv_lib_bind___res_query fi -if test $ac_cv_func_res_search = no ; then - AC_CHECK_LIB(resolv, res_search) - ac_cv_func_res_search=$ac_cv_lib_resolv_res_search +if test $ac_cv_func_res_query = no ; then + AC_CHECK_LIB(resolv, res_query) + ac_cv_func_res_query=$ac_cv_lib_resolv_res_query fi -if test "$ac_cv_func_res_search" = yes ; then - AC_DEFINE(HAVE_RES_SEARCH,1, - [define if you have res_search()]) -elif test $ol_enable_dns = yes ; then - AC_MSG_ERROR([--enable-dns requires res_search]) -elif test $ol_enable_dns != no ; then - AC_MSG_WARN([no res_search, disabling DNS support]) +if test "$ac_cv_func_res_query" = yes ; then + AC_DEFINE(HAVE_RES_QUERY,1, + [define if you have res_query()]) + + if test $ol_enable_dnssrv != no ; then + ol_link_dnssrv=yes + fi fi +if test "$ol_enable_dnssrv" = yes -a "$ol_link_dnssrv" = no ; then + AC_MSG_ERROR([DNSSRV requires res_query()]) +fi -# QUIPU +dnl ---------------------------------------------------------------- +dnl QUIPU if test $ol_enable_quipu != no ; then AC_CHECK_HEADERS(quipu/commonarg.h) @@ -712,31 +752,104 @@ if test $ol_enable_quipu != no ; then fi fi -dnl -dnl check for kerberos -dnl -ol_link_kerberos=no +dnl ---------------------------------------------------------------- +dnl Kerberos +ol_link_kbind=no +ol_link_kpasswd=no +ol_link_krb5=no +ol_link_krb4=no + +if test $ol_with_kerberos = auto -o $ol_with_kerberos = k5 \ + -o $ol_with_kerberos = k5only -o $ol_with_kerberos = k425 ; then + + AC_CHECK_HEADERS(krb5.h) + + if test $ac_cv_header_krb5_h = yes ; then + dnl lazy check for Heimdal Kerberos + AC_CHECK_HEADERS(heim_err.h) + if test $ac_cv_header_heim_err_h = yes ; then + krb5_impl=heimdal + else + krb5_impl=mit + fi + + if test $krb5_impl = mit; then + AC_CHECK_LIB(krb5, main, + [have_krb5=yes + KRB5_LIBS="-lkrb5 -lcrypto -lcom_err"], + [have_krb5=no], + [-lcrypto -lcom_err]) + + elif test $krb5_impl = heimdal; then + AC_CHECK_LIB(krb5, main, + [have_krb5=yes + KRB5_LIBS="-lkrb5 -ldes -lasn1 -lroken -lcom_err"], + [have_krb5=no], + [-ldes -lasn1 -lroken -lcom_err]) + + AC_DEFINE(HAVE_HEIMDAL_KERBEROS, 1, + [define if you have HEIMDAL Kerberos]) + else + have_krb5=no + AC_MSG_WARN([Unrecongized Kerberos5 Implementation]) + fi + + if test $have_krb5 = yes ; then + ol_link_krb5=yes + + AC_DEFINE(HAVE_KRB5, 1, + [define if you have Kerberos V]) + + if test $ol_enable_kpasswd != no ; then + ol_link_kpasswd=yes; + fi + + if test $ol_with_kerberos = k5only ; then + ol_with_kerberos=found + fi + + elif test $ol_with_kerberos != auto ; then + AC_MSG_ERROR([Required Kerberos 5 support not available]) + fi + + fi +fi + +if test $ol_link_krb5 = yes -a \ + \( $ol_with_kerberos = auto -o $ol_with_kerberos = k425 \) ; then -if test $ol_with_kerberos = auto -o $ol_with_kerberos = k5 ; then AC_CHECK_HEADERS(kerberosIV/krb.h kerberosIV/des.h) if test $ac_cv_header_kerberosIV_krb_h = yes ; then - AC_CHECK_LIB(krb4, main, [have_k5=yes], [have_k5=no], - [-lkrb5 -ldes425]) + if test $krb5_impl = mit; then + AC_CHECK_LIB(krb4, main, [have_k425=yes + KRB4_LIBS="-lkrb4 -ldes425"], [have_k425=no], + [-ldes425 -lkrb5 -lcrypto -lcom_err]) - if test $have_k5 = yes ; then - ol_with_kerberos=found - ol_link_kerberos=yes + elif test $krb5_impl = heimdal; then + AC_CHECK_LIB(krb4, main, [have_k425=yes + KRB4_LIBS="-lkrb4"], [have_k425=no], + [-lkrb5 -ldes -lasn1 -lroken -lcom_err]) - KRB_LIBS="-lkrb4 -lkrb5 -ldes425" + else + have_425=no + AC_MSG_WARN([Unrecongized Kerberos5 Implementation]) + fi + + if test $have_k425 = yes ; then + ol_with_kerberos=found + ol_link_krb4=yes - LIBS="$KRB_LIBS $LIBS" + AC_DEFINE(HAVE_KRB425, 1, + [define if you have Kerberos V with IV support]) + AC_DEFINE(HAVE_KRB4, 1, + [define if you have Kerberos IV]) AC_CACHE_CHECK([for des_debug in Kerberos libraries], [ol_cv_var_des_debug], [ dnl save the flags save_LIBS="$LIBS" - LIBS="$KRB_LIBS $LIBS" + LIBS="$KRB4_LIBS $KRB5_LIBS $LIBS" AC_TRY_LINK([ #include #include @@ -758,28 +871,48 @@ des_debug = 1; fi fi -if test $ol_with_kerberos = auto -o $ol_with_kerberos = k4 ; then - AC_CHECK_HEADERS(krb.h des.h) +if test $ol_link_krb5 = yes ; then + ol_with_kerberos=found +fi + +if test $ol_with_kerberos = auto -o $ol_with_kerberos = k4 \ + -o $ol_with_kerberos = kth ; then + + AC_CHECK_HEADERS(krb.h des.h krb-archaeology.h ) if test $ac_cv_header_krb_h = yes ; then AC_CHECK_LIB(krb, main, [have_k4=yes], [have_k4=no], [-ldes]) if test $have_k4 = yes ; then ol_with_kerberos=found - ol_link_kerberos=yes + ol_link_krb4=yes + + AC_DEFINE(HAVE_KRB4, 1, + [define if you have Kerberos IV]) - KRB_LIBS="-lkrb -ldes" + KRB4_LIBS="-lkrb -ldes" + + if test $ac_cv_header_krb_archaeology_h = yes ; then + AC_DEFINE(HAVE_KTH_KERBEROS, 1, + [define if you have Kth Kerberos]) + fi fi fi fi -if test $ol_link_kerberos = yes ; then +if test $ol_link_krb4 = yes -a $ol_enable_kpasswd != no ; then + ol_link_kpasswd=yes; +fi + +if test $ol_link_krb4 = yes -o $ol_link_krb5 = yes ; then AC_DEFINE(HAVE_KERBEROS, 1, [define if you have Kerberos]) + +elif test $ol_with_kerberos != auto -a $ol_with_kerberos != no ; then + AC_MSG_ERROR([Kerberos detection failed.]) fi -dnl -dnl Check for SSL/TLS -dnl +dnl ---------------------------------------------------------------- +dnl TLS/SSL ol_link_tls=no if test $ol_with_tls != no ; then @@ -829,6 +962,7 @@ if test $ol_link_tls = yes ; then AC_DEFINE(HAVE_TLS, 1, [define if you have TLS]) fi +dnl ---------------------------------------------------------------- dnl Tests for reentrant functions necessary to build a dnl thread_safe -lldap. AC_CHECK_FUNCS( \ @@ -869,7 +1003,29 @@ if test "$ac_cv_func_ctime_r" = yes \ AC_DEFINE(LDAP_API_FEATURE_X_OPENLDAP_REENTRANT,1) fi +dnl ---------------------------------------------------------------- +dnl Threads? ol_link_threads=no + +if test $ol_with_threads = auto -o $ol_with_threads = yes \ + -o $ol_with_threads = nt ; then + + OL_NT_THREADS + + if test "$ol_cv_nt_threads" = yes ; then + ol_link_threads=nt + ol_with_threads=found + ol_with_yielding_select=yes + + AC_DEFINE(HAVE_NT_SERVICE_MANAGER,1,[if you have NT Service Manager]) + AC_DEFINE(HAVE_NT_EVENT_LOG,1,[if you have NT Event Log]) + fi + + if test $ol_with_threads = nt ; then + AC_MSG_ERROR([could not locate NT Threads]) + fi +fi + if test $ol_with_threads = auto -o $ol_with_threads = yes \ -o $ol_with_threads = posix ; then @@ -1016,7 +1172,7 @@ dnl [ol_cv_pthread_lpthread_lexc]) fi dnl Check functions for compatibility - AC_CHECK_FUNCS(pthread_kill) + AC_CHECK_FUNCS(pthread_kill pthread_rwlock_destroy) dnl Check for pthread_detach with inclusion dnl as it's symbol may have been mangled. @@ -1301,7 +1457,7 @@ if test $ol_with_threads = manual ; then AC_CHECK_HEADERS(thread.h synch.h) fi -if test $ol_link_threads != no ; then +if test $ol_link_threads != no -a $ol_link_threads != nt ; then dnl needed to get reentrant/threadsafe versions dnl AC_DEFINE(REENTRANT,1) @@ -1408,41 +1564,23 @@ if test $ol_link_threads != no ; then fi dnl ---------------------------------------------------------------- - ol_link_ldbm=no -if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db2 ; then - OL_BERKELEY_DB2 - if test $ol_cv_berkeley_db2 = yes ; then - ol_link_ldbm=db2 - ol_with_ldbm_api=db2 +if test $ol_with_ldbm_api = auto \ + -o $ol_with_ldbm_api = berkeley \ + -o $ol_with_ldbm_api = bcompat ; then - if test $ol_with_ldbm_type = hash ; then - AC_DEFINE(LDBM_USE_DBHASH,1, - [define this to use DBHASH w/ LDBM backend]) - else - AC_DEFINE(LDBM_USE_DBBTREE,1, - [define this to use DBBTREE w/ LDBM backend]) - fi - - dnl $ol_cv_lib_db2 should be yes or -ldb - dnl (it could be no, but that would be an error - if test $ol_cv_lib_db2 != yes ; then - LDBM_LIBS="$LDBM_LIBS $ol_cv_lib_db2" - fi + if test $ol_with_ldbm_api = bcompat; then \ + OL_BERKELEY_COMPAT_DB + else + OL_BERKELEY_DB fi -fi -ol_link_bdb2=no -if test $ol_link_ldbm = db2 -a $ol_enable_bdb2 != no ; then - ol_link_bdb2=yes -fi + if test $ol_cv_berkeley_db != no ; then + AC_DEFINE(HAVE_BERKELEY_DB,1, + [define this if Berkeley DB is available]) -if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db ; then - OL_BERKELEY_DB - - if test $ol_cv_berkeley_db = yes ; then - ol_link_ldbm=db + ol_link_ldbm=berkeley ol_with_ldbm_api=db if test $ol_with_ldbm_type = hash ; then @@ -1461,15 +1599,6 @@ if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = db ; then fi fi -if test $ol_with_ldbm_api = manual ; then - dnl User thinks he can manually configure LDBM api. - ol_link_ldbm=yes - - AC_MSG_WARN([LDBM defines and link options must be set manually]) - - AC_CHECK_HEADERS(db.h db_185.h gdbm.h ndbm.h) -fi - if test $ol_link_ldbm = no -a $ol_with_ldbm_type = btree ; then AC_MSG_WARN(Could not find LDBM with BTREE support) ol_with_ldbm_api=none @@ -1500,9 +1629,7 @@ if test $ol_with_ldbm_api = auto -o $ol_with_ldbm_api = gdbm ; then fi fi -if test $ol_with_ldbm_api = auto ; then - AC_MSG_WARN([skipping automatic checking for NDBM, must be manually enabled.]) -elif test $ol_with_ldbm_api = ndbm ; then +if test $ol_with_ldbm_api = ndbm ; then OL_NDBM if test $ol_cv_ndbm = yes ; then @@ -1525,19 +1652,29 @@ if test $ol_link_ldbm = no -a $ol_enable_ldbm != no ; then ol_enable_ldbm=no fi +dnl ---------------------------------------------------------------- +if test $ol_enable_dynamic = yes -a $enable_shared = yes ; then + LINK_BINS_DYNAMIC="yes" +else + LINK_BINS_DYNAMIC="no" +fi + +dnl ---------------------------------------------------------------- if test $ol_enable_wrappers != no ; then AC_CHECK_HEADERS(tcpd.h) if test $ac_cv_header_tcpd_h != yes ; then have_wrappers=no else - AC_CHECK_LIB(wrap, main, - [have_wrappers=yes], [have_wrappers=no]) + AC_TRY_COMPILE([ +int allow_severity = 0; +int deny_severity = 0; + ],[hosts_access()],[have_wrappers=yes],[have_wrappers=no]) fi if test $have_wrappers = yes ; then AC_DEFINE(HAVE_TCPD,1, [define if you have -lwrap]) - SLAPD_LIBS="$SLAPD_LIBS -lwrap" + WRAP_LIBS="-lwrap" dnl We add another check for -lnsl since some libwrap's dnl need it, but it isn't always included from above @@ -1550,9 +1687,11 @@ if test $ol_enable_wrappers != no ; then AC_MSG_WARN(disabling wrappers support) ol_enable_wrappers=no + WRAP_LIBS="" fi fi +dnl ---------------------------------------------------------------- if test $ol_enable_syslog != no ; then AC_CHECK_FUNC(openlog) if test $ac_cv_func_openlog = no -a $ol_enable_syslog = yes; then @@ -1561,45 +1700,8 @@ if test $ol_enable_syslog != no ; then ol_enable_syslog=$ac_cv_func_openlog fi -if test $ol_enable_dmalloc != no ; then - AC_CHECK_HEADERS(dmalloc.h) - AC_CHECK_LIB(dmalloc, dmalloc_shutdown) -fi - -if test $ol_enable_tcl != no ; then - AC_CHECK_HEADERS(tcl.h) - - if test $ac_cv_header_tcl_h != yes ; then - have_tcl=no - else - AC_CHECK_LIB(tcl,main, - [have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl"], - [have_tcl=no]) - - if test $have_tcl != yes; then - AC_CHECK_LIB(tcl7.6,main, - [have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl7.6"], - [have_tcl=no]) - fi - - if test $have_tcl != yes; then - AC_CHECK_LIB(tcl8.0,main, - [have_tcl=yes; SLAPD_LIBS="$SLAPD_LIBS -ltcl8.0"], - [have_tcl=no]) - fi - fi - - if test $have_tcl != yes ; then - AC_MSG_WARN([could not find -ltcl]) - if test $ol_enable_tcl = yes ; then - AC_MSG_ERROR([could not find tcl, select appropriate options or disable]) - fi - - ol_enable_tcl=no - fi -fi - -# ud needs termcap (should insert check here) +dnl ---------------------------------------------------------------- +dnl ud needs termcap (should insert check here) ol_link_termcap=no AC_CHECK_HEADERS(termcap.h ncurses.h) @@ -1626,11 +1728,12 @@ if test $ol_link_termcap = no ; then TERMCAP_LIBS= fi +dnl ---------------------------------------------------------------- dnl -dnl Check for fetch URL support -dnl should be extended to support other fetch URL APIs +dnl Check for Cyrus SASL dnl ol_link_sasl=no +ol_link_spasswd=no if test $ol_with_cyrus_sasl != no ; then AC_CHECK_HEADER(sasl.h) @@ -1650,6 +1753,28 @@ if test $ol_with_cyrus_sasl != no ; then fi fi +dnl ---------------------------------------------------------------- +dnl Check for entropy sources +if test $cross_compiling != yes ; then + dev=no + if test -r /dev/urandom ; then + dev="/dev/urandom"; + elif test -r /idev/urandom ; then + dev="/idev/urandom"; + elif test -r /dev/srandom ; then + dev="/dev/srandom"; + elif test -r /dev/random ; then + dev="/dev/random"; + elif test -r /idev/random ; then + dev="/idev/random"; + fi + + if test $dev != no ; then + AC_DEFINE_UNQUOTED(URANDOM_DEVICE,"$dev",[set to urandom device]) + fi +fi + +dnl ---------------------------------------------------------------- dnl dnl Check for fetch URL support dnl should be extended to support other fetch URL APIs @@ -1667,6 +1792,7 @@ if test $ol_with_fetch != no ; then fi fi +dnl ---------------------------------------------------------------- dnl dnl Check for GNU readline dnl @@ -1695,7 +1821,8 @@ if test $ol_link_readline = yes ; then fi -# FreeBSD (and others) have crypt(3) in -lcrypt +dnl ---------------------------------------------------------------- +dnl FreeBSD (and others) have crypt(3) in -lcrypt if test $ol_enable_crypt != no ; then AC_CHECK_FUNC(crypt, [have_crypt=yes], [ AC_CHECK_LIB(crypt, crypt, [LUTIL_LIBS="$LUTIL_LIBS -lcrypt" @@ -1714,14 +1841,16 @@ if test $ol_enable_crypt != no ; then fi fi -# FreeBSD (and others) have setproctitle(3) in -lutil +dnl ---------------------------------------------------------------- +dnl FreeBSD (and others) have setproctitle(3) in -lutil if test $ol_enable_proctitle != no ; then AC_CHECK_FUNC(setproctitle, [have_setproctitle=yes], [ AC_CHECK_LIB(util, setproctitle, [have_setproctitle=yes LUTIL_LIBS="$LUTIL_LIBS -lutil"], [have_setproctitle=no - LIBOBJS="$LIBOBJS setproctitle.o"])]) + LIBOBJS="$LIBOBJS setproctitle.o" + LIBSRCS="$LIBSRCS setproctitle.c"])]) if test $have_setproctitle = yes ; then AC_DEFINE(HAVE_SETPROCTITLE,1, @@ -1731,18 +1860,25 @@ fi dnl ---------------------------------------------------------------- dnl Checks for typedefs, structures, and compiler characteristics. -AC_TYPE_GETGROUPS dnl requires AC_TYPE_UID_T AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_PID_T AM_TYPE_PTRDIFF_T AC_TYPE_SIGNAL -OL_TYPE_SIG_ATOMIC_T AC_TYPE_SIZE_T + +AC_CHECK_TYPE(ssize_t, [signed int]) +AC_CHECK_TYPE(caddr_t, [char *]) + OL_TYPE_SOCKLEN_T AC_STRUCT_ST_BLKSIZE AC_HEADER_TIME AC_STRUCT_TM +AC_TYPE_UID_T +OL_TYPE_SIG_ATOMIC_T + +dnl AC_TYPE_GETGROUPS + OL_STRUCT_PASSWD_PW_GECOS OL_STRUCT_PASSWD_PW_PASSWD @@ -1752,31 +1888,25 @@ OL_C_VOLATILE if test $cross_compiling = yes ; then AC_DEFINE(CROSS_COMPILING, 1, [define if cross compiling]) - - AC_DEFINE(LBER_INT_T,long) - AC_DEFINE(LBER_TAG_T,long) - AC_DEFINE(LBER_SOCKET_T,int) - else AC_C_BIGENDIAN - AC_CHECK_SIZEOF(short) - AC_CHECK_SIZEOF(int) - AC_CHECK_SIZEOF(long) +fi - if test "$ac_cv_sizeof_int" -lt 4 ; then - AC_MSG_WARN([OpenLDAP requires 'int' to be 32 bits or greater.]) +AC_COMPILE_CHECK_SIZEOF(short) +AC_COMPILE_CHECK_SIZEOF(int) +AC_COMPILE_CHECK_SIZEOF(long) - AC_DEFINE(LBER_INT_T,long) - AC_DEFINE(LBER_TAG_T,long) - AC_DEFINE(LBER_SOCKET_T,int) - else - AC_DEFINE(LBER_INT_T,int) - AC_DEFINE(LBER_TAG_T,long) - AC_DEFINE(LBER_SOCKET_T,int) - fi +if test "$ac_cv_sizeof_int" -lt 4 ; then + AC_MSG_WARN([OpenLDAP requires 'int' to be 32 bits or greater.]) + + AC_DEFINE(LBER_INT_T,long) +else + AC_DEFINE(LBER_INT_T,int) fi AC_DEFINE(LBER_LEN_T,long) +AC_DEFINE(LBER_SOCKET_T,int) +AC_DEFINE(LBER_TAG_T,long) dnl ---------------------------------------------------------------- dnl Checks for library functions. @@ -1787,8 +1917,17 @@ dnl AM_FUNC_STRTOD OL_FUNC_INET_ATON -dnl we should use vfork instead of fork in a number of places... -dnl AC_FUNC_VFORK +dnl Check for NT specific routines +AC_CHECK_FUNC(_spawnlp, AC_DEFINE(HAVE_SPAWNLP,1,[if you have spawnlp()])) + +AC_CHECK_FUNC(_snprintf, [ac_cv_func_snprintf=yes + AC_DEFINE(snprintf, _snprintf, [define to snprintf routine]) +]) + +AC_CHECK_FUNC(_vsnprintf, [ac_cv_func_vsnprintf=yes + AC_DEFINE(vsnprintf, _vsnprintf, [define to vsnprintf routine]) +]) + AC_FUNC_VPRINTF if test $ac_cv_func_vprintf = yes ; then @@ -1799,6 +1938,7 @@ fi AC_CHECK_FUNCS( \ bcopy \ closesocket \ + chroot \ endgrent \ endpwent \ flock \ @@ -1806,6 +1946,7 @@ AC_CHECK_FUNCS( \ getgrgid \ gethostname \ getpass \ + getpassphrase \ getpwuid \ getpwnam \ getspnam \ @@ -1849,6 +1990,14 @@ AC_CHECK_FUNCS( \ dnl We actually may need to replace more than this. AC_REPLACE_FUNCS(getopt tempnam) +if test "$ac_cv_func_getopt" != yes; then + LIBSRCS="$LIBSRCS getopt.c" +fi + +if test "$ac_cv_func_tempnam" != yes; then + LIBSRCS="$LIBSRCS tempnam.c" +fi + dnl ---------------------------------------------------------------- # Check Configuration OL_SYS_ERRLIST @@ -1872,8 +2021,8 @@ if test "$ol_enable_cache" = no ; then AC_DEFINE(LDAP_NOCACHE,1, [define this to remove -lldap cache support]) fi -if test "$ol_enable_dns" != no ; then - AC_DEFINE(LDAP_API_FEATURE_X_OPENLDAP_V2_DNS,LDAP_VENDOR_VERSION) +if test "$ol_link_kbind" != no ; then + AC_DEFINE(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND,LDAP_VENDOR_VERSION) fi if test "$ol_enable_proctitle" != no ; then AC_DEFINE(LDAP_PROCTITLE,1, @@ -1885,13 +2034,24 @@ fi if test "$ol_enable_cldap" != no ; then AC_DEFINE(LDAP_CONNECTIONLESS,1,[define to support CLDAP]) fi - -if test "$ol_enable_crypt" != no ; then - AC_DEFINE(SLAPD_CRYPT,1,[define to support crypt(3) passwords]) +if test "$ol_enable_unix" != no; then + AC_DEFINE(LDAP_PF_UNIX,1,[define to support PF_UNIX]) +fi +if test "$ol_enable_ipv6" != no; then + AC_DEFINE(LDAP_PF_INET6,1,[define to support PF_INET6]) fi if test "$ol_enable_cleartext" != no ; then AC_DEFINE(SLAPD_CLEARTEXT,1,[define to support cleartext passwords]) fi +if test "$ol_enable_crypt" != no ; then + AC_DEFINE(SLAPD_CRYPT,1,[define to support crypt(3) passwords]) +fi +if test "$ol_link_kpasswd" != no ; then + AC_DEFINE(SLAPD_KPASSWD,1,[define to support Kerberos passwords]) +fi +if test "$ol_link_spasswd" != no ; then + AC_DEFINE(SLAPD_SPASSWD,1,[define to support SASL passwords]) +fi if test "$ol_enable_multimaster" != no ; then AC_DEFINE(SLAPD_MULTIMASTER,1,[define to support multimaster replication]) fi @@ -1904,27 +2064,23 @@ fi if test "$ol_enable_aci" != no ; then AC_DEFINE(SLAPD_ACI_ENABLED,1,[define to support per-object ACIs]) fi -if test "$ol_enable_discreteaci" != no ; then - AC_DEFINE(SLAPD_ACI_DISCRETE_RIGHTS,1,[define to support discrete rights in ACIs]) -fi if test "$ol_link_modules" != no ; then AC_DEFINE(SLAPD_MODULES,1,[define to support modules]) BUILD_SLAPD=yes - MODULES_LIBS=-lltdl SLAPD_MODULES_LDFLAGS="-dlopen self" fi -if test "$ol_link_bdb2" != no ; then - AC_DEFINE(SLAPD_BDB2,1,[define to support BDB2 backend]) +if test "$ol_link_dnssrv" != no ; then + AC_DEFINE(SLAPD_DNSSRV,1,[define to support DNS SRV backend]) BUILD_SLAPD=yes - BUILD_BDB2=yes - if test "$ol_with_bdb2_module" != static ; then - AC_DEFINE(SLAPD_BDB2_DYNAMIC,1, - [define to support dynamic BDB2 backend]) - BUILD_BDB2=mod - BUILD_BDB2_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-bdb2/back_bdb2.la" + BUILD_DNSSRV=yes + if test "$ol_with_dnssrv_module" != static ; then + AC_DEFINE(SLAPD_DNSSRV_DYNAMIC,1, + [define to support dynamic DNS SRV backend]) + BUILD_DNSSRV=mod + BUILD_DNSSRV_DYNAMIC=shared + SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-dnssrv/back_dnssrv.la" fi fi @@ -1967,19 +2123,6 @@ if test "$ol_enable_passwd" != no ; then fi fi -if test "$ol_link_perl" != no ; then - AC_DEFINE(SLAPD_PERL,1,[define to support PERL backend]) - BUILD_SLAPD=yes - BUILD_PERL=yes - if test "$ol_with_perl_module" != static ; then - AC_DEFINE(SLAPD_PERL_DYNAMIC,1, - [define to support dynamic PERL backend]) - BUILD_PERL=mod - BUILD_PERL_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-perl/back_perl.la" - fi -fi - if test "$ol_enable_shell" != no ; then AC_DEFINE(SLAPD_SHELL,1,[define to support SHELL backend]) BUILD_SLAPD=yes @@ -1993,19 +2136,6 @@ if test "$ol_enable_shell" != no ; then fi fi -if test "$ol_enable_tcl" != no ; then - AC_DEFINE(SLAPD_TCL,1,[define to support TCL backend]) - BUILD_SLAPD=yes - BUILD_TCL=yes - if test "$ol_with_tcl_module" != static; then - AC_DEFINE(SLAPD_TCL_DYNAMIC,1, - [define to support dynamic TCL backend]) - BUILD_TCL=mod - BUILD_TCL_DYNAMIC=shared - SLAPD_MODULES_LIST="$SLAPD_MODULES_LIST -dlopen \$(SLAP_DIR)back-tcl/back_tcl.la" - fi -fi - if test "$ol_enable_slurpd" != no -a "$ol_link_threads" != no -a \ $BUILD_SLAPD = yes ; then BUILD_SLURPD=yes @@ -2013,45 +2143,66 @@ fi dnl ---------------------------------------------------------------- +if test "$LINK_BINS_DYNAMIC" = yes; then + LIB_LINKAGE=DYN + LT_LIB_LINKAGE=shared +else + LIB_LINKAGE=STAT + LT_LIB_LINKAGE=static +fi + +if test "$ac_cv_mingw32" = yes ; then + PLAT=NT + DYN_EXT=dll +else + PLAT=UNIX + DYN_EXT=so +fi + +AC_SUBST(LIBSRCS) + +AC_SUBST(PLAT) +AC_SUBST(LIB_LINKAGE) +AC_SUBST(LT_LIB_LINKAGE) +AC_SUBST(DYN_EXT) + AC_SUBST(BUILD_SLAPD) - AC_SUBST(BUILD_BDB2) + AC_SUBST(BUILD_DNSSRV) AC_SUBST(BUILD_LDAP) AC_SUBST(BUILD_LDBM) AC_SUBST(BUILD_PASSWD) - AC_SUBST(BUILD_PERL) AC_SUBST(BUILD_QUIPU) AC_SUBST(BUILD_SHELL) - AC_SUBST(BUILD_TCL) - AC_SUBST(BUILD_BDB2_DYNAMIC) + AC_SUBST(BUILD_DNSSRV_DYNAMIC) AC_SUBST(BUILD_LDAP_DYNAMIC) AC_SUBST(BUILD_LDBM_DYNAMIC) AC_SUBST(BUILD_PASSWD_DYNAMIC) - AC_SUBST(BUILD_PERL_DYNAMIC) AC_SUBST(BUILD_SHELL_DYNAMIC) - AC_SUBST(BUILD_TCL_DYNAMIC) AC_SUBST(BUILD_SLURPD) AC_SUBST(LDAP_LIBS) AC_SUBST(LDIF_LIBS) AC_SUBST(SLAPD_LIBS) +AC_SUBST(QUIPU_LIBS) AC_SUBST(SLURPD_LIBS) AC_SUBST(LDBM_LIBS) AC_SUBST(LTHREAD_LIBS) AC_SUBST(LUTIL_LIBS) +AC_SUBST(WRAP_LIBS) +AC_SUBST(LINK_BINS_DYNAMIC) AC_SUBST(SLAPD_MODULES_CPPFLAGS) AC_SUBST(SLAPD_MODULES_LDFLAGS) AC_SUBST(SLAPD_MODULES_LIST) -AC_SUBST(SLAPD_PERL_CPPFLAGS) -AC_SUBST(SLAPD_PERL_LDFLAGS) - -AC_SUBST(KRB_LIBS) +AC_SUBST(KRB4_LIBS) +AC_SUBST(KRB5_LIBS) AC_SUBST(READLINE_LIBS) AC_SUBST(SASL_LIBS) AC_SUBST(TERMCAP_LIBS) AC_SUBST(TLS_LIBS) AC_SUBST(MODULES_LIBS) +AC_SUBST(AUTH_LIBS) dnl ---------------------------------------------------------------- dnl final output @@ -2072,6 +2223,7 @@ clients/gopher/Makefile:build/top.mk:clients/gopher/Makefile.in:build/rules.mk \ clients/mail500/Makefile:build/top.mk:clients/mail500/Makefile.in:build/rules.mk \ clients/rcpt500/Makefile:build/top.mk:clients/rcpt500/Makefile.in:build/rules.mk \ clients/ud/Makefile:build/top.mk:clients/ud/Makefile.in:build/rules.mk \ +clients/maildap/Makefile:build/top.mk:clients/maildap/Makefile.in:build/rules.mk \ clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk \ include/Makefile:build/top.mk:include/Makefile.in \ libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk \ @@ -2081,16 +2233,15 @@ libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib. libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk \ libraries/libldbm/Makefile:build/top.mk:libraries/libldbm/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/libldif/Makefile:build/top.mk:libraries/libldif/Makefile.in:build/lib.mk:build/lib-static.mk \ +libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk \ libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.mk \ servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk \ servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk \ -servers/slapd/back-bdb2/Makefile:build/top.mk:servers/slapd/back-bdb2/Makefile.in:build/mod.mk \ +servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk \ servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk \ servers/slapd/back-ldbm/Makefile:build/top.mk:servers/slapd/back-ldbm/Makefile.in:build/mod.mk \ servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk \ -servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk \ servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk \ -servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \ servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \ servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \ servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \ diff --git a/contrib/Makefile.in b/contrib/Makefile.in index e74ed3238d..74b14db7d4 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, See COPYRIGHT file ## ## contrib Makefile.in for OpenLDAP diff --git a/contrib/README b/contrib/README index 488b167fea..26e86aaff1 100644 --- a/contrib/README +++ b/contrib/README @@ -1,23 +1,39 @@ -LDAP contrib README +OpenLDAP Contributed Software README -Contributed code lives underneath this contrib directory. It is not as -well-integrated into the LDAP build process as the rest of the LDAP -distribution. Please see the README files in each contrib subdirectory -for build instructions. +OpenLDAP provides a number of freely-distributable LDAP software +packages. Though distributed with OpenLDAP, they are not part of +OpenLDAP. Some packages may be out of date. Each package in +this directory has it's own use and redistribution restrictions +as documented within the package. Current contributions: + gtk-tool + GTK-based frontend from Predrag Balorda - saucer General purpose command-line LDAP client, modeled + ldaptcl + TCL API from NeoSoft + + php3-tool + PHP3-based frontend from Predrag Balorda + + saucer + General purpose command-line LDAP client, modeled after ISODE's DISH (DIrectory SHell) client. Contributed by Eric Rosenquist. See saucer/README and its man page for more information. - web500gw HTTP gateway for X.500, modeled after go500gw. + web_ldap + web frontend (in C) from Jens Moller + + web500gw + HTTP gateway for X.500, modeled after go500gw. Contributed by Frank Richter. See web500gw/README for more information. - whois++ WHOIS++ gateway to X.500. Contributed by Mark Prior. + whois++ + WHOIS++ gateway to X.500. Contributed by Mark Prior. See whois++/README for more information. -Please send your contributions to ldap-support@umich.edu +Please submit your contributions using the OpenLDAP Issue +Tracking System . diff --git a/contrib/gtk-tool/COPYRIGHT b/contrib/gtk-tool/COPYRIGHT new file mode 100644 index 0000000000..755a0ddd37 --- /dev/null +++ b/contrib/gtk-tool/COPYRIGHT @@ -0,0 +1,8 @@ +Copyright 1998,1999,2000 Predrag Balorda, London, UK +All rights reserved. + +Redistribution and use in source and binary forms are permitted only +as authorized by the OpenLDAP Public License. A copy of this +license is available at http://www.OpenLDAP.org/license.html or +in file LICENSE in the top-level directory of the distribution. + diff --git a/contrib/gtk-tool/ChangeLog b/contrib/gtk-tool/ChangeLog new file mode 100644 index 0000000000..cfbf97fd62 --- /dev/null +++ b/contrib/gtk-tool/ChangeLog @@ -0,0 +1,95 @@ +ChangeLog for gtk-tool +06/01/2000 - Pele + * Added cn=schema + +03/01/2000 - Pele + * Fixed localtime() bug in Linux ?;) + +03/01/19100 - Pele + * Auto-select the first server if any supplied as arguments + * A visual bug in the former (deselect a bit messy) + * Follow aliases (not tested with leaf nodes though) + * "Show Debug Info" in "Options" menu + +28/12/1999 - Pele + * Updated Gtk-- API from 1.0 to 1.1 + * Added -d switch (for debugging info) + * Added "Options" menu + +12/01/1999 - Pele + * Added some defines for U-MICH compatibility + * Updated to the latest Gtk-- API (in Gtk-- CVS tree) + * Minor fixes due to the new and cleaner Gtk-- API + * A new server can be added by entering a hostname into the + "url" field at the top and clicking on "Query Server" button + (note that one server still has to be supplied on the command line - + I'll try and fix this tomorrow...to do with ldap_get_opt) + * Somewhat "smarter" Makefile - can someone please look into integrating + gtk-tool into the openldap autoconf stuff? + +09/12/1998 - Pele + * Display of all ldap options in their proper widgets (sliders for + timeout, radio buttons for booleans etc.) when server selected + * Code cleanups + * Misc fixes + +03/12/1998 - Pele + * Added support for multiple servers (via multiple -s options) + * More testing + * Started experimenting with status bar for display of various info + * Got rid of many warning and error messages generate by gtk + * Added a new icon for objectclass=alias; + * Display of some ldap options aquired with ldap_get_option when + server selected. + * Traversing set to only 1 subtree (then 1 by 1); + * Started experimenting with a progress bar for traversal + (so users don't get bored while waiting for subtrees to be aquired and + constructed) + +02/12/1998 - Pele + * Added Gtk_LdapTree class + * Added utils (with debug only) + * "Smart" traversing of ldap tree (only 2-deep, then add 2 subtrees as + the tree gets expanded) + * Lots of updates and bug-fixes + +29/11/1998 - Pele + * Added Gtk_LdapServer class + * Started using cn=config, ldap_get_option (not sure about get_option + though, cn=config looks much nicer for the future-proofing) + * Can traverse, display and serve two (or possibly/hopefully) more + databases on the local machine - remote machines also possible - + need to use "-s hostname" + * The program needs the "-s" switch! Without it it won't run (temporary + "feature") + +28/11/1998 - Pele + * Fixes, enhancements, started using ldap utility api + * It now traverses the whole tree at startup, not sure if it's smart + but I did it because of something that has no relevance to network + traffic + +27/11/1998 - Pele + * Added viewports, both sides now scroll automatically + * Brought back the "cache" stuff, now data gets reused if it's allready + available without redundant searches/listings. + * Editing pixmaps by hand is so much, er, fun! + * Miniscule fixes + +26/11/1998 - Pele + * Added nice icons in the browser pane - looks decent now. + * Fixed scrolling in the data (right) pane - now scrolls if there is + a long tab + * removed class My_Scroller + * removed file Gtk_LdapItem.cc (useless) + * commented-out the part where data gets reused instead of re-querying + the server, stupid I know, but for the time being if resolves some + problems with replacement of right pane. + * Misc. fixes + +26/11/1998 - Pele + * First appearance of ChangeLog + * Fixed removal of scrolled window on the right hand side + thus making gtk-tool a viable project to be worked on + * added command-line parameter parsing - now accepts + -s for server, -p for port, -b for baseDN diff --git a/contrib/gtk-tool/Gtk_LdapServer.cc b/contrib/gtk-tool/Gtk_LdapServer.cc new file mode 100644 index 0000000000..8bb7480989 --- /dev/null +++ b/contrib/gtk-tool/Gtk_LdapServer.cc @@ -0,0 +1,446 @@ +#include "Gtk_LdapServer.h" +#include + +Gtk_LdapServer::Gtk_LdapServer() : Gtk_TreeItem() { + this->hostname = NULL; + this->par = NULL; + this->base_dn = NULL; + this->port = 0; +} + +Gtk_LdapServer::Gtk_LdapServer(My_Window *w, char *h, int p) : Gtk_TreeItem() { + char *s, *s2; + this->par = w; + this->hostname = h; + this->port = p; + this->notebook = NULL; + debug("%s %i\n", this->hostname, this->port); + this->setType(1); + this->getConfig(); +} + +Gtk_LdapServer::Gtk_LdapServer(GtkTreeItem *t) : Gtk_TreeItem(t) { +} + +Gtk_LdapServer::~Gtk_LdapServer() { + debug("Bye\n"); + delete this; +} + +void Gtk_LdapServer::setType(int t) { + debug("Gtk_LdapServer::setType(%i)\n", t); + Gtk_Pixmap *xpm_icon; + Gtk_Label *label; + char *c = NULL; + if (this->get_child() != NULL) this->remove(); + xpm_label = new Gtk_HBox(); + debug(this->hostname); + if (strcasecmp(this->hostname,"localhost") == 0) + xpm_icon=new Gtk_Pixmap(local_server); + else xpm_icon=new Gtk_Pixmap(remote_server); +// sprintf(c, "%s:%i", this->hostname, this->port); +// printf("%s\n", c); + label = new Gtk_Label(this->hostname); + xpm_label->pack_start(*xpm_icon, false, false, 1); + xpm_label->pack_start(*label, false, false, 1); + if (this->get_child() == NULL) this->add(*xpm_label); + this->show_all(); +} + +int Gtk_LdapServer::showDetails() { + debug("Gtk_LdapServer::showDetails()\n"); + if (this->notebook == NULL) this->getOptions(); + if (this->notebook != NULL) { + debug("Have a notebook here"); + if (par->viewport2->get_child() != NULL) { + debug(" and viewport has children"); + par->viewport2->remove(); + debug(" which have been removed\n"); + } + else debug(" and viewport without children\n"); + par->viewport2->add(*this->notebook); + } + this->show_all(); + debug("done\n"); + return 0; +} + +int Gtk_LdapServer::getMonitor() { + debug("Gtk_LdapServer::getMonitor()\n"); + int error, entriesCount; + LDAPMessage *entry, *result_identifier; + BerElement *ber; + char *attribute, **t; + + if ((this->ld = ldap_open(this->hostname, this->port)) == NULL) { + perror("connection"); + } + + error = ldap_search_s(this->ld, "cn=monitor", LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, &result_identifier); + entriesCount = ldap_count_entries(this->ld, result_identifier); + if (entriesCount == 0) { + return 0; + } + + debug("%i tree(s)\n", entriesCount); + for (entry = ldap_first_entry(this->ld, result_identifier); entry != NULL; entry = ldap_next_entry(this->ld, result_identifier)) { + for (attribute = ldap_first_attribute(this->ld, entry, &ber); attribute != NULL; attribute = ldap_next_attribute(this->ld, entry, ber)) { + debug("Attrib: %s\n", attribute); + if (strcasecmp(attribute, "database") == 0) { + debug("have database here\n"); + this->databases = NULL; + t = ldap_get_values(this->ld, entry, attribute); + for (int i=0; idatabases = g_list_append(this->databases, strdup(t[i])); + } + ldap_value_free(t); + debug("databases loaded\n"); + GList *t; + for (int i=0;i>g_list_length(this->databases);i++) { + t = g_list_nth(this->databases, i); + debug("database(%i) %s\n", i, (char*) t->data); + } + } + } + debug("entry done\n"); + } + return entriesCount; +} + +int Gtk_LdapServer::getConfig() { + debug("Gtk_LdapServer::getConfig()\n"); + int error, entriesCount; + LDAPMessage *entry, *result_identifier; + BerElement *ber; + char *attribute, **t; + + if ((this->ld = ldap_open(this->hostname, this->port)) == NULL) { + perror("connection"); + } + + error = ldap_search_s(this->ld, "cn=config", LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, &result_identifier); + entriesCount = ldap_count_entries(this->ld, result_identifier); + if (entriesCount == 0) { + return 0; + } + +// debug("%i tree(s)\n", entriesCount); + for (entry = ldap_first_entry(this->ld, result_identifier); entry != NULL; entry = ldap_next_entry(this->ld, result_identifier)) { + for (attribute = ldap_first_attribute(this->ld, entry, &ber); attribute != NULL; attribute = ldap_next_attribute(this->ld, entry, ber)) { + debug("Attrib: %s\n", attribute); + if (strcasecmp(attribute, "database") == 0) { + debug("have database here\n"); + this->databases = NULL; + t = ldap_get_values(this->ld, entry, attribute); + for (int i=0; idatabases = g_list_append(this->databases, strdup(t[i])); + } + this->databases = g_list_append(this->databases, "ldbm : cn=config"); + this->databases = g_list_append(this->databases, "ldbm : cn=monitor"); + this->databases = g_list_append(this->databases, "ldbm : cn=schema"); + ldap_value_free(t); + debug("databases loaded\n"); + GList *t; + for (int i=0;idatabases);i++) { + t = g_list_nth(this->databases, i); + debug("database(%i) %s\n", i, (char*) t->data); + } + } + } + debug("entry done\n"); + } + return entriesCount; +} + +#ifndef LDAP_GET_OPT /* a temporary fix for usability with (old) U-MICH api */ +char* Gtk_LdapServer::getOptDescription(int option) { + debug("Gtk_LdapServer::getOptDescription(%i) ", option); + char *c; + switch (option) { + case LDAP_OPT_API_INFO: c = "API info"; break; + case LDAP_OPT_CLIENT_CONTROLS: c = "Client controls"; break; + case LDAP_OPT_DEREF: c = "Dereference"; break; + case LDAP_OPT_DESC: c = "Description"; break; + case LDAP_OPT_DNS: c = "DNS Lookup"; break; + case LDAP_OPT_ERROR_NUMBER: c = "Error number"; break; + case LDAP_OPT_ERROR_STRING: c = "Error string"; break; + case LDAP_OPT_SIZELIMIT: c = "Size limit"; break; + case LDAP_OPT_TIMELIMIT: c = "Time limit"; break; + case LDAP_OPT_REFERRALS: c = "Referrals"; break; + case LDAP_OPT_RESTART: c = "Started"; break; + case LDAP_OPT_PROTOCOL_VERSION: c = "Protocol version"; break; + case LDAP_OPT_HOST_NAME: c = "Host name"; break; + case LDAP_OPT_SERVER_CONTROLS: c = "Server controls"; break; + default: c = "No description"; break; + } + debug("%s\n", c); + return c; +} + +int Gtk_LdapServer::getOptType(int option) { + debug("Gtk_LdapServer::getOptType(%i) ", option); + /* types: + * 0 = int, 1 = string, 2 = boolean, + * 3 = range, 4 = LDAPAPIInfo, 5 = unknown + */ + int type; + switch(option) { + /* ints */ + case LDAP_OPT_DEREF: + case LDAP_OPT_DESC: + case LDAP_OPT_ERROR_NUMBER: + case LDAP_OPT_PROTOCOL_VERSION: type = 0; break; + /* strings */ + case LDAP_OPT_ERROR_STRING: + case LDAP_OPT_HOST_NAME: type = 1; break; + /* bools */ + case LDAP_OPT_REFERRALS: + case LDAP_OPT_DNS: + case LDAP_OPT_RESTART: type = 2; break; + /* range */ + case LDAP_OPT_SIZELIMIT: + case LDAP_OPT_TIMELIMIT: type = 3; break; + /* api */ + case LDAP_OPT_API_INFO: type = 4; break; + /* unknowns */ + case LDAP_OPT_SERVER_CONTROLS: + case LDAP_OPT_CLIENT_CONTROLS: + default: type = 5; break; + } + debug("%i\n", type); + return type; +} +#endif /* LDAP_GET_OPT */ + +int Gtk_LdapServer::getOptions() { + debug("Gtk_LdapServer::getOptions()\n"); + if (this->notebook != NULL) return 0; +#ifdef LDAP_GET_OPT /* a temporary fix for usability with (old) U-MICH api */ + Gtk_Label *label; + label = new Gtk_Label("This tool has been compiled with (old) U-MICH API (no LDAP_GET_OPT)\nCompile with the latest -devel (from OpenLDAP cvs tree)\nto get some nice options here"); + this->notebook = new Gtk_Frame("LDAP Options"); + this->notebook->add(*label); + //label->show(); + //this->notebook->show(); + this->notebook->show_all(); + return 0; +#else + LDAPAPIInfo api; + Gtk_HBox *hbox, *mini_hbox; + Gtk_VBox *vbox, *mini_vbox; + Gtk_Table *table; + Gtk_Label *label; + Gtk_RadioButton *radio1, *radio2; + Gtk_HScale *scale; + Gtk_Adjustment *adjustment; + char *description = NULL, *s_value = NULL; +// int i_value; + string label_string; + + int things[10] = { + LDAP_OPT_API_INFO, + LDAP_OPT_CLIENT_CONTROLS, + // LDAP_OPT_DESC, + // LDAP_OPT_DEREF, + LDAP_OPT_DNS, + // LDAP_OPT_ERROR_NUMBER, + // LDAP_OPT_ERROR_STRING, + LDAP_OPT_HOST_NAME, + LDAP_OPT_PROTOCOL_VERSION, + LDAP_OPT_REFERRALS, + LDAP_OPT_RESTART, + LDAP_OPT_SERVER_CONTROLS, + LDAP_OPT_SIZELIMIT, + LDAP_OPT_TIMELIMIT + }; + +/* if (GTK_TREE_ITEM(this->gtkobj())->subtree == NULL) { + this->getSubtree(); + } */ + +// vbox = new Gtk_VBox(); + table = new Gtk_Table(10, 1, TRUE); + + for (int i=0; i<10; i++) { + int i_value; + // debug("%i\n", i); + hbox = new Gtk_HBox(TRUE, 2); + hbox->set_border_width(2); + description = this->getOptDescription(things[i]); + label = new Gtk_Label(description); + label->set_justify(GTK_JUSTIFY_LEFT); + label->set_alignment(0, 0); + hbox->pack_start(*label); + label->show(); + switch (this->getOptType(things[i])) { + case 0: + ldap_get_option(this->ld, things[i], &i_value); + debug("%s value %d\n", description, i_value); + sprintf(s_value, "%d", i_value); + label = new Gtk_Label(s_value); + label->set_justify(GTK_JUSTIFY_LEFT); + label->set_alignment(0, 0); + hbox->pack_end(*label); + label->show(); + break; + case 1: + ldap_get_option(this->ld, things[i], &s_value); + label = new Gtk_Label(s_value); + label->set_justify(GTK_JUSTIFY_LEFT); + label->set_alignment(0, 0); + hbox->pack_end(*label); + label->show(); + break; + case 2: + ldap_get_option(this->ld, things[i], &i_value); + radio1 = new Gtk_RadioButton("Enabled"); + radio2 = new Gtk_RadioButton("Disabled"); + radio2->set_group(radio1->group()); + if (i_value == 1) radio1->set_active(true); + else radio2->set_active(true); + mini_hbox = new Gtk_HBox(FALSE, 2); + mini_hbox->set_border_width(2); + mini_hbox->pack_start(*radio1); + //radio1->show(); + mini_hbox->pack_end(*radio2); + //radio2->show(); + hbox->pack_end(*mini_hbox); + //mini_hbox->show(); + break; + case 3: + ldap_get_option(this->ld, things[i], &i_value); + debug("i_value: %s\n", i_value); + adjustment = new Gtk_Adjustment(i_value, 0.0, 20.0, 1.0, 1.0, 0.0); + scale = new Gtk_HScale(*adjustment); + scale->set_update_policy(GTK_UPDATE_CONTINUOUS); + scale->set_value_pos(GTK_POS_TOP); + scale->set_digits(0); + scale->set_draw_value(true); + hbox->pack_end(*scale); + //scale->show(); + break; + case 4: +#ifdef LDAP_API_INFO_VERSION + api.ldapai_info_version = LDAP_API_INFO_VERSION; +#else + api.ldapai_info_version = 1; +#endif + if (ldap_get_option(this->ld, things[i], &api) != LDAP_SUCCESS) { + perror(this->getOptDescription(things[i])); + break; + } + s_value = api.ldapai_vendor_name; + label = new Gtk_Label(s_value); + label->set_justify(GTK_JUSTIFY_LEFT); + label->set_alignment(0, 0); + hbox->pack_end(*label); + //label->show(); + break; + default: + label = new Gtk_Label("Not implemented (yet)"); + label->set_justify(GTK_JUSTIFY_LEFT); + label->set_alignment(0, 0); + hbox->pack_end(*label); + //label->show(); + break; + } + // hbox->pack_end(*label); + // label->show(); + table->attach(*hbox, 0, 1, i, i+1); + hbox->show(); + } + table->set_border_width(2); + this->notebook = new Gtk_Frame("LDAP Options"); + this->notebook->add(*table); + //table->show(); + this->notebook->show_all(); + return 0; +#endif /* LDAP_GET_OPT */ +} + +Gtk_Tree* Gtk_LdapServer::getSubtree() { + debug("Gtk_LdapServer::getSubtree()\n"); + Gtk_LdapTree *tree, *subtree; + Gtk_LdapTreeItem *treeitem; + int entries; + + debug("this->hostname=%s\n", this->hostname); + debug("this->port=%i", this->port); + + char *c; + char *tok; + + int len = g_list_length(this->databases); + debug("this->databases->length()=%i\n", len); + + tree = new Gtk_LdapTree(); + for (int i=0; idatabases, i); + tok = strdup((char*)t->data); + tok = strtok(tok, ":"); + // c = strtok(NULL, " "); + c = strtok(NULL, "\0"); + debug("database %i %s\n", i, c); + treeitem = new Gtk_LdapTreeItem(c, this->par, this->ld); + subtree = treeitem->getSubtree(this->ld, 1); + debug("inserting %s into %s\n", treeitem->rdn, this->hostname); + tree->append(*treeitem); + if (subtree != NULL) treeitem->set_subtree(*subtree); + treeitem->show(); + // treeitem->setDnd(); + // tree->show(); + } +// this->set_subtree(*tree); + debug("getSubtree() done\n"); + return tree; +} +/* +void Gtk_LdapServer::show_impl() { + debug("%s showed\n", this->hostname); + BaseClassType *sig=static_cast(get_parent_class()); + if (!sig->show) return; + sig->show(gtkobj()); +// Gtk_c_signals_Item *sig=(Gtk_c_signals_Item *)internal_getsignalbase(); +// sig->show(GTK_WIDGET(gtkobj())); +} +*/ +void Gtk_LdapServer::select_impl() { + debug("%s selected\n", this->hostname); +// Gtk_c_signals_Item *sig=(Gtk_c_signals_Item *)internal_getsignalbase(); +// if (!sig->select) return; + this->showDetails(); +// sig->select(GTK_ITEM(gtkobj())); + Gtk_TreeItem::select_impl(); +} + +void Gtk_LdapServer::collapse_impl() { + debug("%s collapsed\n", this->hostname); +// Gtk_c_signals_TreeItem *sig=(Gtk_c_signals_TreeItem *)internal_getsignalbase(); +// if (!sig->collapse) return; +// sig->collapse(GTK_TREE_ITEM(gtkobj())); +// gtk_widget_hide(GTK_WIDGET(GTK_TREE(GTK_TREE_ITEM (this->gtkobj())->subtree))); + Gtk_TreeItem::collapse_impl(); +} + +void Gtk_LdapServer::expand_impl() { + debug("%s expanded\n", this->hostname); + Gtk_TreeItem::expand_impl(); +// BaseClassType *sig=static_cast(get_parent_class()); +// if (!sig->expand) +// { return; } +// sig->expand(gtkobj()); +// Gtk_c_signals_TreeItem *sig=(Gtk_c_signals_TreeItem *)internal_getsignalbase(); +// if (!sig->expand) return; +// sig->expand(GTK_TREE_ITEM(gtkobj())); +// Gtk_Tree *t; +// t = new Gtk_Tree(GTK_TREE(GTK_TREE_ITEM(this->gtkobj())->subtree)); +// bool vis = t->visible(); +// if (vis == false) { +// gtk_widget_show(GTK_WIDGET(GTK_TREE(GTK_TREE_ITEM (this->gtkobj())->subtree))); +// cout << this->dn << " expanded" << endl; +// } +// else { +// gtk_widget_hide(GTK_WIDGET(GTK_TREE(GTK_TREE_ITEM (this->gtkobj())->subtree))); +// cout << this->dn << " collapsed" << endl; +// } +} diff --git a/contrib/gtk-tool/Gtk_LdapServer.h b/contrib/gtk-tool/Gtk_LdapServer.h new file mode 100644 index 0000000000..21466a0b6c --- /dev/null +++ b/contrib/gtk-tool/Gtk_LdapServer.h @@ -0,0 +1,53 @@ +#ifndef GTK_LDAPSERVER_H +#define GTK_LDAPSERVER_H +#include "gtk.h" +#include "utils.h" +#include +#include +#include +#include +#include +#include "icons/local_server.h" +#include "icons/remote_server.h" + +#define LOCAL_SERVER 1 +#define REMOTE_SERVER 2 + +class My_Window; + +class Gtk_LdapServer : public Gtk_TreeItem { +public: + char *dn; + char *hostname; + LDAPMessage **thing; + LDAP *ld; + char *host; + char *base_dn; + int c, port; + My_Window *par; +// Gtk_Notebook *notebook; + Gtk_Frame *notebook; + Gtk_HBox *xpm_label; +// Gtk_Tree *subtree; + Gtk_Menu *popup; + GList *databases; + Gtk_LdapServer(); + Gtk_LdapServer(My_Window *w, char *c, int p); + Gtk_LdapServer(GtkTreeItem *t); + ~Gtk_LdapServer(); + void setType(int t); + int getMonitor(); + int getConfig(); + Gtk_Tree* getSubtree(); +#ifndef LDAP_GET_OPT + char* getOptDescription(int option); + int getOptType(int option); +#endif + int getOptions(); + int showDetails(); +// void show_impl(); + void select_impl(); + void collapse_impl(); + void expand_impl(); +}; +#endif diff --git a/contrib/gtk-tool/Gtk_LdapTree.cc b/contrib/gtk-tool/Gtk_LdapTree.cc new file mode 100644 index 0000000000..3908621aa0 --- /dev/null +++ b/contrib/gtk-tool/Gtk_LdapTree.cc @@ -0,0 +1,26 @@ +#include + +void Gtk_LdapTree::show_impl() { + debug("Gtk_LdapTree::show_impl()\n"); + Gtk_LdapTree *tree; + Gtk_LdapTreeItem *item = NULL; + Gtk_LdapTree::ItemList &items = this->tree(); + Gtk_LdapTree::ItemList::iterator i; // = items.begin(); + debug("iterator\n"); + for (i=items.begin(); i!=items.end();++i) { +// while (i!=items.end()) { + item = (Gtk_LdapTreeItem *)(*i); + debug("new item\n"); + debug("#%s#\n", item->dn); + if (item->get_subtree() == NULL) { + debug("ding!\n"); + tree = item->getSubtree(item->ld, 1); + if (tree != NULL) { + item->set_subtree(*tree); + } + item->setDnd(); + } + } + debug("done\n"); + Gtk_Tree::show_impl(); +} diff --git a/contrib/gtk-tool/Gtk_LdapTreeItem.cc b/contrib/gtk-tool/Gtk_LdapTreeItem.cc new file mode 100644 index 0000000000..0216a6503d --- /dev/null +++ b/contrib/gtk-tool/Gtk_LdapTreeItem.cc @@ -0,0 +1,376 @@ +#include "Gtk_LdapTreeItem.h" + +Gtk_LdapTreeItem::Gtk_LdapTreeItem() : Gtk_TreeItem() { + this->objectClass = NULL; +} + +Gtk_LdapTreeItem::Gtk_LdapTreeItem(char *c, My_Window *w, LDAP *ld) : Gtk_TreeItem() { + debug("Gtk_LdapTreeItem::Gtk_LdapTreeItem(%s)\n", c); + char **s; + this->dn = c; + s = ldap_explode_dn(this->dn, 1); + this->rdn = g_strdup_printf("%s", s[0]); + this->par = w; + this->ld = ld; + this->objectClass = NULL; + this->getDetails(); + this->createPopupMenu(); +} + +void Gtk_LdapTreeItem::setDnd() { + debug("Gtk_LdapTreeItem::setDnd()\n"); + this->set_events(get_events()|GDK_ALL_EVENTS_MASK); + this->drag_dest_set(GTK_DEST_DEFAULT_ALL, target_table, n_targets, static_cast (GDK_ACTION_COPY|GDK_ACTION_MOVE)); + this->drag_data_received.connect(slot(this, &(Gtk_LdapTreeItem::item_drag_data_received))); + this->drag_drop.connect(slot(this,&Gtk_LdapTreeItem::target_drag_drop)); + this->drag_source_set(static_cast(GDK_BUTTON1_MASK|GDK_BUTTON3_MASK), target_table, n_targets, static_cast(GDK_ACTION_COPY|GDK_ACTION_MOVE)); + gtk_drag_source_set(GTK_WIDGET(this->gtkobj()), static_cast(GDK_BUTTON1_MASK|GDK_BUTTON3_MASK), target_table, n_targets, static_cast(GDK_ACTION_COPY|GDK_ACTION_MOVE)); + this->drag_data_get.connect(slot(this, &Gtk_LdapTreeItem::source_drag_data_get)); + this->drag_data_delete.connect(slot(this,&Gtk_LdapTreeItem::source_drag_data_delete)); + this->drag_leave.connect(slot(this,&Gtk_LdapTreeItem::target_drag_leave)); + +} + +Gtk_LdapTreeItem::Gtk_LdapTreeItem(GtkTreeItem *t) : Gtk_TreeItem(t) { +} + +Gtk_LdapTreeItem::~Gtk_LdapTreeItem() { + cout << "Bye" << endl; + delete this; +} + +Gtk_LdapTree* Gtk_LdapTreeItem::getSubtree(LDAP *ld, int counter) { + debug("Gtk_LdapTreeItem::getSubtree(%s)\n", this->dn); + if (counter <= 0) return NULL; + if (this->gtkobj()->subtree != NULL) { + //return (Gtk_LdapTree *)GTK_TREE(this->gtkobj()->subtree); + debug("This item has a subtree\n"); + return (Gtk_LdapTree *)this->get_subtree(); //gtkobj()->subtree); + } + counter--; + Gtk_LdapTree *subtree = NULL, *tree = NULL; + Gtk_LdapTreeItem *subtreeitem = NULL; + LDAPMessage *r_i = NULL, *entry = NULL; + gchar *c; + char **s; + int entriesCount = 0, error; + + this->ld = ld; + if (this->dn == "cn=config" || this->dn == "cn=monitor" || this->dn == "cn=schema") error = ldap_search_s(this->ld, this->dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, &r_i); + else { + if (strcasecmp(this->objectClass,"alias") == 0) error = ldap_search_s(this->ld, this->getAttribute("aliasedobjectname"), LDAP_SCOPE_ONELEVEL, "objectclass=*", NULL, 0, &r_i); + else error = ldap_search_s(this->ld, this->dn, LDAP_SCOPE_ONELEVEL, "objectclass=*", NULL, 0, &r_i); + } +// printf("%s\n", ldap_err2string(error)); + entriesCount = ldap_count_entries(this->ld, r_i); + debug("%i results\n", entriesCount); + if (entriesCount != 0) { + tree = new Gtk_LdapTree(); + // this->set_subtree(*tree); + tree->set_selection_mode(GTK_SELECTION_BROWSE); + tree->set_view_mode(GTK_TREE_VIEW_ITEM); + tree->set_view_lines(false); + entry = ldap_first_entry(this->ld, r_i); + // float i = 1; + gfloat percent = 100/entriesCount; + debug("percent is %f\n", percent); + // this->par->progress.set_percentage(percent/100); + // this->par->progress.show(); + while (entry != NULL) { + subtreeitem = new Gtk_LdapTreeItem(ldap_get_dn(this->ld, entry), this->par, this->ld); + debug("inserting %s into %s\n",subtreeitem->rdn,this->rdn); + tree->append(*subtreeitem); + subtree = subtreeitem->getSubtree(this->ld, counter); + subtreeitem->show(); + if (subtree != NULL) subtreeitem->set_subtree(*subtree); + // subtreeitem->setDnd(); + debug("done\n"); + entry = ldap_next_entry(this->ld, entry); + // gfloat pvalue = (i*percent)/100; + // cout << pvalue << " %" << endl; + // this->par->progress.update(pvalue); + // this->par->progress.show(); + // i++; + } + // this->set_subtree(*tree); + // this->par->progress.update(0); + // this->par->progress->show(); + } +// this->getDetails(); + debug("done\n"); + return tree; +} + +void Gtk_LdapTreeItem::setType(int t) { + debug("Gtk_LdapTreeItem::setType(%s)\n", this->objectClass); + Gtk_Pixmap *xpm_icon; + Gtk_Label *label; + if (this->get_child() != NULL) { + debug("got a child here"); + //xpm_label = new Gtk_HBox(this->get_child()); + this->remove(); + /* + //xpm_label = new Gtk_HBox(*GTK_HBOX(this->get_child()->gtkobj())); + xpm_label = new Gtk_HBox(this->get_child()); //->gtkobj()); + //xpm_label->remove_c(xpm_label->children().nth_data(0)); + Gtk_HBox::BoxList &list = xpm_label->children(); + Gtk_HBox::BoxList::iterator i = list.begin(); + xpm_label->remove(*i); + //xpm_label->remove_c(xpm_label->children().nth_data(0)); + xpm_label->remove(*xpm_label->children().begin()); + */ + } + xpm_label = new Gtk_HBox(); + if (strcasecmp(this->objectClass,"organization") == 0) + //xpm_icon=new Gtk_Pixmap(*xpm_label, root_node); + xpm_icon=new Gtk_Pixmap(root_node); + else if (strcasecmp(this->objectClass,"organizationalunit") == 0) + //xpm_icon=new Gtk_Pixmap(*xpm_label, branch_node); + xpm_icon=new Gtk_Pixmap(branch_node); + else if (strcasecmp(this->objectClass,"person") == 0) + //xpm_icon=new Gtk_Pixmap(*xpm_label, leaf_node); + xpm_icon=new Gtk_Pixmap(leaf_node); + else if (strcasecmp(this->objectClass,"alias") == 0) + //xpm_icon=new Gtk_Pixmap(*xpm_label, alias_node); + xpm_icon=new Gtk_Pixmap(alias_node); + else if (strcasecmp(this->objectClass,"rfc822mailgroup") == 0) + //xpm_icon=new Gtk_Pixmap(*xpm_label, rfc822mailgroup_node); + xpm_icon=new Gtk_Pixmap(rfc822mailgroup_node); + else if (strcasecmp(this->objectClass,"LDAPsubentry") == 0) + xpm_icon=new Gtk_Pixmap(monitor); + else //xpm_icon=new Gtk_Pixmap(*xpm_label, general_node); + xpm_icon=new Gtk_Pixmap(general_node); + label = new Gtk_Label(this->rdn); + xpm_label->pack_start(*xpm_icon, false, false, 1); + xpm_label->pack_start(*label, false, false, 1); + if (this->get_child() == NULL) { + debug("no children - GREAT!!"); + this->add(*xpm_label); + } + //label->show(); + //xpm_icon->show(); + //xpm_label->show(); + show_all(); +} + +int Gtk_LdapTreeItem::showDetails() { + debug("Gtk_LdapTreeItem::showDetails()\n"); + if (this->notebook == NULL) this->getDetails(); + if (this->notebook != NULL) { + debug("Have a notebook here"); + if (par->viewport2->get_child() != NULL) { + debug(" and the viewport has children"); + //par->viewport2->remove(par->viewport2->get_child()); + par->viewport2->remove(); + debug(" which have been removed"); + } + else debug(" and viewport has no children"); + par->viewport2->add(*this->notebook); + this->notebook->show(); + par->viewport2->show(); + return 0; + } + else debug("No notebook and no details"); + return 0; +} + +char* Gtk_LdapTreeItem::getAttribute(char *c) { + int entriesCount, error; + BerElement *ber; + LDAPMessage *entry; + char *attribute, **values; + error = ldap_search_s(this->ld, this->dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, &this->result_identifier); + entriesCount = ldap_count_entries(this->ld, this->result_identifier); + if (entriesCount == 0) return 0; + for (entry = ldap_first_entry(ld, result_identifier); entry != NULL; entry = ldap_next_entry(ld, result_identifier)) { + for (attribute = ldap_first_attribute(ld, entry, &ber); attribute != NULL; attribute = ldap_next_attribute(ld, entry, ber)) { + values = ldap_get_values(ld, entry, attribute); + if (strcasecmp(attribute, "aliasedobjectname") == 0) { + this->aliasedObjectName = strdup(values[0]); + } + } + } + return this->aliasedObjectName; +} + +int Gtk_LdapTreeItem::getDetails() { + debug("Gtk_LdapTreeItem::getDetails()\n"); + int error, entriesCount; + BerElement *ber; + LDAPMessage *entry; + char *attribute, **values; + char attrib[32]; + Gtk_CList *table; + Gtk_Label *label; + GList *child_list; + Gtk_Viewport *viewport; + error = ldap_search_s(this->ld, this->dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, &this->result_identifier); + entriesCount = ldap_count_entries(this->ld, this->result_identifier); + if (entriesCount == 0) return 0; + this->notebook = new Gtk_Notebook(); + this->notebook->set_tab_pos(GTK_POS_LEFT); + const gchar *titles[] = { "values" }; + + for (entry = ldap_first_entry(ld, result_identifier); entry != NULL; entry = ldap_next_entry(ld, result_identifier)) { + for (attribute = ldap_first_attribute(ld, entry, &ber); attribute != NULL; attribute = ldap_next_attribute(ld, entry, ber)) { + values = ldap_get_values(ld, entry, attribute); + if (strcasecmp(attribute, "objectclass") == 0) { + // debug("processing objectclass\n"); + if (strcasecmp(values[0],"top") == 0) + this->objectClass = strdup(values[1]); + else this->objectClass = strdup(values[0]); + } + table = new Gtk_CList(1, titles); + for (int i=0; iappend(t); + } + ldap_value_free(values); + sprintf(attrib, "%s", attribute); + label = new Gtk_Label(attrib); + label->set_alignment(0, 0); + label->set_justify(GTK_JUSTIFY_LEFT); + this->notebook->pages().push_back(Gtk_Notebook_Helpers::TabElem(*table, *label)); + table->show(); + label->show(); + } + } + this->setType(1); + debug("done\n"); + return 0; +} + +void Gtk_LdapTreeItem::createPopupMenu() { + debug("Gtk_LdapTreeItem::createPopupMenu()\n"); + Gtk_MenuItem *item; + + this->menu = new Gtk_Menu(); + + item = new Gtk_MenuItem("Add"); + this->menu->add(*item); + item = new Gtk_MenuItem("Delete"); + this->menu->add(*item); + item = new Gtk_MenuItem(); + this->menu->add(*item); + item = new Gtk_MenuItem("Cut"); + this->menu->add(*item); + item = new Gtk_MenuItem("Copy"); + this->menu->add(*item); + item = new Gtk_MenuItem("Paste"); + this->menu->add(*item); + this->menu->show_all(); + this->menu->activate(); +} +/* +void Gtk_LdapTreeItem::show_impl() { + debug("%s showed\n", this->dn); +// Gtk_c_signals_Base *sig=(Gtk_c_signals_Base *)internal_getsignalbase(); +// sig->show(GTK_WIDGET(gtkobj())); +} +*/ +/* +void Gtk_LdapTreeItem::select_impl() { + debug("%s selected\n", this->dn); + this->showDetails(); + Gtk_TreeItem::select_impl(); +} +*/ + +void Gtk_LdapTreeItem::collapse_impl() { + debug("%s collapsed\n", this->dn); + Gtk_TreeItem::collapse_impl(); +} + +void Gtk_LdapTreeItem::expand_impl() { + debug("%s expanded\n",this->dn); + Gtk_LdapTreeItem *item; + G_List *list; + Gtk_Tree *tree; + Gtk_TreeItem::expand_impl(); +} + +void Gtk_LdapTreeItem::click() { + debug("%s clicked\n", this->dn); +} + +/* +gint Gtk_LdapTreeItem::button_press_event_impl(GdkEventButton *p0) { + debug("Gtk_LdapTreeItem::button_press_event_impl(%i)\n", p0->button); + GdkEventButton *bevent = (GdkEventButton *) p0; + if (p0->button == 3) gtk_menu_popup(this->menu->gtkobj(), NULL, NULL, NULL, NULL, bevent->button, bevent->time); + Gtk_TreeItem::button_press_event_impl(p0); +// Gtk_TreeItem::select_impl(); +} +*/ + +void Gtk_LdapTreeItem::item_drag_data_received(GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time) { + debug("Gtk_LdapTreeItem::item_drag_data_received\n"); + Gdk_DragContext gdc(context); + if ((data->length >= 0) && (data->format == 8)) { + cout << "Received \"" << (gchar *)data->data << "\" in label" << endl; + Gtk_Widget::drag_finish(gdc, true, false, time); + return; + } + + Gtk_Widget::drag_finish(gdc , false, false, time); +} + +gboolean Gtk_LdapTreeItem::target_drag_drop(GdkDragContext *context, + gint x, gint y, guint theTime) { + debug("Gtk_LdapTreeItem::target_drag_drop\n"); + cout << "drop" << endl; + have_drag = false; + +// pixmap.set(trashcan_closed, trashcan_closed_mask); + + Gdk_DragContext gdc(context); + Gdk_Atom *ga = static_cast (context->targets->data); + if (context->targets) { + this->drag_get_data(gdc, *ga, theTime); + return true; + } + + return false; +} + + +void Gtk_LdapTreeItem::source_drag_data_get(GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, guint32 time) { + debug("Gtk_LdapTreeItem::source_drag_data_get\n"); + if (info == TARGET_ROOTWIN) { + cout << "I was dropped on the rootwin" << endl; + } + else { + if ( info == TARGET_URL ) { + gtk_selection_data_set(selection_data, + selection_data->target, 8, + reinterpret_cast < const unsigned char * > + ("file:///home/otaylor/images/weave.png"), 37); + } + else { + gtk_selection_data_set(selection_data, + selection_data->target, 8, + reinterpret_cast + ("I'm Data!"), 9); + } + } +} + +void Gtk_LdapTreeItem::source_drag_data_delete(GdkDragContext *context) { + debug("Gtk_LdapTreeItem::source_drag_data_delete\n"); + debug("Delete the data!\n"); +} + +void Gtk_LdapTreeItem::target_drag_leave(GdkDragContext *context, guint time) { + debug("Gtk_LdapTreeItem::target_drag_leave\n"); + this->have_drag = false; +// pixmap.set(trashcan_closed, trashcan_closed_mask); +} + diff --git a/contrib/gtk-tool/Gtk_LdapTreeItem.h b/contrib/gtk-tool/Gtk_LdapTreeItem.h new file mode 100644 index 0000000000..fecc277368 --- /dev/null +++ b/contrib/gtk-tool/Gtk_LdapTreeItem.h @@ -0,0 +1,83 @@ +#ifndef GTK_LDAPTREEITEM_H +#define GTK_LDAPTREEITEM_H +#include "gtk.h" +#include "utils.h" +#include +#include +#include +#include +#include "icons/root_node.h" +#include "icons/branch_node.h" +#include "icons/leaf_node.h" +#include "icons/alias_node.h" +#include "icons/rfc822mailgroup_node.h" +#include "icons/general_node.h" +#include "icons/monitor.h" + +#define ROOT_NODE 1 +#define BRANCH_NODE 2 +#define LEAF_NODE 3 + +class My_Window; +class Gtk_LdapTree; + +class Gtk_LdapTreeItem : public Gtk_TreeItem { +public: + char *dn; + char *rdn; + char *objectClass; + char *aliasedObjectName; + LDAP *ld; + LDAPMessage *result_identifier; + My_Window *par; + Gtk_Notebook *notebook; + Gtk_HBox *xpm_label; + Gtk_Menu *menu; + enum + { + TARGET_STRING, + TARGET_ROOTWIN, + TARGET_URL + }; + bool have_drag; + + //Functions + Gtk_LdapTreeItem(); + Gtk_LdapTreeItem(char *c, My_Window *w, LDAP *ld); + Gtk_LdapTreeItem(GtkTreeItem *t); + ~Gtk_LdapTreeItem(); + void setDnd(); + gchar* getAttribute(char *c); + Gtk_LdapTree* getSubtree(LDAP *ld, int i); + void setType(int t); + int getDetails(); + void createPopupMenu(); + int showDetails(); +// void show_impl(); +// void select_impl(); + void collapse_impl(); + void expand_impl(); + void click(); +// gint button_press_event_impl(GdkEventButton *p0); + void item_drag_data_received (GdkDragContext *context, + gint x, gint y, GtkSelectionData *data, + guint info, guint32 time); + gboolean target_drag_drop ( GdkDragContext *context, + gint x, gint y, guint time); + + void source_drag_data_get(GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, guint32 time); + void source_drag_data_delete(GdkDragContext *context); + void target_drag_leave(GdkDragContext *context, guint time); +}; + +static GtkTargetEntry target_table[] = { + { "STRING", 0, Gtk_LdapTreeItem::TARGET_STRING }, + { "text/plain", 0, Gtk_LdapTreeItem::TARGET_STRING }, + { "text/uri-list", 0, Gtk_LdapTreeItem::TARGET_URL }, + { "application/x-rootwin-drop", 0, Gtk_LdapTreeItem::TARGET_ROOTWIN } +}; + +static guint n_targets = sizeof(target_table) / sizeof(target_table[0]); +#endif diff --git a/contrib/gtk-tool/INSTALL b/contrib/gtk-tool/INSTALL new file mode 100644 index 0000000000..84a5c594e8 --- /dev/null +++ b/contrib/gtk-tool/INSTALL @@ -0,0 +1,13 @@ +Please read this carefully + +To copile gtk-tool, although OpenLDAP in itself is a very out-of-the-box +straightforward piece of code to compile gtk-tool isn't. You will require following: + + Gtk+1.2.x + Gtk--1.1.x + +So, latest gtk stuff and if you successfully compiled and installed all that it should be easy. If you didn't I really hope you can take some comfort in that I have provided you with some snapshots of what the thing actually looks like. I hope in the near future I would be able to provide you with a static binary..next week perhaps..I don't know, I'm looking for a job right now so no promises... +(I'm no longer looking for a job but the situation with spare time seems even worse - I wish I could do this full-time guys, I really do...) + +Pele +pele@openldap.org diff --git a/contrib/gtk-tool/Makefile b/contrib/gtk-tool/Makefile new file mode 100644 index 0000000000..7ac761ea07 --- /dev/null +++ b/contrib/gtk-tool/Makefile @@ -0,0 +1,32 @@ +HOME_LOCATION=$(shell pwd) +CPLUS= g++ +OPTS=-g #-DDEBUG +INCLUDES=`gtkmm-config --cflags` -I. +GTKMMLIBS=`gtkmm-config --libs` +LDFLAGS=-L/usr/lib -L/usr/X11/lib -L/usr/local/ldap/lib -lldap -llber -L/usr/local/kerberos/lib -lkrb5 -lkrb4 `gtkmm-config --libs` +LIBS=-lXext -lgtkmm -lX11 -lXt -lXxf86dga + +.EXPORT_ALL_VARIABLES: + +SOURCES=My_Window.cc Gtk_LdapTree.cc Gtk_LdapTreeItem.cc Gtk_LdapServer.cc utils.cc main.o +OBJECTS=My_Window.o Gtk_LdapTree.o Gtk_LdapTreeItem.o Gtk_LdapServer.o utils.o main.o + +################################################################################ + +all: main +main: $(OBJECTS) + $(CPLUS) $(OBJECTS) -o main $(LDFLAGS) $(GTKMMLIBS) + exec + +main.o: main.cc + $(CPLUS) -c $(OPTS) $(INCLUDES) $< + +exec: all + chmod a+x main + ls -al main + +%.o: %.cc %.h + $(CPLUS) -c $(OPTS) $(INCLUDES) $< + +clean: + rm -f main a.out *.o straced core diff --git a/contrib/gtk-tool/My_Window.cc b/contrib/gtk-tool/My_Window.cc new file mode 100644 index 0000000000..ee21e94243 --- /dev/null +++ b/contrib/gtk-tool/My_Window.cc @@ -0,0 +1,187 @@ +#include + +My_Window::My_Window(GtkWindowType t) : Gtk_Window(t) { + debug("My_Window(t)\n"); + Gtk_VBox *main_hbox; + Gtk_HBox *top_hbox; + Gtk_VBox *bottom_hbox; + Gtk_Menu *menu, *sub_menu; + Gtk_MenuItem *new_menu, *file_menu, *options_menu, *menuitem; + Gtk_CheckMenuItem *check_menuitem; + + pane = new Gtk_HPaned(); + this->scroller = new Gtk_ScrolledWindow(); + this->viewport = new Gtk_Viewport(); + this->scroller->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + this->scroller->add(*this->viewport); + pane->add1(*this->scroller); + this->scroller->show(); + this->viewport->show(); + + this->scroller2 = new Gtk_ScrolledWindow(); + this->viewport2 = new Gtk_Viewport(); + this->scroller2->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + this->scroller2->add(*this->viewport2); + pane->add2(*this->scroller2); + this->scroller2->show(); + this->viewport2->show(); + + top_hbox = new Gtk_HBox(); + + menu = new Gtk_Menu(); + + sub_menu = new Gtk_Menu(); + menuitem = new Gtk_MenuItem("Server"); + menuitem->activate.connect(slot(this,&My_Window::addServer)); + //connect_to_method(menuitem->activate, this, &addServer); + sub_menu->append(*menuitem); +// menuitem->show(); + new_menu = new Gtk_MenuItem("New..."); + new_menu->set_submenu(*sub_menu); +// sub_menu->show(); + menu->append(*new_menu); +// new_menu->show(); + + menuitem = new Gtk_MenuItem("Quit"); + menuitem->activate.connect(Gtk_Main::quit.slot()); + menu->append(*menuitem); +// menuitem->show(); + this->menubar = new Gtk_MenuBar(); + file_menu = new Gtk_MenuItem("File (?)"); + file_menu->set_submenu(*menu); + this->menubar->append(*file_menu); +// menu->show(); + + menu = new Gtk_Menu(); + check_menuitem = new Gtk_CheckMenuItem("Show Debug Info"); + check_menuitem->toggled.connect(slot(this,&My_Window::setDebug)); + //connect_to_method(check_menuitem->toggled, this, &setDebug); + menu->append(*check_menuitem); + check_menuitem->show(); + options_menu = new Gtk_MenuItem("Options"); + options_menu->set_submenu(*menu); + this->menubar->append(*options_menu); +// menu->show(); + +// file_menu->show(); +// options_menu->show(); + +// top_hbox->pack_start(*this->menubar, TRUE, TRUE, 1); +// this->menubar->show(); + this->urlfield = new Gtk_Entry(); + top_hbox->pack_start(*this->urlfield, TRUE, TRUE, 1); +// this->urlfield->show(); + this->display_button = new Gtk_Button("Query Server"); + this->display_button->clicked.connect(slot(this, &My_Window::getHost)); + //connect_to_method(this->display_button->clicked, this, &getHost); + top_hbox->pack_end(*this->display_button, FALSE, FALSE, 1); +// this->display_button->show(); + + this->status = new Gtk_Statusbar(); +// this->progress = new Gtk_ProgressBar(); +// this->status->add(*progress); +// this->progress->show(); + + bottom_hbox = new Gtk_VBox(); + bottom_hbox->pack_start(*pane, TRUE, TRUE, 1); + bottom_hbox->pack_end(*status, FALSE, TRUE, 1); + pane->show(); +// status->show(); + + main_hbox = new Gtk_VBox(); + main_hbox->pack_start(*this->menubar, FALSE, FALSE, 1); + main_hbox->pack_start(*top_hbox, FALSE, TRUE, 1); + main_hbox->pack_end(*bottom_hbox, TRUE, TRUE, 1); + top_hbox->show(); + bottom_hbox->show(); + this->add(*main_hbox); + this->destroy.connect(Gtk_Main::quit.slot()); + main_hbox->show(); +// this->show_all(); +} + +My_Window::~My_Window() { + cout << "~My_Window()" << endl; + delete this; +} + +int My_Window::debug(const char *format,...) { + if (debug_level > 1) { + va_list args; + int ret; + char *c; + char buff[50]; + unsigned int m_context_id; + va_start(args, format); + ret = vprintf(format, args); + /* if (this->status != NULL) { + m_context_id = this->status->get_context_id("gtk-tool"); + ret = vsprintf(c, format, args); + g_snprintf(buff, 50, "Action: %s", c); + this->status->push(m_context_id, buff); + } + */ va_end(args); + return ret; + } +} + +void My_Window::do_display() { + cout << this->urlfield->get_text() << endl; +} + +void My_Window::getHost() { + debug("My_Window::getHost()\n"); + Gtk_Tree *tree, *subtree; + Gtk_LdapServer *treeitem; + char *host, *prt; + int port; + +// viewport = (Gtk_Viewport *) GTK_VIEWPORT(this->scroller->children()->nth_data(1)); +// viewport = (Gtk_Viewport *)this->scroller->children()->nth_data(1); + if (this->viewport->get_child()!=NULL) { + tree = (Gtk_Tree *)(this->viewport->get_child()); + } + else { + tree = new Gtk_Tree(); + } + string thing; + thing = this->urlfield->get_text(); + gchar **c; + c = g_strsplit(thing.c_str(), ":", 2); + host = c[0]; + prt = c[1]; //strtok(NULL, "\0"); + if (prt != NULL) port = atoi(prt); + else port = LDAP_PORT; + treeitem = new Gtk_LdapServer(this, host, port); + subtree = treeitem->getSubtree(); + tree->append(*treeitem); + treeitem->set_subtree(*subtree); + treeitem->show(); + this->viewport->add(*tree); + tree->show(); + this->viewport->show(); + this->scroller->show(); + treeitem->select(); +} + +void My_Window::setDebug() { + if (debug_level > 0) debug_level = 0; + else debug_level = 1; +} + +void My_Window::addServer() { + debug("%s\n", "Creating new server"); + Gtk_Entry *entry = new Gtk_Entry(); +// entry->connect(slot(entry->activate, this, &getHost)); + entry->activate.connect(slot(this,&My_Window::getHost)); + this->dialog = new Gtk_InputDialog(); +// this->dialog->add(*entry); +// entry->show(); + this->dialog->show(); + +} + +gint My_Window::delete_event_impl(GdkEventAny*) { + //Gtk_Main::instance()->quit(); + return 0; +} diff --git a/contrib/gtk-tool/My_Window.h b/contrib/gtk-tool/My_Window.h new file mode 100644 index 0000000000..f68c480473 --- /dev/null +++ b/contrib/gtk-tool/My_Window.h @@ -0,0 +1,30 @@ +#ifndef MY_WINDOW_H +#define MY_WINDOW_H +#include "cpluscommon.h" +#include "gtk.h" +#include "Gtk_LdapServer.h" +#include "Gtk_LdapTreeItem.h" + +extern int debug_level; + +class My_Window : public Gtk_Window { +public: + Gtk_ScrolledWindow *scroller, *scroller2; + Gtk_Viewport *viewport, *viewport2; + Gtk_Entry *urlfield; + Gtk_Button *display_button; + Gtk_InputDialog *dialog; + Gtk_Paned *pane; + Gtk_MenuBar *menubar; +// Gtk_ProgressBar *progress; + Gtk_Statusbar *status; + My_Window(GtkWindowType t); + ~My_Window(); + int debug(const char *c,...); + void do_display(); + void addServer(); + void getHost(); + void setDebug(); + gint delete_event_impl(GdkEventAny *); +}; +#endif diff --git a/contrib/gtk-tool/README b/contrib/gtk-tool/README new file mode 100644 index 0000000000..e2579e5af0 --- /dev/null +++ b/contrib/gtk-tool/README @@ -0,0 +1,39 @@ +README for gtk-tool v0.7a + +This package has been tested and run with the latest Gtk+1.2/Gtk--1.1 +OpenLDAP 2.0-devel. It should also compile (i.e. it is backward-compatible) with +the U-MICH (old) API but it has not been tested (read compiled) - however the siplicity of the "problem" and a few ifdefs lead me to believe everything should +be allright with gtk-tool now. This thing doesn't run as it should, please +read TODO! + +Just type 'make' to compile and if you have all the necessary stuff it'll do so. +You do need the latest version of Gtk+ and Gtk-- (which may be tricky to build). +You can also edit the Makefile and under "OPTS=-g" add " -DDEBUG" (line should +read "OPTS=-g -DDEBUG") to get a trace of what the gtk-tool is doing (getting +entries, traversing trees etc...) +After that, hopefully all goes well, you start the thing by doing: +./main -s localhost + +It no longer has a default base, instead it reads cn=config off your slapd +and accordignly inserts all available databases under "localhost". If you are +not running slapd on your local machine, then supply it with a "-s hostname" +i.e.: + ./main -s server02.nowhere.net + +or if you feel like having an adventure try multiple servers +i.e.: + ./main -s server02.nowhere.net -s server03.nowhere.com:322 + +etc... +It does not accept -b switch as it no longer needs it to aquire databases. +There's also a -d switch (try it with -d 1) for all the debug info. +But please feel free to add whatever else you consider neccessary to +understanding how this thing works. Enjoy, and I hope this can be useful to +you in some miniscule way. + +All emails to -devel list, and plase make sure you put "GTK-TOOL" +in the subject line, so other people who are not interested don't +have to read our garbage. + +Pele +pele@openldap.org diff --git a/contrib/gtk-tool/TODO b/contrib/gtk-tool/TODO new file mode 100644 index 0000000000..d316745daa --- /dev/null +++ b/contrib/gtk-tool/TODO @@ -0,0 +1,18 @@ +LOADS!!! + +Please someone test this with old U-MICH API - hopefully all is as it should be. + +Priorities: + Now that we have cn=config we can start using ldap_get_option propperly + and be able to run/stop server from the gtk-tool. Other things like + new entries would now come in handy. + Implement searches + Integrate with OpenLDAP build - autoconf stuff (anyone?) + +Optional: + comments in the source code + port it to NT so we can use it with the NT port of OpenLDAP + (they say that there is an NT port of Gtk+?) + +Pele +pele@openldap.org diff --git a/contrib/gtk-tool/common.h b/contrib/gtk-tool/common.h new file mode 100644 index 0000000000..c65ba42ae9 --- /dev/null +++ b/contrib/gtk-tool/common.h @@ -0,0 +1,13 @@ +#ifndef MY_COMMON +#define MY_COMMON + +#include "system.h" +#include "cpluscommon.h" +#include +#include +#include +#include +#include +extern int errno; +extern int debug_level; +#endif diff --git a/contrib/gtk-tool/cpluscommon.h b/contrib/gtk-tool/cpluscommon.h new file mode 100644 index 0000000000..48f1a7c4e7 --- /dev/null +++ b/contrib/gtk-tool/cpluscommon.h @@ -0,0 +1,10 @@ +#ifndef MY_CPLUS_COMMON +#define MY_CPLUS_COMMON + +#include +#include +#include +#include +#include +#include +#endif diff --git a/contrib/gtk-tool/gtk.h b/contrib/gtk-tool/gtk.h new file mode 100644 index 0000000000..c9660247c1 --- /dev/null +++ b/contrib/gtk-tool/gtk.h @@ -0,0 +1,14 @@ +#ifndef MY_GTK_INCLUDES +#define MY_GTK_INCLUDES + +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include + +#endif diff --git a/contrib/gtk-tool/icons/monitor.h b/contrib/gtk-tool/icons/monitor.h new file mode 100644 index 0000000000..ce45960c7a --- /dev/null +++ b/contrib/gtk-tool/icons/monitor.h @@ -0,0 +1,286 @@ +/* XPM */ +static char *monitor[] = { +/* columns rows colors chars-per-pixel */ +"19 19 260 2", +" c Gray0", +". c #0433043a0433", +"X c Gray2", +"o c #062c06220626", +"O c #0cb40cb50cb4", +"+ c #0ccd0d540d92", +"@ c #0d8e0d760e8b", +"# c Gray6", +"$ c #10530f801046", +"% c #10da10c610d7", +"& c #117f11721184", +"* c #11f8120d120c", +"= c Gray7", +"- c #13a7139113a8", +"; c #142214191519", +": c Gray9", +"> c #18e718f318ea", +", c #19a719aa19a1", +"< c Gray12", +"1 c #234e23382345", +"2 c #27ad279627c0", +"3 c #2a872a822a84", +"4 c #2e0d2de92dfb", +"5 c Gray24", +"6 c #3dd03e053df5", +"7 c #6dde57513ad0", +"8 c #78ae78d132cd", +"9 c #7fc87faf3a4e", +"0 c #417d416c41f8", +"q c #43c544184427", +"w c #4594460145b7", +"e c Gray28", +"r c #48b8489a48b0", +"t c #49ba49a849b8", +"y c #4c834c894c48", +"u c Gray30", +"i c Gray31", +"p c #4fb251055619", +"a c #55e2566a426c", +"s c #507c5060506d", +"d c #5122511750e7", +"f c #520551f75202", +"g c Gray32", +"h c #536853575355", +"j c #558b557d5578", +"k c #561455fa5621", +"l c #531353795e7a", +"z c #588d58a8589d", +"x c Gray35", +"c c #5adf5ad25ada", +"v c #5bb45b5e5bd6", +"b c #593c59f85ef7", +"n c #5cc55d315d83", +"m c #5da35da05d68", +"M c Gray37", +"N c #5f285f3e5f24", +"B c #59d65dcc6463", +"V c #5bf95e1566e2", +"C c #4a576f134a1d", +"Z c #4c067f2f4c3e", +"A c #659966275b42", +"S c #7df565484934", +"D c Gray38", +"F c #607761f96387", +"G c #63f964176407", +"H c #646f6454646f", +"J c #64fb65246521", +"K c #65fe66076606", +"L c #661f65e76612", +"P c Gray40", +"I c #662166a2670b", +"U c #669667186662", +"Y c #671c674c672b", +"T c #624b677e6c07", +"R c #628a676a6d3a", +"E c #64d764fd6e4d", +"W c #655e65cc6e6f", +"Q c #668e672c6c5e", +"! c #64e36a126edf", +"~ c #6eae6f8f62d7", +"^ c #68f368de690a", +"/ c #69d969e66a08", +"( c #69f96a6469be", +") c #6af16afd6aff", +"_ c Gray42", +"` c #6b7d6be06e14", +"' c #6bb06c496c6a", +"] c #6cb76cba6cb7", +"[ c #6d8c6d806d6a", +"{ c #6c076dfa6f68", +"} c Gray43", +"| c #6fc56fda6fa1", +" . c #66f166e871f5", +".. c #6a7f6ad97350", +"X. c #6aee705f75d2", +"o. c #6ec4724d76ee", +"O. c #70116fbd7026", +"+. c #70c26f4a7124", +"@. c #72996fba72bc", +"#. c Gray44", +"$. c #70f0712570c3", +"%. c #719a71a371c2", +"&. c #72b372bc7299", +"*. c #7355733672f5", +"=. c Gray45", +"-. c #712f71e47703", +";. c #7457744d7480", +":. c #752374e174e1", +">. c Gray46", +",. c #7630765675ec", +"<. c #7660767f7688", +"1. c #777a7778778d", +"2. c #72e572f77e86", +"3. c #71a774037abe", +"4. c #778677f97e30", +"5. c #77aa780b7795", +"6. c #77fb7806780c", +"7. c #79c570ac7a0a", +"8. c Gray47", +"9. c #795579317930", +"0. c Gray48", +"q. c #7aff7b1e7b62", +"w. c #7bc57bbc7b80", +"e. c #7c3d7bfd7bf5", +"r. c #7cbd7cd57c8f", +"t. c Gray49", +"y. c #7dd67e417e2e", +"u. c #7ef17f057ece", +"i. c #7f3c7ef87f3a", +"p. c Gray50", +"a. c #7e5e794984ba", +"s. c #7efa7858883b", +"d. c #3a32a4303a10", +"f. c #7f0e802f5593", +"g. c #47f3d9d747ed", +"h. c #7df58115862a", +"j. c #80427f288146", +"k. c #876b879d4763", +"l. c #814681036c33", +"z. c #c9c7849537bf", +"x. c #f0f6a65957f2", +"c. c #f3ecf3e9321d", +"v. c #ff25fefa3c32", +"b. c #c79cc70d7fb9", +"n. c #80898076804c", +"m. c #80ee814b8120", +"M. c #812c81338115", +"N. c #8218820b81e7", +"B. c Gray51", +"V. c #832d82e3833e", +"C. c #8361836b8333", +"Z. c #83ed83c78414", +"A. c #846b8463848a", +"S. c #84e1851e84ac", +"D. c Gray52", +"F. c #85fa864a8620", +"G. c #867d867a8661", +"H. c #874486e4873e", +"J. c Gray53", +"K. c #807c815489e4", +"L. c #80ef80b38a26", +"P. c #84b683d98c0f", +"I. c #8808876f87e6", +"U. c #8ab183538acf", +"Y. c #880e87bd880f", +"T. c #8f3485e48ef9", +"R. c #887d88628873", +"E. c #88e2890188c4", +"W. c #8915891388de", +"Q. c #8a0a89c78a0e", +"!. c Gray54", +"~. c #8ad38b0d8b09", +"^. c #8b7a8ae18b80", +"/. c #8bb78b818ba7", +"(. c Gray55", +"). c #8d4b8ce08d0f", +"_. c #8da38dc08d9e", +"`. c #8e2e8dc88e29", +"'. c #8eb28e598ea6", +"]. c #8ea98f258eca", +"[. c Gray56", +"{. c #908f879d90be", +"}. c #90768ef190e7", +"|. c #91ce8ee691f7", +" X c Gray57", +".X c #91fb91f39203", +"XX c #91e4922091fe", +"oX c #921f91f59219", +"OX c #920a920a91f4", +"+X c #92bd9279928f", +"@X c #930092d792e6", +"#X c #933792de936c", +"$X c #937d936f9376", +"%X c #94bd909d9776", +"&X c Gray58", +"*X c #953a95209549", +"=X c Gray59", +"-X c #975f9792979d", +";X c #980d985b9837", +":X c #98e4990298fc", +">X c Gray60", +",X c #9a729a479aac", +" iX(.t.N ,.j % !.>.NXNX", +"aXi./.5 X3Xr , iX1.# z ~.f & J.&.NXNX", +"tX9.yXkXr.H.t , rX;.- G F.d = S.#.NXNX", +"6X8.I.$ v #X0 ; ,X' + n y.q @ y.} NXNX", +"2X>.8X7.{.%XL. .K.h.R X.o...l E ` NXNX", +">X@.7Xg.d.s.b.c.f.P.x.z.V 9Xv.k.W NXNX", +"=X+.}.Z C a.l.9 A 3.S 7 B ~ 8 a Q NXNX", +"$X] |.T.U.j.4.2.-.{ ! T F b l p I NXNX", +"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNX", +"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNX", +"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNX", +"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNX" +}; diff --git a/contrib/gtk-tool/main.cc b/contrib/gtk-tool/main.cc new file mode 100644 index 0000000000..55978ed507 --- /dev/null +++ b/contrib/gtk-tool/main.cc @@ -0,0 +1,113 @@ +#include "cpluscommon.h" +#include "gtk.h" +#include +#include +#include +#include +#include + +int debug_level = 0; + +target_drag_leave(GdkDragContext *context, guint time) { +} + +int main(int argc, char **argv) { + My_Window *window; + Gtk_LdapItem *treeresult; + Gtk_Tree *tree = NULL, *subtree = NULL; + Gtk_Tree *machine, *machinetree; + Gtk_LdapServer *server; + Gtk_Viewport *viewport; + char *host = NULL, *prt = NULL; + char *base_dn = NULL; + int c, port = 0; + GList *hosts = NULL; + int host_count = 0; + char *pair[2]; + + //hosts = new G_List(); + while ((c = getopt(argc, argv, "d:s:p:h")) != -1) { + switch (c) { + case 'd': + debug_level = atoi(optarg); + break; + case 's': + debug("host\n"); + hosts = g_list_append(hosts, (strdup(optarg))); + break; + case 'p': + port = atoi(optarg); break; + case 'h': + default: + fprintf(stderr, "Usage: %s [-d level] [-s server[:port]]*\n", argv[0]); + exit(-1); + } + fprintf(stderr,"b"); + } + debug("%i hosts\n", g_list_length(hosts)); + if (g_list_length(hosts) == 0) { +#ifndef LDAP_GET_OPT + ldap_get_option(NULL, LDAP_OPT_HOST_NAME, host); +#endif /* LDAP_GET_OPT */ + if (host!=NULL) { + hosts = g_list_append(hosts, host); + debug("Default host: %s\n", host); + } else { +#ifndef LDAP_GET_OPT + fprintf(stderr,"Why isn't your LDAP_OPT_HOST_NAME defined?\n"); +#endif + fprintf(stderr,"Supply me with a host please (hint: use -s)\n"); + } + } else { + for (int f=0; fdata); + } + } + if (port == 0) port = LDAP_PORT; + + Gtk_Main m(&argc, &argv); + + window = new My_Window(GTK_WINDOW_TOPLEVEL); + + if (hosts!=NULL) { + tree = new Gtk_Tree(); + window->viewport->add(*tree); + for (int f=0; fdata, ":"); + prt = strtok(NULL, "\0"); + if (prt != NULL) port = atoi(prt); + else port = LDAP_PORT; + server = new Gtk_LdapServer(window, host, port); + subtree = server->getSubtree(); + tree->append(*server); + server->set_subtree(*subtree); + server->show(); + } + //window->viewport->add(*tree); +// tree->show(); + } + +// window->viewport->show(); +// window->scroller->show(); + + //Select first server + if (tree != NULL) { + Gtk_LdapTree::ItemList &items = tree->tree(); + Gtk_LdapTree::ItemList::iterator i = items.begin(); + server = (Gtk_LdapServer *)(* i); + // server->select_impl(); + } + + window->set_title("gtk-tool"); + window->activate(); + window->set_usize(600, 500); + + window->set_events(window->get_events()|GDK_ALL_EVENTS_MASK); + window->drag_dest_set(GTK_DEST_DEFAULT_ALL, target_table, n_targets, static_cast (GDK_ACTION_COPY|GDK_ACTION_MOVE)); + window->drag_source_set(static_cast(GDK_BUTTON1_MASK|GDK_BUTTON3_MASK), target_table, n_targets, static_cast(GDK_ACTION_COPY|GDK_ACTION_MOVE)); + window->drag_leave.connect(window->slot(window,target_drag_leave)); + window->show_all(); + + m.run(); + return 0; +} diff --git a/contrib/gtk-tool/utils.cc b/contrib/gtk-tool/utils.cc new file mode 100644 index 0000000000..9f430cde4a --- /dev/null +++ b/contrib/gtk-tool/utils.cc @@ -0,0 +1,17 @@ +#include +#include + +extern int debug_level; + +int debug(const char *format,...) { + if (debug_level > 0) { +//#ifdef DEBUG + va_list args; + int ret; + va_start(args, format); + ret = vprintf(format, args); + va_end(args); + return ret; +//#endif + } +} diff --git a/contrib/ldaptcl/Makefile.in b/contrib/ldaptcl/Makefile.in index c195b1b392..04586ff58e 100644 --- a/contrib/ldaptcl/Makefile.in +++ b/contrib/ldaptcl/Makefile.in @@ -21,24 +21,24 @@ exec_prefix = @exec_prefix@ # The following definition can be set to non-null for special systems # like AFS with replication. It allows the pathnames used for installation # to be different than those used for actually reference files at -# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix +# run-time. DESTDIR is prepended to $prefix and $exec_prefix # when installing files. -INSTALL_ROOT = +DESTDIR = # Directory in which to search for tcl libraries NEO_LIBRARY = $(exec_prefix)/lib/ldaptcl$(VERSION) # Directory in which to install the ldaptcl binary: -BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin +BIN_INSTALL_DIR = $(DESTDIR)$(exec_prefix)/bin # Directory in which to install the .a or .so binary for the Neo library: -LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib +LIB_INSTALL_DIR = $(DESTDIR)$(exec_prefix)/lib # Path to use at runtime to refer to LIB_INSTALL_DIR: LIB_RUNTIME_DIR = $(exec_prefix)/lib # Top-level directory for man entries: -MANN_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/man/mann +MANN_INSTALL_DIR = $(DESTDIR)$(prefix)/man/mann # The symbols below provide support for dynamic loading and shared diff --git a/contrib/ldaptcl/configure.in b/contrib/ldaptcl/configure.in index a8d16df5d2..a1a5880e60 100644 --- a/contrib/ldaptcl/configure.in +++ b/contrib/ldaptcl/configure.in @@ -2,7 +2,7 @@ dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tk installation dnl to configure the system for the local environment. AC_INIT(neoXldap.c) -# $Id: configure.in,v 1.3 1999/08/03 05:23:03 kunkee Exp $ +# $OpenLDAP$ NEO_VERSION=1.2 NEO_MAJOR_VERSION=1 diff --git a/contrib/ldaptcl/ldap.n b/contrib/ldaptcl/ldap.n new file mode 100644 index 0000000000..685540310f --- /dev/null +++ b/contrib/ldaptcl/ldap.n @@ -0,0 +1,373 @@ +'\" +'\" Copyright (c) 1998 NeoSoft, Inc. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.so man.macros +.TH ldap n "" Ldap "Ldap Tcl Extension" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +ldap \- connect to and query an LDAP server +.SH SYNOPSIS +\fBldap \fBopen \fR \fIcommand\fR \fIhostlist\fR +.br +\fBldap \fBinit \fR \fIcommand\fR \fIhostlist\fR +.br +\fBldap \fBexplode ?-nonames|-list?\fR \fIdn\fR +.br +\fIcommand \fBsubcommand \fIoptions ...\fR +.BE + +.SH OVERVIEW +.PP +A new command by the name of \fIcommand\fR will be created to access +the LDAP database at \fIhostlist\fR. \fIhostlist\fR may contain elements +of the format \fBhost:port\fR if a port other than the default LDAP port +of 389 is required. The LDAP library will attempt to connect to each +host in turn until it succeeds or exhausts the list. +.PP +The \fBexplode\fR form provides a means (via ldap_explode(3)) to explode a DN +into its component parts. \fB-nonames\fR strips off the attribute names, +and -list returns a list suitable for \fBarray set\fR. +.PP +Finally, the last form, described in more detail below, refers genericly +to how the command created by the first two examples is used. +.SH DESCRIPTION + +The Lightweight Directory Access Protocol provides TCP/IP access to +X.500 directory services and/or to a stand-alone LDAP server. + +This code provides a Tcl interface to the +Lightweight Directory Access Protocol package using the Netscape +Software Development Kit. It can also be used with the freely +redistributable University of +Michigan (http://www.umich.edu/~rsug/ldap) version by defining the +UMICH_LDAP macro during compilation. + +.SH CONNECTING TO AN LDAP SERVER + +To create an ldap interface entity, we use the "ldap" command. + + ldap open foo foo.bar.com + +This opens a connection to a LDAP server on foo.bar.com, and makes +a new Tcl command, foo, through which we will manipulate the interface +and make queries to the remote LDAP server. + + ldap init foo foo.bar.com + +Same as above, foo is created, but for "init", opening the connection is +deferred until we actually try to do something. + +For the purposes of this example, we're going to assume that "foo" is the +command created by opening a connection using "ldap open". + +.SH BINDING + +After a connection is made to an LDAP server, an LDAP bind operation must +be performed before other operations can be attempted over the connection. + +Both simple authentication and kerberos authentication are available. +LDAP version 3 supports many new "SSL"-style authentication and encryption +systems, which are not currently supported by the OpenLDAP v1.2 server, and +hence by this interface package. + +Currently simple and kerberos-based authentication, are supported. + +To use LDAP and still have reasonable security in a networked, +Internet/Intranet environment, secure shell can be used to setup +secure, encrypted connections between client machines and the LDAP +server, and between the LDAP server and any replica or slave servers +that might be used. + +To perform the LDAP "bind" operation: + + foo bind simple dn password + + foo bind kerberos_ldap + foo bind kerberos_dsa + foo bind kerberos_both + +It either returns nothing (success), or a Tcl error with appropriate error +text. + +For example, + + foo bind simple "cn=Manager,o=NeoSoft Inc,c=us" "secret" + +If you attempt to bind with one of the kerberos authentication types +described above and your LDAP library was not built with KERBEROS +defined, you will get an unknown auth type error. + +To unbind an LDAP connection previously bound with "bind": + + foo unbind + +Note that unbinding also deletes the command (\fBfoo\fR in this case). +Deleting the command has the same affect. + +The ability of the library to callback to the client, enabling re-binding +while following referrals, is not currently supported. + +.SH DELETING OBJECTS + +To delete an object in the LDAP database, use + + foo delete dn + +To rename an object to another relative distinguished name, use + + foo rename_rdn dn rdn + +To rename an object to another relative distinguished name, leaving +the old entry as some kind of attribute (FIX: not sure if this is +right or how it works) + + foo modify_rdn dn rdn + + +.SH ADDING NEW OBJECTS + + foo add dn attributePairList + +This creates a new distinguished name and defines zero or more attributes. + +"attributePairList" is a list of key-value pairs, the same as would +be returned by "array get" if an array had been set up containing the +key-value pairs. + + foo add "cn=karl, ou=People, o=NeoSoft Inc, c=US" {cn karl ...} + +Some directory servers and/or their client SDKs will automatically +add the leaf attribute value for you. + +Here is a more precise description of how an attributePairList looks: + + {cn {karl {Karl Lehenbauer}} telephone 713-968-5800} + +Note here that two cn values, "karl" and "Karl Lehenbauer", are added. +Is it an error to write: + + {cn {Karl Lehenbauer}} + +Which adds two cn values, "Karl" and "Lehenbauer", when the intention +was to give a single cn value of "Karl Lehenbauer". In real life, one +finds oneself making prodigous use of the \fBlist\fR command rather than +typing hard-coded lists. + +We have noticed that the Netscape server will automatically add the +left-most rdn portion of the DN (ie. cn=karl), whereas the University +of Michigan and OpenLDAP 1.2 versions do not. + +.SH ADDING, DELETING, AND REPLACING OBJECT ATTRIBUTES + +You can have multiple values for a given attribute in an LDAP object. +These are represented in search results, through the Tcl interface, +as a list. + + foo add_attributes dn attributePairList + +This adds key-value pairs to an existing DN. If an attribute being +added already exists, the new value will be appended to the list. +If a particular value being added to an attribute already exists in +the object a Tcl error is raised. + + foo replace_attributes dn attributePairList + +This replaces the specified attributes in an existing DN, leaving +unnamed ones untouched. Any previous values for the supplied attributes +(if any) are discarded. + + foo delete_attributes dn attributePairList + +This deletes attributes in the list. If an attribute "foo" has the +value list {bar snap}, and you delete using the attributePairList "foo bar", +"foo" will still have "snap". + +If you provide an empty string ("") for the value list, +the entire attribute will be deleted. + +.SH SEARCHING + +The Tcl interface to searching takes a control array, which contains +a couple of mandatory key-value pairs, and can contain a number of +optional key-value pairs as well, for controlling the search, a +destination array, into which the specified attributes (or all attributes +of matching DNs if none are specified) and values are stored. + +The "code" part is executed repeatedly, once for each DN matching the +search criteria. + + foo search controlArray destArray code + + Using data in the control array, a search is performed of the + LDAP server opened when foo was created. Possible elements + of the control array are enumerated blow. + + controlArray(base) is the DN being searched from. (required) + + controlArray(filter) contains the search criteria. (required) + + controlArray(scope) must be "base", "one_level", or "subtree". + If not specified, scope defaults to "subtree". + + controlArray(deref) must be "never", "search", "find", or "always" + If not specified, deref defaults to "never" + + controlArray(attributes) is a list of attributes to be fetched. + If not specified, all attributes are fetched. + + controlArray(timeout) a timeout value in seconds (may contain + fractional values -- extremely very small values are useful + for forcing timeout conditions to test timeouts). + + For each matching record, destArray is populated with none, + some or all attribute-value pairs. + +Note: There are some additional parameters that can be set, such as +how long the synchronous version of the routines should wait before +timing out, the interfaces for which are not available in the current +version. + +.SH CACHING (Note: Netscape clients do not have caching interfaces). + +The UMich and OpenLDAP client libraries offers the client application fairly +fine-grained control of caching of results retrieved from searches, +offering significant performance improvement and reduced +network traffic. + +By default, the cache is disabled. + +To enable caching of data received from an LDAP connection, + + foo cache enable timeout maxmem + + ...where timeout is specified in seconds, and maxmem is the + maximum memory to be used for caching, in bytes. + + If maxmem is 0, the cache size is restricted only by the timeout. + + foo cache disable + + ...temporarily inhibits use of the cache (while disabled, new requests + are not cached and the cache is not checked when returning results). + + Disabling the cache does not delete its contents. + + foo cache destroy + + ...turns off caching and completely removes the cache from memory. + + foo cache flush + + ...deletes the entire cache contents, but does not affect + whether or not the cache is being used. + + foo cache uncache dn + + ...removes from the cache all request results that make reference + to the specified DN. + + This should be used, for example, after doing an add_attributes, + delete_attributes, or replace_attributes (ldap_modify(3)) + involving the requested DN. Generally this should not be needed, + as the Tcl interface automatically performs this operation on + any dn that is modified (add,replace,delete) while caching is + enabled. + + foo cache no_errors + + ...suppresses caching of any requests that result in an error. + + foo cache size_errors + + ...suppresses caching of any requests that result in an error, + except for requests resulting in "sizelimit exceeded", which + are cached. This is the default. + + foo cache all_errors + + ...enables caching of all requests, including those that result + in errors. + +.SH IMPLEMENTATION DECISIONS + +Because we used the new "Tcl object" C interfaces, this package only works +with Tcl 8.0 or above. + +This package interfaces with the University of Michigan LDAP protocol +package, version 3.3, and OpenLDAP version 1.2, both of which are +implementations of version 2 of the LDAP protocol. + +Although an LDAP client (or server) could be written in native Tcl 8.0, +as Tcl 8.0 and above can do binary I/O, and Tcl 8 and above have strings +that are fully eight-bit clean, for a first implementation, to minimize +compatibility problems, we created a C interface to the UMich LDAP library. + +A native Tcl implementation would be cool because we could bring the receiving +of messages into the normal Tcl event loop and run the LDAP interface fully +asynchronous. + +This implementation is blocking, and blocking only. That is to say that +the Tcl event loop is frozen while the ldap routines are waiting on data. + +This could be fixed either by recoding all of the I/O in the LDAP library +to use Tcl's I/O system instead, or by simply coding the LDAP interface in +native Tcl, as mentioned above. + +Another advantage of coding in high-level Tcl, of course, is that the +client would immediately be cross-platform to Windows and the Mac, as +well as Unix. + +Binary data is not currently supported. It will probably be trivial to +add, we just haven't dug into it yet. + + +.SH FOR MORE INFORMATION + +This document principally describes how to use our Tcl interface to the +LDAP library works. + +For more information on LDAP and the University of Michigan LDAP package, +please visit the website mentioned above. The package includes substantial +documentation in the form of UNIX manual pages, a SLAPD/SLURPD guide +in Adobe Portable Document Format (pdf), and a number of Internet RFCs +related to LDAP services. + +.SH AUTHORS +It was written by Karl Lehenbauer, of NeoSoft, Inc., in August and +September of 1997. Ldap explode, and numerous bug fixes and extensions +by Randy Kunkee, also of NeoSoft, Inc., in 1998-1999. + +.SH KEYWORDS +element, join, list, separator +.SH BUGS +The \fBldap init\fR syntax fails to return anything useful. Use +\fBldap open\fR instead. + +\fBPackage require Ldaptcl\fR won't work unless the ldap and lber libraries +are also shared, and ldaptcl.so is itself created with the correct flags +(eg. -R for Solaris). In short there's a lot of details to make this part +work, but it should work out of the box for Solaris. Other systems may +require that LD_LIBRARY_PATH or other appropraite environment variables +be set at build and/or runtime. + +An asynchronous interface should be provided with callbacks. + +We have never tested Kerberos authentication. + +It does not tolerate some illegal operations very well. + +It is possible to create empty attributes, ie. attributes which are present +but have no value. This is done by deleting the attribute values rather +than, eg. "foo delete_attributes dn {telephone {}}" which would delete +the telephone attribute altogether. A search for presence of the attribute +may return an object, and yet it may have no value. This interface presents +such an object as not having the attribute at all (ie. you cannot tell). +The Netscape SDK does this for you, so this makes the behavior consistent +when using UMICH_LDAP. + +\--enable-netscape configuration support has not been tested and probably +has bugs. diff --git a/contrib/ldaptcl/neoXldap.c b/contrib/ldaptcl/neoXldap.c index 978ea6aafa..2ba7b6545b 100644 --- a/contrib/ldaptcl/neoXldap.c +++ b/contrib/ldaptcl/neoXldap.c @@ -23,7 +23,7 @@ * Requests for permission may be sent to NeoSoft Inc, 1770 St. James Place, * Suite 500, Houston, TX, 77056. * - * $Id: neoXldap.c,v 1.5 1999/08/03 05:23:03 kunkee Exp $ + * $OpenLDAP$ * */ @@ -76,7 +76,6 @@ ** In OpenLDAP 2.x-devel, its 2000 + the draft number, ie 2002. ** This section is for OPENLDAP. */ -#define ldap_attributefree(p) ldap_memfree(p) #define ldap_memfree(p) free(p) #ifdef LDAP_OPT_ERROR_NUMBER #define ldap_get_lderrno(ld) (ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &lderrno), lderrno) @@ -89,7 +88,6 @@ /* ** Netscape SDK w/ ldap_set_option, ldap_get_option */ -#define ldap_attributefree(p) ldap_memfree(p) #define LDAP_ERR_STRING(ld) \ ldap_err2string(ldap_get_lderrno(ldap)) #else @@ -99,7 +97,6 @@ #define ldap_memfree(p) free(p) #define ldap_ber_free(p, n) ber_free(p, n) #define ldap_value_free_len(bvals) ber_bvecfree(bvals) -#define ldap_attributefree(p) #define ldap_get_lderrno(ld) (ld->ld_errno) #define LDAP_ERR_STRING(ld) \ ldap_err2string(ld->ld_errno) @@ -107,9 +104,15 @@ typedef struct ldaptclobj { LDAP *ldap; - int flags + int caching; /* flag 1/0 if caching is enabled */ + long timeout; /* timeout from last cache enable */ + long maxmem; /* maxmem from last cache enable */ + Tcl_Obj *trapCmdObj; /* error handler */ + int *traplist; /* list of errorCodes to trap */ + int flags; } LDAPTCL; + #define LDAPTCL_INTERRCODES 0x001 #include "ldaptclerr.h" @@ -117,7 +120,7 @@ typedef struct ldaptclobj { static LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp) { - char shortbuf[6]; + char shortbuf[16]; char *errp; int lderrno; @@ -131,6 +134,33 @@ LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp) errp = ldaptclerrorcode[code]; Tcl_SetErrorCode(interp, errp, NULL); + if (ldaptcl->trapCmdObj) { + int *i; + Tcl_Obj *cmdObj; + if (ldaptcl->traplist != NULL) { + for (i = ldaptcl->traplist; *i && *i != code; i++) + ; + if (*i == 0) return; + } + (void) Tcl_EvalObj(interp, ldaptcl->trapCmdObj); + } +} + +static +LDAP_ErrorStringToCode(Tcl_Interp *interp, char *s) +{ + int offset; + int code; + + offset = (strncasecmp(s, "LDAP_", 5) == 0) ? 0 : 5; + for (code = 0; code < LDAPTCL_MAXERR; code++) { + if (!ldaptclerrorcode[code]) continue; + if (strcasecmp(s, ldaptclerrorcode[code]+offset) == 0) + return code; + } + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, s, " is an invalid code", (char *) NULL); + return -1; } /*----------------------------------------------------------------------------- @@ -149,7 +179,7 @@ LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp) * o TCL_ERROR if an error occured, with error message in interp. *----------------------------------------------------------------------------- */ -static int +int LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) Tcl_Interp *interp; LDAP *ldap; @@ -178,6 +208,8 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) return TCL_ERROR; ldap_memfree(dn); } + attributeNameObj = Tcl_NewObj(); + Tcl_IncrRefCount (attributeNameObj); for (attributeName = ldap_first_attribute (ldap, entry, &ber); attributeName != NULL; attributeName = ldap_next_attribute(ldap, entry, ber)) { @@ -191,17 +223,17 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) as an error, we ignore it to present a consistent interface with Netscape's server */ - attributeNameObj = Tcl_NewStringObj (attributeName, -1); - Tcl_IncrRefCount (attributeNameObj); attributeDataObj = Tcl_NewObj(); + Tcl_SetStringObj(attributeNameObj, attributeName, -1); for (i = 0; bvals[i] != NULL; i++) { Tcl_Obj *singleAttributeValueObj; - singleAttributeValueObj = Tcl_NewStringObj (bvals[i]->bv_val, -1); + singleAttributeValueObj = Tcl_NewStringObj(bvals[i]->bv_val, bvals[i]->bv_len); if (Tcl_ListObjAppendElement (interp, attributeDataObj, singleAttributeValueObj) == TCL_ERROR) { + ber_free(ber, 0); return TCL_ERROR; } } @@ -215,10 +247,9 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - Tcl_DecrRefCount (attributeNameObj); } - ldap_attributefree(attributeName); } + Tcl_DecrRefCount (attributeNameObj); return Tcl_EvalObj (interp, evalCodeObj); } @@ -244,8 +275,9 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) * o TCL_ERROR if an error occured, with error message in interp. *----------------------------------------------------------------------------- */ -static int -LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destArrayNameObj, evalCodeObj, timeout_p) +int +LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, + destArrayNameObj, evalCodeObj, timeout_p, all, sortattr) Tcl_Interp *interp; LDAPTCL *ldaptcl; char *base; @@ -256,6 +288,8 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr Tcl_Obj *destArrayNameObj; Tcl_Obj *evalCodeObj; struct timeval *timeout_p; + int all; + char *sortattr; { LDAP *ldap = ldaptcl->ldap; char filter[BUFSIZ]; @@ -264,18 +298,17 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr int abandon; int tclResult = TCL_OK; int msgid; - LDAPMessage *resultMessage; - LDAPMessage *entryMessage; + LDAPMessage *resultMessage = 0; + LDAPMessage *entryMessage = 0; + char *sortKey; - Tcl_Obj *resultObj; int lderrno; - resultObj = Tcl_GetObjResult (interp); - sprintf(filter, filtpatt, value); + fflush(stderr); if ((msgid = ldap_search (ldap, base, scope, filter, attrs, 0)) == -1) { - Tcl_AppendStringsToObj (resultObj, + Tcl_AppendResult (interp, "LDAP start search error: ", LDAP_ERR_STRING(ldap), (char *)NULL); @@ -284,73 +317,85 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr } abandon = 0; - while ((resultCode = ldap_result (ldap, - msgid, - 0, - timeout_p, - &resultMessage)) == LDAP_RES_SEARCH_ENTRY) { + if (sortattr) + all = 1; + tclResult = TCL_OK; + while (!abandon) { + resultCode = ldap_result (ldap, msgid, all, timeout_p, &resultMessage); + if (resultCode != LDAP_RES_SEARCH_RESULT && + resultCode != LDAP_RES_SEARCH_ENTRY) + break; + if (sortattr) { + sortKey = (strcasecmp(sortattr, "dn") == 0) ? NULL : sortattr; + ldap_sort_entries(ldap, &resultMessage, sortKey, strcasecmp); + } entryMessage = ldap_first_entry(ldap, resultMessage); - tclResult = LDAP_ProcessOneSearchResult (interp, - ldap, - entryMessage, - destArrayNameObj, - evalCodeObj); - ldap_msgfree(resultMessage); - if (tclResult != TCL_OK) { - if (tclResult == TCL_CONTINUE) { - tclResult = TCL_OK; - } else if (tclResult == TCL_BREAK) { - tclResult = TCL_OK; - abandon = 1; - break; - } else if (tclResult == TCL_ERROR) { - char msg[100]; - sprintf(msg, "\n (\"search\" body line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - abandon = 1; - break; - } else { - abandon = 1; - break; + while (entryMessage) { + tclResult = LDAP_ProcessOneSearchResult (interp, + ldap, + entryMessage, + destArrayNameObj, + evalCodeObj); + if (tclResult != TCL_OK) { + if (tclResult == TCL_CONTINUE) { + tclResult = TCL_OK; + } else if (tclResult == TCL_BREAK) { + tclResult = TCL_OK; + abandon = 1; + break; + } else if (tclResult == TCL_ERROR) { + char msg[100]; + sprintf(msg, "\n (\"search\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, msg, -1); + abandon = 1; + break; + } else { + abandon = 1; + break; + } } + entryMessage = ldap_next_entry(ldap, entryMessage); } + if (resultCode == LDAP_RES_SEARCH_RESULT || all) + break; + if (resultMessage) + ldap_msgfree(resultMessage); + resultMessage = NULL; } - if (abandon || resultCode == 0) { - ldap_abandon(ldap, msgid); - if (resultCode == 0) { - Tcl_SetErrorCode (interp, "TIMEOUT", (char*) NULL); - Tcl_SetStringObj (resultObj, "LDAP timeout retrieving results", -1); - return TCL_ERROR; - } - } else { - if (resultCode == LDAP_RES_SEARCH_RESULT) { - if ((errorCode = ldap_result2error (ldap, resultMessage, 0)) - != LDAP_SUCCESS) { - Tcl_AppendStringsToObj (resultObj, - "LDAP search error: ", - ldap_err2string(errorCode), - (char *)NULL); - ldap_msgfree(resultMessage); - LDAP_SetErrorCode(ldaptcl, errorCode, interp); - return TCL_ERROR; - } - } - - - if (resultCode == -1) { - Tcl_AppendStringsToObj (resultObj, - "LDAP result search error: ", - LDAP_ERR_STRING(ldap), - (char *)NULL); - LDAP_SetErrorCode(ldaptcl, -1, interp); - return TCL_ERROR; - } else + if (abandon) { + if (resultMessage) ldap_msgfree(resultMessage); + if (resultCode == LDAP_RES_SEARCH_ENTRY) + ldap_abandon(ldap, msgid); + return tclResult; + } + if (resultCode == -1) { + Tcl_ResetResult (interp); + Tcl_AppendResult (interp, + "LDAP result search error: ", + LDAP_ERR_STRING(ldap), + (char *)NULL); + LDAP_SetErrorCode(ldaptcl, -1, interp); + return TCL_ERROR; } + if ((errorCode = ldap_result2error (ldap, resultMessage, 0)) + != LDAP_SUCCESS) { + Tcl_ResetResult (interp); + Tcl_AppendResult (interp, + "LDAP search error: ", + ldap_err2string(errorCode), + (char *)NULL); + if (resultMessage) + ldap_msgfree(resultMessage); + LDAP_SetErrorCode(ldaptcl, errorCode, interp); + return TCL_ERROR; + } + if (resultMessage) + ldap_msgfree(resultMessage); return tclResult; } @@ -366,7 +411,7 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr * See the user documentation. *----------------------------------------------------------------------------- */ -static int +int NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) ClientData clientData; Tcl_Interp *interp; @@ -383,6 +428,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) int mod_op = 0; char *m, *s, *errmsg; int errcode; + int tclResult; Tcl_Obj *resultObj = Tcl_GetObjResult (interp); @@ -586,11 +632,11 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) nPairs = attribObjc / 2; - modArray = (LDAPMod **)ckalloc (sizeof(LDAPMod *) * (nPairs + 1)); + modArray = (LDAPMod **)malloc (sizeof(LDAPMod *) * (nPairs + 1)); modArray[nPairs] = (LDAPMod *) NULL; for (i = 0; i < nPairs; i++) { - mod = modArray[i] = (LDAPMod *) ckalloc (sizeof(LDAPMod)); + mod = modArray[i] = (LDAPMod *) malloc (sizeof(LDAPMod)); mod->mod_op = mod_op; mod->mod_type = Tcl_GetStringFromObj (attribObjv [i * 2], NULL); @@ -600,7 +646,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) } valPtrs = mod->mod_vals.modv_strvals = \ - (char **)ckalloc (sizeof (char *) * (valuesObjc + 1)); + (char **)malloc (sizeof (char *) * (valuesObjc + 1)); valPtrs[valuesObjc] = (char *)NULL; for (j = 0; j < valuesObjc; j++) { @@ -610,7 +656,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) * value be NULL to indicate entire attribute is to be * deleted */ if ((*valPtrs [j] == '\0') - && (mod->mod_op == LDAP_MOD_DELETE)) { + && (mod->mod_op == LDAP_MOD_DELETE || mod->mod_op == LDAP_MOD_REPLACE)) { valPtrs [j] = NULL; } } @@ -620,14 +666,16 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) result = ldap_add_s (ldap, dn, modArray); } else { result = ldap_modify_s (ldap, dn, modArray); + if (ldaptcl->caching) + ldap_uncache_entry (ldap, dn); } /* free the modArray elements, then the modArray itself. */ for (i = 0; i < nPairs; i++) { - ckfree ((char *) modArray[i]->mod_vals.modv_strvals); - ckfree ((char *) modArray[i]); + free ((char *) modArray[i]->mod_vals.modv_strvals); + free ((char *) modArray[i]); } - ckfree ((char *) modArray); + free ((char *) modArray); /* FIX: memory cleanup required all over the place here */ if (result != LDAP_SUCCESS) { @@ -666,6 +714,12 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) double timeoutTime; struct timeval timeout, *timeout_p; + char *paramString; + int cacheThis = -1; + int all = 0; + + char *sortattr; + Tcl_Obj *destArrayNameObj; Tcl_Obj *evalCodeObj; @@ -701,7 +755,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) "filter", 0); if (filterPatternString == (char *)NULL) { - filterPatternString = "objectclass=*"; + filterPatternString = "(objectclass=*)"; } /* Fetch scope setting from control array. @@ -795,6 +849,20 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) timeout_p = &timeout; } + paramString = Tcl_GetVar2 (interp, controlArrayName, "cache", 0); + if (paramString) { + if (Tcl_GetInt(interp, paramString, &cacheThis) == TCL_ERROR) + return TCL_ERROR; + } + + paramString = Tcl_GetVar2 (interp, controlArrayName, "all", 0); + if (paramString) { + if (Tcl_GetInt(interp, paramString, &all) == TCL_ERROR) + return TCL_ERROR; + } + + sortattr = Tcl_GetVar2 (interp, controlArrayName, "sort", 0); + #ifdef UMICH_LDAP ldap->ld_deref = deref; ldap->ld_timelimit = 0; @@ -802,7 +870,23 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) ldap->ld_options = 0; #endif - return LDAP_PerformSearch (interp, + /* Caching control within the search: if the "cache" control array */ + /* value is set, disable/enable caching accordingly */ + +#if 0 + if (cacheThis >= 0 && ldaptcl->caching != cacheThis) { + if (cacheThis) { + if (ldaptcl->timeout == 0) { + Tcl_SetStringObj(resultObj, "Caching never before enabled, I have no timeout value to use", -1); + return TCL_ERROR; + } + ldap_enable_cache(ldap, ldaptcl->timeout, ldaptcl->maxmem); + } + else + ldap_disable_cache(ldap); + } +#endif + tclResult = LDAP_PerformSearch (interp, ldaptcl, baseString, scope, @@ -811,7 +895,20 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) "", destArrayNameObj, evalCodeObj, - timeout_p); + timeout_p, + all, + sortattr); + /* Following the search, if we changed the caching behavior, change */ + /* it back. */ +#if 0 + if (cacheThis >= 0 && ldaptcl->caching != cacheThis) { + if (cacheThis) + ldap_disable_cache(ldap); + else + ldap_enable_cache(ldap, ldaptcl->timeout, ldaptcl->maxmem); + } +#endif + return tclResult; } #if defined(UMICH_LDAP) || (defined(OPEN_LDAP) && !defined(LDAP_API_VERSION)) @@ -840,19 +937,28 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) } if (STREQU (cacheCommand, "enable")) { - long timeout; - long maxmem; + long timeout = ldaptcl->timeout; + long maxmem = ldaptcl->maxmem; - if (objc != 5) + if (objc > 5) return TclX_WrongArgs (interp, objv [0], - "cache enable timeout maxmem"); + "cache enable ?timeout? ?maxmem?"); - if (Tcl_GetLongFromObj (interp, objv [3], &timeout) == TCL_ERROR) + if (objc > 3) { + if (Tcl_GetLongFromObj (interp, objv [3], &timeout) == TCL_ERROR) + return TCL_ERROR; + } + if (timeout == 0) { + Tcl_SetStringObj(resultObj, + objc > 3 ? "timeouts must be greater than 0" : + "no previous timeout to reference", -1); return TCL_ERROR; + } - if (Tcl_GetLongFromObj (interp, objv [4], &maxmem) == TCL_ERROR) - return TCL_ERROR; + if (objc > 4) + if (Tcl_GetLongFromObj (interp, objv [4], &maxmem) == TCL_ERROR) + return TCL_ERROR; if (ldap_enable_cache (ldap, timeout, maxmem) == -1) { Tcl_AppendStringsToObj (resultObj, @@ -862,6 +968,9 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) LDAP_SetErrorCode(ldaptcl, -1, interp); return TCL_ERROR; } + ldaptcl->caching = 1; + ldaptcl->timeout = timeout; + ldaptcl->maxmem = maxmem; return TCL_OK; } @@ -869,11 +978,13 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) if (STREQU (cacheCommand, "disable")) { ldap_disable_cache (ldap); + ldaptcl->caching = 0; return TCL_OK; } if (STREQU (cacheCommand, "destroy")) { ldap_destroy_cache (ldap); + ldaptcl->caching = 0; return TCL_OK; } @@ -911,6 +1022,75 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) return TCL_ERROR; } #endif + if (STREQU (subCommand, "trap")) { + Tcl_Obj *listObj, *resultObj; + int *p, l, i, code; + + if (objc > 4) + return TclX_WrongArgs (interp, objv [0], + "trap command ?errorCode-list?"); + if (objc == 2) { + if (!ldaptcl->trapCmdObj) + return TCL_OK; + resultObj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(interp, resultObj, ldaptcl->trapCmdObj); + if (ldaptcl->traplist) { + listObj = Tcl_NewObj(); + for (p = ldaptcl->traplist; *p; p++) { + Tcl_ListObjAppendElement(interp, listObj, + Tcl_NewStringObj(ldaptclerrorcode[*p], -1)); + } + Tcl_ListObjAppendElement(interp, resultObj, listObj); + } + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + } + if (ldaptcl->trapCmdObj) { + Tcl_DecrRefCount (ldaptcl->trapCmdObj); + ldaptcl->trapCmdObj = NULL; + } + if (ldaptcl->traplist) { + free(ldaptcl->traplist); + ldaptcl->traplist = NULL; + } + Tcl_GetStringFromObj(objv[2], &l); + if (l == 0) + return TCL_OK; /* just turn off trap */ + ldaptcl->trapCmdObj = objv[2]; + Tcl_IncrRefCount (ldaptcl->trapCmdObj); + if (objc < 4) + return TCL_OK; /* no code list */ + if (Tcl_ListObjLength(interp, objv[3], &l) != TCL_OK) + return TCL_ERROR; + if (l == 0) + return TCL_OK; /* empty code list */ + ldaptcl->traplist = (int*)malloc(sizeof(int) * (l + 1)); + ldaptcl->traplist[l] = 0; + for (i = 0; i < l; i++) { + Tcl_ListObjIndex(interp, objv[3], i, &resultObj); + code = LDAP_ErrorStringToCode(interp, Tcl_GetStringFromObj(resultObj, NULL)); + if (code == -1) { + free(ldaptcl->traplist); + ldaptcl->traplist = NULL; + return TCL_ERROR; + } + ldaptcl->traplist[i] = code; + } + return TCL_OK; + } + if (STREQU (subCommand, "trapcodes")) { + int code; + Tcl_Obj *resultObj; + Tcl_Obj *stringObj; + resultObj = Tcl_GetObjResult(interp); + + for (code = 0; code < LDAPTCL_MAXERR; code++) { + if (!ldaptclerrorcode[code]) continue; + Tcl_ListObjAppendElement(interp, resultObj, + Tcl_NewStringObj(ldaptclerrorcode[code], -1)); + } + return TCL_OK; + } #ifdef LDAP_DEBUG if (STREQU (subCommand, "debug")) { if (objc != 3) { @@ -948,8 +1128,12 @@ NeoX_LdapObjDeleteCmd(clientData) LDAPTCL *ldaptcl = (LDAPTCL *)clientData; LDAP *ldap = ldaptcl->ldap; + if (ldaptcl->trapCmdObj) + Tcl_DecrRefCount (ldaptcl->trapCmdObj); + if (ldaptcl->traplist) + free(ldaptcl->traplist); ldap_unbind(ldap); - ckfree((char*) ldaptcl); + free((char*) ldaptcl); } /*----------------------------------------------------------------------------- @@ -1081,8 +1265,13 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv) ldap->ld_deref = LDAP_DEREF_NEVER; /* Turn off alias dereferencing */ #endif - ldaptcl = (LDAPTCL *) ckalloc(sizeof(LDAPTCL)); + ldaptcl = (LDAPTCL *) malloc(sizeof(LDAPTCL)); ldaptcl->ldap = ldap; + ldaptcl->caching = 0; + ldaptcl->timeout = 0; + ldaptcl->maxmem = 0; + ldaptcl->trapCmdObj = NULL; + ldaptcl->traplist = NULL; ldaptcl->flags = 0; Tcl_CreateObjCommand (interp, diff --git a/contrib/ldaptcl/tkAppInit.c b/contrib/ldaptcl/tkAppInit.c new file mode 100644 index 0000000000..68fd956803 --- /dev/null +++ b/contrib/ldaptcl/tkAppInit.c @@ -0,0 +1,119 @@ +/* + * tkXAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for use with + * applications built with Extended Tcl and Tk on Unix systems. This is based + * on the the UCB Tk file tkAppInit.c + *----------------------------------------------------------------------------- + * Copyright 1991-1996 Karl Lehenbauer and Mark Diekhans. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies. Karl Lehenbauer and + * Mark Diekhans make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + *----------------------------------------------------------------------------- + * $OpenLDAP$ + *----------------------------------------------------------------------------- + */ + +#include "tclExtend.h" +#include "tk.h" + +/* + * The following variable is a special hack that insures the tcl + * version of matherr() is used when linking against shared libraries + * Even if matherr is not used on this system, there is a dummy version + * in libtcl. + */ +EXTERN int matherr (); +int (*tclDummyMathPtr)() = matherr; + + +/*----------------------------------------------------------------------------- + * main -- + * + * This is the main program for the application. + *----------------------------------------------------------------------------- + */ +#ifdef __cplusplus +int +main (int argc, + char **argv) +#else +int +main (argc, argv) + int argc; + char **argv; +#endif +{ +#ifdef USE_TCLX + TkX_Main(argc, argv, Tcl_AppInit); +#else + Tk_Main(argc, argv, Tcl_AppInit); +#endif + return 0; /* Needed only to prevent compiler warning. */ +} + +/*----------------------------------------------------------------------------- + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. Most + * applications, especially those that incorporate additional packages, will + * have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error message in + * interp->result if an error occurs. + *----------------------------------------------------------------------------- + */ +#ifdef __cplusplus +int +Tcl_AppInit (Tcl_Interp *interp) +#else +int +Tcl_AppInit (interp) + Tcl_Interp *interp; +#endif +{ + if (Tcl_Init (interp) == TCL_ERROR) { + return TCL_ERROR; + } +#ifdef USE_TCLX + if (Tclx_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tclx", Tclx_Init, Tclx_SafeInit); +#endif + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL); +#ifdef USE_TCLX + if (Tkx_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tkx", Tkx_Init, (Tcl_PackageInitProc *) NULL); +#endif + + if (Ldaptcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Ldaptcl", Ldaptcl_Init, + (Tcl_PackageInitProc *) NULL); + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishxrc", TCL_GLOBAL_ONLY); + return TCL_OK; +} diff --git a/contrib/php3-tool/COPYRIGHT b/contrib/php3-tool/COPYRIGHT new file mode 100644 index 0000000000..755a0ddd37 --- /dev/null +++ b/contrib/php3-tool/COPYRIGHT @@ -0,0 +1,8 @@ +Copyright 1998,1999,2000 Predrag Balorda, London, UK +All rights reserved. + +Redistribution and use in source and binary forms are permitted only +as authorized by the OpenLDAP Public License. A copy of this +license is available at http://www.OpenLDAP.org/license.html or +in file LICENSE in the top-level directory of the distribution. + diff --git a/contrib/php3-tool/index.php3 b/contrib/php3-tool/index.php3 new file mode 100644 index 0000000000..c76777638d --- /dev/null +++ b/contrib/php3-tool/index.php3 @@ -0,0 +1,111 @@ + + + + + PHP3 Thingy + + + +ldap_action = $qm->get_action(); + $lm->base_dn = $qm->get_base_dn(); + $lm->host = $qm->get_host(); + $lm->search_filter = $qm->get_search_filter(); + $prefs->loadPreferences(); + display_advanced_form(); + if (!$lm->connect($lm->host)) { + echo "Couldn't connect to ".$lm->host."
\n"; + echo "Bye"; + return 0; + } + if (!$lm->ldapTakeAction($lm->ldap_action) || $lm->entriesCount == 0) { + echo "Didn't find anything for ".$lm->ldap_action." on ".$lm->search_filter." from ".$lm->base_dn."
\n"; + return 0; + } + else { + // echo "I got ".$lm->entriesCount." entries for ".$lm->ldap_action." on ".$lm->search_filter." from ".$lm->base_dn."
\n"; + $get_entries_s_t = microtime(); + $lm->getEntries(); + $get_entries_e_t = microtime(); + // echo "Disconnecting from ".$lm->host."
\n"; + $lm->disconnect(); + } + if (($qm->get_mode() == "tree") && ($lm->ldap_action == "list")) { + $display_entries_s_t = microtime(); + ?> + + + +
+

formatHTMLBaseDN($lm->base_dn);?>

+
+

+ " ", 1 => ","); + $e = $lm->entries[0]; + $s = ldap_dn2ufn($e->dn); + $firstel = $lm->stripString($s, $tokens); + for ($i=0; $ientries); $i++) { + $c = ""; + $e = $lm->entries[$i]; + $s = ldap_dn2ufn($e->dn); + $tin = $lm->stripString($s, $tokens); + ?>

+

+ + + dn, 1); echo $n[0]; ?>

+
+
+ + formatHTMLAttributes(); echo $c; ?> +
+
+
formatHTMLEntries(); + echo $c; + } + $display_entries_e_t = microtime(); +// echo "
"; +// $t1 = $lm->calculateTime("getEntries()", $get_entries_s_t, $get_entries_e_t); +// $t2 = $lm->calculateTime("displayEntries()", $display_entries_s_t, $display_entries_e_t); +// $main_end_time = microtime(); +// $t3 = $lm->calculateTime("main()", $main_start_time, $main_end_time); +// $t = $t3 - ($t1 + $t2); +// echo "Ether : ".$t." seconds
\n"; +// echo "
"; + return 1; +} +$return = main(); +?> + + diff --git a/contrib/saucer/Makefile.in b/contrib/saucer/Makefile.in index 3d5479968b..ca810b5672 100644 --- a/contrib/saucer/Makefile.in +++ b/contrib/saucer/Makefile.in @@ -17,7 +17,7 @@ saucer: ${OBJS} $(LDAP_LIBDEPEND) $(LTLINK) -o $@ $(OBJS) $(LIBS) install-local: $(PROGRAMS) FORCE - -$(MKDIR) $(bindir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 saucer $(bindir) - -test -d $(MANDIR) || $(MKDIR) $(mandir) $(MANDIR) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/saucer.1 $(MANDIR)/saucer.1 + -$(MKDIR) $(DESTDIR)$(bindir) + $(LTINSTALL) $(INSTALLFLAGS) -m 755 saucer $(DESTDIR)$(bindir) + -$(MKDIR) $(DESTDIR)$(MANDIR) + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/saucer.1 $(DESTDIR)$(MANDIR)/saucer.1 diff --git a/contrib/saucer/main.c b/contrib/saucer/main.c index a49a3bf896..f736a70a21 100644 --- a/contrib/saucer/main.c +++ b/contrib/saucer/main.c @@ -67,7 +67,7 @@ extern int optind; int option; int portnum = LDAP_PORT; char *progname; -char true_filter[] = "objectClass=*"; /* Always succeeds */ +char true_filter[] = "(objectClass=*)"; /* Always succeeds */ char *username; int cmd_help(char **cmdargv, int cmdargc); diff --git a/contrib/tweb/Makefile.openldap b/contrib/tweb/Makefile.openldap index 218a65d074..bbb9ba4b27 100644 --- a/contrib/tweb/Makefile.openldap +++ b/contrib/tweb/Makefile.openldap @@ -15,7 +15,7 @@ # Creation date: Z D D V V * # August 16 1995 Z D D V V * # Last modification: Z D D V V * -# September 9 1999 ZZZZ DDD V * +# September 13 1999 ZZZZ DDD V * # * #/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/ #----------------------------------------------------------------------------- @@ -35,10 +35,11 @@ ######################################################################### # where is your LDAP client library located -LDAP_RUNTIME=/LDAP -LDAP_SOURCE =/LDAP/ldap-3.3 +# WE NEED portable.h AND ldap_log.h, SO POINT TO THE SOURCE TREE +LDAP_RUNTIME=../.. +LDAP_SOURCE =../.. -LIBDIR= $(LDAP_RUNTIME)/lib +LIBDIR= $(LDAP_RUNTIME)/libraries INCDIR= $(LDAP_RUNTIME)/include # where is some version information for your LDAP client library diff --git a/contrib/tweb/README b/contrib/tweb/README index 91b088d5fe..ddda6edb0f 100644 --- a/contrib/tweb/README +++ b/contrib/tweb/README @@ -14,7 +14,7 @@ * Creation date: Z D D V V * * September 14 1995 Z D D V V * * Last modification: Z D D V V * -* January 19 1999 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/ @@ -69,6 +69,19 @@ INSTALLATION several configuration parameters TWEB provides for runtime configuration of the program. + SINCE THE CODE IS ONLY THE CORE GATEWAY, WITH SOME PRIVATE EXTENSIONS + NOT INCLUDED INTO THAT DISTRIBUTION, DO NOT DELETE CODE BETWEEN + + #ifdef TUE_TEL + #endif + + AND + + #ifdef AMBIXGW + #endif + + IN ANY OF THE SUPPORTED FILES !!! + SUPPORT diff --git a/contrib/tweb/dn.c b/contrib/tweb/dn.c index 7518372cbe..86060bbfe9 100644 --- a/contrib/tweb/dn.c +++ b/contrib/tweb/dn.c @@ -16,21 +16,27 @@ * Creation date: Z D D V V * * April 24 1996 Z D D V V * * Last modification: Z D D V V * -* December 14 1996 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: dn.c,v 1.6 1999/09/10 15:01:16 zrnsk01 Exp $ + * $Id: dn.c,v 1.8 1999/09/13 13:47:44 zrnsk01 Exp $ * */ /* dn.c - routines for dealing with distinguished names */ #include "tgeneral.h" +#include "tglobal.h" #include "strng_exp.h" #include "dn.h" +#if OL_LDAPV == 2 +#define LDAP_DEBUG_ANY 0xffff +#endif + + /* * dn_normalize - put dn into a canonical format. the dn is * normalized in place, as well as returned. @@ -119,10 +125,7 @@ char *dn; break; default: -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 - -# define LDAP_DEBUG_ANY 0xffff +#if OL_LDAPV >= 2 if ( ldap_debug & LDAP_DEBUG_ANY ) fprintf( stderr, "dn_normalize - unknown state %d\n", state ); @@ -131,7 +134,6 @@ char *dn; syslog( ldap_syslog_level, "dn_normalize - unknown state %d\n", state ); -# endif #else Debug( LDAP_DEBUG_ANY, "dn_normalize - unknown state %d\n", state, 0, 0 ); diff --git a/contrib/tweb/html.c b/contrib/tweb/html.c index 7406c624bf..abaa35d14c 100644 --- a/contrib/tweb/html.c +++ b/contrib/tweb/html.c @@ -252,7 +252,7 @@ GLOB_STRUCT *glob; char *cPtr, *ptype; char *tattr; - if ( (rc = ldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + if ( (rc = ldap_search_s( ld, dn, LDAP_SCOPE_BASE, NULL, NULL, 0, &res )) != LDAP_SUCCESS ) { do_error(fp, rc, NOT_FOUND, glob); return; @@ -342,7 +342,7 @@ GLOB_STRUCT *glob; timeout.tv_sec = glob->timeout; timeout.tv_usec = 0; - if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL, NULL, 0, &timeout, &res )) != LDAP_SUCCESS ) { do_error(fp, rc, NOT_FOUND, glob); return; diff --git a/contrib/tweb/queries.c b/contrib/tweb/queries.c index 1e0ebb40cc..5c19448465 100644 --- a/contrib/tweb/queries.c +++ b/contrib/tweb/queries.c @@ -15,12 +15,12 @@ * Creation date: Z D D V V * * August 16 1995 Z D D V V * * Last modification: Z D D V V * -* May 11 1999 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: queries.c,v 1.6 1999/09/10 15:01:18 zrnsk01 Exp $ + * $Id: queries.c,v 1.8 1999/09/13 13:47:47 zrnsk01 Exp $ * */ @@ -43,6 +43,10 @@ struct hostent *hp; LDAP *ld; char tstring[100]; +#if OL_LDAPV > 0 + int ldap_opt; +#endif + /* get time for performance log */ gettimeofday(×tore[2], NULL); @@ -85,7 +89,13 @@ struct hostent *hp; len = strlen( buf ); if ( debug ) { fprintf( stderr, "got %d bytes\n", len ); + +#if OL_LDAPV > 2 + ber_bprint( buf, len ); +#else lber_bprint( buf, len ); +#endif + } /* strip of white spaces */ @@ -309,23 +319,21 @@ struct hostent *hp; rewind(fp); /* follow aliases while searching */ -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_ALWAYS; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_ALWAYS; #endif if ( !searchaliases ) -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_FINDING ); + ldap_opt = LDAP_DEREF_FINDING; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_FINDING; #endif @@ -376,32 +384,29 @@ struct hostent *hp; glob->svc_cnt); /* accesses with resolvation of alias-entries */ -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_ALWAYS; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_ALWAYS; #endif if ( !searchaliases ) -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_FINDING ); + ldap_opt = LDAP_DEREF_FINDING; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_FINDING; #endif /* bind to DSA by order of the user as Web-DN - (if with DN1 or DN2 was decided at check4access) */ + (DN1 or DN2 was decided at check4access) */ -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 /* a dummy call as long as socket connections are not settled * with OpenLDAP @@ -409,12 +414,6 @@ struct hostent *hp; if ( dosyslog ) syslog( LOG_INFO, "do_queries(): calling ldap_simple_bind_s()...\n" ); -# else - - if ( dosyslog ) - syslog( LOG_INFO, "do_queries(): calling ldap_simple_bind_s()...\n" ); - -# endif #endif if ( (rc=ldap_simple_bind_s( ld, glob->webdn, glob->webpw )) diff --git a/contrib/tweb/tgeneral.h b/contrib/tweb/tgeneral.h index 4eb0adcbf8..bdaf57be7f 100644 --- a/contrib/tweb/tgeneral.h +++ b/contrib/tweb/tgeneral.h @@ -14,12 +14,12 @@ * Creation date: Z D D V V * * August 16 1995 Z D D V V * * Last modification: Z D D V V * -* May 14 1999 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: tgeneral.h,v 1.6 1999/09/10 15:01:20 zrnsk01 Exp $ + * $Id: tgeneral.h,v 1.8 1999/09/13 13:47:47 zrnsk01 Exp $ * */ @@ -68,6 +68,24 @@ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ #include #include +/* Support of LDAP API versions */ +#if LDAP_API_VERSION >= 2003 && LDAP_API_VERSION <= 2010 +#define OL_LDAPV 3 +#else +# if LDAP_API_VERSION >= 2001 && LDAP_API_VERSION <= 2010 +# define OL_LDAPV 2 +# else +# define OL_LDAPV 0 +# endif +#endif + +# define ldap_debug debug + +#if OL_LDAPV > 2 +# include "portable.h" +# include "ldap_log.h" +#endif + extern int errno; diff --git a/contrib/tweb/tglobal.h b/contrib/tweb/tglobal.h index f115592ad5..147c32049b 100644 --- a/contrib/tweb/tglobal.h +++ b/contrib/tweb/tglobal.h @@ -13,12 +13,12 @@ * Creation date: Z D D V V * * August 16 1996 Z D D V V * * Last modification: Z D D V V * -* December 29 1998 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: tglobal.h,v 1.6 1999/09/10 15:01:20 zrnsk01 Exp $ + * $Id: tglobal.h,v 1.8 1999/09/13 13:47:47 zrnsk01 Exp $ * */ @@ -32,21 +32,18 @@ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ extern int debug; extern int dosyslog; +extern int ldap_syslog; +extern int ldap_syslog_level; + extern struct timeval timestore[]; extern int items_displayed; extern int searchaliases; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 - -extern LDAPFriendlyMap *fm; - -# else +#if OL_LDAPV >= 2 extern LDAPFriendlyMap *fm; -# endif #else extern FriendlyMap *fm; diff --git a/contrib/tweb/tweb.h b/contrib/tweb/tweb.h index fe1d49ec61..1c6869e851 100644 --- a/contrib/tweb/tweb.h +++ b/contrib/tweb/tweb.h @@ -14,12 +14,12 @@ * Creation date: Z D D V V * * August 16 1995 Z D D V V * * Last modification: Z D D V V * -* December 31 1998 ZZZZ DDD V * +* September 13 1999 ZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: tweb.h,v 1.6 1999/09/10 15:01:20 zrnsk01 Exp $ + * $Id: tweb.h,v 1.8 1999/09/13 13:47:47 zrnsk01 Exp $ * */ @@ -34,23 +34,20 @@ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ #include "support_exp.h" PRIVATE void do_child(); -int debug; +int debug = 0; +int ldap_syslog = 0; +int ldap_syslog_level = 0; + int dosyslog = 0; GLOB_STRUCT *globP; int searchaliases = 1; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 - -LDAPFriendlyMap *fm = NULL; - -# else +#if OL_LDAPV >= 2 LDAPFriendlyMap *fm = NULL; -# endif #else FriendlyMap *fm = NULL; diff --git a/contrib/tweb/x500.c b/contrib/tweb/x500.c index a8a02f70a2..447060fbde 100644 --- a/contrib/tweb/x500.c +++ b/contrib/tweb/x500.c @@ -15,12 +15,12 @@ * Creation date: Z D D V V * * August 16 1995 Z D D V V * * Last modification: Z D D V V * -* September 10 1999 ZZZZZ DDD V * +* September 13 1999 ZZZZZ DDD V * * * _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/ /* - * $Id: x500.c,v 1.8 1999/09/10 15:01:20 zrnsk01 Exp $ + * $Id: x500.c,v 1.10 1999/09/13 13:47:48 zrnsk01 Exp $ * */ @@ -143,6 +143,10 @@ GLOB_STRUCT *glob; int count; char *ufn; +#if OL_LDAPV > 0 + int ldap_opt; +#endif + if(!attrs) attrs = (char**) charray_dup(sattrs); @@ -162,12 +166,11 @@ GLOB_STRUCT *glob; timeout.tv_sec = glob->timeout; timeout.tv_usec = 0; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_FINDING; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_FINDING; #endif @@ -182,12 +185,11 @@ GLOB_STRUCT *glob; if (rc == LDAP_SIZELIMIT_EXCEEDED) glob->persRestricted = TRUE; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_ALWAYS; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_ALWAYS; #endif @@ -348,6 +350,10 @@ GLOB_STRUCT *glob; char *ufn; char title[BUFSIZ], title2[BUFSIZ]; +#if OL_LDAPV > 0 + int ldap_opt; +#endif + glob->no_browse = FALSE; /* query string: base-DN?[OS]=filter @@ -384,14 +390,12 @@ GLOB_STRUCT *glob; filtertype = (scope == LDAP_SCOPE_ONELEVEL ? "web500gw onelevel" : "web500gw subtree"); -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, - scope == LDAP_SCOPE_ONELEVEL ? LDAP_DEREF_FINDING : - LDAP_DEREF_ALWAYS ); + ldap_opt = ( scope == LDAP_SCOPE_ONELEVEL ? LDAP_DEREF_FINDING : + LDAP_DEREF_ALWAYS ); + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = (scope == LDAP_SCOPE_ONELEVEL ? LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS); @@ -408,8 +412,7 @@ GLOB_STRUCT *glob; if (dosyslog) { -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 int ld_errno; @@ -417,7 +420,6 @@ GLOB_STRUCT *glob; syslog (LOG_INFO, "ldap_search_st(): %s", ldap_err2string ( ld_errno )); -# endif #else syslog (LOG_INFO, "ldap_search_st(): %s", ldap_err2string (ld->ld_errno)); @@ -437,12 +439,11 @@ GLOB_STRUCT *glob; } items_displayed = count; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_ALWAYS; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_ALWAYS; #endif @@ -1660,6 +1661,10 @@ GLOB_STRUCT *glob; char *url = NULL; char **uri = NULL, *urlnola, raw_string[BUFSIZ]; +#if OL_LDAPV > 0 + int ldap_opt; +#endif + oc = ldap_get_values( ld, e, "objectClass" ); if(!(aoc = make_oc_to_string(oc))) return; @@ -1816,12 +1821,11 @@ GLOB_STRUCT *glob; timeout.tv_sec = glob->timeout; timeout.tv_usec = 0; -#if defined LDAP_VENDOR_NAME && defined LDAP_API_VERSION -# if LDAP_API_VERSION > 2001 && LDAP_API_VERSION < 2010 +#if OL_LDAPV > 0 - ldap_set_option( ld, LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + ldap_opt = LDAP_DEREF_ALWAYS; + ldap_set_option( ld, LDAP_OPT_DEREF, &ldap_opt ); -# endif #else ld->ld_deref = LDAP_DEREF_ALWAYS; #endif diff --git a/contrib/web_ldap/Makefile.in b/contrib/web_ldap/Makefile.in index 0157d0f452..1b3d64f47d 100644 --- a/contrib/web_ldap/Makefile.in +++ b/contrib/web_ldap/Makefile.in @@ -13,6 +13,6 @@ web_ldap: ${OBJS} $(LDAP_LIBDEPEND) $(LTLINK) -o $@ $(OBJS) $(LIBS) install-local: $(PROGRAMS) FORCE - -test -d $(libexecdir) || $(MKDIR) $(libexecdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 web_ldap $(libexecdir) + -$(MKDIR) $(DESTDIR)$(libexecdir) + $(LTINSTALL) $(INSTALLFLAGS) -m 755 web_ldap $(DESTDIR)$(libexecdir) @echo ">> You must copy and edit web_ldap.cfg and web_ldap.html as needed. <<" diff --git a/contrib/whois++/Makefile b/contrib/whois++/Makefile index a2f9b2eccc..1c29f747a5 100644 --- a/contrib/whois++/Makefile +++ b/contrib/whois++/Makefile @@ -19,10 +19,17 @@ FACILITY = LOG_LOCAL3 # #SYSLIBS = -li -lsyslog # +# If you want POSIX international support (format of dates), on ultrix +# +#INTERNATIONAL = -DINTERNATIONAL +# # If you want RFC931 logging you must have log_tcp source available # +#RFC931DEF = -DRFC931 +#RFC931SRC = /local/src/log_tcp/rfc931.c + SRCS = whois++.c command.c config.c describe.c help.c output.c template.c \ - util.c version.c # /local/src/log_tcp/rfc931.c + util.c version.c $(RFC931SRC) HDRS = whois++.h OBJS = ${SRCS:.c=.o} HOST = `hostname` @@ -36,7 +43,8 @@ DEFINES = -DETCDIR=\"$(ETCDIR)\" -DBUILD="\"$(USER)@$(HOST) on $(DATE)\"" \ -DCONFIG_DIRECTORY=\"$(CONFIG_DIRECTORY)\" -DMAIN \ -DHELP_DIRECTORY=\"$(HELP_DIRECTORY)\" -DREVISION="$(REVISION)" \ -DPROTOCOL="\"[FIRST DRAFT - 15 April 1993]\"" -DRELEASE=\"BETA\" \ - -DFACILITY=$(FACILITY) -DDEFAULT_LDAPHOST=\"$(LDAPHOST)\" # -DRFC931 + -DFACILITY=$(FACILITY) -DDEFAULT_LDAPHOST=\"$(LDAPHOST)\" \ + $(INTERNATIONAL) $(RFC931DEF) CFLAGS = -I$(LDAPSRC)/include -I/usr/local/include $(ACFLAGS) LIBS = -L$(LDAPSRC)/libraries/libldap -lldap -L$(LDAPSRC)/libraries/liblber \ @@ -52,16 +60,17 @@ whois++.o: whois++.c $(HDRS) install: inst-whois++ -inst-whois++: $(ETCDIR)/whois++d - -mkdir -p $(CONFIG_DIRECTORY) - cp -r templates $(CONFIG_DIRECTORY) - -mkdir -p $(HELP_DIRECTORY) - cp -r helpfiles/* $(HELP_DIRECTORY) - sed -e 's#ETCDIR#$(ETCDIR)#' whois++d.man > $(MANDIR)/man$(MANSEC)/whois++d.$(MANSEC) +inst-whois++: $(DESTDIR)$(ETCDIR)/whois++d + -$(MKDIR) $(DESTDIR)$(CONFIG_DIRECTORY) + cp -r templates $(DESTDIR)$(CONFIG_DIRECTORY) + -$(MKDIR) $(DESTDIR)$(HELP_DIRECTORY) + cp -r helpfiles/* $(DESTDIR)$(HELP_DIRECTORY) + -$(MKDIR) $(DESTDIR)$(MANDIR)/man$(MANSEC) + sed -e 's#ETCDIR#$(ETCDIR)#' whois++d.man > $(DESTDIR)$(MANDIR)/man$(MANSEC)/whois++d.$(MANSEC) @echo "Don't forget to modify and install the tailor file" -$(ETCDIR)/whois++d: whois++d - install -c -m 755 whois++d $(ETCDIR) +$(DESTDIR)$(ETCDIR)/whois++d: whois++d + install -c -m 755 whois++d $(DESTDIR)$(ETCDIR) lint:; lint $(SRCS) diff --git a/contrib/whois++/whois++.c b/contrib/whois++/whois++.c index ce807193e2..d353408a94 100644 --- a/contrib/whois++/whois++.c +++ b/contrib/whois++/whois++.c @@ -53,6 +53,7 @@ char **argv; struct hostent *hp; static struct sockaddr sa; struct sockaddr_in *sin = (struct sockaddr_in *) (&sa); + /* #### length should be socklen_t when we include portable.h #### */ int length = sizeof(sa); static char options[] = "[-b searchbase] [-d debug ] \ [-h ldaphost ] [-i] [-l] [-s sizelimit] [-t timelimit] [-T tailorfile ] \ @@ -178,10 +179,10 @@ char **argv; } } - if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) { + if ( (ld = ldap_init( ldaphost, LDAP_PORT )) == NULL ) { printFormatted( lineLength, TRUE, stdout, "Connection to LDAP port on %s has failed", ldaphost ); - syslog( LOG_ERR, "Connection to LDAP port on %s has failed", + syslog( LOG_ERR, "Initialization of LDAP session (%s)", ldaphost ); exit( 1 ); } @@ -194,13 +195,6 @@ char **argv; case LDAP_SUCCESS: break; - case LDAP_UNAVAILABLE: - printFormatted( lineLength, TRUE, stdout, - "Sorry, the X.500 service is temporarily unavailable. \ -Please try again later." ); - syslog( LOG_NOTICE, "X.500 service temporarily unavailable" ); - exit( 1 ); - default: printFormatted( lineLength, TRUE, stdout, "Bind to Directory failed, %s", @@ -220,7 +214,7 @@ Please try again later." ); exit( 1 ); } entry = ldap_first_entry( ld, result ); - organisation = strdup( ldap_dn2ufn( ldap_get_dn( ld, entry ) ) ); + organisation = ldap_dn2ufn( ldap_get_dn( ld, entry ) ); category = ldap_get_values( ld, entry, "businessCategory" ); printFormatted( lineLength, FALSE, stdout, diff --git a/doc/Makefile.in b/doc/Makefile.in index 754eee763d..d292b0480f 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, See COPYRIGHT file ## ## doc Makefile.in for OpenLDAP diff --git a/doc/devel/asn-layman.txt b/doc/devel/asn-layman.txt new file mode 100644 index 0000000000..d4fbe64be9 --- /dev/null +++ b/doc/devel/asn-layman.txt @@ -0,0 +1,1855 @@ +A Layman's Guide to a Subset of ASN.1, BER, and DER + +An RSA Laboratories Technical Note +Burton S. Kaliski Jr. +Revised November 1, 1993 + + +Supersedes June 3, 1991 version, which was also published as +NIST/OSI Implementors' Workshop document SEC-SIG-91-17. +PKCS documents are available by electronic mail to +. + +Copyright (C) 1991-1993 RSA Laboratories, a division of RSA +Data Security, Inc. License to copy this document is granted +provided that it is identified as "RSA Data Security, Inc. +Public-Key Cryptography Standards (PKCS)" in all material +mentioning or referencing this document. +003-903015-110-000-000 + + +Abstract. This note gives a layman's introduction to a +subset of OSI's Abstract Syntax Notation One (ASN.1), Basic +Encoding Rules (BER), and Distinguished Encoding Rules +(DER). The particular purpose of this note is to provide +background material sufficient for understanding and +implementing the PKCS family of standards. + + +1. Introduction + +It is a generally accepted design principle that abstraction +is a key to managing software development. With abstraction, +a designer can specify a part of a system without concern +for how the part is actually implemented or represented. +Such a practice leaves the implementation open; it +simplifies the specification; and it makes it possible to +state "axioms" about the part that can be proved when the +part is implemented, and assumed when the part is employed +in another, higher-level part. Abstraction is the hallmark +of most modern software specifications. + +One of the most complex systems today, and one that also +involves a great deal of abstraction, is Open Systems +Interconnection (OSI, described in X.200). OSI is an +internationally standardized architecture that governs the +interconnection of computers from the physical layer up to +the user application layer. Objects at higher layers are +defined abstractly and intended to be implemented with +objects at lower layers. For instance, a service at one +layer may require transfer of certain abstract objects +between computers; a lower layer may provide transfer +services for strings of ones and zeroes, using encoding +rules to transform the abstract objects into such strings. +OSI is called an open system because it supports many +different implementations of the services at each layer. + +OSI's method of specifying abstract objects is called ASN.1 +(Abstract Syntax Notation One, defined in X.208), and one +set of rules for representing such objects as strings of +ones and zeros is called the BER (Basic Encoding Rules, +defined in X.209). ASN.1 is a flexible notation that allows +one to define a variety data types, from simple types such +as integers and bit strings to structured types such as sets +and sequences, as well as complex types defined in terms of +others. BER describes how to represent or encode values of +each ASN.1 type as a string of eight-bit octets. There is +generally more than one way to BER-encode a given value. +Another set of rules, called the Distinguished Encoding +Rules (DER), which is a subset of BER, gives a unique +encoding to each ASN.1 value. + +The purpose of this note is to describe a subset of ASN.1, +BER and DER sufficient to understand and implement one OSI- +based application, RSA Data Security, Inc.'s Public-Key +Cryptography Standards. The features described include an +overview of ASN.1, BER, and DER and an abridged list of +ASN.1 types and their BER and DER encodings. Sections 2-4 +give an overview of ASN.1, BER, and DER, in that order. +Section 5 lists some ASN.1 types, giving their notation, +specific encoding rules, examples, and comments about their +application to PKCS. Section 6 concludes with an example, +X.500 distinguished names. + +Advanced features of ASN.1, such as macros, are not +described in this note, as they are not needed to implement +PKCS. For information on the other features, and for more +detail generally, the reader is referred to CCITT +Recommendations X.208 and X.209, which define ASN.1 and BER. + +Terminology and notation. In this note, an octet is an eight- +bit unsigned integer. Bit 8 of the octet is the most +significant and bit 1 is the least significant. + +The following meta-syntax is used for in describing ASN.1 +notation: + + BIT monospace denotes literal characters in the type + and value notation; in examples, it generally + denotes an octet value in hexadecimal + + n1 bold italics denotes a variable + + [] bold square brackets indicate that a term is + optional + + {} bold braces group related terms + + | bold vertical bar delimits alternatives with a + group + + ... bold ellipsis indicates repeated occurrences + + = bold equals sign expresses terms as subterms + + +2. Abstract Syntax Notation One + +Abstract Syntax Notation One, abbreviated ASN.1, is a +notation for describing abstract types and values. + +In ASN.1, a type is a set of values. For some types, there +are a finite number of values, and for other types there are +an infinite number. A value of a given ASN.1 type is an +element of the type's set. ASN.1 has four kinds of type: +simple types, which are "atomic" and have no components; +structured types, which have components; tagged types, which +are derived from other types; and other types, which include +the CHOICE type and the ANY type. Types and values can be +given names with the ASN.1 assignment operator (::=) , and +those names can be used in defining other types and values. + +Every ASN.1 type other than CHOICE and ANY has a tag, which +consists of a class and a nonnegative tag number. ASN.1 +types are abstractly the same if and only if their tag +numbers are the same. In other words, the name of an ASN.1 +type does not affect its abstract meaning, only the tag +does. There are four classes of tag: + + Universal, for types whose meaning is the same in all + applications; these types are only defined in + X.208. + + Application, for types whose meaning is specific to an + application, such as X.500 directory services; + types in two different applications may have the + same application-specific tag and different + meanings. + + Private, for types whose meaning is specific to a given + enterprise. + + Context-specific, for types whose meaning is specific + to a given structured type; context-specific tags + are used to distinguish between component types + with the same underlying tag within the context of + a given structured type, and component types in + two different structured types may have the same + tag and different meanings. + +The types with universal tags are defined in X.208, which +also gives the types' universal tag numbers. Types with +other tags are defined in many places, and are always +obtained by implicit or explicit tagging (see Section 2.3). +Table 1 lists some ASN.1 types and their universal-class +tags. + + Type Tag number Tag number + (decimal) (hexadecimal) + INTEGER 2 02 + BIT STRING 3 03 + OCTET STRING 4 04 + NULL 5 05 + OBJECT IDENTIFIER 6 06 + SEQUENCE and SEQUENCE OF 16 10 + SET and SET OF 17 11 + PrintableString 19 13 + T61String 20 14 + IA5String 22 16 + UTCTime 23 17 + + Table 1. Some types and their universal-class tags. + +ASN.1 types and values are expressed in a flexible, +programming-language-like notation, with the following +special rules: + + o Layout is not significant; multiple spaces and + line breaks can be considered as a single space. + + o Comments are delimited by pairs of hyphens (--), + or a pair of hyphens and a line break. + + o Identifiers (names of values and fields) and type + references (names of types) consist of upper- and + lower-case letters, digits, hyphens, and spaces; + identifiers begin with lower-case letters; type + references begin with upper-case letters. + +The following four subsections give an overview of simple +types, structured types, implicitly and explicitly tagged +types, and other types. Section 5 describes specific types +in more detail. + + +2.1 Simple types + +Simple types are those not consisting of components; they +are the "atomic" types. ASN.1 defines several; the types +that are relevant to the PKCS standards are the following: + + BIT STRING, an arbitrary string of bits (ones and + zeroes). + + IA5String, an arbitrary string of IA5 (ASCII) + characters. + + INTEGER, an arbitrary integer. + + NULL, a null value. + + OBJECT IDENTIFIER, an object identifier, which is a + sequence of integer components that identify an + object such as an algorithm or attribute type. + + OCTET STRING, an arbitrary string of octets (eight-bit + values). + + PrintableString, an arbitrary string of printable + characters. + + T61String, an arbitrary string of T.61 (eight-bit) + characters. + + UTCTime, a "coordinated universal time" or Greenwich + Mean Time (GMT) value. + +Simple types fall into two categories: string types and non- +string types. BIT STRING, IA5String, OCTET STRING, +PrintableString, T61String, and UTCTime are string types. + +String types can be viewed, for the purposes of encoding, as +consisting of components, where the components are +substrings. This view allows one to encode a value whose +length is not known in advance (e.g., an octet string value +input from a file stream) with a constructed, indefinite- +length encoding (see Section 3). + +The string types can be given size constraints limiting the +length of values. + + +2.2 Structured types + +Structured types are those consisting of components. ASN.1 +defines four, all of which are relevant to the PKCS +standards: + + SEQUENCE, an ordered collection of one or more types. + + SEQUENCE OF, an ordered collection of zero or more + occurrences of a given type. + + SET, an unordered collection of one or more types. + + SET OF, an unordered collection of zero or more + occurrences of a given type. + +The structured types can have optional components, possibly +with default values. + + +2.3 Implicitly and explicitly tagged types + +Tagging is useful to distinguish types within an +application; it is also commonly used to distinguish +component types within a structured type. For instance, +optional components of a SET or SEQUENCE type are typically +given distinct context-specific tags to avoid ambiguity. + +There are two ways to tag a type: implicitly and explicitly. + +Implicitly tagged types are derived from other types by +changing the tag of the underlying type. Implicit tagging is +denoted by the ASN.1 keywords [class number] IMPLICIT (see +Section 5.1). + +Explicitly tagged types are derived from other types by +adding an outer tag to the underlying type. In effect, +explicitly tagged types are structured types consisting of +one component, the underlying type. Explicit tagging is +denoted by the ASN.1 keywords [class number] EXPLICIT (see +Section 5.2). + +The keyword [class number] alone is the same as explicit +tagging, except when the "module" in which the ASN.1 type is +defined has implicit tagging by default. ("Modules" are +among the advanced features not described in this note.) + +For purposes of encoding, an implicitly tagged type is +considered the same as the underlying type, except that the +tag is different. An explicitly tagged type is considered +like a structured type with one component, the underlying +type. Implicit tags result in shorter encodings, but +explicit tags may be necessary to avoid ambiguity if the tag +of the underlying type is indeterminate (e.g., the +underlying type is CHOICE or ANY). + + +2.4 Other types + +Other types in ASN.1 include the CHOICE and ANY types. The +CHOICE type denotes a union of one or more alternatives; the +ANY type denotes an arbitrary value of an arbitrary type, +where the arbitrary type is possibly defined in the +registration of an object identifier or integer value. + + +3. Basic Encoding Rules + +The Basic Encoding Rules for ASN.1, abbreviated BER, give +one or more ways to represent any ASN.1 value as an octet +string. (There are certainly other ways to represent ASN.1 +values, but BER is the standard for interchanging such +values in OSI.) + +There are three methods to encode an ASN.1 value under BER, +the choice of which depends on the type of value and whether +the length of the value is known. The three methods are +primitive, definite-length encoding; constructed, definite- +length encoding; and constructed, indefinite-length +encoding. Simple non-string types employ the primitive, +definite-length method; structured types employ either of +the constructed methods; and simple string types employ any +of the methods, depending on whether the length of the value +is known. Types derived by implicit tagging employ the +method of the underlying type and types derived by explicit +tagging employ the constructed methods. + +In each method, the BER encoding has three or four parts: + + Identifier octets. These identify the class and tag + number of the ASN.1 value, and indicate whether + the method is primitive or constructed. + + Length octets. For the definite-length methods, these + give the number of contents octets. For the + constructed, indefinite-length method, these + indicate that the length is indefinite. + + Contents octets. For the primitive, definite-length + method, these give a concrete representation of + the value. For the constructed methods, these + give the concatenation of the BER encodings of the + components of the value. + + End-of-contents octets. For the constructed, indefinite- + length method, these denote the end of the + contents. For the other methods, these are absent. + +The three methods of encoding are described in the following +sections. + + +3.1 Primitive, definite-length method + +This method applies to simple types and types derived from +simple types by implicit tagging. It requires that the +length of the value be known in advance. The parts of the +BER encoding are as follows: + +Identifier octets. There are two forms: low tag number (for +tag numbers between 0 and 30) and high tag number (for tag +numbers 31 and greater). + + Low-tag-number form. One octet. Bits 8 and 7 specify + the class (see Table 2), bit 6 has value "0," + indicating that the encoding is primitive, and + bits 5-1 give the tag number. + + Class Bit Bit + 8 7 + universal 0 0 + application 0 1 + context-specific 1 0 + private 1 1 + + Table 2. Class encoding in identifier octets. + + High-tag-number form. Two or more octets. First octet + is as in low-tag-number form, except that bits 5-1 + all have value "1." Second and following octets + give the tag number, base 128, most significant + digit first, with as few digits as possible, and + with the bit 8 of each octet except the last set + to "1." + +Length octets. There are two forms: short (for lengths +between 0 and 127), and long definite (for lengths between 0 +and 21008-1). + + Short form. One octet. Bit 8 has value "0" and bits 7-1 + give the length. + + Long form. Two to 127 octets. Bit 8 of first octet has + value "1" and bits 7-1 give the number of + additional length octets. Second and following + octets give the length, base 256, most significant + digit first. + +Contents octets. These give a concrete representation of the +value (or the value of the underlying type, if the type is +derived by implicit tagging). Details for particular types +are given in Section 5. + + +3.2 Constructed, definite-length method + +This method applies to simple string types, structured +types, types derived simple string types and structured +types by implicit tagging, and types derived from anything +by explicit tagging. It requires that the length of the +value be known in advance. The parts of the BER encoding are +as follows: + +Identifier octets. As described in Section 3.1, except that +bit 6 has value "1," indicating that the encoding is +constructed. + +Length octets. As described in Section 3.1. + +Contents octets. The concatenation of the BER encodings of +the components of the value: + + o For simple string types and types derived from + them by implicit tagging, the concatenation of the + BER encodings of consecutive substrings of the + value (underlying value for implicit tagging). + + o For structured types and types derived from them + by implicit tagging, the concatenation of the BER + encodings of components of the value (underlying + value for implicit tagging). + + o For types derived from anything by explicit + tagging, the BER encoding of the underlying value. + +Details for particular types are given in Section 5. + + +3.3 Constructed, indefinite-length method + +This method applies to simple string types, structured +types, types derived simple string types and structured +types by implicit tagging, and types derived from anything +by explicit tagging. It does not require that the length of +the value be known in advance. The parts of the BER encoding +are as follows: + +Identifier octets. As described in Section 3.2. + +Length octets. One octet, 80. + +Contents octets. As described in Section 3.2. + +End-of-contents octets. Two octets, 00 00. + +Since the end-of-contents octets appear where an ordinary +BER encoding might be expected (e.g., in the contents octets +of a sequence value), the 00 and 00 appear as identifier and +length octets, respectively. Thus the end-of-contents octets +is really the primitive, definite-length encoding of a value +with universal class, tag number 0, and length 0. + + +4. Distinguished Encoding Rules + +The Distinguished Encoding Rules for ASN.1, abbreviated DER, +are a subset of BER, and give exactly one way to represent +any ASN.1 value as an octet string. DER is intended for +applications in which a unique octet string encoding is +needed, as is the case when a digital signature is computed +on an ASN.1 value. DER is defined in Section 8.7 of X.509. + +DER adds the following restrictions to the rules given in +Section 3: + + 1. When the length is between 0 and 127, the short + form of length must be used + + 2. When the length is 128 or greater, the long form + of length must be used, and the length must be + encoded in the minimum number of octets. + + 3. For simple string types and implicitly tagged + types derived from simple string types, the + primitive, definite-length method must be + employed. + + 4. For structured types, implicitly tagged types + derived from structured types, and explicitly + tagged types derived from anything, the + constructed, definite-length method must be + employed. + +Other restrictions are defined for particular types (such as +BIT STRING, SEQUENCE, SET, and SET OF), and can be found in +Section 5. + + +5. Notation and encodings for some types + +This section gives the notation for some ASN.1 types and +describes how to encode values of those types under both BER +and DER. + +The types described are those presented in Section 2. They +are listed alphabetically here. + +Each description includes ASN.1 notation, BER encoding, and +DER encoding. The focus of the encodings is primarily on the +contents octets; the tag and length octets follow Sections 3 +and 4. The descriptions also explain where each type is used +in PKCS and related standards. ASN.1 notation is generally +only for types, although for the type OBJECT IDENTIFIER, +value notation is given as well. + + +5.1 Implicitly tagged types + +An implicitly tagged type is a type derived from another +type by changing the tag of the underlying type. + +Implicit tagging is used for optional SEQUENCE components +with underlying type other than ANY throughout PKCS, and for +the extendedCertificate alternative of PKCS #7's +ExtendedCertificateOrCertificate type. + +ASN.1 notation: + +[[class] number] IMPLICIT Type + +class = UNIVERSAL | APPLICATION | PRIVATE + +where Type is a type, class is an optional class name, and +number is the tag number within the class, a nonnegative +integer. + +In ASN.1 "modules" whose default tagging method is implicit +tagging, the notation [[class] number] Type is also +acceptable, and the keyword IMPLICIT is implied. (See +Section 2.3.) For definitions stated outside a module, the +explicit inclusion of the keyword IMPLICIT is preferable to +prevent ambiguity. + +If the class name is absent, then the tag is context- +specific. Context-specific tags can only appear in a +component of a structured or CHOICE type. + +Example: PKCS #8's PrivateKeyInfo type has an optional +attributes component with an implicit, context-specific tag: + +PrivateKeyInfo ::= SEQUENCE { + version Version, + privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + privateKey PrivateKey, + attributes [0] IMPLICIT Attributes OPTIONAL } + +Here the underlying type is Attributes, the class is absent +(i.e., context-specific), and the tag number within the +class is 0. + +BER encoding. Primitive or constructed, depending on the +underlying type. Contents octets are as for the BER encoding +of the underlying value. + +Example: The BER encoding of the attributes component of a +PrivateKeyInfo value is as follows: + + o the identifier octets are 80 if the underlying + Attributes value has a primitive BER encoding and + a0 if the underlying Attributes value has a + constructed BER encoding + + o the length and contents octets are the same as the + length and contents octets of the BER encoding of + the underlying Attributes value + +DER encoding. Primitive or constructed, depending on the +underlying type. Contents octets are as for the DER encoding +of the underlying value. + + +5.2 Explicitly tagged types + +Explicit tagging denotes a type derived from another type by +adding an outer tag to the underlying type. + +Explicit tagging is used for optional SEQUENCE components +with underlying type ANY throughout PKCS, and for the +version component of X.509's Certificate type. + +ASN.1 notation: + +[[class] number] EXPLICIT Type + +class = UNIVERSAL | APPLICATION | PRIVATE + +where Type is a type, class is an optional class name, and +number is the tag number within the class, a nonnegative +integer. + +If the class name is absent, then the tag is context- +specific. Context-specific tags can only appear in a +component of a SEQUENCE, SET or CHOICE type. + +In ASN.1 "modules" whose default tagging method is explicit +tagging, the notation [[class] number] Type is also +acceptable, and the keyword EXPLICIT is implied. (See +Section 2.3.) For definitions stated outside a module, the +explicit inclusion of the keyword EXPLICIT is preferable to +prevent ambiguity. + +Example 1: PKCS #7's ContentInfo type has an optional +content component with an explicit, context-specific tag: + +ContentInfo ::= SEQUENCE { + contentType ContentType, + content + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + +Here the underlying type is ANY DEFINED BY contentType, the +class is absent (i.e., context-specific), and the tag number +within the class is 0. + +Example 2: X.509's Certificate type has a version component +with an explicit, context-specific tag, where the EXPLICIT +keyword is omitted: + +Certificate ::= ... + version [0] Version DEFAULT v1988, +... + +The tag is explicit because the default tagging method for +the ASN.1 "module" in X.509 that defines the Certificate +type is explicit tagging. + +BER encoding. Constructed. Contents octets are the BER +encoding of the underlying value. + +Example: the BER encoding of the content component of a +ContentInfo value is as follows: + + o identifier octets are a0 + + o length octets represent the length of the BER + encoding of the underlying ANY DEFINED BY + contentType value + + o contents octets are the BER encoding of the + underlying ANY DEFINED BY contentType value + +DER encoding. Constructed. Contents octets are the DER +encoding of the underlying value. + + +5.3 ANY + +The ANY type denotes an arbitrary value of an arbitrary +type, where the arbitrary type is possibly defined in the +registration of an object identifier or associated with an +integer index. + +The ANY type is used for content of a particular content +type in PKCS #7's ContentInfo type, for parameters of a +particular algorithm in X.509's AlgorithmIdentifier type, +and for attribute values in X.501's Attribute and +AttributeValueAssertion types. The Attribute type is used by +PKCS #6, #7, #8, #9 and #10, and the AttributeValueAssertion +type is used in X.501 distinguished names. + +ASN.1 notation: + +ANY [DEFINED BY identifier] + +where identifier is an optional identifier. + +In the ANY form, the actual type is indeterminate. + +The ANY DEFINED BY identifier form can only appear in a +component of a SEQUENCE or SET type for which identifier +identifies some other component, and that other component +has type INTEGER or OBJECT IDENTIFIER (or a type derived +from either of those by tagging). In that form, the actual +type is determined by the value of the other component, +either in the registration of the object identifier value, +or in a table of integer values. + +Example: X.509's AlgorithmIdentifier type has a component of +type ANY: + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + +Here the actual type of the parameter component depends on +the value of the algorithm component. The actual type would +be defined in the registration of object identifier values +for the algorithm component. + +BER encoding. Same as the BER encoding of the actual value. + +Example: The BER encoding of the value of the parameter +component is the BER encoding of the value of the actual +type as defined in the registration of object identifier +values for the algorithm component. + +DER encoding. Same as the DER encoding of the actual value. + + +5.4 BIT STRING + +The BIT STRING type denotes an arbitrary string of bits +(ones and zeroes). A BIT STRING value can have any length, +including zero. This type is a string type. + +The BIT STRING type is used for digital signatures on +extended certificates in PKCS #6's ExtendedCertificate type, +for digital signatures on certificates in X.509's +Certificate type, and for public keys in certificates in +X.509's SubjectPublicKeyInfo type. + +ASN.1 notation: + +BIT STRING + +Example: X.509's SubjectPublicKeyInfo type has a component +of type BIT STRING: + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + publicKey BIT STRING } + +BER encoding. Primitive or constructed. In a primitive +encoding, the first contents octet gives the number of bits +by which the length of the bit string is less than the next +multiple of eight (this is called the "number of unused +bits"). The second and following contents octets give the +value of the bit string, converted to an octet string. The +conversion process is as follows: + + 1. The bit string is padded after the last bit with + zero to seven bits of any value to make the length + of the bit string a multiple of eight. If the + length of the bit string is a multiple of eight + already, no padding is done. + + 2. The padded bit string is divided into octets. The + first eight bits of the padded bit string become + the first octet, bit 8 to bit 1, and so on through + the last eight bits of the padded bit string. + +In a constructed encoding, the contents octets give the +concatenation of the BER encodings of consecutive substrings +of the bit string, where each substring except the last has +a length that is a multiple of eight bits. + +Example: The BER encoding of the BIT STRING value +"011011100101110111" can be any of the following, among +others, depending on the choice of padding bits, the form of +length octets, and whether the encoding is primitive or +constructed: + +03 04 06 6e 5d c0 DER encoding + +03 04 06 6e 5d e0 padded with "100000" + +03 81 04 06 6e 5d c0 long form of length octets + +23 09 constructed encoding: "0110111001011101" + "11" + 03 03 00 6e 5d + 03 02 06 c0 + +DER encoding. Primitive. The contents octects are as for a +primitive BER encoding, except that the bit string is padded +with zero-valued bits. + +Example: The DER encoding of the BIT STRING value +"011011100101110111" is + +03 04 06 6e 5d c0 + + +5.5 CHOICE + +The CHOICE type denotes a union of one or more alternatives. + +The CHOICE type is used to represent the union of an +extended certificate and an X.509 certificate in PKCS #7's +ExtendedCertificateOrCertificate type. + +ASN.1 notation: + +CHOICE { + [identifier1] Type1, + ..., + [identifiern] Typen } + +where identifier1 , ..., identifiern are optional, distinct +identifiers for the alternatives, and Type1, ..., Typen are +the types of the alternatives. The identifiers are primarily +for documentation; they do not affect values of the type or +their encodings in any way. + +The types must have distinct tags. This requirement is +typically satisfied with explicit or implicit tagging on +some of the alternatives. + +Example: PKCS #7's ExtendedCertificateOrCertificate type is +a CHOICE type: + +ExtendedCertificateOrCertificate ::= CHOICE { + certificate Certificate, -- X.509 + extendedCertificate [0] IMPLICIT ExtendedCertificate +} + +Here the identifiers for the alternatives are certificate +and extendedCertificate, and the types of the alternatives +are Certificate and [0] IMPLICIT ExtendedCertificate. + +BER encoding. Same as the BER encoding of the chosen +alternative. The fact that the alternatives have distinct +tags makes it possible to distinguish between their BER +encodings. + +Example: The identifier octets for the BER encoding are 30 +if the chosen alternative is certificate, and a0 if the +chosen alternative is extendedCertificate. + +DER encoding. Same as the DER encoding of the chosen +alternative. + + +5.6 IA5String + +The IA5String type denotes an arbtrary string of IA5 +characters. IA5 stands for International Alphabet 5, which +is the same as ASCII. The character set includes non- +printing control characters. An IA5String value can have any +length, including zero. This type is a string type. + +The IA5String type is used in PKCS #9's electronic-mail +address, unstructured-name, and unstructured-address +attributes. + +ASN.1 notation: + +IA5String + +BER encoding. Primitive or constructed. In a primitive +encoding, the contents octets give the characters in the IA5 +string, encoded in ASCII. In a constructed encoding, the +contents octets give the concatenation of the BER encodings +of consecutive substrings of the IA5 string. + +Example: The BER encoding of the IA5String value +"test1@rsa.com" can be any of the following, among others, +depending on the form of length octets and whether the +encoding is primitive or constructed: + +16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d DER encoding + +16 81 0d long form of length octets + 74 65 73 74 31 40 72 73 61 2e 63 6f 6d + +36 13 constructed encoding: "test1" + "@" + "rsa.com" + 16 05 74 65 73 74 31 + 16 01 40 + 16 07 72 73 61 2e 63 6f 6d + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + +Example: The DER encoding of the IA5String value +"test1@rsa.com" is + +16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d + + +5.7 INTEGER + +The INTEGER type denotes an arbitrary integer. INTEGER +values can be positive, negative, or zero, and can have any +magnitude. + +The INTEGER type is used for version numbers throughout +PKCS, cryptographic values such as modulus, exponent, and +primes in PKCS #1's RSAPublicKey and RSAPrivateKey types and +PKCS #3's DHParameter type, a message-digest iteration count +in PKCS #5's PBEParameter type, and version numbers and +serial numbers in X.509's Certificate type. + +ASN.1 notation: + +INTEGER [{ identifier1(value1) ... identifiern(valuen) }] + +where identifier1, ..., identifiern are optional distinct +identifiers and value1, ..., valuen are optional integer +values. The identifiers, when present, are associated with +values of the type. + +Example: X.509's Version type is an INTEGER type with +identified values: + +Version ::= INTEGER { v1988(0) } + +The identifier v1988 is associated with the value 0. X.509's +Certificate type uses the identifier v1988 to give a default +value of 0 for the version component: + +Certificate ::= ... + version Version DEFAULT v1988, +... + +BER encoding. Primitive. Contents octets give the value of +the integer, base 256, in two's complement form, most +significant digit first, with the minimum number of octets. +The value 0 is encoded as a single 00 octet. + +Some example BER encodings (which also happen to be DER +encodings) are given in Table 3. + + Integer BER encoding + value + 0 02 01 00 + 127 02 01 7F + 128 02 02 00 80 + 256 02 02 01 00 + -128 02 01 80 + -129 02 02 FF 7F + + Table 3. Example BER encodings of INTEGER values. + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + + +5.8 NULL + +The NULL type denotes a null value. + +The NULL type is used for algorithm parameters in several +places in PKCS. + +ASN.1 notation: + +NULL + +BER encoding. Primitive. Contents octets are empty. + +Example: The BER encoding of a NULL value can be either of +the following, as well as others, depending on the form of +the length octets: + +05 00 + +05 81 00 + +DER encoding. Primitive. Contents octets are empty; the DER +encoding of a NULL value is always 05 00. + + +5.9 OBJECT IDENTIFIER + +The OBJECT IDENTIFIER type denotes an object identifier, a +sequence of integer components that identifies an object +such as an algorithm, an attribute type, or perhaps a +registration authority that defines other object +identifiers. An OBJECT IDENTIFIER value can have any number +of components, and components can generally have any +nonnegative value. This type is a non-string type. + +OBJECT IDENTIFIER values are given meanings by registration +authorities. Each registration authority is responsible for +all sequences of components beginning with a given sequence. +A registration authority typically delegates responsibility +for subsets of the sequences in its domain to other +registration authorities, or for particular types of object. +There are always at least two components. + +The OBJECT IDENTIFIER type is used to identify content in +PKCS #7's ContentInfo type, to identify algorithms in +X.509's AlgorithmIdentifier type, and to identify attributes +in X.501's Attribute and AttributeValueAssertion types. The +Attribute type is used by PKCS #6, #7, #8, #9, and #10, and +the AttributeValueAssertion type is used in X.501 +distinguished names. OBJECT IDENTIFIER values are defined +throughout PKCS. + +ASN.1 notation: + +OBJECT IDENTIFIER + +The ASN.1 notation for values of the OBJECT IDENTIFIER type +is + +{ [identifier] component1 ... componentn } + +componenti = identifieri | identifieri (valuei) | valuei + +where identifier, identifier1, ..., identifiern are +identifiers, and value1, ..., valuen are optional integer +values. + +The form without identifier is the "complete" value with all +its components; the form with identifier abbreviates the +beginning components with another object identifier value. +The identifiers identifier1, ..., identifiern are intended +primarily for documentation, but they must correspond to the +integer value when both are present. These identifiers can +appear without integer values only if they are among a small +set of identifiers defined in X.208. + +Example: The following values both refer to the object +identifier assigned to RSA Data Security, Inc.: + +{ iso(1) member-body(2) 840 113549 } +{ 1 2 840 113549 } + +(In this example, which gives ASN.1 value notation, the +object identifier values are decimal, not hexadecimal.) +Table 4 gives some other object identifier values and their +meanings. + + Object identifier value Meaning + { 1 2 } ISO member bodies + { 1 2 840 } US (ANSI) + { 1 2 840 113549 } RSA Data Security, Inc. + { 1 2 840 113549 1 } RSA Data Security, Inc. PKCS + { 2 5 } directory services (X.500) + { 2 5 8 } directory services-algorithms + + Table 4. Some object identifier values and their meanings. + +BER encoding. Primitive. Contents octets are as follows, +where value1, ..., valuen denote the integer values of the +components in the complete object identifier: + + 1. The first octet has value 40 * value1 + value2. + (This is unambiguous, since value1 is limited to + values 0, 1, and 2; value2 is limited to the range + 0 to 39 when value1 is 0 or 1; and, according to + X.208, n is always at least 2.) + + 2. The following octets, if any, encode value3, ..., + valuen. Each value is encoded base 128, most + significant digit first, with as few digits as + possible, and the most significant bit of each + octet except the last in the value's encoding set + to "1." + +Example: The first octet of the BER encoding of RSA Data +Security, Inc.'s object identifier is 40 * 1 + 2 = 42 = +2a16. The encoding of 840 = 6 * 128 + 4816 is 86 48 and the +encoding of 113549 = 6 * 1282 + 7716 * 128 + d16 is 86 f7 +0d. This leads to the following BER encoding: + +06 06 2a 86 48 86 f7 0d + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + + +5.10 OCTET STRING + +The OCTET STRING type denotes an arbitrary string of octets +(eight-bit values). An OCTET STRING value can have any +length, including zero. This type is a string type. + +The OCTET STRING type is used for salt values in PKCS #5's +PBEParameter type, for message digests, encrypted message +digests, and encrypted content in PKCS #7, and for private +keys and encrypted private keys in PKCS #8. + +ASN.1 notation: + +OCTET STRING [SIZE ({size | size1..size2})] + +where size, size1, and size2 are optional size constraints. +In the OCTET STRING SIZE (size) form, the octet string must +have size octets. In the OCTET STRING SIZE (size1..size2) +form, the octet string must have between size1 and size2 +octets. In the OCTET STRING form, the octet string can have +any size. + +Example: PKCS #5's PBEParameter type has a component of type +OCTET STRING: + +PBEParameter ::= SEQUENCE { + salt OCTET STRING SIZE(8), + iterationCount INTEGER } + +Here the size of the salt component is always eight octets. + +BER encoding. Primitive or constructed. In a primitive +encoding, the contents octets give the value of the octet +string, first octet to last octet. In a constructed +encoding, the contents octets give the concatenation of the +BER encodings of substrings of the OCTET STRING value. + +Example: The BER encoding of the OCTET STRING value 01 23 45 +67 89 ab cd ef can be any of the following, among others, +depending on the form of length octets and whether the +encoding is primitive or constructed: + +04 08 01 23 45 67 89 ab cd ef DER encoding + +04 81 08 01 23 45 67 89 ab cd ef long form of length octets + +24 0c constructed encoding: 01 ... 67 + 89 ... ef + 04 04 01 23 45 67 + 04 04 89 ab cd ef + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + +Example: The BER encoding of the OCTET STRING value 01 23 45 +67 89 ab cd ef is + +04 08 01 23 45 67 89 ab cd ef + + +5.11 PrintableString + +The PrintableString type denotes an arbitrary string of +printable characters from the following character set: + + A, B, ..., Z + a, b, ..., z + 0, 1, ..., 9 + (space) ' ( ) + , - . / : = ? + +This type is a string type. + +The PrintableString type is used in PKCS #9's challenge- +password and unstructuerd-address attributes, and in several +X.521 distinguished names attributes. + +ASN.1 notation: + +PrintableString + +BER encoding. Primitive or constructed. In a primitive +encoding, the contents octets give the characters in the +printable string, encoded in ASCII. In a constructed +encoding, the contents octets give the concatenation of the +BER encodings of consecutive substrings of the string. + +Example: The BER encoding of the PrintableString value "Test +User 1" can be any of the following, among others, depending +on the form of length octets and whether the encoding is +primitive or constructed: + +13 0b 54 65 73 74 20 55 73 65 72 20 31 DER encoding + +13 81 0b long form of length octets + 54 65 73 74 20 55 73 65 72 20 31 + +33 0f constructed encoding: "Test " + "User 1" + 13 05 54 65 73 74 20 + 13 06 55 73 65 72 20 31 + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + +Example: The DER encoding of the PrintableString value "Test +User 1" is + +13 0b 54 65 73 74 20 55 73 65 72 20 31 + + +5.12 SEQUENCE + +The SEQUENCE type denotes an ordered collection of one or +more types. + +The SEQUENCE type is used throughout PKCS and related +standards. + +ASN.1 notation: + +SEQUENCE { + [identifier1] Type1 [{OPTIONAL | DEFAULT value1}], + ..., + [identifiern] Typen [{OPTIONAL | DEFAULT valuen}]} + +where identifier1 , ..., identifiern are optional, distinct +identifiers for the components, Type1, ..., Typen are the +types of the components, and value1, ..., valuen are optional +default values for the components. The identifiers are +primarily for documentation; they do not affect values of +the type or their encodings in any way. + +The OPTIONAL qualifier indicates that the value of a +component is optional and need not be present in the +sequence. The DEFAULT qualifier also indicates that the +value of a component is optional, and assigns a default +value to the component when the component is absent. + +The types of any consecutive series of components with the +OPTIONAL or DEFAULT qualifier, as well as of any component +immediately following that series, must have distinct tags. +This requirement is typically satisfied with explicit or +implicit tagging on some of the components. + +Example: X.509's Validity type is a SEQUENCE type with two +components: + +Validity ::= SEQUENCE { + start UTCTime, + end UTCTime } + +Here the identifiers for the components are start and end, +and the types of the components are both UTCTime. + +BER encoding. Constructed. Contents octets are the +concatenation of the BER encodings of the values of the +components of the sequence, in order of definition, with the +following rules for components with the OPTIONAL and DEFAULT +qualifiers: + + o if the value of a component with the OPTIONAL or + DEFAULT qualifier is absent from the sequence, + then the encoding of that component is not + included in the contents octets + + o if the value of a component with the DEFAULT + qualifier is the default value, then the encoding + of that component may or may not be included in + the contents octets + +DER encoding. Constructed. Contents octets are the same as +the BER encoding, except that if the value of a component +with the DEFAULT qualifier is the default value, the +encoding of that component is not included in the contents +octets. + + +5.13 SEQUENCE OF + +The SEQUENCE OF type denotes an ordered collection of zero +or more occurrences of a given type. + +The SEQUENCE OF type is used in X.501 distinguished names. + +ASN.1 notation: + +SEQUENCE OF Type + +where Type is a type. + +Example: X.501's RDNSequence type consists of zero or more +occurences of the RelativeDistinguishedName type, most +significant occurrence first: + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +BER encoding. Constructed. Contents octets are the +concatenation of the BER encodings of the values of the +occurrences in the collection, in order of occurence. + +DER encoding. Constructed. Contents octets are the +concatenation of the DER encodings of the values of the +occurrences in the collection, in order of occurence. + + +5.14 SET + +The SET type denotes an unordered collection of one or more +types. + +The SET type is not used in PKCS. + +ASN.1 notation: + +SET { + [identifier1] Type1 [{OPTIONAL | DEFAULT value1}], + ..., + [identifiern] Typen [{OPTIONAL | DEFAULT valuen}]} + +where identifier1, ..., identifiern are optional, distinct +identifiers for the components, Type1, ..., Typen are the +types of the components, and value1, ..., valuen are +optional default values for the components. The identifiers +are primarily for documentation; they do not affect values +of the type or their encodings in any way. + +The OPTIONAL qualifier indicates that the value of a +component is optional and need not be present in the set. +The DEFAULT qualifier also indicates that the value of a +component is optional, and assigns a default value to the +component when the component is absent. + +The types must have distinct tags. This requirement is +typically satisfied with explicit or implicit tagging on +some of the components. + +BER encoding. Constructed. Contents octets are the +concatenation of the BER encodings of the values of the +components of the set, in any order, with the following +rules for components with the OPTIONAL and DEFAULT +qualifiers: + + o if the value of a component with the OPTIONAL or + DEFAULT qualifier is absent from the set, then the + encoding of that component is not included in the + contents octets + + o if the value of a component with the DEFAULT + qualifier is the default value, then the encoding + of that component may or may not be included in + the contents octets + +DER encoding. Constructed. Contents octets are the same as +for the BER encoding, except that: + + 1. If the value of a component with the DEFAULT + qualifier is the default value, the encoding of + that component is not included. + + 2. There is an order to the components, namely + ascending order by tag. + + +5.15 SET OF + +The SET OF type denotes an unordered collection of zero or +more occurrences of a given type. + +The SET OF type is used for sets of attributes in PKCS #6, +#7, #8, #9 and #10, for sets of message-digest algorithm +identifiers, signer information, and recipient information +in PKCS #7, and in X.501 distinguished names. + +ASN.1 notation: + +SET OF Type + +where Type is a type. + +Example: X.501's RelativeDistinguishedName type consists of +zero or more occurrences of the AttributeValueAssertion +type, where the order is unimportant: + +RelativeDistinguishedName ::= + SET OF AttributeValueAssertion + +BER encoding. Constructed. Contents octets are the +concatenation of the BER encodings of the values of the +occurrences in the collection, in any order. + +DER encoding. Constructed. Contents octets are the same as +for the BER encoding, except that there is an order, namely +ascending lexicographic order of BER encoding. Lexicographic +comparison of two different BER encodings is done as +follows: Logically pad the shorter BER encoding after the +last octet with dummy octets that are smaller in value than +any normal octet. Scan the BER encodings from left to right +until a difference is found. The smaller-valued BER encoding +is the one with the smaller-valued octet at the point of +difference. + + +5.16 T61String + +The T61String type denotes an arbtrary string of T.61 +characters. T.61 is an eight-bit extension to the ASCII +character set. Special "escape" sequences specify the +interpretation of subsequent character values as, for +example, Japanese; the initial interpretation is Latin. The +character set includes non-printing control characters. The +T61String type allows only the Latin and Japanese character +interepretations, and implementors' agreements for directory +names exclude control characters [NIST92]. A T61String value +can have any length, including zero. This type is a string +type. + +The T61String type is used in PKCS #9's unstructured-address +and challenge-password attributes, and in several X.521 +attributes. + +ASN.1 notation: + +T61String + +BER encoding. Primitive or constructed. In a primitive +encoding, the contents octets give the characters in the +T.61 string, encoded in ASCII. In a constructed encoding, +the contents octets give the concatenation of the BER +encodings of consecutive substrings of the T.61 string. + +Example: The BER encoding of the T61String value "cl'es +publiques" (French for "public keys") can be any of the +following, among others, depending on the form of length +octets and whether the encoding is primitive or constructed: + +14 0f DER encoding + 63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73 + +14 81 0f long form of length octets + 63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73 + +34 15 constructed encoding: "cl'es" + " " + "publiques" + 14 05 63 6c c2 65 73 + 14 01 20 + 14 09 70 75 62 6c 69 71 75 65 73 + +The eight-bit character c2 is a T.61 prefix that adds an +acute accent (') to the next character. + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + +Example: The DER encoding of the T61String value "cl'es +publiques" is + +14 0f 63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73 + + +5.17 UTCTime + +The UTCTime type denotes a "coordinated universal time" or +Greenwich Mean Time (GMT) value. A UTCTime value includes +the local time precise to either minutes or seconds, and an +offset from GMT in hours and minutes. It takes any of the +following forms: + +YYMMDDhhmmZ +YYMMDDhhmm+hh'mm' +YYMMDDhhmm-hh'mm' +YYMMDDhhmmssZ +YYMMDDhhmmss+hh'mm' +YYMMDDhhmmss-hh'mm' + +where: + + YY is the least significant two digits of the year + + MM is the month (01 to 12) + + DD is the day (01 to 31) + + hh is the hour (00 to 23) + + mm are the minutes (00 to 59) + + ss are the seconds (00 to 59) + + Z indicates that local time is GMT, + indicates that + local time is later than GMT, and - indicates that + local time is earlier than GMT + + hh' is the absolute value of the offset from GMT in + hours + + mm' is the absolute value of the offset from GMT in + minutes + +This type is a string type. + +The UTCTime type is used for signing times in PKCS #9's +signing-time attribute and for certificate validity periods +in X.509's Validity type. + +ASN.1 notation: + +UTCTime + +BER encoding. Primitive or constructed. In a primitive +encoding, the contents octets give the characters in the +string, encoded in ASCII. In a constructed encoding, the +contents octets give the concatenation of the BER encodings +of consecutive substrings of the string. (The constructed +encoding is not particularly interesting, since UTCTime +values are so short, but the constructed encoding is +permitted.) + +Example: The time this sentence was originally written was +4:45:40 p.m. Pacific Daylight Time on May 6, 1991, which can +be represented with either of the following UTCTime values, +among others: + +"910506164540-0700" + +"910506234540Z" + +These values have the following BER encodings, among others: + +17 0d 39 31 30 35 30 36 32 33 34 35 34 30 5a + +17 11 39 31 30 35 30 36 31 36 34 35 34 30 2D 30 37 30 + 30 + +DER encoding. Primitive. Contents octets are as for a +primitive BER encoding. + + +6. An example + +This section gives an example of ASN.1 notation and DER +encoding: the X.501 type Name. + + +6.1 Abstract notation + +This section gives the ASN.1 notation for the X.501 type +Name. + +Name ::= CHOICE { + RDNSequence } + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +RelativeDistinguishedName ::= + SET OF AttributeValueAssertion + +AttributeValueAssertion ::= SEQUENCE { + AttributeType, + AttributeValue } + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= ANY + +The Name type identifies an object in an X.500 directory. +Name is a CHOICE type consisting of one alternative: +RDNSequence. (Future revisions of X.500 may have other +alternatives.) + +The RDNSequence type gives a path through an X.500 directory +tree starting at the root. RDNSequence is a SEQUENCE OF type +consisting of zero or more occurences of +RelativeDistinguishedName. + +The RelativeDistinguishedName type gives a unique name to an +object relative to the object superior to it in the +directory tree. RelativeDistinguishedName is a SET OF type +consisting of zero or more occurrences of +AttributeValueAssertion. + +The AttributeValueAssertion type assigns a value to some +attribute of a relative distinguished name, such as country +name or common name. AttributeValueAssertion is a SEQUENCE +type consisting of two components, an AttributeType type and +an AttributeValue type. + +The AttributeType type identifies an attribute by object +identifier. The AttributeValue type gives an arbitrary +attribute value. The actual type of the attribute value is +determined by the attribute type. + + +6.2 DER encoding + +This section gives an example of a DER encoding of a value +of type Name, working from the bottom up. + +The name is that of the Test User 1 from the PKCS examples +[Kal93]. The name is represented by the following path: + + (root) + | + countryName = "US" + | + organizationName = "Example Organization" + | + commonName = "Test User 1" + +Each level corresponds to one RelativeDistinguishedName +value, each of which happens for this name to consist of one +AttributeValueAssertion value. The AttributeType value is +before the equals sign, and the AttributeValue value (a +printable string for the given attribute types) is after the +equals sign. + +The countryName, organizationName, and commonUnitName are +attribute types defined in X.520 as: + +attributeType OBJECT IDENTIFIER ::= + { joint-iso-ccitt(2) ds(5) 4 } + +countryName OBJECT IDENTIFIER ::= { attributeType 6 } +organizationName OBJECT IDENTIFIER ::= + { attributeType 10 } +commonUnitName OBJECT IDENTIFIER ::= + { attributeType 3 } + + +6.2.1 AttributeType + +The three AttributeType values are OCTET STRING values, so +their DER encoding follows the primitive, definite-length +method: + +06 03 55 04 06 countryName + +06 03 55 04 0a organizationName + +06 03 55 04 03 commonName + +The identifier octets follow the low-tag form, since the tag +is 6 for OBJECT IDENTIFIER. Bits 8 and 7 have value "0," +indicating universal class, and bit 6 has value "0," +indicating that the encoding is primitive. The length octets +follow the short form. The contents octets are the +concatenation of three octet strings derived from +subidentifiers (in decimal): 40 * 2 + 5 = 85 = 5516; 4; and +6, 10, or 3. + + +6.2.2 AttributeValue + +The three AttributeValue values are PrintableString values, +so their encodings follow the primitive, definite-length +method: + +13 02 55 53 "US" + +13 14 "Example Organization" + 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 + 74 69 6f 6e + +13 0b "Test User 1" + 54 65 73 74 20 55 73 65 72 20 31 + +The identifier octets follow the low-tag-number form, since +the tag for PrintableString, 19 (decimal), is between 0 and +30. Bits 8 and 7 have value "0" since PrintableString is in +the universal class. Bit 6 has value "0" since the encoding +is primitive. The length octets follow the short form, and +the contents octets are the ASCII representation of the +attribute value. + + +6.2.3 AttributeValueAssertion + +The three AttributeValueAssertion values are SEQUENCE +values, so their DER encodings follow the constructed, +definite-length method: + +30 09 countryName = "US" + 06 03 55 04 06 + 13 02 55 53 + +30 1b organizationName = "Example Organizaiton" + 06 03 55 04 0a + 13 14 ... 6f 6e + +30 12 commonName = "Test User 1" + 06 03 55 04 0b + 13 0b ... 20 31 + +The identifier octets follow the low-tag-number form, since +the tag for SEQUENCE, 16 (decimal), is between 0 and 30. +Bits 8 and 7 have value "0" since SEQUENCE is in the +universal class. Bit 6 has value "1" since the encoding is +constructed. The length octets follow the short form, and +the contents octets are the concatenation of the DER +encodings of the attributeType and attributeValue +components. + + +6.2.4 RelativeDistinguishedName + +The three RelativeDistinguishedName values are SET OF +values, so their DER encodings follow the constructed, +definite-length method: + +31 0b + 30 09 ... 55 53 + +31 1d + 30 1b ... 6f 6e + +31 14 + 30 12 ... 20 31 + +The identifier octets follow the low-tag-number form, since +the tag for SET OF, 17 (decimal), is between 0 and 30. Bits +8 and 7 have value "0" since SET OF is in the universal +class Bit 6 has value "1" since the encoding is constructed. +The lengths octets follow the short form, and the contents +octets are the DER encodings of the respective +AttributeValueAssertion values, since there is only one +value in each set. + + +6.2.5 RDNSequence + +The RDNSequence value is a SEQUENCE OF value, so its DER +encoding follows the constructed, definite-length method: + +30 42 + 31 0b ... 55 53 + 31 1d ... 6f 6e + 31 14 ... 20 31 + +The identifier octets follow the low-tag-number form, since +the tag for SEQUENCE OF, 16 (decimal), is between 0 and 30. +Bits 8 and 7 have value "0" since SEQUENCE OF is in the +universal class. Bit 6 has value "1" since the encoding is +constructed. The lengths octets follow the short form, and +the contents octets are the concatenation of the DER +encodings of the three RelativeDistinguishedName values, in +order of occurrence. + + +6.2.6 Name + +The Name value is a CHOICE value, so its DER encoding is the +same as that of the RDNSequence value: + +30 42 + 31 0b + 30 09 + 06 03 55 04 06 attributeType = countryName + 13 02 55 53 attributeValue = "US" + 31 1d + 30 1b + 06 03 55 04 0a attributeType = organizationName + 13 14 attributeValue = "Example Organization" + 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 + 74 69 6f 6e + + 31 14 + 30 12 + 06 03 55 04 03 attributeType = commonName + 13 0b attributeValue = "Test User 1" + 54 65 73 74 20 55 73 65 72 20 31 + + +References + +PKCS #1 RSA Laboratories. PKCS #1: RSA Encryption + Standard. Version 1.5, November 1993. + +PKCS #3 RSA Laboratories. PKCS #3: Diffie-Hellman Key- + Agreement Standard. Version 1.4, November 1993. + +PKCS #5 RSA Laboratories. PKCS #5: Password-Based + Encryption Standard. Version 1.5, November 1993. + +PKCS #6 RSA Laboratories. PKCS #6: Extended-Certificate + Syntax Standard. Version 1.5, November 1993. + +PKCS #7 RSA Laboratories. PKCS #7: Cryptographic Message + Syntax Standard. Version 1.5, November 1993. + +PKCS #8 RSA Laboratories. PKCS #8: Private-Key Information + Syntax Standard. Version 1.2, November 1993. + +PKCS #9 RSA Laboratories. PKCS #9: Selected Attribute + Types. Version 1.1, November 1993. + +PKCS #10 RSA Laboratories. PKCS #10: Certification Request + Syntax Standard. Version 1.0, November 1993. + +X.200 CCITT. Recommendation X.200: Reference Model of + Open Systems Interconnection for CCITT + Applications. 1984. + +X.208 CCITT. Recommendation X.208: Specification of + Abstract Syntax Notation One (ASN.1). 1988. + +X.209 CCITT. Recommendation X.209: Specification of + Basic Encoding Rules for Abstract Syntax Notation + One (ASN.1). 1988. + +X.500 CCITT. Recommendation X.500: The + Directory--Overview of Concepts, Models and + Services. 1988. + +X.501 CCITT. Recommendation X.501: The Directory-- + Models. 1988. + +X.509 CCITT. Recommendation X.509: The Directory-- + Authentication Framework. 1988. + +X.520 CCITT. Recommendation X.520: The Directory-- + Selected Attribute Types. 1988. + +[Kal93] Burton S. Kaliski Jr. Some Examples of the PKCS + Standards. RSA Laboratories, November 1993. + +[NIST92] NIST. Special Publication 500-202: Stable + Implementation Agreements for Open Systems + Interconnection Protocols. Part 11 (Directory + Services Protocols). December 1992. + + +Revision history + + +June 3, 1991 version + +The June 3, 1991 version is part of the initial public +release of PKCS. It was published as NIST/OSI Implementors' +Workshop document SEC-SIG-91-17. + + +November 1, 1993 version + +The November 1, 1993 version incorporates several editorial +changes, including the addition of a revision history. It is +updated to be consistent with the following versions of the +PKCS documents: + + PKCS #1: RSA Encryption Standard. Version 1.5, November + 1993. + + PKCS #3: Diffie-Hellman Key-Agreement Standard. Version + 1.4, November 1993. + + PKCS #5: Password-Based Encryption Standard. Version + 1.5, November 1993. + + PKCS #6: Extended-Certificate Syntax Standard. Version + 1.5, November 1993. + + PKCS #7: Cryptographic Message Syntax Standard. Version + 1.5, November 1993. + + PKCS #8: Private-Key Information Syntax Standard. + Version 1.2, November 1993. + + PKCS #9: Selected Attribute Types. Version 1.1, + November 1993. + + PKCS #10: Certification Request Syntax Standard. + Version 1.0, November 1993. + +The following substantive changes were made: + + Section 5: Description of T61String type is added. + + Section 6: Names are changed, consistent with other + PKCS examples. + + +Author's address + +Burton S. Kaliski Jr., Ph.D. +Chief Scientist +RSA Laboratories (415) 595-7703 +100 Marine Parkway (415) 595-4126 (fax) +Redwood City, CA 94065 USA burt@rsa.com diff --git a/doc/devel/guidelines b/doc/devel/guidelines new file mode 100644 index 0000000000..3f81652b0e --- /dev/null +++ b/doc/devel/guidelines @@ -0,0 +1,110 @@ +$OpenLDAP$ + +This document is being replaced with: + http://www.openldap.org/devel/programming.html +and + http://www.openldap.org/devel/contributing.html + +However, some of the info here is still useful. + +Coding guide lines and and hints for OpenLDAP developers. +========================================================= + +Please add to this file when new points come up. + + +C source +-------- + +OpenLDAP requires many Standard C features to *build*. This +includes functional prototypes and offsetof macro. It is +possible to *build* OpenLDAP with a number of C translators +which are not fully compliant with Standard C. + +OpenLDAP supports compiling and linking *with* applications +with most C compilers and libraries. The installed headers +are designed to provide K&R C compatiable function declarations +on non-standard compilers. In cases where the compiler does +not define __STDC__ but requires prototypes (ie: MSVC), the +application should define LDAP_NEEDS_PROTOTYPES. In cases +where the compiler does define __STDC__ but does not support +prototypes, the application should define LDAP_NO_PROTOTYPES. + +.c files in the OpenLDAP source tree MUST #include "portable.h" before +any other include file, even system includes. portable.h may control +aspects of system includes, such as whether or not thread-safe library +functions are used. (Separate applications can't use portable.h, since +it is not installed. They can use ldap_features.h, though.) + +.h files that are NOT INSTALLED may depend on features from portable.h. +.h files that *are* installed (from include/) should not depend on it. + +Avoid unnecessary changes, like reindenting code, even if that leaves +the code a little ugly. Often switching your editors tab stops to +4 or 8 may make code easier to read. Unnecessary changes make it +harder to maintain and merge different CVS branches of the source. + +Please follow the style of surrounding code. + +Use feature-specific #if tests (like #ifdef HAVE_LWP) which configure +can figure out, not system-specific test (like #ifdef __SunOS_5_6). + +When available, use include files from ldap/include/ac/ to get system +features or functions. The files try to fix crippled system +includes, and to hide #ifdef messes that portable programs need in order +to find a feature. Note that a file is not necessarily +designed to be equivalent to standard C's file. + +Nonstatic function and variable definitions in .c files should be +preceded by their declarations in .h files. Avoid implicit function +declarations. External declarations with should be avoided. In +.c files, include the appropriate .h file to obtain the declaration. +If the declaration is not available in any system header, add it +to the most appropriate ac/xxx.h header. Do NOT add extern +declarations to .c files. + +When a function returns non-void, it should return a meaningful value. +Avoid implicit int. + +It is recommended that ldap_cdef.h macros LDAP_F and LDAP_P be used +even for non-installed headers. See lber.h and ldap.h for examples. + + +CVS updating +------------ + + describes how to check out +-stable. To get the -devel (HEAD) branch, omit `-r OPENLDAP_STABLE'. +You can use 'cvs status -v README' to get a list available CVS tags. + +Core members should subscribe to the -core mailing list. This +list is for private discussions between core team members. The +openldap-devel@openldap.org mailing list is the primary developer +forum for both technical disscusions and coordinating efforts. + +Please test patches before committing. This should include compiling +and linking the system AND running the test suite. + +In general, a patch/bugfix should be applied to -devel and tested. +When the patch is considered stable, then it can be merged into -stable. +Same goes for other release engineering branches (like +OPENLDAP_REL_ENG_1_1). (-stable is rel eng 1.0). +Specific procjects may get their own branches, to be merged later. + +Log messages: Just describe the change and reason. CVS adds your name, +date, etc. + + +Various tips and hints +---------------------- + +How to correct a CVS log message: +Commit the unchanged files again with the `-f' flag and with a log +message stating how the previous log was in error: + cvs commit -f cldap.c os-ip.c +Preferably, prepend a line something like this to the message: +"Forced commit to correct previous log, files were not changed." + +Modify ldapconfig.h instead of ldapconfig.h.edit. Then `cvs commit' +from the include directory won't accidentally commit your private +ldapconfig.h.edit. diff --git a/doc/drafts/README b/doc/drafts/README index f6dfd9cbb3..cfe85242af 100644 --- a/doc/drafts/README +++ b/doc/drafts/README @@ -6,3 +6,11 @@ Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." + +OpenLDAP maintains copies of drafts for which we have and/or +are planning "experimental" implementations of. The I-D +found in this directory may be stale, expired, or otherwise +out of date. + +Please refer to http://www.ietf.org/ for latest revisions (and +status). diff --git a/doc/drafts/draft-good-ldap-ldif-xx.txt b/doc/drafts/draft-good-ldap-ldif-xx.txt index 56654338ee..86d5589c90 100644 --- a/doc/drafts/draft-good-ldap-ldif-xx.txt +++ b/doc/drafts/draft-good-ldap-ldif-xx.txt @@ -1,12 +1,9 @@ - - - LDAP Data Interchange Format (LDIF) Gordon Good INTERNET-DRAFT Netscape Communications - 22 February 1999 +Status: Standards-Track 19 October 1999 The LDAP Data Interchange Format (LDIF) - Technical Specification - Filename: draft-good-ldap-ldif-03.txt + Filename: draft-good-ldap-ldif-05.txt Status of this Memo @@ -27,7 +24,7 @@ Status of this Memo To view the list Internet-Draft Shadow Directories, see http://www.ietf.org/shadow.html. - This Internet Draft expires August 22nd, 1999. + This Internet Draft expires 19 April, 2000. Abstract @@ -52,14 +49,14 @@ Background and Intended Usage -Good February 22, 1999 [Page 1] +Good October 18, 1999 [Page 1] -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 of data import tools from legacy systems is facilitated. A fairly simple set of tools written in awk or perl can, for example, convert - a database of personnel information into an LDIF file. Thie file can + a database of personnel information into an LDIF file. This file can then be imported into a directory server, regardless of the internal database representation the target directory server uses. @@ -73,8 +70,8 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 The application/directory MIME content-type [1] is a general framework and format for conveying directory information, and is independent of any particular directory service. The LDIF format is - a simpler format which is perhaps easier to create, and also may also - be used, as noted, to describe a set of changes to be applied to a + a simpler format which is perhaps easier to create, and may also be + used, as noted, to describe a set of changes to be applied to a directory. The key words "MUST", "MAY", and "SHOULD" used in this document are @@ -92,9 +89,9 @@ Definition of the LDAP Data Interchange Format entry. An LDIF file specifies a set of directory entries, or a set of changes to be applied to directory entries, but not both. - There is a one-to-one correlation between LDAP operations which - modify the directory (add, delete, modify, and modrdn), and the types - of changerecords described below ("add", "delete", "modify", and + There is a one-to-one correlation between LDAP operations that modify + the directory (add, delete, modify, and modrdn), and the types of + changerecords described below ("add", "delete", "modify", and "modrdn" or "moddn"). This correspondence is intentional, and permits a straightforward translation from LDIF changerecords to protocol operations. @@ -102,84 +99,186 @@ Definition of the LDAP Data Interchange Format Formal Syntax Definition of LDIF The following definition uses the augmented Backus-Naur Form - specified in RFC 822 [2]. + specified in RFC 2234 [2]. + + ldif-file = ldif-content / ldif-changes + + + +Good October 18, 1999 [Page 2] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + ldif-content = version-spec 1*(1*SEP ldif-attrval-record) + + ldif-changes = version-spec 1*(1*SEP ldif-change-record) + + ldif-attrval-record = dn-spec SEP 1*attrval-spec + + ldif-change-record = dn-spec SEP *control changerecord + + version-spec = "version:" FILL version-number + + version-number = 1*DIGIT + ; version-number MUST be "1" for the + ; LDIF format described in this document. + + dn-spec = "dn:" (FILL distinguishedName / + ":" FILL base64-distinguishedName) + + distinguishedName = SAFE-UTF8-STRING + ; a distinguished name, as defined in [3] + + base64-distinguishedName = BASE64-UTF8-STRING + ; a distinguishedName which has been base64 + ; encoded (see note 10, below) + + rdn = SAFE-UTF8-STRING + ; a relative distinguished name, defined as + ; in [3] + + base64-rdn = BASE64-UTF8-STRING + ; an rdn which has been base64 encoded (see + ; note 10, below) + + control = "control:" FILL ldap-oid ; controlType + 0*1(1*SPACE ("true" / "false")) ; criticality + 0*1(value-spec) ; controlValue + SEP + ; (See note 9, below) + + ldap-oid = 1*DIGIT 0*1("." 1*DIGIT) + ; An LDAPOID, as defined in [4] + + attrval-spec = AttributeDescription value-spec SEP + + value-spec = ":" ( FILL 0*1(SAFE-STRING) / + ":" FILL (BASE64-STRING) / + "<" FILL url) + ; See notes 7 and 8, below + + - ldif-file = ldif-content / ldif-changes +Good October 18, 1999 [Page 3] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + url = + ; (See Note 6, below) + + AttributeDescription = AttributeType [";" options] + ; Definition taken from [4] + + AttributeType = ldap-oid / (ALPHA *(attr-type-chars)) + + options = option / (option ";" options) + + option = 1*opt-char + + attr-type-chars = ALPHA / DIGIT / "-" + + opt-char = attr-type-chars + + changerecord = "changetype:" FILL + (change-add / change-delete / + change-modify / change-moddn) + + change-add = "add" SEP 1*attrval-spec + + change-delete = "delete" SEP + + change-moddn = ("modrdn" / "moddn") SEP + "newrdn:" ( FILL rdn / + ":" FILL base64-rdn) SEP + "deleteoldrdn:" FILL ("0" / "1") SEP + 0*1("newsuperior:" + ( FILL distinguishedName / + ":" FILL base64-distinguishedName) SEP) + change-modify = "modify" SEP *mod-spec -Good February 22, 1999 [Page 2] + mod-spec = ("add:" / "delete:" / "replace:") + FILL AttributeDescription SEP + *attrval-spec + "-" SEP + + SPACE = %x20 + ; ASCII SP, space + + FILL = *SPACE + + SEP = (CR LF / LF) + + CR = %x0D + ; ASCII CR, carriage return + + + +Good October 18, 1999 [Page 4] -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - - ldif-content = version-spec 1*SEP - ldif-attrval-record *(1*SEP ldif-attrval-record) - ldif-changes = version-spec 1*SEP - ldif-change-record *(1*SEP ldif-change-record) - ldif-attrval-record = dn-spec SEP 1*(attrval-spec SEP) - ldif-change-record = dn-spec SEP 1*(changerecord SEP) - - version-spec = "version:" *SPACE version-number - version-number = 1*DIGIT ; version-number MUST be "1" for the - ; LDIF format described in this document. - - dn-spec = ("dn:" *SPACE dn) / ("dn::" *SPACE base64-dn) - dn = - base64-dn = - rdn = - base64-rdn = - - attrval-spec = attribute-description ((":") / (":" *SPACE value) / - ("::" *SPACE base64-value) / - (":<" *SPACE url)) - url = - ; (See Note 6, below) - attribute-description = - value = 1*safe-initval *safe - ; (See Note 9, below) - safe = - safe-initval = - base64-value = - - changerecord = change-add / change-delete / change-modify / - change-moddn - change-add = "changetype:" *SPACE "add" 1*(SEP attrval-spec) - change-delete = "changetype:" *SPACE "delete" - change-moddn = "changetype:" *SPACE ("modrdn" / "moddn") SEP - ("newrdn:" *SPACE rdn / - "newrdn::" *SPACE base-64-rdn) SEP - "deleteoldrdn:" *SPACE ("0" / "1") - 0,1*(SEP (("newsuperior:" *SPACE dn) / - ("newsuperior::" *SPACE base-64-dn))) - change-modify = "changetype:" *SPACE "modify" 1*(SEP mod-spec) - mod-spec = mod-add-spec / mod-delete-spec / mod-replace-spec - - - -Good February 22, 1999 [Page 3] +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + LF = %x0A + ; ASCII LF, line feed + + ALPHA = %x41-5A / %x61-7A + ; A-Z / a-z + + DIGIT = %x30-39 + ; 0-9 + + UTF8-1 = %x80-BF + + UTF8-2 = %xC0-DF UTF8-1 + + UTF8-3 = %xE0-EF 2UTF8-1 + + UTF8-4 = %xF0-F7 3UTF8-1 + + UTF8-5 = %xF8-FB 4UTF8-1 + + UTF8-6 = %xFC-FD 5UTF8-1 + + SAFE-CHAR = %x01-09 / %x0B-0C / %x0E-7F + ; any value <= 127 decimal except NUL, LF, and CR + + SAFE-INIT-CHAR = %x01-09 / %x0B-0C / %x0E-1F / + %x21-39 / %x3B / %x3D-7F + ; any value <= 127 except NUL, LF, CR, + ; SPACE, colon (":", ASCII 58 decimal) + ; and less-than ("<" , ASCII 60 decimal) + + SAFE-STRING = [SAFE-INIT-CHAR *SAFE-CHAR] + + SAFE-UTF8-CHAR = SAFE-CHAR / UTF8-2 / UTF8-3 / + UTF8-4 / UTF8-5 / UTF8-6 + + SAFE-INIT-UTF8-CHAR = SAFE-INIT-CHAR / UTF8-2 / UTF8-3 / + UTF8-4 / UTF8-5 / UTF8-6 + + SAFE-UTF8-STRING = [SAFE-INIT-UTF8-CHAR *SAFE-UTF8-CHAR] + + BASE64-UTF8-STRING = BASE64-STRING + ; MUST be the base64 encoding of a valid + ; string of UTF-8 characters + + BASE64-CHAR = %x2B / %x2F / %x30-39 / %x3D / %x41-5A / %x61-7A + ; +, /, 0-9, =, A-Z, and a-z + ; as specified in [5] + + + + +Good October 18, 1999 [Page 5] -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 - mod-add-spec = "add:" *SPACE attribute-description - 1*(SEP attrval-spec) SEP "-" - mod-delete-spec = "delete:" *SPACE attribute-description - *(SEP attrval-spec) SEP "-" - mod-replace-spec = "replace:" *SPACE attribute-description - *(SEP attrval-spec) SEP "-" - SPACE = - SEP = (CR LF / LF) - CR = - LF = - DIGIT = + BASE64-STRING = [*(BASE64-CHAR)] Notes on LDIF Syntax @@ -189,23 +288,32 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 choose to interpret the contents as an older LDIF file format, supported by the University of Michigan ldap-3.3 implementation [8]. - 2) Any line, including comment lines, in an LDIF file MAY be wrapped - by inserting a line separator (SEP) and a SPACE. Any line which - begins with a single space MUST be treated as a continuation of the - previous line. When joining folded lines, exactly one space character - at the beginning of each continued line must be discarded. - - 3) Any line which begins with a pound-sign ("#", ASCII 35) is a + 2) Any non-empty line, including comment lines, in an LDIF file MAY + be folded by inserting a line separator (SEP) and a SPACE. Folding + MUST NOT occur before the first character of the line. In other + words, folding a line into two lines, the first of which is empty, is + not permitted. Any line that begins with a single space MUST be + treated as a continuation of the previous (non-empty) line. When + joining folded lines, exactly one space character at the beginning of + each continued line must be discarded. Implementations SHOULD NOT + fold lines in the middle of a multi-byte UTF-8 character. + + 3) Any line that begins with a pound-sign ("#", ASCII 35) is a comment line, and MUST be ignored when parsing an LDIF file. - 4) Any dn or value which contains characters other than those defined - as "safe", or begins with a character other than those defined as - "safe-initval", above, MUST be base-64 encoded. Other values MAY be - base-64 encoded. + 4) Any dn or rdn that contains characters other than those defined as + "SAFE-UTF8-CHAR", or begins with a character other than those defined + as "SAFE-INIT-UTF8-CHAR", above, MUST be base-64 encoded. Other + values MAY be base-64 encoded. Any value that contains characters + other than those defined as "SAFE-CHAR", or begins with a character + other than those defined as "SAFE-INIT-CHAR", above, MUST be base-64 + encoded. Other values MAY be base-64 encoded. - 5) To represent a zero-length attribute value, use an attrval-spec of - "attribute-description:". For example, "seeAlso:" represents a - zero-length "seeAlso" attribute value. + 5) When a zero-length attribute value is to be included directly in + an LDIF file, it MUST be represented as AttributeDescription ":" FILL + SEP. For example, "seeAlso:" followed by a newline represents a + zero-length "seeAlso" attribute value. It is also permissible for + the value referred to by a URL to be of zero length. 6) When a URL is specified in an attrval-spec, the following conventions apply: @@ -216,28 +324,41 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 associated with each supported URL will be documented in an associated Applicability Statement. - 7) While it is permissible for character values larger than 126 to be + 7) Distinguished names, relative distinguished names, and attribute + values of DirectoryString syntax MUST be valid UTF-8 strings. -Good February 22, 1999 [Page 4] +Good October 18, 1999 [Page 6] -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - - contained in an attribute value, implementations SHOULD base-64 - encode any value which contains such characters when generating LDIF. - However, implementations MAY leave the values unencoded. This - relaxation is designed to allow editing of LDIF files containing - UTF-8 data. - - 8) Attribute values contained in LDIF files represent directory data, - and therefore MUST be valid UTF-8 strings. Implementations which read - LDIF MAY interpret files in which the values are stored in some other - character set encoding, but implementations MUST NOT generate LDIF - content which does not contain valid UTF-8 data. - - 9) Values that end with SPACE SHOULD be base-64 encoded. +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + Implementations that read LDIF MAY interpret files in which these + entities are stored in some other character set encoding, but + implementations MUST NOT generate LDIF content which does not contain + valid UTF-8 data. + + 8) Values or distinguished names that end with SPACE SHOULD be base- + 64 encoded. + + 9) When controls are included in an LDIF file, implementations MAY + choose to ignore some or all of them. This may be necessary if the + changes described in the LDIF file are being sent on an LDAPv2 + connection (LDAPv2 does not support controls), or the particular + controls are not supported by the remote server. If the criticality + of a control is "true", then the implementation MUST either include + the control, or MUST NOT send the operation to a remote server. + + 10) When an attrval-spec, distinguishedName, or rdn is base64- + encoded, the encoding rules specified in [5] are used with the + following exceptions: a) The requirement that base64 output streams + must be represented as lines of no more than 76 characters is + removed. Lines in LDIF files may only be folded according to the + folding rules described in note 2, above. b) Base64 strings in [5] + may contain characters other than those defined in BASE64-CHAR, and + are ignored. LDIF does not permit any extraneous characters, other + than those used for line folding. Examples of LDAP Data Interchange Format @@ -261,6 +382,14 @@ Examples of LDAP Data Interchange Format objectclass: top objectclass: person objectclass: organizationalPerson + + + +Good October 18, 1999 [Page 7] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + cn: Bjorn Jensen sn: Jensen telephonenumber: +1 408 555 1212 @@ -273,21 +402,13 @@ Examples of LDAP Data Interchange Format objectclass:person objectclass:organizationalPerson cn:Barbara Jensen - - - -Good February 22, 1999 [Page 5] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - cn:Barbara J Jensen cn:Babs Jensen sn:Jensen uid:bjensen telephonenumber:+1 408 555 1212 - description:Babs is a big sailing fan, and travels extensively in search of - perfect sailing conditions. + description:Babs is a big sailing fan, and travels extensively in sea + rch of perfect sailing conditions. title:Product Manager, Rod and Reel Division Example 3: A file containing a base-64-encoded value @@ -317,6 +438,14 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 objectclass: organizationalUnit ou:: 5Za25qWt6YOo # ou:: + + + +Good October 18, 1999 [Page 8] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + ou;lang-ja:: 5Za25qWt6YOo # ou;lang-ja:: ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2 @@ -329,14 +458,6 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM= objectclass: top objectclass: person - - - -Good February 22, 1999 [Page 6] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - objectclass: organizationalPerson objectclass: inetOrgPerson uid: rogasawara @@ -374,6 +495,13 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 Example 5: A file containing a reference to an external file + + +Good October 18, 1999 [Page 9] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + version: 1 dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com objectclass: top @@ -386,13 +514,6 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 telephonenumber: +1 408 555 1212 jpegphoto:< file:///usr/local/directory/photos/hjensen.jpg - - -Good February 22, 1999 [Page 7] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - Example 6: A file containing a series of change records and comments version: 1 @@ -429,6 +550,14 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 # Modify an entry: add an additional value to the postaladdress attribute, # completely delete the description attribute, replace the telephonenumber # attribute with two values, and delete a specific value from the + + + +Good October 18, 1999 [Page 10] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + # facsimiletelephonenumber attribute dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com changetype: modify @@ -441,18 +570,32 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 telephonenumber: +1 408 555 1234 telephonenumber: +1 408 555 5678 - - - - -Good February 22, 1999 [Page 8] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - delete: facsimiletelephonenumber facsimiletelephonenumber: +1 408 555 9876 - + # Modify an entry: replace the postaladdress attribute with an empty + # set of values (which will cause the attribute to be removed), and + # delete the entire description attribute. Note that the first will + # always succeed, while the second will only succeed if at least + # one value for the description attribute is present. + dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com + changetype: modify + replace: postaladdress + - + delete: description + - + + Example 7: An LDIF file containing a change record with a control + version: 1 + # Delete an entry. The operation will attach the LDAPv3 + # Tree Delete Control defined in [9]. The criticality + # field is "true" and the controlValue field is + # absent, as required by [9]. + dn: ou=Product Development, dc=airius, dc=com + control: 1.2.840.113556.1.4.805 true + changetype: delete + Security Considerations @@ -463,6 +606,14 @@ Security Considerations Since ":<" directives can cause external content to be included when processing an LDIF file, one should be cautious of accepting LDIF + + + +Good October 18, 1999 [Page 11] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + files from external sources. A "trojan" LDIF file could name a file with sensitive contents and cause it to be included in a directory entry, which a hostile entity could read via LDAP. @@ -497,14 +648,6 @@ Appendix A: Differences from previous versions of this document ldif-02.txt 1) The BNF has been modified such that a simple attribute name - - - -Good February 22, 1999 [Page 9] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - ("attrname") has been replaced with an "attribute-description" as defined in the LDAPv3 protocol document [4]. This permits language codes and other attribute options to be carried in an LDIF file. @@ -520,9 +663,16 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 Differences between draft-ietf-asid-ldif-02.txt and draft-good-ldap- ldif-00.txt + + +Good October 18, 1999 [Page 12] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + 1) The "charset-option" and "charset-name" productions were removed from the BNF, due to objections within the working group. UTF-8 is - the only character set which may be used in LDIF. + the only character set that may be used in LDIF. 2) Examples were reworked to reflect the above change, and to include an example of a non-western language represented in UTF-8. @@ -532,9 +682,9 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 1) Added version identifiers to the examples - they were missing. - 2) Clarified that LDIF file must use UTF-8. + 2) Clarified that LDIF files must use UTF-8. - Differences between draft-ietf-good-ldif-01.txt and draft-good-ldap- + Differences between draft-good-ldap-ldif-01.txt and draft-good-ldap- ldif-02.txt 1) Added a recommendation that values ending in SPACE should be @@ -544,7 +694,7 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 3) Updated header to reflect new IETF I-D guidelines. - Differences between draft-ietf-good-ldif-02.txt and draft-good-ldap- + Differences between draft-good-ldap-ldif-02.txt and draft-good-ldap- ldif-03.txt 1) Fixed reference from RFC 1779 to RFC 2253. @@ -554,13 +704,6 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 3) Comment lines may be folded (this is now explicitly mentioned in note 2). - - -Good February 22, 1999 [Page 10] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 - - 4) Moved this section (differences between draft versions) to an appendix. @@ -569,6 +712,87 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 6) Cleaned up references section. + Differences between draft-good-ldap-ldif-03.txt and draft-good-ldap- + ldif-04.txt + + 1) The grammar now requires that an LDIF file end with one or more + SEP sequences (newlines). This was inadvertently prohibited in + earlier revisions of the grammar. + + + +Good October 18, 1999 [Page 13] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + 2) Several minor spelling and typographical errors were fixed. + + 3) Reworked the grammar to make it more readable. Hallvard Furuseth + (University of Oslo) provided the new BNF. + + 4) Excluded NUL from "safe" production. + + 5) Changed "0,1*xxx" "0*1xxx" in compliance with RFC822. + + 6) Fixed a glitch in the grammar that allowed multiple changetypes + within a single LDIF change record. The intent is that only one + changetype per change record is permitted. + + 7) Fixed a mistake in example 2 (folded attribute value). + + 8) The BNF now explicitly requires that zero-length attribute values + be encoded as attribute-description ":" FILL SEP. + + 9) Factored "changetype: FILL" out of the productions for change-add, + change-delete, change-moddn, and change-modify. + + 10) RFC 2251 permits an LDAP modify operation with no modifications, + and also permits an attribute with no values. Although it's unclear + what the purpose of these constructs might be, I altered the BNF to + allow these to be described in LDIF. + + 11) The BNF may now carry LDAP v3 controls in ldif-change-records. + The "value-spec" production was factored out to allow it to be used + in the definition of a control. + + 12) Clarified the rules for line-folding to prohibit a line from + being folded into two lines, the first of which is empty. This + guarantees that the sequence SEP SEP terminates an LDIF record, and + allows, for example, "perl -n00" to be used to read an entire LDIF + record into the $_ variable. + + Differences between draft-good-ldap-ldif-04.txt and draft-good-ldap- + ldif-05.txt + + 1) The grammar has been rewritten to use the RFC2234 ABNF, replacing + the RFC822 ABNF. + + 2) The grammar makes fewer uses of . + + 3) DNs, RDNs, and attribute values with DirectoryString are now + explicitly called out as UTF-8 strings. + + 4) An error in the BNF for "control" was fixed. + + + +Good October 18, 1999 [Page 14] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 + + + 5) An additional ldif-change-record was added to example 6. + + 6) Since RFC 1521 defines base-64 encoding with different folding + rules, and permits illegal characters (which should be ignored), an + explanatory note has been added. This note explains that lines must + be folded according to LDIF rules, not RFC 1521 rules, and that + extraneous characters are not permitted. + + 7) DNs, values, and rdns containing octets > 127 must be base-64 + encoded. + Acknowledgments @@ -578,6 +802,10 @@ Acknowledgments supported by the National Science Foundation under Grant No. NCR- 9416667. + Members of the IETF LDAP Extensions Working group provided many + helpful suggestions. In particular, Hallvard B. Furuseth of the + University of Oslo made many significant contributions to this + document, including a thorough review and rewrite of the BNF. References @@ -586,9 +814,9 @@ References mation", RFC 2425, September 1998, - [2] Crocker, D.H., "Standard for the Format of ARPA Internet Text - Messages", RFC 822, August 1982, - + [2] Crocker, D., Overell, P., "Augmented BNF for Syntax Specifica- + tions: ABNF" , RFC 2234, November 1997, + [3] Wahl, M., Kille, S., Howes, T., "A String Representation of Dis- tinguished Names", RFC 2253, @@ -602,21 +830,21 @@ References Extensions) Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies", section 5.2, "Base64 Content-Transfer-Encoding", RFC 1521, December 1993, - - [6] T. Berners-Lee, L. Masinter, M. McCahill, "Uniform Resource - Locators (URL)", RFC 1738, December 1994, - - [7] S. Bradner, "Key Words for use in RFCs to Indicate Requirement +Good October 18, 1999 [Page 15] + +INTERNET-DRAFT LDAP Data Interchange Format 19 October 1999 -Good February 22, 1999 [Page 11] - -INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 + + [6] T. Berners-Lee, L. Masinter, M. McCahill, "Uniform Resource + Locators (URL)", RFC 1738, December 1994, + + [7] S. Bradner, "Key Words for use in RFCs to Indicate Requirement Levels", Harvard University, RFC 2119, March 1997, @@ -624,6 +852,11 @@ INTERNET-DRAFT LDAP Data Interchange Format 22 February 1999 gan, April 1996. + [9] M. P. Armijo, "Tree Delete Control", Microsoft Corporation, + INTERNET-DRAFT June 1999, + + Author's Address @@ -636,7 +869,7 @@ Author's Address Phone: +1 650 937-3825 EMail: ggood@netscape.com - This Internet Draft expires August 22nd, 1999. + This Internet Draft expires 19 April, 2000. @@ -656,17 +889,5 @@ Author's Address - - - - - - - - - - - - -Good February 22, 1999 [Page 12] - +Good October 18, 1999 [Page 16] + \ No newline at end of file diff --git a/doc/drafts/draft-ietf-asid-ldapv3-attributes-03.txt b/doc/drafts/draft-ietf-asid-ldapv3-attributes-03.txt new file mode 100644 index 0000000000..d622f7e563 --- /dev/null +++ b/doc/drafts/draft-ietf-asid-ldapv3-attributes-03.txt @@ -0,0 +1,2261 @@ + +Network Working Group M. Wahl +INTERNET-DRAFT Critical Angle Inc. +Obsoletes: RFC 1778 A. Coulbeck + ISODE Consortium + T. Howes + Netscape Communications Corp. + S. Kille + ISODE Consortium +Intended Category: Standards Track October 22, 1996 + + + Lightweight Directory Access Protocol: + Standard and Pilot Attribute Definitions + + +1. Status of this Memo + + This document is an Internet-Draft. Internet-Drafts are working + documents of the Internet Engineering Task Force (IETF), its areas, and + its working groups. Note that other groups may also distribute working + documents as Internet-Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference material + or to cite them other than as "work in progress." + + To learn the current status of any Internet-Draft, please check the + "1id-abstracts.txt" listing contained in the Internet-Drafts Shadow + Directories on ds.internic.net (US East Coast), nic.nordu.net (Europe), + ftp.isi.edu (US West Coast), or munnari.oz.au (Pacific Rim). + +2. Abstract + + The Lightweight Directory Access Protocol (LDAP) [1] requires that the + contents of AttributeValue fields in protocol elements be octet + strings. This document defines the requirements that must be + satisfied by encoding rules used to render directory attribute + syntaxes into a form suitable for use in the LDAP, then goes on to + define the encoding rules for the standard set of attribute syntaxes + of [2],[3] and [4]. It also identifies all the attribute types, object + classes and matching rules for LDAP version 3. + +3. Overview + + Section 4 states the general requirements and notations for attribute + types, object classes, syntax and matching rule definitions. + + The core definitions are given in section 5, those which are based on + X.500(1993) in section 6, and other optional definitions in section 7. + + + + + +Wahl, Coulbeck, Howes & Kille [Page 1] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +4. General Issues + +4.1. Attribute Types + + The attribute types are described by sample values for the subschema + "attributeTypes" attribute, which is written in the + AttributeTypeDescription syntax. While lines have been folded for + readability, the values transferred in protocol would not contain + newlines. + + The AttributeTypeDescription is encoded according to the following BNF, + and the productions for , and + are given in sections 4.2.1. + + ::= "(" + -- AttributeType identifier + [ "NAME" ] -- name used in AttributeType + [ "DESC" ] + [ "OBSOLETE" ] + [ "SUP" ] -- derived from this other AttributeType + [ "EQUALITY" ] -- Matching Rule name + [ "ORDERING" ] -- Matching Rule name + [ "SUBSTR" ] -- Matching Rule name + [ "SYNTAX" ] -- see section 4.2 + [ "SINGLE-VALUE" ] -- default multi-valued + [ "COLLECTIVE" ] -- default not collective + [ "NO-USER-MODIFICATION" ] -- default user modifiable + [ "USAGE" ] -- default user applications + ")" + + ::= + "userApplications" + | "directoryOperation" + | "distributedOperation" -- DSA-shared + | "dSAOperation" -- DSA-specific, value depends on server + + Servers are not required to provide the same or any text + in the description part of the subschema values they maintain. + + Servers must implement all the attribute types in section 5.1, and + may also implement the types listed in sections 6.1 and 7.1. Servers must + be able to perform equality matching of values, but need not perform + any additional validity checks on attribute values. + + Servers may recognize additional names and attributes not listed in this + document. Later documents may define additional types. + + Servers may implement additional attribute types not listed in this + document, and if they do so, must publish the definitions of the types + in the attributeTypes attribute of their subschema subentries. + + AttributeDescriptions may be used as the value in a NAME part of an + AttributeTypeDescription. Note that these are case insensitive. + +Wahl, Coulbeck, Howes & Kille [Page 2] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +4.2. Syntaxes + + This section defines general requirements for LDAP attribute value + syntax encodings. All documents defining attribute syntax encodings for + use with LDAP are expected to conform to these requirements. + + The encoding rules defined for a given attribute syntax must produce + octet strings. To the greatest extent possible, encoded octet + strings should be usable in their native encoded form for display + purposes. In particular, encoding rules for attribute syntaxes + defining non-binary values should produce strings that can be + displayed with little or no translation by clients implementing + LDAP. There are a few cases (e.g. Audio) however, when it is not sensible + to produce a printable representation, and clients must not assume that + an unrecognized syntax is a string representation. + +4.2.1. Common Encoding Aspects + + In these encodings where an arbitrary string is used as part of a larger + production (other than a Distinguished Name), a backslash quoting mechanism + is used to encode the following separator symbol character (such as ''', + '$' or '#') if it should occur in that string. The backslash is followed + by a pair of hexadecimal digits representing the next character. A + backslash itself in the string which forms part of a larger syntax is + always transmitted as '\5C' or '\5c'. + + For the purposes of defining the encoding rules for attribute syntaxes, + the following auxiliary BNF definitions will be used: + + ::= 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | + 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | + 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | + 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | + 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | + 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' + + ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + + ::= | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | + 'A' | 'B' | 'C' | 'D' | 'E' | 'F' + + ::= | | '-' + +

::= | | ''' | '(' | ')' | '+' | ',' | '-' | '.' | + '/' | ':' | '?' | ' ' + + ::= | + + ::= | + + ::= | + + ::= | + +Wahl, Coulbeck, Howes & Kille [Page 3] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ::=

|

+ + ::= ' ' | ' ' + + ::= | empty + + ::= any sequence of octets formed from the UTF-8 [11] + transformation of a character from ISO 10646 [12] + + ::= | + + ::= | '(' ')' + + ::= | "" + + ::= ''' ''' + + ::= | '(' ')' + + ::= '$' | + + -- is defined in 5.2.1.15 + +4.2.2 Binary Transfer of Values + + This encoding format is used if the binary encoding is requested by the + client for an attribute, or if the attribute syntax name is 'Binary'. The + value, an instance of the ASN.1 AttributeValue type, is BER-encoded, + subject to the restrictions of section 5.1 of [1], and this sequence of + octets is used as the value. + + All servers must implement this form for both generating Search responses + and parsing Add, Compare and Modify requests. Clients must be prepared + receiving values in binary (e.g. userCertificate or audio), and must not + simply display binary or unrecognized values to users. + +4.2.3. Syntax Namees + + Names of syntaxes for use with LDAP are ASCII strings which either + begin with a letter and contain only letters or digits. The names are + case insensitive. Historically since syntaxes correspond to ASN.1 types, + they have been named starting with a capital letter. A suggested upper + bound on the number of characters in value with a DirectoryString or + IA5String syntax or the number of bytes in a value for all other syntaxes + may be indicated by appending this bound count inside of curly braces, e.g. + "DirectoryString{64}". Note that a single character of the DirectoryString + may be encoded in more than one byte since UTF-8 is a variable-length + encoding. + + Syntax names do not have global scope: two clients or servers may + know of different syntaxes with the same name. + + + +Wahl, Coulbeck, Howes & Kille [Page 4] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + The definition of additional arbitrary syntaxes is strongly depreciated + since it will hinder interoperability: today's client and server + implementations generally do not have the ability to dynamically recognize + new syntaxes. In most cases attributes will be defined with the + DirectoryString syntax. + + The following syntax names are used for attributes in this document. + Servers are only required to implement the syntaxes in section 5.2. + + AccessPoint ACIItem + AttributeTypeDescription Audio + Binary BitString + Certificate CertificateList + CertificatePair DataQualitySyntax + DeliveryMethod DirectoryString + DITContentRuleDescription DN + DSAQualitySyntax DSEType + EnhancedGuide FacsimileTelephoneNumber + Fax GeneralizedTime + Guide IA5String + INTEGER JPEG + MailPreference MasterAndShadowAccessPoints + MatchingRuleDescription MatchingRuleUseDescription + ModifyRight NameAndOptionalUID + NameFormDescription NumericString + ObjectClassDescription OID + OtherMailbox Password + PostalAddress PresentationAddress + PrintableString ProtocolInformation + SubtreeSpecification SupplierAndConsumers + SupplierInformation SupplierOrConsumer + TelephoneNumber TeletexTerminalIdentifier + TelexNumber UTCTime + +4.3. Object Classes + + These are described as sample values for the subschema "objectClasses" + attribute for a server which implements the LDAP schema. + While lines have been folded for readability, the values transferred in + protocol would not contain newlines. + + Object class descriptions are written according to the following BNF: + + ::= "(" + -- ObjectClass identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + [ "SUP" ] -- Superior ObjectClasses + [ ( "ABSTRACT" | "STRUCTURAL" | "AUXILIARY" ) ] -- default structural + [ "MUST" ] -- AttributeTypes + [ "MAY" ] -- AttributeTypes + ")" + +Wahl, Coulbeck, Howes & Kille [Page 5] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + Servers must implement all the object classes in section 5.3: + account alias + applicationEntity applicationProcess + certificationAuthority country + dNSDomain dSA + device document + documentSeries domain + domainRelatedObject friendlyCountry + groupOfNames groupOfUniqueNames + locality newPilotPerson + organization organizationalPerson + organizationalRole organizationalUnit + person pilotDSA + pilotObject pilotOrganization + qualityLabelledData rFC822localPart + residentialPerson room + simpleSecurityObject strongAuthenticationUser + top + + and may also implement the object classes of 6.3 and 7.3. + + Servers may implement additional object classes not listed in this + document, and if they do so, must publish the definitions of the classes + in the objectClasses attribute of their subschema subentries. Later + documents may define additional object classes. + +4.4. Matching Rules + + Matching rules are used by servers to compare attribute values against + assertion values when performing Search and Compare operations. + + Most of the attributes given in this document will have an equality + matching rule defined. + + Matching rule descriptions are written according to the following BNF: + + ::= "(" + -- MatchingRule identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + "SYNTAX" + ")" + + Servers must implement all the matching rules in section 5.4: + bitStringMatch caseExactIA5Match + caseIgnoreIA5Match caseIgnoreListMatch + caseIgnoreMatch distinguishedNameMatch + generalizedTimeMatch integerMatch + numericStringMatch objectIdentifierMatch + octetStringMatch telephoneNumberMatch + + and may also implement the matching rules of 6.4 and 7.4. + +Wahl, Coulbeck, Howes & Kille [Page 6] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + Servers may implement additional matching rules not listed in this + document, and if they do so, must publish the definitions of the + matching rules in the matchingRules attribute of their + subschema subentries. + +5. Mandatory Definitions + + Section 5 contains definitions which must be implemented by all servers. + + +5.1. Attribute Types + + Servers must recognize all the attributes of this section (5.1.1 - 5.1.5). + +5.1.1. Standard User Attributes + + The attributes listed in this section are those defined in X.520(1993), + likely to be present in user entries. Servers must recognize all the + attributes of this section. The semantics of attributes 2.5.4.0 through + 2.5.4.40 are summarized in RFC 1274. + + ( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch SYNTAX 'OID' ) + + ( 2.5.4.1 NAME 'aliasedObjectName' EQUALITY distinguishedNameMatch + SYNTAX 'DN' SINGLE-VALUE ) + + ( 2.5.4.2 NAME 'knowledgeInformation' EQUALITY caseIgnoreMatch + SYNTAX 'DirectoryString{32768}' ) + + ( 2.5.4.3 NAME 'cn' SUP name ) + + ( 2.5.4.4 NAME 'sn' SUP name ) + + ( 2.5.4.5 NAME 'serialNumber' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'PrintableString{64}' ) + + ( 2.5.4.6 NAME 'c' SUP name SINGLE-VALUE ) + + ( 2.5.4.7 NAME 'l' SUP name ) + + ( 2.5.4.8 NAME 'st' SUP name ) + + ( 2.5.4.9 NAME 'street' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{128}' ) + + ( 2.5.4.10 NAME 'o' SUP name ) + + ( 2.5.4.11 NAME 'ou' SUP name ) + + ( 2.5.4.12 NAME 'title' SUP name ) + + ( 2.5.4.13 NAME 'description' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{1024}' ) + +Wahl, Coulbeck, Howes & Kille [Page 7] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.4.14 NAME 'searchGuide' SYNTAX 'Guide' ) + + ( 2.5.4.15 NAME 'businessCategory' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{128}' ) + + ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch + SUBSTRINGS caseIgnoreListSubstringsMatch SYNTAX 'PostalAddress' ) + + ( 2.5.4.17 NAME 'postalCode' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{40}' ) + + ( 2.5.4.18 NAME 'postOfficeBox' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{40}' ) + + ( 2.5.4.19 NAME 'physicalDeliveryOfficeName' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{128}' ) + + ( 2.5.4.20 NAME 'telephoneNumber' EQUALITY telephoneNumberMatch + SUBSTRINGS telephoneNumberSubstringsMatch SYNTAX 'TelephoneNumber{32}' ) + + ( 2.5.4.21 NAME 'telexNumber' SYNTAX 'TelexNumber' ) + + ( 2.5.4.22 NAME 'teletexTerminalIdentifier' + SYNTAX 'TeletexTerminalIdentifier' ) + + ( 2.5.4.23 NAME 'facsimileTelephoneNumber' + SYNTAX 'FacsimileTelephoneNumber' ) + + ( 2.5.4.24 NAME 'x121Address' EQUALITY numericStringMatch + SUBSTRINGS numericStringSubstringsMatch SYNTAX 'NumericString{15}' ) + + ( 2.5.4.25 NAME 'internationaliSDNNumber' EQUALITY numericStringMatch + SUBSTRINGS numericStringSubstringsMatch SYNTAX 'NumericString{16}' ) + + ( 2.5.4.26 NAME 'registeredAddress' SUP postalAddress + SYNTAX 'PostalAddress' ) + + ( 2.5.4.27 NAME 'destinationIndicator' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'PrintableString{128}' ) + + ( 2.5.4.28 NAME 'preferredDeliveryMethod' SYNTAX 'DeliveryMethod' + SINGLE-VALUE ) + + ( 2.5.4.29 NAME 'presentationAddress' EQUALITY presentationAddressMatch + SYNTAX 'PresentationAddress' SINGLE-VALUE ) + + ( 2.5.4.30 NAME 'supportedApplicationContext' + EQUALITY objectIdentifierMatch SYNTAX 'OID' ) + + ( 2.5.4.31 NAME 'member' SUP distinguishedName ) + + ( 2.5.4.32 NAME 'owner' SUP distinguishedName ) + + +Wahl, Coulbeck, Howes & Kille [Page 8] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.4.33 NAME 'roleOccupant' SUP distinguishedName ) + + ( 2.5.4.34 NAME 'seeAlso' SUP distinguishedName ) + + ( 2.5.4.35 NAME 'userPassword' EQUALITY octetStringMatch + SYNTAX 'Password{128}' ) + + ( 2.5.4.36 NAME 'userCertificate' SYNTAX 'Certificate' ) + + ( 2.5.4.37 NAME 'cACertificate' SYNTAX 'Certificate' ) + + ( 2.5.4.38 NAME 'authorityRevocationList' SYNTAX 'CertificateList' ) + + ( 2.5.4.39 NAME 'certificateRevocationList' SYNTAX 'CertificateList' ) + + ( 2.5.4.40 NAME 'crossCertificatePair' SYNTAX 'CertificatePair' ) + + ( 2.5.4.41 NAME 'name' + DESC 'The name attribute type is the attribute supertype from which + string attribute types typically used for naming may be formed.' + EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{32768}' ) + + ( 2.5.4.42 NAME 'givenName' SUP name ) + + ( 2.5.4.43 NAME 'initials' + DESC 'The initials attribute type contains the initials of some or all + of an individuals names, but not the surname(s).' + SUP name ) + + ( 2.5.4.44 NAME 'generationQualifier' + DESC 'e.g. Jr or II.' + SUP name ) + + ( 2.5.4.45 NAME 'x500UniqueIdentifier' + DESC 'used to distinguish between objects when a distinguished name has + been reused.' + EQUALITY bitStringMatch SYNTAX 'BitString' ) + + ( 2.5.4.46 NAME 'dnQualifier' + DESC 'The dnQualifier attribute type specifies disambiguating + information to add to the relative distinguished name of an + entry. It is intended to be used for entries held in multiple + DSAs which would otherwise have the same name, and that its + value be the same in a given DSA for all entries to which this + information has been added.' + EQUALITY caseIgnoreMatch + ORDERING caseIgnoreOrderingMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'PrintableString' ) + + ( 2.5.4.47 NAME 'enhancedSearchGuide' SYNTAX 'EnhancedGuide' ) + + + +Wahl, Coulbeck, Howes & Kille [Page 9] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.4.48 NAME 'protocolInformation' EQUALITY protocolInformationMatch + SYNTAX 'ProtocolInformation' ) + + ( 2.5.4.49 NAME 'distinguishedName' + DESC 'This is not the name of the object itself, but a base type + from which attributes with DN syntax inherit.' + EQUALITY distinguishedNameMatch + SYNTAX 'DN' ) + + ( 2.5.4.50 NAME 'uniqueMember' EQUALITY uniqueMemberMatch + SYNTAX 'NameAndOptionalUID' ) + + ( 2.5.4.51 NAME 'houseIdentifier' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{32768}' ) + +5.1.2. Pilot User Attributes + + These attributes are defined in RFC 1274. Servers must recognize all the + attributes of this section. + + ( 0.9.2342.19200300.100.1.1 NAME 'uid' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORaddress' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.3 NAME 'mail' EQUALITY caseIgnoreIA5Match + SUBSTRINGS caseIgnoreIA5SubstringsMatch SYNTAX 'IA5String{256}' ) + + ( 0.9.2342.19200300.100.1.4 NAME 'info' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{2048}' ) + + ( 0.9.2342.19200300.100.1.5 NAME 'drink' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.6 NAME 'roomNumber' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.7 NAME 'photo' SYNTAX 'Fax{250000}' ) + + ( 0.9.2342.19200300.100.1.8 NAME 'userClass' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.9 NAME 'host' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.10 NAME 'manager' + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + + ( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + +Wahl, Coulbeck, Howes & Kille [Page 10] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 0.9.2342.19200300.100.1.12 NAME 'documentTitle' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.13 NAME 'documentVersion' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor' + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + + ( 0.9.2342.19200300.100.1.15 NAME 'documentLocation' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.20 NAME 'homePhone' EQUALITY telephoneNumberMatch + SUBSTRINGS telephoneNumberSubstringsMatch SYNTAX 'TelephoneNumber{32}' ) + + ( 0.9.2342.19200300.100.1.21 NAME 'secretary' + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + + ( 0.9.2342.19200300.100.1.22 NAME 'otherMailbox' SYNTAX 'OtherMailbox' ) + + ( 0.9.2342.19200300.100.1.25 NAME 'dc' EQUALITY caseIgnoreIA5Match + SUBSTRINGS caseIgnoreIA5SubstringsMatch SYNTAX 'IA5String' ) + + ( 0.9.2342.19200300.100.1.26 NAME 'dNSRecord' + EQUALITY caseExactIA5Match SYNTAX 'IA5String' ) + + ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain' + EQUALITY caseIgnoreIA5Match SUBSTRINGS caseIgnoreIA5SubstringsMatch + SYNTAX 'IA5String' ) + + ( 0.9.2342.19200300.100.1.38 NAME 'associatedName' + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + + ( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress' + EQUALITY caseIgnoreListMatch + SUBSTRINGS caseIgnoreListSubstringsMatch SYNTAX 'PostalAddress' ) + + ( 0.9.2342.19200300.100.1.40 NAME 'personalTitle' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString' ) + + ( 0.9.2342.19200300.100.1.41 NAME 'mobile' EQUALITY telephoneNumberMatch + SUBSTRINGS telephoneNumberSubstringsMatch SYNTAX 'TelephoneNumber{32}' ) + + ( 0.9.2342.19200300.100.1.42 NAME 'pager' EQUALITY telephoneNumberMatch + SUBSTRINGS telephoneNumberSubstringsMatch SYNTAX 'TelephoneNumber{32}' ) + + ( 0.9.2342.19200300.100.1.43 NAME 'co' EQUALITY caseIgnoreMatch + SUBSTRINGS caseIgnoreSubstringsMatch SYNTAX 'DirectoryString' ) + + + +Wahl, Coulbeck, Howes & Kille [Page 11] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString' ) + + ( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.46 NAME 'janetMailbox' + EQUALITY caseIgnoreIA5Match SUBSTRINGS caseIgnoreIA5SubstringsMatch + SYNTAX 'IA5String{256}' ) + + ( 0.9.2342.19200300.100.1.47 NAME 'mailPreferenceOption' + SYNTAX 'INTEGER' SINGLE-VALUE } + + ( 0.9.2342.19200300.100.1.48 NAME 'buildingName' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString{256}' ) + + ( 0.9.2342.19200300.100.1.49 NAME 'dSAQuality' + SYNTAX 'DSAQualitySyntax' SINGLE-VALUE ) + + ( 0.9.2342.19200300.100.1.50 NAME 'singleLevelQuality' + SYNTAX 'DataQualitySyntax' SINGLE-VALUE ) + + ( 0.9.2342.19200300.100.1.51 NAME 'subtreeMinimumQuality' + SYNTAX 'DataQualitySyntax' SINGLE-VALUE ) + + ( 0.9.2342.19200300.100.1.52 NAME 'subtreeMaximumQuality' + SYNTAX 'DataQualitySyntax' SINGLE-VALUE ) + + ( 0.9.2342.19200300.100.1.53 NAME 'personalSignature' + SYNTAX 'Fax{50000}' ) + + ( 0.9.2342.19200300.100.1.54 NAME 'dITRedirect' + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + + ( 0.9.2342.19200300.100.1.55 NAME 'audio' SYNTAX 'Audio{250000}' ) + + ( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher' + EQUALITY caseIgnoreMatch SUBSTRINGS caseIgnoreSubstringsMatch + SYNTAX 'DirectoryString' ) + + ( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' SYNTAX 'JPEG' ) + + + + + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 12] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.1.3. Standard Operational Attributes + + All servers must recognize the attribute types defined in this + section. + + ( 2.5.18.1 NAME 'createTimestamp' EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch SYNTAX 'GeneralizedTime' + SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation ) + + ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch SYNTAX 'GeneralizedTime' + SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation ) + + ( 2.5.18.3 NAME 'creatorsName' EQUALITY distinguishedNameMatch SYNTAX 'DN' + SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation ) + + ( 2.5.18.4 NAME 'modifiersName' EQUALITY distinguishedNameMatch SYNTAX 'DN' + SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation ) + + ( 2.5.18.10 NAME 'subschemaSubentry' + DESC 'The value of this attribute is the name of a subschema subentry, + an entry in which the server makes available attributes specifying + the schema.' + EQUALITY distinguishedNameMatch SYNTAX 'DN' NO-USER-MODIFICATION + SINGLE-VALUE USAGE directoryOperation ) + + ( 2.5.21.5 NAME 'attributeTypes' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'AttributeTypeDescription' USAGE directoryOperation ) + + ( 2.5.21.6 NAME 'objectClasses' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'ObjectClassDescription' USAGE directoryOperation ) + +5.1.4. LDAP Operational Attributes + + All servers must recognize the attribute types defined in this section. + (Of course, it is not required that the server provide values for these + attributes, when the attribute corresponds to a feature which the server + does not implement.) + + ( 1.3.6.1.4.1.1466.101.120.1 NAME 'administratorsAddress' + DESC 'This attribute\27s values are string containing the addresses of + the LDAP server\27s human administrator. This information may + be of use when tracking down problems in an Internet distributed + directory. For simplicity the syntax of the values are limited to + being URLs of the mailto form with an RFC 822 address: + "mailto:user@domain". Future versions of this protocol may permit + other forms of addresses.' + SYNTAX 'IA5String' USAGE dSAOperation ) + + + + +Wahl, Coulbeck, Howes & Kille [Page 13] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 1.3.6.1.4.1.1466.101.120.2 NAME 'currentTime' + DESC 'This attribute has a single value, a string containing a + GeneralizedTime character string. This attribute need only + be present if the server supports LDAP strong or protected + simple authentication. Otherwise if the server does not know + the current time, or does not choose to present it to clients, + this attribute need not be present. The client may wish to + use this value to detect whether a strong or protected bind + is failing because the client and server clocks are not + sufficiently synchronized. Clients must not use this time + field for setting their own system clock.' + SYNTAX 'GeneralizedTime' SINGLE-VALUE USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.3 NAME 'serverName' + DESC 'This attribute\27s value is the server\27s Distinguished Name. + If the server does not have a Distinguished Name it will not + be able to accept X.509-style strong authentication, and this + attribute must be absent. However the presence of this + attribute does not guarantee that the server will be able to + perform strong authentication. If the server acts as a + gateway to more than one X.500 DSA capable of strong + authentication, there may be multiple values of this + attribute, one per DSA. (Note: this attribute is distinct + from myAccessPoint, for it is not required that a server + have a presentation address in order to perform strong + authentication.) (Note: it is likely that clients will + retrieve this attribute in binary.)' + SYNTAX 'DN' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.4 NAME 'certificationPath' + DESC 'This attribute contains a binary DER encoding of an + AF.CertificatePath data type, which is the certificate + path for a server. If the server does not have a certificate + path this attribute must be absent. (Note: this attribute + may only be retrieved in binary.)' + SYNTAX 'CertificatePath' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts' + DESC 'The values of this attribute correspond to naming contexts + which this server masters or shadows. If the server does + not master any information (e.g. it is an LDAP gateway to a + public X.500 directory) this attribute must be absent. If + the server believes it contains the entire directory, the + attribute must have a single value, and that value must + be the empty string (indicating the null DN of the root). + This attribute will allow clients to choose suitable base + objects for searching when it has contacted a server.' + SYNTAX 'DN' USAGE dSAOperation ) + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 14] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' + DESC 'The values of this attribute are URLs of other servers which + may be contacted when this server becomes unavailable. If + the server does not know of any other servers which could be + used this attribute must be absent. Clients may cache this + information in case their preferred LDAP server later becomes + unavailable.' + SYNTAX 'IA5String' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension' + DESC 'The values of this attribute are OBJECT IDENTIFIERs, + the names of supported extended operations + which the server supports. If the server does not support + any extensions this attribute must be absent.' + SYNTAX 'OID' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl' + DESC 'The values of this attribute are the names of supported session + controls which the server supports. If the server does not + support any controls this attribute must be absent.' + SYNTAX 'LDAPString' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms' + DESC 'The values of this attribute are the names of supported SASL + mechanisms which the server supports. If the server does not + support any mechanisms this attribute must be absent.' + SYNTAX 'LDAPString' USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.8 NAME 'entryName' + SYNTAX 'DN' SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation ) + + ( 1.3.6.1.4.1.1466.101.120.9 NAME 'modifyRights' + SYNTAX 'ModifyRight' NO-USER-MODIFICATION USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.10 NAME 'incompleteEntry' + SYNTAX 'BOOLEAN' NO-USER-MODIFICATION USAGE dSAOperation ) + + ( 1.3.6.1.4.1.1466.101.120.11 NAME 'fromEntry' + SYNTAX 'BOOLEAN' NO-USER-MODIFICATION USAGE dSAOperation ) + +5.1.5. LDAP User Attributes + + The following attributes may be of use in naming entries, or as + descriptive attributes in entries. + + ( 1.3.6.1.4.1.1466.101.121.1 NAME 'url' + DESC 'Uniform Resource Locator' + EQUALITY caseExactIA5Match SYNTAX 'IA5String' ) + + Note that the associatedDomain attribute may be used to hold a DNS name. + + + + +Wahl, Coulbeck, Howes & Kille [Page 15] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2. Syntaxes + +5.2.1. Standard User Syntaxes + + Servers must recognize all the syntaxes described in this section. + +5.2.1.1. BitString + + The encoding of a value with BitString syntax is according to the + following BNF: + + ::= ''' ''B' + + ::= '0' | '1' | + empty + + +5.2.1.2. PrintableString + + The encoding of a value with PrintableString syntax is the string + value itself. PrintableString is limited to the characters in + production

of section 4.1. + +5.2.1.3. DirectoryString + + A string with DirectoryString syntax is encoded in the UTF-8 form of + ISO 10646 (a superset of Unicode). Servers and clients must be prepared to + receive arbitrary Unicode characters in values. + + For characters in the PrintableString form, the value is encoded as the + string value itself. + + If it is of the TeletexString form, then the characters are transliterated + to their equivalents in UniversalString, and encoded in UTF-8 [11]. + + If it is of the UniversalString or BMPString forms [12], UTF-8 is used to + encode them. + + Note: the form of DirectoryString is not indicated in protocol unless the + attribute value is carried in binary. Servers which convert to DAP must + choose an appropriate form. Servers must not reject values merely because + they contain legal Unicode characters outside of the range of printable + ASCII. + +5.2.1.4. Certificate + + Because of the changes from X.509(1988) and X.509(1993) and additional + changes to the ASN.1 definition to support certificate extensions, no + string representation is defined, and values with Certificate syntax + must only be transferred using the binary encoding, by requesting or + returning the attributes with descriptions "userCertificate;binary" or + "caCertificate;binary". The BNF notation in RFC 1778 for + "User Certificate" is not recommended to be used. + +Wahl, Coulbeck, Howes & Kille [Page 16] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.1.5. CertificateList + + Because of the incompatibility of the X.509(1988) and X.509(1993) + definitions of revocation lists, values with CertificateList syntax + must only be transferred using a binary encoding, by requesting or + returning the attributes with descriptions + "certificateRevocationList;binary" or "authorityRevocationList;binary". + The BNF notation in RFC 1778 for "Authority Revocation List" is not + recommended to be used. + +5.2.1.6. CertificatePair + + Because the Certificate is being carried in binary, values with + CertificatePair syntax must only be transferred using a binary encoding, + by requesting or returning the attribute description + "crossCertificatePair;binary". The BNF notation in RFC 1778 for + "Certificate Pair" is not recommended to be used. + +5.2.1.7. CountryString + + A value of CountryString syntax is encoded the same as a value of + DirectoryString syntax. Note that this syntax is limited to values of + exactly two printable string characters. + + ::=

+ +5.2.1.8. DN + + Values with DN (Distinguished Name) syntax are encoded to have the + representation defined in [5]. Note that this representation is not + reversible to the original ASN.1 encoding as the CHOICE of any + DirectoryString element in an RDN is no longer known. + +5.2.1.9. DeliveryMethod + + Values with DeliveryMethod syntax are encoded according to the + following BNF: + + ::= | '$' + + ::= 'any' | 'mhs' | 'physical' | 'telex' | 'teletex' | + 'g3fax' | 'g4fax' | 'ia5' | 'videotex' | 'telephone' + +5.2.1.10. EnhancedGuide + + Values with the EnhancedGuide syntax are encoded according to the + following BNF: + + ::= '#' '#' + + ::= "baseobject" | "oneLevel" | "wholeSubtree" + + + +Wahl, Coulbeck, Howes & Kille [Page 17] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + The production is defined in the Guide syntax below. + This syntax has been added subsequent to RFC 1778. + +5.2.1.11. FacsimileTelephoneNumber + + Values with the FacsimileTelephoneNumber syntax are encoded according + to the following BNF: + + ::= [ '$' ] + + ::= | '$' + + ::= 'twoDimensional' | 'fineResolution' | 'unlimitedLength' | + 'b4Length' | 'a3Width' | 'b4Width' | 'uncompressed' + + In the above, the first is the actual fax number, + and the tokens represent fax parameters. + +5.2.1.12. Guide + + Values with the Guide syntax are encoded according to the following + BNF: + + ::= [ '#' ] + + ::= an encoded value with OID syntax + + ::= | | '!' + + ::= [ '(' ] '&' [ ')' ] | + [ '(' ] '|' [ ')' ] + + ::= [ '(' ] '$' [ ')' ] + + ::= "EQ" | "SUBSTR" | "GE" | "LE" | "APPROX" + +5.2.1.13. NameAndOptionalUID + + The encoding of a value with the NameAndOptionalUID syntax is according + to the following BNF: + + ::= + [ '#' ] + + Although the '#' character may occur in a string representation of a + distinguished name, no additional special quoting is done in the + distinguished name other than that of [5]. + + This syntax has been added subsequent to RFC 1778. + + + + + +Wahl, Coulbeck, Howes & Kille [Page 18] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.1.14. NumericString + + The encoding of a string with the NumericString syntax is the string + value itself. + +5.2.1.15. OID + + Values with OID (Object Identifier) syntax are encoded according to the + following BNF: + + ::= | + + ::= + + ::= | '.' + + In the above BNF, is the syntactic representation of an + object descriptor, which must consist of letters and digits, starting + with a letter. When encoding values with OID syntax, the first encoding + option must be used in preference to the second. That is, in encoding + object identifiers, object descriptors (where assigned and known by + the implementation) must be used in preference to numeric oids to + the greatest extent possible. All permitted object descriptors for use + in LDAP are given in this document. No other object descriptors may be + used. (Note that clients must expect that LDAPv2 implementations + will return object descriptors other than those listed.) + +5.2.1.16. Password + + Values with Password syntax are encoded as octet strings. + +5.2.1.17. PostalAddress + + Values with the PostalAddress syntax are encoded according to the + following BNF: + + ::= | '$' + + In the above, each component of a postal address value is + encoded as a value of type DirectoryString syntax. Backslashes and + dollar characters, if they occur in the component, are quoted as + described in section 4.2. + +5.2.1.18. PresentationAddress + + Values with the PresentationAddress syntax are encoded to have the + representation described in [6]. + +5.2.1.20. TelephoneNumber + + Values with the TelephoneNumber syntax are encoded as if they were + Printable String types. Telephone numbers are recommended in X.520 to + be in international form, e.g. "+1 512 305 0280". + +Wahl, Coulbeck, Howes & Kille [Page 19] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.1.21. TeletexTerminalIdentifier + + Values with the TeletexTerminalIdentifier syntax are encoded according + to the following BNF: + + ::= 0*('$' ) + + ::= + + ::= ':' + + ::= 'graphic' | 'control' | 'misc' | 'page' | 'private' + + ::= + + In the above, the first is the encoding of the + first portion of the teletex terminal identifier to be encoded, and + the subsequent 0 or more are subsequent portions + of the teletex terminal identifier. + +5.2.1.22. TelexNumber + + Values with the TelexNumber syntax are encoded according to the + following BNF: + + ::= '$' '$' + + ::= + + ::= + + ::= + + In the above, is the syntactic representation of the + number portion of the TELEX number being encoded, is the + TELEX country code, and is the answerback code of a + TELEX terminal. + +5.2.1.23. UTCTime + + Values with UTCTime syntax are encoded as if they were printable + strings with the strings containing a UTCTime value. This is historical; + new attribute definitions must use GeneralizedTime instead. + +5.2.1.24. Boolean + + Values with Boolean syntax are encoded according to the following + BNF: + + ::= "TRUE" | "FALSE" + + Boolean values have an encoding of "TRUE" if they are logically true, + and have an encoding of "FALSE" otherwise. + +Wahl, Coulbeck, Howes & Kille [Page 20] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.2. Pilot Syntaxes + + Servers must recognize all the syntaxes described in this section. + +5.2.2.1. Audio + + The encoding of a value with Audio syntax is the octets of the value + itself, an 8KHz uncompressed encoding compatible with the SunOS + 4.1.3 'play' utility. + +5.2.2.2. DSAQualitySyntax + + Values with this syntax are encoded according to the following BNF: + + ::= [ '#' ] + + ::= 'DEFUNCT' | 'EXPERIMENTAL' | 'BEST-EFFORT' | + 'PILOT-SERVICE' | 'FULL-SERVICE' + + ::= encoded as a PrintableString + +5.2.2.3. DataQualitySyntax + + Values with this syntax are encoded according to the following BNF: + + ::= '#' '#' + [ '#' ] + + ::= '+' + + ::= '$' + + ::= '+' + + ::= 'NONE' | 'SAMPLE' | 'SELECTED' | + 'SUBSTANTIAL' | 'FULL' + + ::= 'UNKNOWN' | 'EXTERNAL' | 'SYSTEM-MAINTAINED' | + 'USER-SUPPLIED' + +5.2.2.4. IA5String + + The encoding of a value with IA5String syntax is the string value + itself. + +5.2.2.5. JPEG + + Values with JPEG syntax are encoded as if they were octet strings + containing JPEG images in the JPEG File Interchange Format (JFIF), as + described in [8]. + + + + +Wahl, Coulbeck, Howes & Kille [Page 21] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.2.6. MailPreference + + Values with MailPreference syntax are encoded according to the + following BNF: + + ::= "NO-LISTS" | "ANY-LIST" | "PROFESSIONAL-LISTS" + +5.2.2.7. OtherMailbox + + Values of the OtherMailbox syntax are encoded according to the + following BNF: + + ::= '$' + + ::= an encoded Printable String + + ::= an encoded IA5 String + + In the above, represents the type of mail system in + which the mailbox resides, for example "MCIMail"; and is the + actual mailbox in the mail system defined by . + +5.2.2.8. Fax + + Values with Fax syntax are encoded as if they were octet strings + containing Group 3 Fax images as defined in [7]. + +5.2.3. Operational Syntaxes + + Servers must recognize all the syntaxes described in this section. + +5.2.3.1. AttributeTypeDescription + + Values with this syntax are encoded according to the BNF given at the + start of section 4.1. For example, + + ( 2.5.4.0 NAME 'objectClass' SYNTAX 'OID' ) + +5.2.3.2. GeneralizedTime + + Values of this syntax are encoded as printable strings, represented + as specified in X.208. Note that the time zone must be specified. + It is strongly recommended that Zulu time zone be used. For example, + + 199412161032Z + +5.2.3.3. INTEGER + + Values with INTEGER syntax are encoded as the decimal representation + of their values, with each decimal digit represented by the its + character equivalent. So the number 1321 is represented by the character + string "1321". + + +Wahl, Coulbeck, Howes & Kille [Page 22] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +5.2.3.4. ObjectClassDescription + + Values of this syntax are encoded according to the BNF in section 4.3. + +5.3. Object Classes + +5.3.1. Standard Classes + + Servers must recognize the object classes listed here as values of + the objectClass attribute. With the exception of groupOfUniqueNames, + they are described in RFC 1274. + + ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass ) + + ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL MUST aliasedObjectName ) + + ( 2.5.6.2 NAME 'country' SUP top STRUCTURAL MUST c + MAY ( searchGuide $ description ) ) + + ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL + MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) ) + + ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST o + MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ + x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + street $ postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ st $ l $ description ) ) + + ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ou + MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ + x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + street $ postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ st $ l $ description ) ) + + ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn ) + MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) ) + + ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL + MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + street $ postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ ou $ st $ l ) ) + + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 23] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL MUST cn + MAY ( x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $ + postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ ou $ st $ l $ description ) ) + + ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST ( member $ cn ) + MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) + + ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL MUST l + MAY ( businessCategory $ x121Address $ registeredAddress $ + destinationIndicator $ preferredDeliveryMethod $ telexNumber $ + teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ + facsimileTelephoneNumber $ preferredDeliveryMethod $ street $ + postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ st $ l ) ) + + ( 2.5.6.11 NAME 'applicationProcess' SUP top STRUCTURAL MUST cn + MAY ( seeAlso $ ou $ l $ description ) ) + + ( 2.5.6.12 NAME 'applicationEntity' SUP top STRUCTURAL + MUST ( presentationAddress $ cn ) + MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $ + description ) ) + + ( 2.5.6.13 NAME 'dSA' SUP applicationEntity STRUCTURAL + MAY knowledgeInformation ) + + ( 2.5.6.14 NAME 'device' SUP top STRUCTURAL MUST cn + MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) ) + + ( 2.5.6.15 NAME 'strongAuthenticationUser' SUP top STRUCTURAL + MUST userCertificate ) + + ( 2.5.6.16 NAME 'certificationAuthority' SUP top STRUCTURAL + MUST ( authorityRevocationList $ certificateRevocationList $ + cACertificate ) MAY crossCertificatePair ) + + ( 2.5.6.17 NAME 'groupOfUniqueNames' SUP top STRUCTURAL + MUST ( uniqueMember $ cn ) + MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) + +5.3.2. Pilot Classes + + These object classes are defined in RFC 1274. All servers must recognize + these object class names. + + ( 0.9.2342.19200300.100.4.3 NAME 'pilotObject' SUP top STRUCTURAL + MAY ( jpegPhoto $ audio $ dITRedirect $ lastModifiedBy $ + lastModifiedTime $ uniqueIdentifier $ manager $ photo $ info ) ) + + +Wahl, Coulbeck, Howes & Kille [Page 24] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 0.9.2342.19200300.100.4.4 NAME 'newPilotPerson' SUP person + STRUCTURAL MAY ( personalSignature $ mailPreferenceOption $ + organizationalStatus $ pagerTelephoneNumber $ mobileTelephoneNumber $ + otherMailbox $ janetMailbox $ businessCategory $ + preferredDeliveryMethod $ personalTitle $ secretary $ + homePostalAddress $ homePhone $ userClass $ roomNumber $ + favouriteDrink $ rfc822Mailbox $ textEncodedORaddress $ userid ) ) + + ( 0.9.2342.19200300.100.4.5 NAME 'account' SUP top STRUCTURAL + MUST userid MAY ( host $ ou $ o $ l $ seeAlso $ description ) ) + + ( 0.9.2342.19200300.100.4.6 NAME 'document' SUP ( top $ pilotObject ) + STRUCTURAL MUST documentIdentifier + MAY ( documentPublisher $ documentStore $ documentAuthorSurName $ + documentAuthorCommonName $ abstract $ subject $ keywords $ + updatedByDocument $ updatesDocument $ obsoletedByDocument $ + obsoletesDocument $ documentLocation $ documentAuthor $ + documentVersion $ documentTitle $ ou $ o $ l $ seeAlso $ description $ + cn ) ) + + ( 0.9.2342.19200300.100.4.7 NAME 'room' SUP top STRUCTURAL MUST cn + MAY ( telephoneNumber $ seeAlso $ description $ roomNumber ) ) + + ( 0.9.2342.19200300.100.4.9 NAME 'documentSeries' SUP top STRUCTURAL + MUST cn MAY ( ou $ o $ l $ telephoneNumber $ seeAlso $ description ) ) + + ( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCTURAL + MUST dc + MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ + x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + street $ postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ st $ l $ description $ o $ + associatedName ) ) + + ( 0.9.2342.19200300.100.4.14 NAME 'rFC822localPart' SUP domain + STRUCTURAL + MAY ( x121Address $ registeredAddress $ destinationIndicator $ + preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + streetAddress $ postOfficeBox $ postalCode $ postalAddress $ + physicalDeliveryOfficeName $ telephoneNumber $ seeAlso $ description $ + sn $ cn ) ) + + ( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain' SUP domain STRUCTURAL + MAY dNSRecord ) + + ( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject' SUP top + STRUCTURAL MUST associatedDomain ) + + ( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry' SUP country + STRUCTURAL MUST co ) + +Wahl, Coulbeck, Howes & Kille [Page 25] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject' SUP top + STRUCTURAL MUST userPassword ) + + ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization' + SUP ( organization $ organizationalUnit ) STRUCTURAL + MAY buildingName ) + + ( 0.9.2342.19200300.100.4.21 NAME 'pilotDSA' SUP dSA STRUCTURAL + MUST dSAQuality ) + + ( 0.9.2342.19200300.100.4.23 NAME 'qualityLabelledData' SUP top + STRUCTURAL MUST singleLevelQuality + MAY ( subtreeMaximumQuality $ subtreeMinimumQuality ) ) + +5.4. Matching Rules + + Servers must recognize the following matching rules, used for equality + matching, and must be capable of performing the matching rules. + For all these rules, the assertion syntax is the same as the value syntax. + + ( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 'OID' ) + ( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 'DN' ) + ( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 'DirectoryString' ) + ( 2.5.13.8 NAME 'numericStringMatch' SYNTAX 'NumericString' ) + ( 2.5.13.11 NAME 'caseIgnoreListMatch' SYNTAX 'PostalAddress' ) + ( 2.5.13.14 NAME 'integerMatch' SYNTAX 'INTEGER' ) + ( 2.5.13.16 NAME 'bitStringMatch' SYNTAX 'BitString' ) + ( 2.5.13.17 NAME 'octetStringMatch' SYNTAX 'Password' ) + ( 2.5.13.20 NAME 'telephoneNumberMatch' SYNTAX 'TelephoneNumber' ) + ( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 'GeneralizedTime' ) + ( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' SYNTAX 'IA5String' ) + ( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' SYNTAX 'IA5String' ) + + When performing the caseIgnoreMatch, caseIgnoreListMatch, + telephoneNumberMatch, caseExactIA5Match and caseIgnoreIA5Match, + multiple adjoining whitespace characters are treated the same as + an individual space, and leading and trailing whitespace is ignored. + +6. X.500 Definitions + + Servers which implement the X.500(1993) protocols are required to recognize + these attributes types, syntaxes, object classes and matching rules, where + they correspond to X.500 features implemented by that server. No other + servers are required to implement any definitions in section 6, although + they may do so. + + Clients must not assume these definitions are recognized by all servers. + +6.1. Attribute Types + +6.1.1. User Attributes + + All user attributes of X.500 are listed in section 5.1.1. + +Wahl, Coulbeck, Howes & Kille [Page 26] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +6.1.2. Collective Attributes + + These attributes are stored in collective attribute subentries, but may + be visible in user entries if requested. + + Each of these collective attributes is a subtype of the attribute which + has the OID without the final ".1", e.g. "collectivePostalCode" is a + subtype of "postalCode". + + ( 2.5.4.7.1 NAME 'collectiveLocalityName' SUP l COLLECTIVE ) + + ( 2.5.4.8.1 NAME 'collectiveStateOrProvinceName' SUP st COLLECTIVE ) + + ( 2.5.4.9.1 NAME 'collectiveStreetAddress' SUP street COLLECTIVE ) + + ( 2.5.4.10.1 NAME 'collectiveOrganizationName' SUP o COLLECTIVE ) + + ( 2.5.4.11.1 NAME 'collectiveOrganizationalUnitName' SUP ou COLLECTIVE ) + + ( 2.5.4.16.1 NAME 'collectivePostalAddress' SUP postalAddress COLLECTIVE ) + + ( 2.5.4.17.1 NAME 'collectivePostalCode' SUP postalCode COLLECTIVE ) + + ( 2.5.4.18.1 NAME 'collectivePostOfficeBox' SUP postOfficeBox COLLECTIVE ) + + ( 2.5.4.19.1 NAME 'collectivePhysicalDeliveryOfficeName' + SUP physicalDeliveryOfficeName COLLECTIVE ) + + ( 2.5.4.20.1 NAME 'collectiveTelephoneNumber' SUP telephoneNumber + COLLECTIVE ) + + ( 2.5.4.21.1 NAME 'collectiveTelexNumber' SUP 'TelexNumber' COLLECTIVE ) + + ( 2.5.4.22.1 NAME 'collectiveTeletexTerminalIdentifier' + SUP teletexTerminalIdentifier COLLECTIVE ) + + ( 2.5.4.23.1 NAME 'collectiveFacsimileTelephoneNumber' + SUP facsimileTelephoneNumber COLLECTIVE ) + + ( 2.5.4.25.1 NAME 'collectiveInternationaliSDNNumber' + SUP internationaliSDNNumber COLLECTIVE ) + +6.1.3. Standard Operational Attributes + + These attributes are defined in X.501(1993) Annexes B through E. + + ( 2.5.18.5 NAME 'administrativeRole' EQUALITY objectIdentifierMatch + SYNTAX 'OID' USAGE directoryOperation ) + + ( 2.5.18.6 NAME 'subtreeSpecification' SYNTAX 'SubtreeSpecification' + SINGLE-VALUE USAGE directoryOperation ) + + + +Wahl, Coulbeck, Howes & Kille [Page 27] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.18.7 NAME 'collectiveExclusions' EQUALITY objectIdentifierMatch + SYNTAX 'OID' USAGE directoryOperation ) + + ( 2.5.21.1 NAME 'dITStructureRules' EQUALITY integerFirstComponentMatch + SYNTAX 'DITStructureRuleDescription' USAGE directoryOperation ) + + ( 2.5.21.2 NAME 'dITContentRules' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'DITContentRuleDescription' USAGE directoryOperation ) + + ( 2.5.21.4 NAME 'matchingRules' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'MatchingRuleDescription' USAGE directoryOperation ) + + ( 2.5.21.7 NAME 'nameForms' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'NameFormDescription' USAGE directoryOperation ) + + ( 2.5.21.8 NAME 'matchingRuleUse' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 'MatchingRuleUseDescription' USAGE directoryOperation ) + + ( 2.5.21.9 NAME 'structuralObjectClass' EQUALITY objectIdentifierMatch + SYNTAX 'OID' SINGLE-VALUE NO-USER-MODIFICATION + USAGE directoryOperation ) + + ( 2.5.21.10 NAME 'governingStructuralRule' EQUALITY integerMatch + SYNTAX 'INTEGER' SINGLE-VALUE NO-USER-MODIFICATION + USAGE directoryOperation ) + + ( 2.5.24.1 NAME 'accessControlScheme' EQUALITY objectIdentifierMatch + SYNTAX 'OID' SINGLE-VALUE USAGE directoryOperation ) + + ( 2.5.24.4 NAME 'prescriptiveACI' + EQUALITY directoryStringFirstComponentMatch SYNTAX 'ACIItem' + USAGE directoryOperation ) + + ( 2.5.24.5 NAME 'entryACI' + EQUALITY directoryStringFirstComponentMatch SYNTAX 'ACIItem' + USAGE directoryOperation ) + + ( 2.5.24.6 NAME 'subentryACI' + EQUALITY directoryStringFirstComponentMatch SYNTAX 'ACIItem' + USAGE directoryOperation ) + + ( 2.5.12.0 NAME 'dseType' EQUALITY bitStringMatch SYNTAX 'DSEType' + SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation ) + + ( 2.5.12.1 NAME 'myAccessPoint' EQUALITY accessPointMatch + SYNTAX 'AccessPoint' SINGLE-VALUE NO-USER-MODIFICATION + USAGE dSAOperation ) + + + +Wahl, Coulbeck, Howes & Kille [Page 28] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ( 2.5.12.2 NAME 'superiorKnowledge' EQUALITY accessPointMatch + SYNTAX 'AccessPoint' SINGLE-VALUE NO-USER-MODIFICATION + USAGE dSAOperation ) + + ( 2.5.12.3 NAME 'specificKnowledge' + EQUALITY masterAndShadowAccessPointsMatch + SYNTAX 'MasterAndShadowAccessPoints' + SINGLE-VALUE NO-USER-MODIFICATION USAGE distributedOperation ) + + ( 2.5.12.4 NAME 'nonSpecificKnowledge' + EQUALITY masterAndShadowAccessPointsMatch + SYNTAX 'MasterAndShadowAccessPoints' NO-USER-MODIFICATION + USAGE distributedOperation ) + + ( 2.5.12.5 NAME 'supplierKnowledge' + EQUALITY supplierOrConsumerInformationMatch + SYNTAX 'SupplierInformation' + NO-USER-MODIFICATION USAGE dSAOperation ) + + ( 2.5.12.6 NAME 'consumerKnowledge' + EQUALITY supplierOrConsumerInformationMatch + SYNTAX 'SupplierOrConsumer' + NO-USER-MODIFICATION USAGE dSAOperation ) + + ( 2.5.12.7 NAME 'secondaryShadows' + EQUALITY supplierAndConsumersMatch + SYNTAX 'SupplierAndConsumers' + NO-USER-MODIFICATION USAGE dSAOperation ) + +6.1.4. LDAP-defined Operational Attributes + +6.1.4.1. targetSystem + + ( 1.3.6.1.4.1.1466.101.120.12 NAME 'targetSystem' + SYNTAX 'AccessPoint' SINGLE-VALUE NO-USER-MODIFICATION + USAGE distributedOperation ) + + The value of this attribute may be supplied in an AddEntry operation + to inform the Directory of the target server on which the entry is to + be held. This is used to create a new naming context in the directory + tree. A server which does not permit the use of this attribute must + return an appropriate error code if it is present in the attribute list. + This attribute will generally not be present in the entry after the add + is completed. + + + + + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 29] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +6.2. Syntaxes + +6.2.1. Standard Syntaxes + +6.2.1.1. ACIItem + + This syntax appears too complicated for a compact string representation + to be useful. Clients must only request and servers must only return + values which use the the binary encoding of the value, e.g. + "entryACI;binary". + + It is recommended that clients that wish to only determine whether they + have been granted permission to modify an entry use the "modifyRights" + attribute rather than attempt to parse this syntax. + +6.2.1.2. AccessPoint + + Values with AccessPoint syntax are encoded according to the + following BNF: + + ::= ( '(' '#' + ')' ) | + -- Optional protocol info absent, parenthesis required + ( '(' '#' + '#' + ::= | + '(' ')' + + ::= | + '$' + + +6.2.1.3. DITContentRuleDescription + + Values with this syntax are encoded according to the following BNF: + + ::= "(" + -- Structural ObjectClass identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + [ "AUX" ] -- Auxiliary ObjectClasses + [ "MUST" ] -- AttributeType identifiers + [ "MAY" ] -- AttributeType identifiers + [ "NOT" ] -- AttributeType identifiers + ")" + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 30] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +6.2.1.4. DITStructureRuleDescription + + Values with this syntax are encoded according to the following BNF: + + ::= "(" + -- DITStructureRule identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + "FORM" -- NameForm + [ "SUP" ] -- superior DITStructureRules + ")" + + ::= + + ::= + | + "(" ")" + + ::= + + | + -- empty list + +6.2.1.5. DSEType + + Values with DSEType syntax are encoded according to the following BNF: + + ::= '(' ')' + + ::= | '$' + + ::= 'root' | 'glue' | 'cp' | 'entry' | 'alias' | 'subr' | + 'nssr' | 'supr' | 'xr' | 'admPoint' | 'subentry' | + 'shadow' | 'zombie' | 'immSupr' | 'rhob' | 'sa' + +6.2.1.6. MasterAndShadowAccessPoints + + Values of this syntax are encoded according to the following BNF: + + ::= | + '(' ::= | + '$' + + ::= '#' + + ::= 'master' | 'shadow' + +6.2.1.7. MatchingRuleDescription + + Values of this syntax are encoded according to the BNF of section 4.4. + +Wahl, Coulbeck, Howes & Kille [Page 31] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +6.2.1.8. MatchingRuleUseDescription + + Values of this syntax are encoded according to the following BNF: + + ::= "(" + -- MatchingRule identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + "APPLIES" -- AttributeType identifiers + ")" + +6.2.1.9. NameFormDescription + + Values of this syntax are encoded according to the following BNF: + + ::= "(" + -- NameForm identifier + [ "NAME" ] + [ "DESC" ] + [ "OBSOLETE" ] + "OC" -- Structural ObjectClass + "MUST" -- AttributeTypes + [ "MAY" ] -- AttributeTypes + ")" + +6.2.1.10. SubtreeSpecification + + Values of this syntax are encoded according to the following BNF: + + ::= '(' [] '#' + [] '#' + [] '#' [] '#' + [] ')' + + ::= + + ::= '(' ')' + + ::= | '$' + + ::= ( 'before ' ) | + ( 'after ' ) + + ::= + + ::= + + ::= | '!' | + '( &' ')' | + '( |' ')' + + ::= | '$' + +Wahl, Coulbeck, Howes & Kille [Page 32] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +6.2.1.11. SupplierInformation + + Values of this syntax are encoded according to the following BNF: + + ::= + -- supplier is master -- + '(' 'master' '#' ')' | + + -- supplier is not master, master unspecified -- + '(' 'shadow' '#' ')' | + + -- supplier not master, master specified -- + ['('] 'shadow' '#' '#' [')'] + +6.2.1.12. SupplierOrConsumer + + Values of this syntax are encoded according to the following BNF: + + ::= '#' + + ::= '.' + + ::= + + ::= + +6.2.1.13. SupplierAndConsumers + + Values of this syntax are encoded according to the following BNF: + + ::= '#' + + ::= + + ::= | '(' ')' + + ::= | + '$' + +6.2.1.14. ProtocolInformation + + A value with the ProtocolInformation syntax is encoded according to the + following BNF: + + ::= '#' + + + ::= As appears in PresentationAddress + + ::= | + '(' ')' + + + +Wahl, Coulbeck, Howes & Kille [Page 33] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ::= | + '$' + + ::= + + For example, + + NS+12345678 # 1.2.3.4.5 + +6.2.2. LDAP-defined Syntaxes + + There is currently one syntax defined here. + +6.2.2.1 ModifyRight + + This syntax is a printable encoding of the following ASN.1 data type: + + ModifyRight ::= SEQUENCE { + item CHOICE { + entry [0] NULL, + attribute [1] AttributeType, + value [2] AttributeValueAssertion }, + permission [3] BIT STRING { add(0), remove(1), rename(2), move(3) } } + + The syntax is encoded according to the following BNF: + + ::= [] + -- perm list is absent when none of the bits set in permission + + ::= | | + + ::= 'entry' + + ::= 'attribute' + + ::= 'value' + + -- is the string encoding of the value + + ::= | + -- one or more of the bits in permission, if set + + ::= 'add' | 'remove' | 'rename' | 'move' + + ::= [ ] '#' [ ] + + ::= [ ] '$' [ ] + + + + + + + +Wahl, Coulbeck, Howes & Kille [Page 34] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + For example, + + # entry + add $ remove # attribute $ cn + add $ remove # attribute $ sn + remove # value $ memberName $ CN=Babs, O=Michigan, C=US + +6.3. Object Classes + + The following object classes may be recognized. + + ( 2.5.17.0 NAME 'subentry' SUP top STRUCTURAL + MUST ( cn $ subtreeSpecification ) ) + + ( 2.5.17.1 NAME 'accessControlSubentry' AUXILIARY ) + + ( 2.5.17.2 NAME 'collectiveAttributeSubentry' AUXILIARY ) + + ( 2.5.20.1 NAME 'subschema' AUXILIARY + MAY ( dITStructureRules $ nameForms $ ditContentRules $ + objectClasses $ attributeTypes $ matchingRules $ matchingRuleUse ) ) + +6.4. Matching Rules + + Only servers which implement the attribute types which reference these + matching rules in their definition are required to implement these rules. + + The definitions of the rules can be found in [2] and [3]. + + Name OID + ===================================== =========== + caseIgnoreOrderingMatch 2.5.13.3 + caseIgnoreSubstringsMatch 2.5.13.4 + caseExactMatch 2.5.13.5 + caseExactOrderingMatch 2.5.13.6 + caseExactSubstringsMatch 2.5.13.7 + numericStringOrderingMatch 2.5.13.9 + numericStringSubstringsMatch 2.5.13.10 + caseIgnoreListSubstringsMatch 2.5.13.12 + booleanMatch 2.5.13.13 + integerOrderingMatch 2.5.13.15 + octetStringOrderingMatch 2.5.13.18 + octetStringSubstringsMatch 2.5.13.19 + telephoneNumberSubstringsMatch 2.5.13.21 + presentationAddressMatch 2.5.13.22 + uniqueMemberMatch 2.5.13.23 + protocolInformationMatch 2.5.13.24 + uTCTimeMatch 2.5.13.25 + uTCTimeOrderingMatch 2.5.13.26 + generalizedTimeOrderingMatch 2.5.13.28 + integerFirstComponentMatch 2.5.13.29 + objectIdentifierFirstComponentMatch 2.5.13.30 + directoryStringFirstComponentMatch 2.5.13.31 + +Wahl, Coulbeck, Howes & Kille [Page 35] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + wordMatch 2.5.13.32 + keywordMatch 2.5.13.33 + accessPointMatch 2.5.14.0 + masterAndShadowAccessPointsMatch 2.5.14.1 + supplierOrConsumerInformationMatch 2.5.14.2 + supplierAndConsumersMatch 2.5.14.3 + +6.5. Other + + The string 'excludeAllCollectiveAttributes' is defined as a synonym + for the OID 2.5.18.0. It would typically be used as a value of the + collectiveExclusions attribute. + +7. Other Optional Definitions + +7.1. Attribute Types + +7.1.1. Obsolete Attributes + + Implementors must use modifyTimestamp and modifiersName instead. + + ( 0.9.2342.19200300.100.1.23 NAME 'lastModifiedTime' OBSOLETE + SYNTAX 'UTCTime' ) + + ( 0.9.2342.19200300.100.1.24 NAME 'lastModifiedBy' OBSOLETE + EQUALITY distinguishedNameMatch SYNTAX 'DN' ) + +7.2. Syntaxes + +7.2.1 MHSORAddress + + Values of type MHSORAddress are encoded as strings, according to + the format defined in [10]. + +7.2.2 DLSubmitPermission + + Values of type DLSubmitPermission are encoded as strings, according + to the following BNF: + + ::= ':' + | ':' + + ::= 'group_member' + + ::= + + ::= an encoded Distinguished Name + + ::= 'individual' | 'dl_member' | 'pattern' + + ::= + + + +Wahl, Coulbeck, Howes & Kille [Page 36] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + + ::=

'#' + |
+ +
::= ':' + + ::= ':' + + = 'X400' + + = 'X500' + + where is as defined in RFC 1327. + +7.3. Object Classes + +7.3.1. Obsolete Classes + + ( 0.9.2342.19200300.100.4.22 NAME 'oldQualityLabelledData' SUP top + STRUCTURAL MUST dSAQuality + MAY ( subtreeMaximumQuality $ subtreeMinimumQuality ) ) + + The oldQualityLabelledData object class is historical and must not be + used for defining new objects. + +7.3.2. extensibleObject + + ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject' + SUP top AUXILIARY ) + + This class, if present in an entry, permits that entry to optionally + hold any attribute. The MAY attribute list of this class is implicitly + the set of all attributes known to the server. The mandatory attributes + of the other object classes of this entry are still required to be + present. + + Note that not all servers will implement this object class, and those + which do not will reject requests to add entries which contain this + object class, or modify an entry to add this object class. + +7.4. Matching Rules + +7.4.1. caseIgnoreIA5SubstringsMatch + + ( 1.3.6.1.4.1.1466.109.114.3 + NAME 'caseIgnoreIA5SubstringsMatch' SYNTAX 'IA5String' ) + + This matching rule may be used to compare components of an IA5 string + against an attribute whose values have IA5 string syntax. + +8. Security Considerations + + Security issues are not discussed in this memo. + + +Wahl, Coulbeck, Howes & Kille [Page 37] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +9. Acknowledgements + + This document is based substantially on RFC 1778, written by Tim Howes, + Steve Kille, Wengyik Yeong and Colin Robbins. + + Many of the attribute syntax encodings defined in this document are + adapted from those used in the QUIPU and the IC R3 X.500 + implementations. The contributions of the authors of both these + implementations in the specification of syntaxes in this document are + gratefully acknowledged. + +10. Authors Addresses + + Mark Wahl + Critical Angle Inc. + 4815 West Braker Lane #502-385 + Austin, TX 78759 + USA + + EMail: M.Wahl@critical-angle.com + + + Andy Coulbeck + ISODE Consortium + The Dome, The Square + Richmond TW9 1DT + United Kingdom + + Phone: +44 181-332-9091 + EMail: A.Coulbeck@isode.com + + + + + Tim Howes + Netscape Communications Corp. + 501 E. Middlefield Rd + Mountain View, CA 94043 + USA + + Phone: +1 415 254-1900 + EMail: howes@netscape.com + + + Steve Kille + ISODE Consortium + The Dome, The Square + Richmond + TW9 1DT + UK + + Phone: +44-181-332-9091 + EMail: S.Kille@isode.com + +Wahl, Coulbeck, Howes & Kille [Page 38] + +INTERNET-DRAFT LDAP Standard and Pilot Attributes October 1996 + +11. Bibliography + + [1] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol + (Version 3)", INTERNET-DRAFT , + October 1996. + + [2] The Directory: Selected Attribute Types. ITU-T Recommendation + X.520, 1993. + + [3] The Directory: Models. ITU-T Recommendation X.501, 1993. + + [4] P. Barker, S. Kille, "The COSINE and Internet X.500 Schema", RFC + 1274, November 1991. + + [5] M. Wahl, S. Kille, "A UTF-8 String Representation of Distinguished + Names", INTERNET-DRAFT , August 1996. + + [6] S. Kille, "A String Representation for Presentation Addresses", + RFC 1278, University College London, November 1991. + + [7] Terminal Equipment and Protocols for Telematic Services - + Standardization of Group 3 facsimile apparatus for document + transmission. CCITT, Recommendation T.4. + + [8] JPEG File Interchange Format (Version 1.02). Eric Hamilton, + C-Cube Microsystems, Milpitas, CA, September 1, 1992. + + [9] The Directory: Selected Object Classes. ITU-T Recommendation + X.521, 1993. + + [10] H. Alvestrand, S. Kille, R. Miles, M. Rose, S. Thompson, + "Mapping between X.400 and RFC-822 Message Bodies", RFC 1495, + August 1993. + + [11] M. Davis, UTF-8, (WG2 N1036) DAM for ISO/IEC 10646-1. + + [12] Universal Multiple-Octet Coded Character Set (UCS) - Architecture + and Basic Multilingual Plane, ISO/IEC 10646-1 : 1993. + + [13] The Directory: Authentication Framework. ITU-T Recommendation + X.509 (1993). + + [14] Abstract Syntax Notation One (ASN.1) - Specification of Basic + Notation. ITU-T Recommendation X.680, 1994. + + + + + + + + + +Expires: April 1997 +Wahl, Coulbeck, Howes & Kille [Page 39] diff --git a/doc/drafts/draft-ietf-ldapext-acl-model-xx.txt b/doc/drafts/draft-ietf-ldapext-acl-model-xx.txt index ecdb41cd81..9beb721f9f 100644 --- a/doc/drafts/draft-ietf-ldapext-acl-model-xx.txt +++ b/doc/drafts/draft-ietf-ldapext-acl-model-xx.txt @@ -1,11 +1,19 @@ + + + + + + + Internet-Draft E. Stokes LDAP Extensions WG D. Byrne - Intended Category: Standards Track B. Blakley - Expires: 25 December 1999 IBM - 25 June 1999 + Intended Category: Standards Track IBM + Expires: 10 September 2000 B. Blakley + Dascom + 10 March 2000 Access Control Model for LDAP - + STATUS OF THIS MEMO @@ -18,7 +26,7 @@ working documents as Internet-Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at - any time. It is inappropriate to use Internet- Drafts as + any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." @@ -42,25 +50,30 @@ This document describes the access control model for the Lightweight Directory Application Protocol (LDAP) - directory service. It includes a description of the - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 1] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 1] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 + directory service. It includes a description of the model, the LDAP controls, and the extended operations to - the LDAP protocol. A separate document defines the - corresponding application programming interfaces (APIs). - RFC2219 [Bradner97] terminology is used. + the LDAP protocol. The current LDAP APIs are sufficient + for most access control operations. An API (in a + separate document) is needed for the extended operation + getEffectiveAccess and specifyCredentials. + + The keywords "MUST", "SHOULD", and "MAY" used in this + document are to be interpreted as described in + [Bradner97]. @@ -73,16 +86,15 @@ need to provide an access control model definition for LDAP directory content among servers within an enterprise and the Internet. Currently LDAP does not define an - access control model, but is needed to ensure consistent - secure access across heterogeneous LDAP implementations. - The major objective is to provide a simple, but secure, - highly efficient access control model for LDAP while also - providing the appropriate flexibility to meet the needs - of both the Internet and enterprise environments and - policies. This document defines the model and the - protocol extensions (controls and extended operations). - A separate document defines the corresponding application - programming interfaces (APIs). + access control model, but one is needed to ensure + consistent secure access across heterogeneous LDAP + implementations. The major objective is to provide a + simple, but secure, highly efficient access control model + for LDAP while also providing the appropriate flexibility + to meet the needs of both the Internet and enterprise + environments and policies. This document defines the + model and the protocol extensions (controls and extended + operations). 2. Overview @@ -97,51 +109,29 @@ subject and the rules which govern the use of the target object. - This proposal defines the protocol elements for - transmission of this access control policy data in an - LDAP environment and an attribute that defines the access - control mechanism in effect for a given part of the LDAP - namespace. The instantiation of an access control model - - - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 2] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 2] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 - at the directory server is not defined in this document. - By defining only what flows on the wire allows existing - access control mechanisms to be used at the directory - server. - - No mechanisms are defined in this document to control - access to access control information or for storage of - access control information at the server; this is vendor - dependent. - A separate requirements document for access control - exists. The access control model used the requirements - documents as a guideline for the development of this - specification and are reflected in this specification to - the extent that the working group could agree on an - access control model. The access control model defines - A wire protocol for interoperability: The existing - LDAP protocol flows for add, delete, modify, etc are - used to manipulate access control information. - There are additional LDAP controls and extended - protocol operations defined to further help - management of access control information: - getEffectiveRights and specifyCredentials. + LDAP protocol flows for add, delete, modify, and + search are used to manipulate access control + information. There is an additional LDAP control + and extended protocol operation defined, + getEffectiveRights, to further help management of + access control information. - A set of access control information (ACI) attributes for application portability: These attributes are @@ -153,25 +143,42 @@ information. - A set of attributes to identity the access control - mechanisms supported by a server. + mechanisms supported by a server and in a given part + of the namespace. Encoding of access control information on the wire is per the LDAPv3 specifications. + The instantiation of an access control model at the + directory server is not defined in this document. + + No mechanisms are defined in this document to control + access to access control information or for storage of + access control information at the server; this is vendor + dependent. + + A separate requirements document for access control + exists. The access control model used the requirements + documents as a guideline for the development of this + specification and are reflected in this specification to + the extent that the working group could agree on an + access control model. + + - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 3] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 3] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 @@ -186,11 +193,11 @@ security attribute's granted rights for the objects governed by the access control list to which it belongs. - The "access control policy information" (acpi) for an - object or a collection of objects defines which subject - security attributes entitle a subject to which granted - rights. The access control policy information for an - object is stored in an access control list. + The "access control information" (aci) for an object or a + collection of objects defines which subject security + attributes entitle a subject to which granted rights. + The access control information for an object may be + stored in an access control list. An "access decision" is a boolean-valued function which answers the question: "can the subject with these subject @@ -199,8 +206,8 @@ An "access decision function" is an algorithm which makes an access decision based on subject security attributes, - access control policy information, an object identifier, - and an operation name (possibly augmented by additional + access control information, an object identifier, and an + operation name (possibly augmented by additional contextual information). An "access decision function interface" is a programmatic @@ -223,14 +230,14 @@ - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 4] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 4] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 @@ -248,17 +255,6 @@ An "identity" is a subject security attribute which is unique to a single subject. - An "object" is the target of operations in an information - system. - - An "operation" is the result of executing the code - accessed through a named entry point in an information - system. - - An "operation name" is the name of the entry point - through which an operation is invoked in an information - system. - A "privilege attribute" is a subject security attribute which may be shared by several subjects. @@ -266,7 +262,7 @@ to authorize a requester to perform a specific operation on an object of a specific type. - A "right" is the basic unit of access control policy + A "right" is the basic unit of access control administration. For each object type in an information system, a security administrator defines a set of required rights for each operation. For each object in @@ -279,52 +275,48 @@ specified target object. A "role" is a privilege attribute asserting a subject's + organizational position and entitlement to perform the + operations appropriate to that organizational position. + A "subject' is an entity which initiate actions in an + information system. + A "subject security attribute" is a defined property + which is used by a security policy evaluation system to + make policy decisions. - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 5] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 5] - Internet-Draft Access Control Model 25 June 1999 - organizational position and entitlement to perform the - operations appropriate to that organizational position. - A "subject" is an entity which intiates actions in an - information system. + Internet-Draft Access Control Model 10 March 2000 - A "subject security attribute" is a defined property - which is used by a security policy evaluation system to - make policy decisions. 4. The Model + The access control mechanism described in this draft + addresses these activities: - 4.1 Access Control Activity Lifecycle - - The access control proposal described in this draft - addresses four activities: + - Definition of subject security attributes + information - - Creation of subject security attribute information - and access control policy information + - Definition of access control policy - - Retrieval of subject security attribute information - at the time an access request is made + - Retrieval of subject security attributes - - Evaluation of access requests against policy, - resulting in an access decision + - Retrieval of effective access rights - - Replication of access control policy information - from one server to another + - Externalization of access control policy information - 4.2 Access Control Information Model + 4.1 Access Control Information Model This document does not define formats for storage of access control information; it does define the @@ -341,50 +333,65 @@ - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 6] - Internet-Draft Access Control Model 25 June 1999 - The diagram below illustrates the componentry of an LDAP + + + + + + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 6] + + + + + + + Internet-Draft Access Control Model 10 March 2000 + + + + The diagram below illustrates the componentry of a LDAP system and the placement of the function specified in this draft. - +-------------+ - | Application | - +-------------+ - +--------+ - | LDAP | - | Client | - +--------+ - | - | - | <-- LDAP Extended Access Control - Controls - | or Extended Access Control - Operations - v - +-----------------------------+ - | LDAP Server (e.g. SLAPD) | - +-----------------------------+ - . | - . | - . | - . | - v v - +----------+ +-----------+ - | Access | | | - | Control |<.....| Datastore | - | Manager | | | - +----------+ +-----------+ - - LDAP clients use the controls and extended operations + +-------------+ + | Application |<--attrs to address ACI + +-------------+ - ldapACI + +--------+ - policyOwner + | LDAP | + | Client | + +--------+ + | + | <-- LDAP control + | - getEffectiveAccess + | + | <-- LDAP extended operation + | - getEffectiveAccess + v + +-----------------------------+ + | LDAP Server (e.g. SLAPD) | + +-----------------------------+ + . | + . | + . | + . | + v v + +----------+ +-----------+ + | Access | | |<-attrs to define + | Control |<--| Datastore | access control mechanisms + | Manager | | | - supportedACIMechanisms + +----------+ +-----------+ - aCIMechanisms + + LDAP clients use the control and extended operation specified in this document to administer access control policy enforced by LDAP servers. Servers may store access control information in any way they choose. In @@ -392,1273 +399,1422 @@ of their datastores to store and enforce LDAP access control, or they may implement access control managers external to their datastores. Datastores and external - access control managers may implement any access control + access control managers may implement any access control rule syntax and semantics they choose, as long as the - semantics is compatible with that defined in the section + semantics are compatible with that defined in the section titled "Operational Semantics of Access Control - Operations" (found after the control and extended - + Operations". - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 7] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 7] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 - operation definition). The access control administration mechanisms specified in this document are neutral with respect to policy inheritance mechanisms, explicit vs. implicit denial, and group nesting. - 4.3 Bind and Credentials - - A bind authenticates a principal to the directory. A - principal is represented by a DN. A principal has a set - of credentials that are used for determining whether - access to resources specified in ldap operations. These - credentials may be pushed to the server by the client or - may be pulled by the server from the directory data. - Credentials may be local with respect to the server. If - not local (owned by another server or administrative - scope), then the server may decide to define a trust - model that states how to evaluate the trust of a - credential at bind time. The definition of such a trust - model is outside the scope of this document. - - 5. Access Control Information Schema + 5. Access Control Mechanism Attributes + There are several attributes defined associated with + access control. Two attributes are defined to identify + which access control mechanisms are supported by a given + server and by a given subtree: supportedACIMechanisms + and aCIMechanisms. - 5.1 Attributes + 5.1 Root DSE Attribute for Access Control Mechanism - 5.1.1 Root DSE Attribute for Access Control Mechanism - - The following attribute may be included in the Root DSE. + The server advertises which access control mechanisms it + supports by inclusion of the 'supportedACIMechanisms' + attribute in the root DSE. This attribute is a list of + OIDs, each of which identify an access control mechanism + supported by the server. ( NAME 'supportedACIMechanisms' DESC list of access control mechanisms supported by this directory server SYNTAX LDAPOID + USAGE dSAOperation ) - Two access control mechanisms are defined by this - document: + The access control mechanism defined is: LDAPv3 - X500 + Other vendor access control mechanisms can be defined (by + OID) and are the responsibility of those vendors to + provide the definition and OID. + 5.2 Subschema Attribute for Access Control Mechanism - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 8] + A given naming context must provide information about + which access control mechanisms are in effect for that + portion of the namespace. The following attribute must + be in each subschema entry associated with a naming + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 8] - Internet-Draft Access Control Model 25 June 1999 - Other vendor access control mechanisms can be defined (by - OID) and are the responsibility of those vendors to - provide the definition and OID. + Internet-Draft Access Control Model 10 March 2000 + - 5.1.2 Subschema Attribute for Access Control Mechanism - A given naming context must provide information about - which access control mechanism is in effect for that - portion of the namespace. The following attribute must - be in each subschema entry associated with a naming context whose access control mechanism is different from adjacent naming contexts supported by that directory server. - - aCIMechanism lists the value (an OID) that defines - the access control mechanism in effect for the scope - of that subschema entry - - 5.2 Other Defined Parameters/OIDs - + aCIMechanisms lists the values (list of OIDs) that + defines the access control mechanism in effect for the + scope of that subschema entry. More than one mechanism + may be in effect for the scope of that subschema entry. - 5.2.1 Rights Families and Rights + ( + NAME 'aCIMechanisms' + DESC list of access control mechanisms supported + in this subtree + SYNTAX LDAPOID + USAGE dSAOperation + ) - The following rights families are defined: - LDAPv3 - X500 - Other parties can (and will) define other rights - families. It is the responsibility of those parties to - provide the definition and OID. - 5.2.1.1 LDAPv3 Rights Family + 6. Access Control Information Attributes - Access rights can apply to an entire object or to - attributes of the object. Each of the LDAP access rights - are discrete. One permission does not imply another - permission. The rights may be ORed together to provide - the desired rights list. - Rights which apply to attributes are: + The intent of the following attribute definitions is to + design a common interchange format. Any given LDAP + server should be able to translate the below defined + attributes into a meaningful operation requests. Each + server should be able to understand the attributes; there + should not be any ambiguity into what any part of the + syntax means. - 1 Read Read attribute values - 2 Write Write attribute values - 4 Search Search entries with specified attributes - 8 Compare Compare attributes + While the end goal is to have a common behavior model + between different LDAP server implementations, the + attribute definition alone will not ensure identical ACL + processing behavior between servers. The semantics of + how a server interprets the ACI syntax are defined in the + "Operational Semantics of Access Control' section of this + document. Additionally, while the server must recognize + and act on the attribute when received over the wire, + there are no requirements for the server to physically + store this attribute. + The attribute definition maintains an assumption that the + receiving server supports inheritance within the security + model. If the server does not support inheritance, the + receiving server must expand any inherited information - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 9] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 9] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 - Rights that apply to an entire object are: - 16 Add Add an object below this object - 32 Delete Delete this object - 64 EditDN Edit an object's DN + based on the scope flag. If the server does not support + partial inheritance and both the entry and subtree scope + are used, then entry is the prevailing scope. - Rights that apply to the object to which the directory - object points are: + Two attributes are defined so access control information + (ACI) can be addressed in a server independent of server + implementation. These attributes are used in typical + LDAP APIs and in LDIF output of ACI. These two attributes + may be queried or set on all directory objects: ldapACI + and policyOwner. Their BNF and definitions are defined + below. - 128 Manage Perform a privileged operation; used to - restrict access to operations which - read or write especially sensitive data - 256 Use Execute; useful in controlling access to - the objects referred to by directory - entries than in controlling access to - the directory entries themselves - 512 Get Get retrieves the attribute values - 1024 Set Set writes the attribute values - 5.2.1.2 The X.500 Rights Family + 6.1 The BNF - + < ldapACI > ::= < acl entry syntax > - 5.2.2 DN Types + < acl entry syntax > ::= + '#' + + '#' + + < rights > + '#' + < dnType > + + '#' + < subjectDn > - The following DN Types are defined: + < policyOwner > ::= < familyOid > + '#' + + + '#' +< dnType > + '#' + < subjectDn > - - access-id, OID= + < subjectDn > ::= < printable string > | "public" | "this" - - group, OID= + < familyOid > ::= < oid > - - role, OID= + ::= "entry" | "subtree" - access-id, group, and role MUST be supported. An acess- - id is a non-collection (non-group and non-role objects) - DN that can be authenticated. + < dnType > ::= "access-id" | "role" | "group" | "subtree" + | "ipAddress" | "kerberosID" + | - Other parties can (and will) define other DN Types. It - is the responsibility of those parties to provide the - definition and OID. + < kerberosID > ::= < userID > + '@' + < realm > + < userID > ::= < printableString > + < realm > ::= < printableString > + < rights > ::= "grant" + ';' + + ';'+ + | "deny" + ';' + + ';'+ | + "grant"+';'++';'+"deny"+';'++';'+ + < permissions > ::= [ ] | [ + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 10] - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 10] + Internet-Draft Access Control Model 10 March 2000 - Internet-Draft Access Control Model 25 June 1999 + + [ ',' + ] ]* - 6. Access Control Parameters for LDAP Controls & Extended - Operations + < attr > ::= ["collection" + ':' + [ "[all]" | "[entry]" + | ] ] + | ["attribute" + ':' ] - This section defines the parameters used in the access - control LDAP controls and extended operations in this - document. + < permission > ::= "a" | "d" | "r" | "s" | "w" | + "c" | "e" | "b" - targetDN specifies the initial directory entry in DN - syntax on which the control or extended operation is - performed. + These are the permissions defined for the IETF LDAP family + OID. + "a" corresponds to add + "d" corresponds to delete + "r" corresponds to read + "s" corresponds to search + "w" corresponds to write + "c" corresponds to compare + "e" corresponds to editDN + "b" corresponds to browseDN - whichObject specifies whether the access control - information which is get/set is for the target directory - entry (ENTRY) or the target directory entry and its - subtree (SUBTREE). - rightsFamily specifies the family of rights that will be - get/set for the control or extended operation performed. - A rights family has a defined set of rights. + 6.2 Other Defined Parameters - rightsList in the SearchResultEntry is of the form - specified in the LDIF BNF for . + This section defines additional parameters that are used + in the two attributes that address access control + information. - dnType speficies the type of subject security attribute. - Defined types are access-id, group, and role. - subjectDN is a LDAP string that defines the subject or - value of the dnType. The subjectDN may be a DN or - another string such as IPAddress (dotted-decimal string - representation) on which access control is get/set. If - the subject is an entry in the directory, then the syntax - of the LDAP string is DN. We define two well-known - subjectDNs, the strings + 6.2.1 Families and Rights - - public - meaning public access for all users + The familyOID tells what permission set etc. will follow + in the string. This allows a different permission set, + scope etc., but with the same syntax. - - this - meaning the user whose name matches the entry - being accessed + The following family is defined: + IETF-LDAPv3 - Four operations are defined: + Other families can be defined (by OID). It is the + responsibility of those parties to provide the definition + and OID. - - ACI_GRANT grants the rights specified in the - rightsList for the given subject. If an access - control list does not exist for the specified - entry/attribute, then the access control list is + 6.2.1.1 IETF-LDAPv3 Family + Access rights can apply to an entire object or to - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 11] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 11] - Internet-Draft Access Control Model 25 June 1999 + Internet-Draft Access Control Model 10 March 2000 - created with the granted rights for the given - subject. If the access control list already exists - for the specified entry/attribute, then the access - control list is modified to grant the rights for the - given subject. - - ACI_DENY denies the rights specified in the - rightsList for the given subject. No implementation - is implied for this operation. For example, denial - of rights may be implemented as explicit denial - (negative rights) on the access control list or - removal of rights from the access control list. - - ACI_REPLACE replaces the entire access control list - for the specified entry/attribute. If an access - control list does not exist for the specified - entry/attribute, then the access control list is - created with the granted rights for the given - subject. + attributes of the object. Each of the LDAP access rights + are discrete. One permission does not imply another + permission. The rights which apply to attributes and the + entry parallel the type of ldap operations that can be + performed. - - ACI_DELETE deletes the entire access control list - for the specified entry/attribute. + Rights which apply to attributes: - attrs specifies the list of attributes against which the - operation is performed. attrs can be defined using a - LDAP filter expression. + r Read Read attribute values + w Write Write attribute values + s Search Search entries with specified attributes + c Compare Compare attributes + Rights that apply to an entire entry: - 7. Access Control Information (ACI) Controls + a Add Add an entry below this entry + d Delete Delete this entry + e EditDN Edit an entry's DN + b BrowseDN Browse an entry's DN - The access control information controls provide a way to - manipulate access control information in conjunction with - an LDAP operation such as ldap_add, ldap_modify, or - ldap_search. Three LDAP controls are defined for - transmission of access control information. These - controls allow access control information to be get/set - while manipulating other directory information. The - controls are: + When searching, the ldap search filter specifies the + returned set of attributes. To do the search, browse (b) + must be set for the entry (you can search only entries + that you have permission to search so you can't discover + things you don't have permission to) and search (s) must + be set for all attributes used in the filter if you are + testing for existence, otherwise search (s) and read (r) + must be set for all attributes used in the filter because + the filter specifies a test for other than existence. + For a search to return attribute names only, search (s) + must be set for the attribute. For a search to return + attribute names and values, search (s) and read (r) must + be set for the attribute. Search (s) implies knowledge + of the attribute; read (r) implies knowledge of the + value. - - getEffectiveRights to obtain the effective rights - for a given directory entry(s) for a given subject - during a ldap_search operation - - specifyCredentials to specify a set of credentials - for the bind identity (DN) during a ldap_bind + 6.2.2 DN Types + The following DN Types strings are defined and MUST be + supported: + - access-id - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 12] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 12] - Internet-Draft Access Control Model 25 June 1999 - operation - 7.1 getEffectiveRights Control + Internet-Draft Access Control Model 10 March 2000 - 7.1.1 Request Control - This control is included in the ldap_search message as - part of the controls field of the LDAPMessage, as - defined in Section 4.1.12 of [LDAPv3]. + - group - The controlType is set to . The - criticality MAY be either TRUE or FALSE (where absent is - also equivalent to FALSE) at the client's option. The - controlValue is an OCTET STRING, whose value is the BER - encoding of a value of the following SEQUENCE: + - role - getEffectiveRightsRequest ::= SEQUENCE { - targetDN LDAPDN, - effectiveRightsRequest SEQUENCE OF SEQUENCE { - rightsFamily LDAPOID | "*", - whichObject ENUMERATED { - LDAP_ENTRY (1), - LDAP_SUBTREE (2) - }, - dnType LDAPOID | "*", - subjectDN LDAPString, - } - } + The following DN Types strings are defined and SHOULD be + supported: - The targetDN specifies the initial directory entry in DN - syntax on which the getEffectiveRights control is - performed. request is a set of sequences that state the - whichObject (entry or entry plus subtree) and specifics - of the control request to be performed. One or more - rightsFamily can be be obtained for a given subjectDN ad - dnType. A "*" in the rightsFamily field indicates that - the rights for all rights families defined for the - subjectDN / dnType are to be returned. This control is - applied to the scope set by the ldap_search operation, - i.e. base, one-level, subtree. + - ipAddress - 7.1.2 Response Control + - kerberosID - This control is included in the ldap_search_response + An access-id is a non-collection (non-group and non-role + objects) DN that can be authenticated. + groupOfNames and groupOfUniqueNames (or subclasses from + those object classes) must be recognized as a collection + object. This aids in interoperability during + replication. - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 13] + Other parties can (and will) define other DN Types. It + is the responsibility of those parties to provide the + definition. + 6.3 Basic ACI Attribute (ldapACI) + ( + NAME 'ldapACI' + DESC 'ldap access control information' + EQUALITY caseIgnoreMatch + SYNTAX directoryString + USAGE directoryOperation + ) + Within the access control syntax, the family OID + describes the permissions, dnType, subjectDn and scope + that will be found in the following string. If the OID + within the ldapACI attribute is listed as other than the + IETF-LDAPv3 family OID, the syntax is the same, but one + or more of the scope, dnType, subjectDn or permissions + may vary from the defined syntax. + Within the access control syntax, there is a string which + describes the rights. This is a composite of the + permissions and resources to which the subject is being - Internet-Draft Access Control Model 25 June 1999 + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 13] - message as part of the controls field of the LDAPMessage, - as defined in Section 4.1.12 of [LDAPv3]. - The controlType is set to . The - criticality MAY be either TRUE or FALSE (where absent is - also equivalent to FALSE). The controlValue is an OCTET - STRING, whose value is the BER encoding of a value of the - following SEQUENCE: - getEffectiveRightsResponse ::= { - result ENUMERATED { - success (0), - operationsError (1), - unavailableCriticalExtension (12), - noSuchAttribute (16), - undefinedAttributeType (17), - invalidAttributeSyntax (21), - unavailable (52), - unwillingToPerform (53), - other (80) - } - } - The effective rights returned are returned with each - entry returned by the search result. The control - response for ldap_search is: - PartialEffectiveRightsList ::= SEQUENCE OF SEQUENCE { - rightFamily LDAPOID, - rightsList ENUMERATED, - whichObject ENUMERATED { - LDAP_ENTRY (1), - LDAP_SUBTREE (2) - } - } + Internet-Draft Access Control Model 10 March 2000 - Although this extends the search operation, there are no - incompatibilities between versions. LDAPv2 cannot send a - control, hence the above structure cannot be returned to - a LDAPv2 client. A LDAPv3 client cannot send this - request to a LDAPv2 server. A LDAPv3 server not - supporting this control cannot return the additional - data. + granted or denied access. The set of permissions is + fixed. Either or both of the actions "grant" | "deny" + may be used when creating or updating ldapACI. + describes either an attribute name or an attribute + collection. The keyword attribute indicates that the + following printable string refers to an attribute name. + If the string refers to an attribute not defined in the + given server's schema, the server SHOULD report an error. + The keyword "collection" indicates that the string that + follows describes a group of attributes. The method for + grouping attributes is server specific. Another option + for the collection printable string is "[entry]". This is + provided to describe permissions which apply to an entire + object. This could mean actions such as delete the + object, or add a child object. The third option for a + collection is "[all]" which means the permission set + should apply to all attributes. Even if the server does + not support attribute grouping, it MUST recognize the + "[all]" and "[entry]" keywords. If the server receives + an unrecognized attribute collection name, the server + SHOULD return an error. If the server supports grouping, + the grouping is server and implementation specific. + If the keyword "[all]" and another attribute are both + specified within an aci, the more specific permission set + for the attribute overrides the less specific permission + set for "[all]". - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 14] + All permissions (for grant and deny) for an attribute and + a given DN MUST be contained within one ldapACI value, + i.e. (in abbreviated form) + ldapACI: ...grant attr1 DN1 + ldapACI: ...deny attr1 DN1 + must be ldapACI: ...grant ... deny... attr1 DN1 + Using the defined BNF it is possible for the permission + string to be empty. The ACI + ldapACI: 1.2.3.4#subtree#grant;; + attribute:attr1#group#cn=Dept XYZ,c=US + ldapACI: 1.2.3.4#subtree#grant;r,s; - Internet-Draft Access Control Model 25 June 1999 + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 14] - 7.1.3 Client-Server Interaction - The getEffectiveRightsRequest control requests the rights - that MUST be in effect for requested directory - entry/attribute based on the subject DN. The server that - consumes the search operation looks up the rights for the - returned directory information based on the subject DN - and returns that rights information. - There are six possible scenarios that may occur as a - result of the getEffectiveRights control being included - on the search request: - 1. If the server does not support this control and the - client specified TRUE for the control's criticality - field, then the server MUST return - unavailableCriticalExtension as a return code in - the searchResponse message and not send back any - other results. This behavior is specified in - section 4.1.12 of [LDAPv3]. - 2. If the server does not support this control and the - client specified FALSE for the control's - criticality field, then the server MUST ignore the - control and process the request as if it were not - present. This behavior is specified in section - 4.1.12 of [LDAPv3]. + Internet-Draft Access Control Model 10 March 2000 - 3. If the server supports this control but for some - reason such as cannot process specified - rightsFamily and the client specified TRUE for the - control's criticality field, then the server SHOULD - do the following: return - unavailableCriticalExtension as a return code in - the searchResult message. - 4. If the server supports this control but for some - reason such as cannot process specified - rightsFamily and the client specified FALSE for the - control's criticality field, then the server should - process as 'no rights returned for that family' and - include the result Unavailable in the - getEffectiveRightsResponse control in the - searchResult message. + collection:[all]#group#cn=Dept XYZ,c=US + means that this group (Dept XYZ) is granted permission to + read and search all attributes except attr1 because attr1 + is more specific than "[all]". - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 15] + 6.3.1 LDAP Operations + The attributes which are defined for access control + interchange may be used in all LDAP operations. + Within the ldapmodify-delete operation, the entire acl + may be deleted by specifying + dn: cn = some Entry + changetype: modify + delete: ldapACI + In this case, the entry would then inherit its ACI from + some other node in the tree depending on the server + inheritance model. - Internet-Draft Access Control Model 25 June 1999 + Similarly, if all values of ldapACI are deleted, then the + access control information for that entry is defined by + that implementation's inheritance model. + 6.3.2 Grant/Deny Evaluation Rules - 5. If the server supports this control and can return - the rights per the rightsFamily information, then - it should include the getEffectiveRightsResponse - control in the searchResult message with a result - of success. + More specific policies must override less specific ones + (e.g. individual user entry in ACI takes precedence over + group entry). - 6. If the search request failed for any other reason, - then the server SHOULD omit the - getEffectiveRightsResponse control from the - searchResult message. + Deny takes precedence over Grant. When there are + conflicting ACI values, deny takes precedence over grant. + Deny is the default when there is no access control + information. - The client application is assured that the correct rights - are returned for scope of the search operation if and - only if the getEffectiveRightsResponse control returns - the rights. If the server omits the - getEffectiveRightsResponse control from the searchResult - message, the client SHOULD assume that the control was - ignored by the server. + Precendence of Scope Types (highest to lowest) - The getEffectiveRightsResponse control, if included by - the server in the searchResponse message, should have the - getEffectiveRightsResult set to either success if the - rights are returned or set to the appropriate error code - as to why the rights could not be returned. + - entry - The server may not be able to return a right because it - may not exist in that directory object's attribute; in - this case, the rights request is ignored with success. + - subtree - 7.2 specifyCredentials Control - 7.2.1 Request Control - This control is included in the ldap_bind message as - part of the controls field of the LDAPMessage, as - defined in Section 4.1.12 of [LDAPv3]. + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 15] - The controlType is set to . The - criticality MAY be either TRUE or FALSE (where absent is - also equivalent to FALSE) at the client's option. The - controlValue is an OCTET STRING, whose value is the BER - encoding of a value of the following SEQUENCE: - specifyCredentialRequest ::= SEQUENCE { - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 16] + Internet-Draft Access Control Model 10 March 2000 + Precedence of Privilege Attribute dnTypes within a scope + (highest to lowest): + - ipAddress - Internet-Draft Access Control Model 25 June 1999 + - access-id, kerberosID (both same precedence) + - group + - role - credential LDAPString - } - } + - subtree - The credential specifies the credential (e.g. groups, - roles, etc) that the client is requesting be associated - with the bind DN for access control determination in - subsequent ldap operations. This provides a 'push' model - for credentials where the client attempts to 'push' the - credential to the server. The server may process at bind - time as follows: + Although other types can be defined given the BNF, use of + the well-known types aids in interoperability and + operational consistency. - - server may unconditionally ignore - - server may unconditionally accept + 6.4 Policy Owner Attribute (policyOwner) - - server may define trust model and evaluate of the - trust of each credential + ( + NAME 'policyOwner' + DESC 'Policy Owner Access Control Information' + EQUALITY caseIgnoreMatch + SYNTAX directoryString + USAGE directoryOperation + ) - If this control is not used, it is assumed that the - server determines (pulls) the credentials associated with - the bind DN when needed in subsequent ldap operations to - provide access control. + Policy ownership controls administrative subdomains. It + can also control who has permission to set / change acls + for implementations that do not have ACI controlling + access to itself. If there are multiple policy owners + it is implementation specific as to the behavior of + whether policy owner #1 can override policy owner # 2. - 7.2.2 Response Control + The syntax for policyOwner includes the 'scope' flag. + Servers which do not support inheritance must expand the + policyOwner inheritance similar to the expansion of the + ACI. The scope and any inheritance hierarchy for policy + ownership is distinct from any inheritance hierarchy + defined for ACI values. - This control is included in the ldap_bind message as part - of the controls field of the LDAPMessage, as defined in - Section 4.1.12 of [LDAPv3]. + If the policy owner is not specified for any object in + the tree, behavior is implementation defined. For + instance, if no object anywhere in the tree has a policy - The controlType is set to . The - criticality MAY be either TRUE or FALSE (where absent is - also equivalent to FALSE). The controlValue is an OCTET - STRING, whose value is the BER encoding of a value of the - following SEQUENCE: - specifyCredentialsResponse ::= { - result ENUMERATED { - success (0), - operationsError (1), - unavailableCriticalExtension (12), - unavailable (52), - unwillingToPerform (53), - other (80) - } + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 16] - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 17] + Internet-Draft Access Control Model 10 March 2000 - Internet-Draft Access Control Model 25 June 1999 + owner, then the server could simply assert that the 'root + DN' is considered the policy owner for all objects. An + alternate approach might be that the implementation + defines the entryDN to be the policy owner. - } + 6.5 ACI Examples - No data is returned; just the result is returned. + The examples use a family OID = 1.2.3.4 - Although this extends the bind operation, there are no - incompatibilities between versions. LDAPv2 cannot send a - control. A LDAPv3 client cannot send this request to a - LDAPv2 server. A LDAPv3 server not supporting this - control cannot return the additional data. - 7.2.3 Client-Server Interaction + 6.5.1 Attribute Definition - The specifyCredentialsRequest control specifies the - credentials that the client wants the server to use for - access control in subsequent ldap operations. The server - that consumes the bind operation may unconditionally - accept, ignore, or evaluate the trust of the specified - credentials at bind time and returns only a success or - failure response (no data returned). + The following two examples show an administrative + subdomain being established. The first example shows a + single user being assigned the policyOwner for the entire + domain. The second example shows a group of IDs assigned + to the policy Owner. - There are six possible scenarios that may occur as a - result of the specifyCredential control being included on - the bind request: + policyOwner: 1.2.3.4#subtree#access-id#cn=Hoyt + policyOwner: 1.2.3.4#subtree#group#cn=System + Owners,o=Company - 1. If the server does not support this control and the - client specified TRUE for the control's criticality - field, then the server MUST return - unavailableCriticalExtension as a return code in - the bindResponse message. This behavior is - specified in section 4.1.12 of [LDAPv3]. + The next example shows a ldapACI attribute where a group + "cn=Dept XYZ, c=US" is being given permissions to read, + search and compare attribute attr1. The permission + applies to the entire subtree below the node containing + this ACI. - 2. If the server does not support this control and the - client specified FALSE for the control's - criticality field, then the server MUST ignore the - control and process the request as if it were not - present. This behavior is specified in section - 4.1.12 of [LDAPv3]. + ldapACI:1.2.3.4#subtree#grant;r,s,c; + attribute:attr1#group#cn=Dept XYZ,c=US - 3. If the server supports this control but for some - reason such as cannot process specified credential - (e.g. server decided to evaluate the trust of that - credential and the result is the server not - trusting all the credentials or unconditionally - ignores the credential) and the client specified + The next example shows an ACI attribute where a role + "cn=SysAdmins,o=Company" is being given permissions to + add objects below this node and read, search, and compare + attributes attr2 and attr3. The permission applies to the + entire subtree below the node containing this ACI. + ldapACI: 1.2.3.4#subtree#grant;a; + collection:[entry]#role#cn=SysAdmins,o=Company + ldapACI: 1.2.3.4#subtree#grant;r,s,c; + attribute:attr2#role#cn=SysAdmins,o=Company - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 18] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 17] - Internet-Draft Access Control Model 25 June 1999 - TRUE for the control's criticality field, then the - server SHOULD do the following: return - unavailableCriticalExtension as a return code in - the bindResult message and omit the - specifyCredentialResponse control in the bindResult - message. + Internet-Draft Access Control Model 10 March 2000 - 4. If the server supports this control but for some - reason such as cannot process specified credential - (e.g. server decided to evaluate the trust of that - credential and the result is the server not - trusting all the credentials or unconditionally - ignores the credential) and the client specified - FALSE for the control's criticality field, then the - server should process as 'credential ignored' and - include the result Unavailable in the - specifyCredentialResponse control in the bindResult - message. - - 5. If the server supports this control and evaulates - the trust of that credential and the result is the - server trusting all the credentials, then it should - include the specifyCredentialResponse control in - the bindResult message with a result of success. - - 6. If the bind request failed for any other reason, - then the server SHOULD omit the - specifyCredentialResponse control from the - bindResult message. - The client application is assured that the correct - credentials are used by the server when specified by the - client for subsequent ldap operations if and only if the - specifyCredentialResponse is successful. If the server - omits the specifyCredentialResponse control from the - bindResponse message, the client SHOULD assume that the - control was ignored by the server. - The specifyCredentialResponse control, if included by the - server in the bindResponse message, should have the - bindResult set to either success if the credentials were - accepted by the server or set to the appropriate error - code as to why the credentials were not accepted. + ldapACI: 1.2.3.4#subtree#grant;r,s,c; + attribute:attr3#role#cn=SysAdmins,o=Company + 6.5.2 Modifying the ldapACI Values + Modify-Replace works as defined in the ldap oepration + modify. If the attribute value does not exist, create the + value. If the attribute does exist, replace the value. If + the ldapACI value is replaced, all ldapACI values are + replaced. + A given ldapACI for an entry: - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 19] + ldapACI: 1.2.3.4#subtree#deny;r,w; + collection:[all]#group#cn=Dept ABC + ldapACI: 1.2.3.4#subtree#grant;r; + attribute:attr1#group#cn=Dept XYZ + perform the following change: + dn: cn=someEntry + changetype: modify + replace: ldapACI + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all];#group#cn=Dept LMN + The resulting ACI is: + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all];#group#cn=Dept LMN - Internet-Draft Access Control Model 25 June 1999 + ( ldapACI values for Dept XYZ and ABC are lost through the + replace ) + During an ldapmodify-add, if the ACI does not exist, the + create the ACI with the specific ldapACI value(s). If the + ACI does exist, then add the specified values to the given + ldapACI. For example a given ACI: + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all]#group#cn=Dept XYZ - 8. Access Control Extended Operations + with a modification: - Two extended operations (analogous to the controls) are - defined for transmission of access control information. - These operations help with the management of access - control information independent of manipulating other - directory information. The extended operations are: - - LDAP Get Effective Rights to obtain the effective - rights for a given directory entry for a given - subject - 8.1 LDAP Get Effective Rights Operation + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 18] - ldapGetEffectiveRightsRequest ::= [APPLICATION 23] - SEQUENCE { - requestName [0] , - requestValue [1] OCTET STRING OPTIONAL } - where - requestValue ::= SEQUENCE { - targetDN LDAPDN, - updates SEQUENCE OF SEQUENCE { - rightsFamily LDAPOID | "*", - whichObject ENUMERATED { - LDAP_ENTRY (1), - LDAP_SUBTREE (2) - }, - dnType LDAPOID | "*", - subjectDN LDAPString, - } - } - The requestName is a dotted-decimal representation of the - OBJECT IDENTIFIER corresponding to the request. The - requestValue is information in a form defined by that - request, encapsulated inside an OCTET STRING. - The server will respond to this with an LDAPMessage - containing the ExtendedResponse which is a rights list. + Internet-Draft Access Control Model 10 March 2000 - ldpGetEffectiveRightsResponse ::= [APPLICATION 24] - SEQUENCE { + dn: cn=someEntry + changetype: modify + add: ldapACI + ldapACI: 1.2.3.4#subtree#grant;r; + attribute:attr1#group#cn=Dept XYZ - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 20] + would yield an multi-valued aci of: + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all]#group#cn=Dept XYZ + ldapACI: 1.2.3.4#subtree#grant;r; + attribute:attr1#group#cn=Dept XYZ + To delete a particular ACI value, use the regular ldapmodify + - delete syntax + Given an ACI of: + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all]#group#cn=Dept XYZ + ldapACI: 1.2.3.4#subtree#grant;r; + attribute:attr1#group#cn=Dept XYZ - Internet-Draft Access Control Model 25 June 1999 + dn: cn = some Entry + changetype: modify + delete: ldapACI + ldapACI: 1.2.3.4#subtree#grant;r; + attribute:attr1#group#cn=Dept XYZ + would yield a remaining ACI on the server of + ldapACI: 1.2.3.4#subtree#grant;r,w; + collection:[all]#group#cn=Dept XYZ - COMPONENTS OF LDAPResult, - responseName [10] OPTIONAL, - effectiveRights [11] OCTET STRING OPTIONAL } - where + 6.5.3 Evaluation - effectiveRights ::= SEQUENCE OF SEQUENCE { - rightFamily LDAPOID, - rightsList ENUMERATED, - whichObject ENUMERATED { - LDAP_ENTRY (1), - LDAP_SUBTREE (2) - }, - subjectDnType LDAPOID, - subjectDN LDAPSTRING - } + These examples assume that the ldapACI entries listed in + each example are the only ACI which applies to the entry + in question; if backing-store ACI also exists, the + effective policy may be different from that listed in + each example. See section 7 for a discussion of the + semantics of ldapACI entries when backing-store ACI + administration is also used. - If the server does not recognize the request name, it - MUST return only the response fields from LDAPResult, - containing the protocolError result code. + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 19] - 9. Access Control Information Attributes/LDIF - The intent of the following attribute definitions is to - design a common interchange format. Any given LDAP server - should be able to translate the below defined attributes - into a meaningful operation requests. Each server should be - able to understand the attributes; there should not be any - ambiguity into what any part of the syntax means. - While the end goal is to have a common behavior model - between different LDAP server implementations, the attribute - definition alone will not ensure identical ACL processing - behavior between servers. The semantics of how a server - interprets the ACI syntax are not defined here. What 'deny' - means on server1 might be different than on server2. - Additionally, while the server must recognize and act on the - attribute when received over the wire, there are no - requirements for the server to actually implement this - attribute. - The attribute definition maintains an assumption that the - receiving server supports inheritance within the security + Internet-Draft Access Control Model 10 March 2000 - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 21] + Assume cn=jsmith is a member of group cn=G1. Assume + cn=jsmith is a member of group cn=G2. + Example #1 + dn: o=XYZ, c=US + ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr1; + #access-id#cn=jsmith,ou=ABC,o=XYZ,c=US + ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr1; + #group#cn=G1,ou=ABC,o=XYZ,c=US + What rights does cn=jsmith have to attr1 of o=XYZ,c=US? + Read (r) access; access-id is higher precedence than + group. - Internet-Draft Access Control Model 25 June 1999 + Example #2 + dn: o=XYZ, c=US + ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr2; + #group#cn=G1,ou=ABC,o=XYZ,c=US + ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr2; + #group#cn=G2,ou=ABC,o=XYZ,c=US + What rights does cn=jsmith have to attr2 of o=XYZ,c=US? + Read-write (r,w) access; ACI is combined because both + dnTypes (group) have same precedence. - model. If the server does not support inheritance, the - receiving server must expand any inherited information based - on the scope flag. + Example #3 + dn: o=XYZ, c=US + ldapACI: 1.2.3.4#subtree#grant;r,w;attribute:attr3; + #group#cn=G1,ou=ABC,o=XYZ,c=US + ldapACI: 1.2.3.4#subtree#deny;w;attribute:attr3; + #group#cn=G2,ou=ABC,o=XYZ,c=US + What rights does cn=jsmith have to attr3 of o=XYZ, c=US? + Read access; write is denied (deny has precedence over + grant). - 9.1 ACI Attributes - There are three attributes which may be queried or set on - all directory objects: aci, vendorAci and policyOwner. The - syntax of these attributes is defined below. + Example #4 + dn: o=XYZ, c=US + ldapACI: 1.2.3.4#subtree#grant;w;attribute:attr4; + #access-id#cn=jsmith,ou=ABC,o=XYZ,c=US + ldapACI: 1.2.3.4#subtree#grant;r;attribute:attr4; + #subtree#ou=ABC,ou=XYZ,c=US - 9.1.1 The BNF - < aci > ::= < acl syntax > + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 20] - < vendorAci > ::= + '#' + < printable string > - < acl syntax > ::= + '#' + + '#' - + < rights > + '#' + < dnType > - + '#' + < subjectDn > - < policyOwner > ::= < familyOid > + '#' + - + '#' +< dnType > + '#' + < subjectDn > - < subjectDn > ::= < printable string > - < familyOid > ::= < oid > - ::= "entry" | "subtree" | + Internet-Draft Access Control Model 10 March 2000 - < level > ::= numericstring - < dnType > ::= "access-id" | "role" | "group" - < rights > ::= [ ] | [ < right > + [ '$' - + ] * ] + What rights does cn=jsmith have to attr4 of o=XYZ, c=US? + Write (w); rights given to an access-id take precedence + over those given to a subtree. - < right > ::= + ';' + - + ';' + - < action > ::= "grant" | "deny" - < permissions > ::= [ ] | [ < permission > - + [ ',' + ] * ] + 7. Operational Semantics of Access Control Operations + The semantics of access control operations described in + this document are defined operationally in terms of + "histories". A history is a sequence of actions (x1, x2, + ..., xN). - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 22] + 7.1 Types of actions + We consider five types of actions: + - LDAP Access Control Policy Update actions: + invocations of ldap modify when used to add, delete, + or replace the aci attribute; invocations of ldap + add when used to add an entry with an aci attribute. + A LDAP Access Control Policy Update action may + replace the policy (by completely replacing the aci + attribute with new policy information) or it may + grant or deny specific rights while leaving others + unaffected. + - LDAP Access Control Policy Query operations: + invocations of ldap search when used to retrieve the + aci attribute; invocations of ldap search with the + getEffectiveRightsRequest control; invocations of + the ldapGetEffectiveRightsRequest extended + operation. + - Datastore Access Control Policy Update Actions: any + operation implemented by the server which LDAP is + using as its datastore which changes the access + policy enforced with respect to attempts to access + LDAP directory entries and their attributes. - Internet-Draft Access Control Model 25 June 1999 + - LDAP Access Request operations: invocations of LDAP + entry or attribute access operations (Read, Update, + Search, Compare, etc...). - < attrs > ::= [ < attributeString> - + [ ',' + < attributeString > ] * ] + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 21] - < attributeString > ::= "[all]" | "[entry]" - | - < permission > ::= "a" | "d" | "r" | "s" | "w" | - "c" | "g" | "s" | "m" | "u" | "e" - These are the permissions defined for the IETF family OID. - "a" corresponds to add - "d" corresponds to delete - "r" corresponds to read - "w" corresponds to write - "c" corresponds to compare - "g" corresponds to get - "s" corresponds to set - "m" corresponds to manage - "u" corresponds to use - "e" corresponds to editDn - 9.1.2 VendorACI - ( vendorAciOID NAME 'vendorACI' DESC 'Vendor specific - Access control information' EQUALITY caseIgnoreMatch SYNTAX - directoryString ) + Internet-Draft Access Control Model 10 March 2000 - The Vendor specific ACI information is listed in its own - attribute. This may be used by vendors to provide vendor - specific access control related information which can not be - expressed in defined ACISyntax. Within the vendorACI, the - oid determines the format or the printable string to follow. - 9.1.3 Policy Owner + - Other operations: anything else, including Datastore + operations which do not change the access policy + enforced by the server. - ( policySyntaxOID DESC 'PolicyOwner Syntax' ) ( - policyOwnerOID NAME 'policyOwner' DESC 'Policy Owner Access - Control Information' EQUALITY caseIgnoreMatch SYNTAX - policySyntaxOID ) - Policy ownership controls administrative subdomains. It can - also control who has permission to set / change acls for - implementations that do not have ACI controlling access to + 7.2 Semantics of Histories + The semantics of histories are defined as follows: + - LDAP Update (Replace), LDAP Query - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 23] + The Query will show that the subject has all rights + granted by the Update operation, and no rights not + granted by the Update operation. + - LDAP Update (Grant), LDAP Query + The Query will show that the subject has all rights + granted by the Update operation. The Query may show + that the subject also has other rights not granted + by the Update operation, depending on the policy in + force before the Update operation. + - LDAP Update (Deny), LDAP Query + The Query will show that the subject does not have + any right denied by the Update operation. The Query + may show that the subject has rights not denied by + the Update operation, depending on the policy in + force before the Update operation. + - LDAP Update (Replace), LDAP Access Request - Internet-Draft Access Control Model 25 June 1999 + The Request will succeed if it requires only rights + granted to the requesting subject by the Update + operation. The Request will fail if it requires any + right not granted by the Update operation. + - LDAP Update (Grant), LDAP Access Request + The Request will succeed if it requires only rights + granted to the requesting subject by the Update + operation. The Request may succeed if it requires + rights not granted by the Update operation, + depending on the policy in force before the Update - itself. If there are multiple policy owners it is - implementation specific as to the behavior of whether policy - owner #1 can override policy owner # 2. - The syntax for policyOwner includes the 'scope' flag. - Servers which do not support inheritance must expand the - policyOwner inheritance similar to the expansion of the ACI. - The scope and any inheritance hierarchy for policy ownership - is distinct from any inheritance hierarchy defined for ACI - values. - If the policy owner is not specified for any object in the - tree, behavior is implementation defined. For instance, if - no object anywhere in the tree has a policy owner, then the - server could simply assert that the 'root DN' is considered - the policy owner for all objects. An alternate approach - might be that the implementation defines the entryDN to be - the policy owner. + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 22] - 9.1.4 ACI - ( aciSyntaxOID DESC 'ACI Syntax' ) - ( aciOID NAME 'aci' DESC 'Access control information' - EQUALITY caseIgnoreMatch SYNTAX aciSyntaxOID ) - Within the access control syntax, the family OID describes - the permissions, dnType, subjectDn and scope that will be - found in the following string. If the OID within the ACI - attribute is listed as other than the IETF family oid, the - syntax is the same as listed below, but one or more of the - scope, dnType, subjectDn or permissions may vary from the - IETF defined syntax. - Within the access control syntax, there is a string which - describes the rights. This is a composite of the permissions - and resources to which the user is being granted or denied - access. The set of permissions is fixed. Either of the - actions "grant" | "deny" may be used when creating or - updating ACI. - The attributeString is an attribute Name (defined to be a - printable string). If the string refers to an attribute not - defined in the given server's schema, the server SHOULD - report an error. Another option for the attributeString is + Internet-Draft Access Control Model 10 March 2000 - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 24] + operation. + - LDAP Update (Deny), LDAP Access Request + The Request will fail if it requires any right + denied to the requesting subject by the Update + operation. If the Request requires only rights + which were not denied by the Update operation, it + may succeed, depending on the policy in force before + the Update operation. + - LDAP Update (Replace), Other, LDAP Query + The Query will show that the subject has all rights + granted by the Update operation, and no rights not + granted by the Update operation. + - LDAP Update (Grant), Other, LDAP Query - Internet-Draft Access Control Model 25 June 1999 + The Query will show that the subject has all rights + granted by the Update operation. The Query may show + that the subject also has other rights not granted + by the Update operation, depending on the policy in + force before the Update operation. + - LDAP Update (Deny), Other, LDAP Query + The Query will show that the subject does not have + any right denied by the Update operation. The Query + may show that the subject has rights not denied by + the Update operation, depending on the policy in + force before the Update operation. - "[entry]". This is provided to describe permissions which - apply to an entire object. This could mean actions such as - delete the object, or add a child object. The third option - for attributeString is "[all]" which means the permission - set should apply to all attributes. + - LDAP Update (Replace), Other, LDAP Access Request - If the keyword "[all]" and another attribute are both - specified within an aci, the more specific permission set - for the attribute overrides the less specific permission set - for "[all]". + The Request will succeed if it requires only rights + granted to the requesting subject by the Update + operation. The Request will fail if it requires any + right not granted by the Update operation. - If two ACIs contain identical familyOID, scope, DnTypes and - DNs, the permission given DN is specified in two distinct - acis on any given entry, the rights lists can be combined - into one list. For example, + - LDAP Update (Grant), Other, LDAP Access Request - aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ - aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ + The Request will succeed if it requires only rights + granted to the requesting subject by the Update + operation. The Request may succeed if it requires - is the equivalent of - aci: 1.2.3.4#subtree#grant;r,w;[all]; - r,attribute1#group#cn=Dept XYZ - Using the defined BNF it is possible for the permission - string to be empty. The ACI + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 23] - aci: 1.2.3.4#subtree#grant;;attribute1$grant;r,s; - [all]#group#cn=Dept XYZ,c=US - means that this group is granted permission to read and - search all attributes except attribute1. - Similarly, the ACI - aci: 1.2.3.4#subtree##group#cn=Dept XYZ, c=US - simply means that no permissions have been defined for this - group. It is up to the server implementation as to whether - the group does or does not receive permission to attributes - on an entry with an empty rights list. - Multiple attributeStrings can be listed after any given - permission set; for instance, "r,w ; attribute1, - attribute2". This means that if the server supports a + Internet-Draft Access Control Model 10 March 2000 - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 25] + rights not granted by the Update operation, + depending on the policy in force before the Update + operation. + - LDAP Update (Deny), Other, LDAP Access Request + The Request will fail if it requires any right + denied to the requesting subject by the Update + operation. If the Request requires only rights + which were not denied by the Update operation, it + may succeed, depending on the policy in force before + the Update operation. + - LDAP Update (Replace), Datastore Policy Update, LDAP + Query + The result of the Query is not defined. + - LDAP Update (Grant), Datastore Policy Update, LDAP + Query - Internet-Draft Access Control Model 25 June 1999 + The result of the Query is not defined. + - LDAP Update (Deny), Datastore Policy Update, LDAP + Query + The result of the Query is not defined. - attribute aggregation mechanism, attribute1 and attribute2 - should be considered to be part of the same group. If the - server does not support a grouping mechanism, the permission - set applies independently to attribute1 and attribute2. For - servers that do not support attribute grouping, "grant ; r,w - ; attribute1, attribute2" results in the same operations as - "grant ; r,w; attribute1$grant; r,w; attribute2" + - LDAP Update (Replace), Datastore Policy Update, LDAP + Access Request + The result of the Access Request is not defined. - 9.1.5 LDAP Operations + - LDAP Update (Grant), Datastore Policy Update, LDAP + Access Request - The attributes which are defined for access control - interchange may be used in all LDAP operations. + The result of the Access Request is not defined. - Within the ldapmodify-delete operation, the entire acl may - be deleted by specifying + - LDAP Update (Deny), Datastore Policy Update, LDAP + Access Request - dn: cn = some Entry - changetype: modify - delete: aci + The result of the Access Request is not defined. - In this case, the entry would then inherit its ACI from some - other node in the tree depending on the server inheritance - model. - Deleting the last ACI value from an entry is not the same as - deleting the ACI from the entry. It is possible for an entry - to contain an ACI with no values. In this case, nothing is - returned to the client when querying the aci. It is server - dependent whether access is granted or denied in the absence - of any ACI information. Deleting an ACI value which does - not exist will result in an unchanged ACI and a return code - specifying that the attribute value does not exist. - 9.2 Examples - 9.2.1 Attribute Definition + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 24] - Pretend IETFFamilyOID = 1.2.3.4 - The following two examples show an administrative - subdomain being established. The first example shows a - single user being assigned the policyOwner for the entire - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 26] + Internet-Draft Access Control Model 10 March 2000 + 8. Access Control Parameters for LDAP Controls & Extended + Operations + This section defines the parameters used in the access + control LDAP controls and extended operations in this + document. - Internet-Draft Access Control Model 25 June 1999 + targetDN specifies the initial directory entry in DN + syntax on which the control or extended operation is + performed. + whichObject specifies whether the access control + information (in the get effective rights control) which + is retrieved is for the target directory entry (ENTRY) or + the target directory entry and its subtree (SUBTREE). + family specifies the family OID that will be retrieved + for the get effective rights control or extended + operation performed. A family has a defined set of + rights, among other things. - domain. The second example shows a group of ids assigned - to the policy Owner. + rights in the get effective rights control or extended + operation response is of the form specified in the BNF + for . - policyOwner: 1.2.3.4#subtree#access-id#cn=Hoyt + dnType speficies the type of subject security attribute. + Defined types are specified in the BNF. - policyOwner: 1.2.3.4#subtree#group#cn=System Owners, - o=Company + subjectDN is a LDAP string that defines the subject or + value of the dnType. The subjectDN may be a DN or + another string such as IPAddress (dotted-decimal string + representation) on which access control is get/set. If + the subject is an entry in the directory, then the syntax + of the LDAP string is DN. The well-known subjectDNs + strings are defined - The next example shows an aci attribute where a group - "cn=Dept XYZ, c=US" is being given permissions to read, - search and compare attribute1. The permission should - apply to the entire subtree below the node containing - this ACI. + - public - meaning public access for all users - aci:1.2.3.4#subtree#grant;r,s,c; - attribute1#group#cn=Dept XYZ,c=US + - this - meaning the user whose name matches the entry + being accessed - The next example shows an ACI attribute where a role - "cn=SysAdmins,o=Company" is being given permissions to - add objects below this node, and read, search and compare - attributes 2 and 3. The permission should apply to the - entire subtree below the node containing this ACI. + - * - meaning everyone who has access to the entry - aci: 1.2.3.4#subtree#grant;a;[entry]$grant; - r,s,c;attribute2, attribute3#role# - cn=SysAdmins,o=Company - 9.2.2 Modifying the ACI Values - Replace works similarly to all other attributes. If the - attribute value does not exist, create the value. If the - attribute does exist, replace the value. If the ACI value - is replaced, all ACI values are replaced. - A given aci for an entry: - aci: 1.2.3.4#subtree#deny;r,w;[all]$grant;r,s,c; - attribute2#group#cn=Dept ABC + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 25] - aci: 1.2.3.4#subtree#grant;r;[all]$grant;r,s,c; - attribute1#group#cn=Dept XYZ - perform the following change: - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 27] + Internet-Draft Access Control Model 10 March 2000 + 9. Access Control Information (ACI) Controls + The access control information controls provide a way to + manipulate access control information in conjunction with + a LDAP operation. One LDAP control is defined. This + control allows access control information to be get/set + while manipulating other directory information for that + entry. The control is: + - getEffectiveRights to obtain the effective rights + for a given directory entry(s) for a given subject + during a ldap_search operation - Internet-Draft Access Control Model 25 June 1999 + 9.1 getEffectiveRights Control + 9.1.1 Request Control - dn: cn=someEntry - changetype: modify - replace: aci - aci: 1.2.3.4#subtree#grant;r,w;[all];#group#cn=Dept LMN + This control may only be included in the ldap_search + message as part of the controls field of the + LDAPMessage, as defined in Section 4.1.12 of [LDAPv3]. - The resulting acl is: + The controlType is set to . The + criticality MAY be either TRUE or FALSE (where absent is + also equivalent to FALSE) at the client's option. The + controlValue is an OCTET STRING, whose value is the BER + encoding of a value of the following SEQUENCE: - aci: 1.2.3.4#subtree#grant;r,w;[all];#group#cn=Dept LMN + getEffectiveRightsRequest ::= SEQUENCE { + effectiveRightsRequest SEQUENCE OF SEQUENCE { + family LDAPOID | "*", + whichObject ENUMERATED { + LDAP_ENTRY (1), + LDAP_SUBTREE (2) + }, + dnType "access-id"|"group"|"role"| + "ipAddress"|"kerberosID"| + | "*", + subjectDN LDAPString | "public" | + "this" | "*" + } + } - ( aci values for Dept XYZ and ABC are lost through the - replace ) + The effectiveRightsRequest is a set of sequences that + state the whichObject (entry or entry plus subtree) and - During an ldapmodify-add, if the ACI does not exist, the - create the ACI with the specific aci value(s). If the ACI - does exist, then add the specified values to the given ACI. - For example a given ACI: - aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ - with a modification: + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 26] - dn: cn=someEntry - changetype: modify - add: aci - aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ - would yield an multi-valued aci of: - aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ - aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ - To delete a particular aci value, use the regular ldapmodify - - delete syntax - Given an ACI of: - aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ - aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ - dn: cn = some Entry - changetype: modify - delete: aci - aci: 1.2.3.4#subtree#grant;r;attribute1#group#cn=Dept XYZ + Internet-Draft Access Control Model 10 March 2000 - would yield a remaining ACI on the server of + + + specifics of the control request to be performed. One or + more family can be be obtained for a given subjectDN ad + dnType. A "*" in the family field indicates that the + rights for all families defined for the subjectDN / + dnType are to be returned. A "*" in the dnType field + specifies that all DN types are to be used in returning + the effective rights. This control is applied to the + filter and scope set by the ldap_search operation, i.e. + base, one-level, subtree. So the attributes/values + returned are defined by the ldap_search operation. + + 9.1.2 Response Control + + This control is included in the ldap_search_response + message as part of the controls field of the LDAPMessage, + as defined in Section 4.1.12 of [LDAPv3]. + + The controlType is set to . There is + no need to set the criticality on the response. The + controlValue is an OCTET STRING, whose value is the BER + encoding of a value of the following SEQUENCE: + + getEffectiveRightsResponse ::= { + result ENUMERATED { + success (0), + operationsError (1), + unavailableCriticalExtension (12), + noSuchAttribute (16), + undefinedAttributeType (17), + invalidAttributeSyntax (21), + insufficientRights (50), + unavailable (52), + unwillingToPerform (53), + other (80) + } + } + + The effective rights returned are returned with each + entry returned by the search result. The control + response for ldap_search is: + + PartialEffectiveRightsList ::= SEQUENCE OF SEQUENCE { + family LDAPOID, + rights in BNF>, + whichObject ENUMERATED { + + + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 27] + + + + + + + Internet-Draft Access Control Model 10 March 2000 + + + + LDAP_ENTRY (1), + LDAP_SUBTREE (2) + }, + dnType "access-id"|"group"| + "role"|"ipAddress"| + "kerberosID"| + | + "*", + subjectDN LDAPString | "public" | + "this" | "*" + } + + Although this extends the search operation, there are no + incompatibilities between versions. LDAPv2 cannot send a + control, hence the above structure cannot be returned to + a LDAPv2 client. A LDAPv3 client cannot send this + request to a LDAPv2 server. A LDAPv3 server not + supporting this control cannot return the additional + data. + + 9.1.3 Client-Server Interaction + + The getEffectiveRightsRequest control requests the rights + that MUST be in effect for requested directory + entry/attribute based on the subject DN. The server that + consumes the search operation looks up the rights for the + returned directory information based on the subject DN + and returns that rights information. + + There are six possible scenarios that may occur as a + result of the getEffectiveRights control being included + on the search request: + + + 1. If the server does not support this control and the + client specified TRUE for the control's criticality + field, then the server MUST return + unavailableCriticalExtension as a return code in + the searchResponse message and not send back any + other results. This behavior is specified in + section 4.1.12 of [LDAPv3]. + + 2. If the server does not support this control and the + client specified FALSE for the control's + criticality field, then the server MUST ignore the + + + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 28] - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 28] + Internet-Draft Access Control Model 10 March 2000 + control and process the request as if it were not + present. This behavior is specified in section + 4.1.12 of [LDAPv3]. - Internet-Draft Access Control Model 25 June 1999 + 3. If the server supports this control but for some + reason such as cannot process specified family and + the client specified TRUE for the control's + criticality field, then the server SHOULD do the + following: return unavailableCriticalExtension as a + return code in the searchResult message. + 4. If the server supports this control but for some + reason such as cannot process specified family and + the client specified FALSE for the control's + criticality field, then the server should process + as 'no rights returned for that family' and include + the result Unavailable in the + getEffectiveRightsResponse control in the + searchResult message. + 5. If the server supports this control and can return + the rights per the family information, then it + should include the getEffectiveRightsResponse + control in the searchResult message with a result + of success. - aci: 1.2.3.4#subtree#grant;r,w;[all]#group#cn=Dept XYZ + 6. If the search request failed for any other reason, + then the server SHOULD omit the + getEffectiveRightsResponse control from the + searchResult message. + The client application is assured that the correct rights + are returned for scope of the search operation if and + only if the getEffectiveRightsResponse control returns + the rights. If the server omits the + getEffectiveRightsResponse control from the searchResult + message, the client SHOULD assume that the control was + ignored by the server. + + The getEffectiveRightsResponse control, if included by + the server in the searchResponse message, should have the + getEffectiveRightsResult set to either success if the + rights are returned or set to the appropriate error code + as to why the rights could not be returned. + + + + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 29] + + + + + + + Internet-Draft Access Control Model 10 March 2000 + + + + The server may not be able to return a right because it + may not exist in that directory object's attribute; in + this case, the rights request is ignored with success. + + + 10. Access Control Extended Operation + + An extended operation, get effective rights, is defined + to obtain the effective rights for a given directory + entry for a given subject. This operation may help with + the management of access control information independent + of manipulating other directory information. + + + 10.1 LDAP Get Effective Rights Operation + + ldapGetEffectiveRightsRequest ::= [APPLICATION 23] + SEQUENCE { + requestName [0] , + requestValue [1] OCTET STRING OPTIONAL } + + where + + requestValue ::= SEQUENCE { + targetDN LDAPDN, + updates SEQUENCE OF SEQUENCE { + family LDAPOID | "*", + whichObject ENUMERATED { + LDAP_ENTRY (1), + LDAP_SUBTREE (2) + }, + attr SEQUENCE { + attr in BNF > + }, + dnType "access-id"|"group"| + "role"|"ipAddress"| + "kerberosID"| + | + "*", + subjectDN LDAPString | "public" | + "this" | "*" + } + } - 10. Security Considerations - This draft proposes protocol elements for transmission of - security policy information. Security considerations are - discussed throughout this draft. Because subject + + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 30] + + + + + + + Internet-Draft Access Control Model 10 March 2000 + + + + The requestName is a dotted-decimal representation of the + OBJECT IDENTIFIER corresponding to the request. The + requestValue is information in a form defined by that + request, encapsulated inside an OCTET STRING. + + The server will respond to this with an LDAPMessage + containing the ExtendedResponse which is a rights list. + + ldapGetEffectiveRightsResponse ::= [APPLICATION 24] + SEQUENCE { + COMPONENTS OF LDAPResult, + responseName [10] OPTIONAL, + effectiveRights [11] OCTET STRING OPTIONAL } + + where + + effectiveRights ::= SEQUENCE OF SEQUENCE { + family LDAPOID, + rights in BNF>, + whichObject ENUMERATED { + LDAP_ENTRY (1), + LDAP_SUBTREE (2) + }, + dnType "access-id"|"group"|"role"| + "ipAddress"|"kerberosID"| + , + subjectDN LDAPString | "public" | "this" + } + + If the server does not recognize the request name, it + MUST return only the response fields from LDAPResult, + containing the protocolError result code. + + + + 11. Security Considerations + + This document proposes protocol elements for transmission + of security policy information. Security considerations + are discussed throughout this draft. Because subject security attribute information is used to evaluate decision requests, it is security-sensitive information and must be protected against unauthorized modification @@ -1666,7 +1822,19 @@ - 11. References + + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 31] + + + + + + + Internet-Draft Access Control Model 10 March 2000 + + + + 12. References [LDAPv3] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol (v3)", RFC 2251, December 1997. @@ -1675,8 +1843,8 @@ Framework" ECMA TR/46, July 1988 [REQTS] Stokes, Byrne, Blakley, "Access Control - Requirements for LDAP, INTERNET-DRAFT , August 1998. + Requirements for LDAP", INTERNET-DRAFT , February 2000. [ATTR] M.Wahl, A, Coulbeck, T. Howes, S. Kille, "Lightweight Directory Access Protocol (v3)": Attribute @@ -1695,20 +1863,6 @@ Ellen Stokes Bob Blakley IBM Dascom 11400 Burnet Rd 5515 Balcones Drive - - - - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 29] - - - - - - - Internet-Draft Access Control Model 25 June 1999 - - - Austin, TX 78758 Austin, TX 78731 USA USA mail-to: stokes@austin.ibm.com mail-to: blakley@dascom.com @@ -1728,12 +1882,14 @@ + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 32] + Internet-Draft Access Control Model 10 March 2000 @@ -1757,14 +1913,12 @@ - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 30] - Internet-Draft Access Control Model 25 June 1999 @@ -1787,6 +1941,7 @@ + Stokes, Byrne, Blakley Expires 10 September 2000 [Page 33] @@ -1797,14 +1952,55 @@ + CONTENTS + 1. Introduction....................................... 2 + 2. Overview........................................... 2 + 3. Terminology........................................ 4 + 4. The Model.......................................... 6 + 4.1 Access Control Information Model............. 6 + + 5. Access Control Mechanism Attributes................ 8 + 5.1 Root DSE Attribute for Access Control + Mechanism.................................... 8 + 5.2 Subschema Attribute for Access Control + Mechanism.................................... 8 + + 6. Access Control Information Attributes.............. 9 + 6.1 The BNF...................................... 10 + 6.2 Other Defined Parameters..................... 11 + 6.2.1 Families and Rights 11 + 6.2.2 DN Types 12 + 6.3 Basic ACI Attribute (ldapACI)................ 13 + 6.3.1 LDAP Operations 15 + 6.3.2 Grant/Deny Evaluation Rules 15 + 6.4 Policy Owner Attribute (policyOwner)......... 16 + 6.5 ACI Examples................................. 17 + 6.5.1 Attribute Definition 17 + 6.5.2 Modifying the ldapACI Values 18 + 6.5.3 Evaluation 19 + + 7. Operational Semantics of Access Control + Operations......................................... 21 + 7.1 Types of actions............................. 21 + 7.2 Semantics of Histories....................... 22 + + 8. Access Control Parameters for LDAP Controls & + Extended Operations................................ 25 + + 9. Access Control Information (ACI) Controls.......... 26 + 9.1 getEffectiveRights Control................... 26 + 9.1.1 Request Control 26 + 9.1.2 Response Control 27 + 9.1.3 Client-Server Interaction 28 + - i - @@ -1816,7 +2012,13 @@ - Stokes, Byrne, Blakley Expires 25 December 1999 [Page 31] + 10. Access Control Extended Operation.................. 30 + 10.1 LDAP Get Effective Rights Operation.......... 30 + + 11. Security Considerations............................ 31 + + 12. References......................................... 32 + @@ -1827,55 +2029,38 @@ - CONTENTS - 1. Introduction....................................... 2 - 2. Overview........................................... 2 - 3. Terminology........................................ 4 - 4. The Model.......................................... 6 - 4.1 Access Control Activity Lifecycle............. 6 - 4.2 Access Control Information Model.............. 6 - 4.3 Bind and Credentials.......................... 8 - 5. Access Control Information Schema.................. 8 - 5.1 Attributes.................................... 8 - 5.1.1 Root DSE Attribute for Access Control - Mechanism 8 - 5.1.2 Subschema Attribute for Access Control - Mechanism 9 - 5.2 Other Defined Parameters/OIDs................. 9 - 5.2.1 Rights Families and Rights 9 - 5.2.2 DN Types 10 - 6. Access Control Parameters for LDAP Controls & - Extended Operations................................ 11 - 7. Access Control Information (ACI) Controls.......... 12 - 7.1 getEffectiveRights Control.................... 13 - 7.1.1 Request Control 13 - 7.1.2 Response Control 13 - 7.1.3 Client-Server Interaction 15 - 7.2 specifyCredentials Control.................... 16 - 7.2.1 Request Control 16 - 7.2.2 Response Control 17 - 7.2.3 Client-Server Interaction 18 - 8. Access Control Extended Operations................. 20 - 8.1 LDAP Get Effective Rights Operation........... 20 - 10. Security Considerations............................ 29 - 11. References......................................... 29 - - i - + + + + + + + + + + + + + + + + - ii - @@ -1935,7 +2120,7 @@ - - ii - + - iii - diff --git a/doc/drafts/draft-ietf-ldapext-authmeth-xx.txt b/doc/drafts/draft-ietf-ldapext-authmeth-xx.txt deleted file mode 100644 index 62102e372b..0000000000 --- a/doc/drafts/draft-ietf-ldapext-authmeth-xx.txt +++ /dev/null @@ -1,784 +0,0 @@ - -Network Working Group M. Wahl -INTERNET-DRAFT Innosoft International, Inc. - H. Alvestrand - MaXware AS - J. Hodges - Stanford University - RL "Bob" Morgan - Stanford University -Expires in six months from June 21, 1999 - - - Authentication Methods for LDAP - - -1. Status of this Memo - - This document is an Internet-Draft. Internet-Drafts are working - documents of the Internet Engineering Task Force (IETF), its - areas, and its working groups. Note that other groups may also - distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six - months and may be updated, replaced, or obsoleted by other - documents at any time. It is inappropriate to use Internet-Drafts - as reference material or to cite them other than as "work in - progress." - - To view the entire list of current Internet-Drafts, please check - the "1id-abstracts.txt" listing contained in the Internet-Drafts - Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net - (Northern Europe), ftp.nis.garr.it (Southern Europe), munnari.oz.au - (Pacific Rim), ftp.ietf.org (US East Coast), or ftp.isi.edu - (US West Coast). - -2. Abstract - - This document specifies particular combinations of security - mechanisms which are required and recommended in LDAP [1] - implementations. - -3. Introduction - - LDAP version 3 is a powerful access protocol for directories. - - It offers means of searching, fetching and manipulating directory - content, and ways to access a rich set of security functions. - - In order to function for the best of the Internet, it is vital - that these security functions be interoperable; therefore there - has to be a minimum subset of security functions that is common to - all implementations that claim LDAPv3 conformance. - - - -Wahl, Alvestrand, Hodges, Morgan Page 1 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - Basic threats to an LDAP directory service include: - - (1) Unauthorized access to data via data-fetching operations, - - (2) Unauthorized access to reusable client authentication - information by monitoring others' access, - - (3) Unauthorized access to data by monitoring others' access, - - (4) Unauthorized modification of data, - - (5) Unauthorized modification of configuration, - - (6) Unauthorized or excessive use of resources (denial of - service), and - - (7) Spoofing of directory: Tricking a client into believing - that information came from the directory when in fact it - did not, either by modifying data in transit or misdirecting - the client's connection. - - Threats (1), (4), (5) and (6) are due to hostile clients. Threats - (2), (3) and (7) are due to hostile agents on the path between client - and server, or posing as a server. - - The LDAP protocol suite can be protected with the following - security mechanisms: - - (1) Client authentication by means of the SASL [2] mechanism set, - possibly backed by the TLS credentials exchange mechanism, - - (2) Client authorization by means of access control based on - the requestor's authenticated identity, - - (3) Data integrity protection by means of the TLS protocol or - data-integrity SASL mechanisms, - - (4) Protection against snooping by means of the TLS protocol - or data-encrypting SASL mechanisms, - - (5) Resource limitation by means of administrative limits on - service controls, and - - (6) Server authentication by means of the TLS protocol or SASL - mechanism. - - At the moment, imposition of access controls is done by means - outside the scope of the LDAP protocol. - - In this document, the term "user" represents any application which - is an LDAP client using the directory to retrieve or store information. - -Wahl, Alvestrand, Hodges, Morgan Page 2 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in - this document are to be interpreted as described in RFC 2119 [3]. - -4. Example deployment scenarios - - The following scenarios are typical for LDAP directories on the - Internet, and have different security requirements. (In the - following, "sensitive" means data that will cause real damage to - the owner if revealed; there may be data that is protected but - not sensitive). This is not intended to be a comprehensive list, - other scenarios are possible, especially on physically protected - networks. - - (1) A read-only directory, containing no sensitive data, - accessible to "anyone", and TCP connection hijacking - or IP spoofing is not a problem. This directory requires - no security functions except administrative service limits. - - (2) A read-only directory containing no sensitive data; read - access is granted based on identity. TCP connection - hijacking is not currently a problem. This scenario requires - a secure authentication function. - - (3) A read-only directory containing no sensitive data; and - the client needs to ensure that the directory data is - authenticated by the server and not modified while being - returned from the server. - - (4) A read-write directory, containing no sensitive data; read - access is available to "anyone", update access to properly - authorized persons. TCP connection hijacking is not - currently a problem. This scenario requires a secure - authentication function. - - (5) A directory containing sensitive data. This scenario - requires session confidentiality protection AND secure - authentication. - -5. Authentication and Authorization: Definitions and Concepts - - This section defines basic terms, concepts, and interrelationships - regarding authentication, authorization, credentials, and identity. - These concepts are used in describing how various security - approaches are utilized in client authentication and authorization. - - - - - - - -Wahl, Alvestrand, Hodges, Morgan Page 3 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - -5.1. Access Control Policy - - An access control policy is a set of rules defining the protection - of resources, generally in terms of the capabilities of persons or - other entities accessing those resources. A common expression of an - access control policy is an access control list. Security objects - and mechanisms, such as those described here, enable the expression of - access control policies and their enforcement. Access control - policies are typically expressed in terms of access control attributes - as described below. - -5.2. Access Control Factors - - A request, when it is being processed by a server, may be associated - with a wide variety of security-related factors (section 4.2 of [1]). - The server uses these factors to determine whether and how to process - the request. These are called access control factors (ACFs). They - might include source IP address, encryption strength, the type of - operation being requested, time of day, etc. Some factors may be - specific to the request itself, others may be associated with the - connection via which the request is transmitted, others (e.g. time of - day) may be "environmental". - - Access control policies are expressed in terms of access control - factors. E.g., a request having ACFs i,j,k can perform operation Y - on resource Z. The set of ACFs that a server makes available for such - expressions is implementation-specific. - -5.3. Authentication, Credentials, Identity - - Authentication credentials are the evidence supplied by one party to - another, asserting the identity of the supplying party (e.g. a user) - who is attempting to establish an association with the other party - (typically a server). Authentication is the process of generating, - transmitting, and verifying these credentials and thus the identity - they assert. An authentication identity is the name presented in a - credential. - - There are many forms of authentication credentials -- the form used - depends upon the particular authentication mechanism negotiated by the - parties. For example: X.509 certificates, Kerberos tickets, simple - identity and password pairs. Note that an authentication mechanism may - constrain the form of authentication identities used with it. - -5.4. Authorization Identity - - An authorization identity is one kind of access control factor. It is - the name of the user or other entity that requests that operations be - performed. Access control policies are often expressed in terms of - authorization identities; e.g., entity X can perform operation Y on - resource Z. - -Wahl, Alvestrand, Hodges, Morgan Page 4 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - The authorization identity bound to an association is often exactly the - same as the authentication identity presented by the client, but it may - be different. SASL allows clients to specify an authorization identity - distinct from the authentication identity asserted by the client's - credentials. This permits agents such as proxy servers to authenticate - using their own credentials, yet request the access privileges of the - identity for which they are proxying [2]. Also, the form of - authentication identity supplied by a service like TLS may not - correspond to the authorization identities used to express a server's - access control policy, requiring a server-specific mapping to be done. - The method by which a server composes and validates an authorization - identity from the authentication credentials supplied by a client is - implementation-specific. - -6. Required security mechanisms - - It is clear that allowing any implementation, faced with the above - requirements, to pick and choose among the possible alternatives - is not a strategy that is likely to lead to interoperability. In - the absence of mandates, clients will be written that do not - support any security function supported by the server, or worse, - support only mechanisms like cleartext passwords that provide - clearly inadequate security. - - Active intermediary attacks are the most difficult for an attacker - to perform, and for an implementation to protect against. Methods - that protect only against hostile client and passive eavesdropping - attacks are useful in situations where the cost of protection - against active intermediary attacks is not justified based on the - perceived risk of active intermediary attacks. - - Given the presence of the Directory, there is a strong desire to - see mechanisms where identities take the form of a Distinguished - Name and authentication data can be stored in the directory; this - means that either this data is useless for faking authentication - (like the Unix "/etc/passwd" file format used to be), or its - content is never passed across the wire unprotected - that is, - it's either updated outside the protocol or it is only updated in - sessions well protected against snooping. It is also desirable - to allow authentication methods to carry authorization identities - based on existing forms of user identities for backwards compatibility - with non-LDAP-based authentication services. - - Therefore, the following implementation conformance requirements - are in place: - - (1) For a read-only, public directory, anonymous authentication, - described in section 7, can be used. - - - - -Wahl, Alvestrand, Hodges, Morgan Page 5 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - (2) Implementations providing password-based authenticated access - MUST support authentication using Digest, as described in - section 8.1. This provides client authentication with - protection against passive eavesdropping attacks, but does - not provide protection against active intermediary attacks. - - (3) For a directory needing session protection and - authentication, the Start TLS extended operation, and either - the simple authentication choice or the SASL EXTERNAL - mechanism, are to be used together. Implementations SHOULD - support authentication with a password as described in - section 8.2, and SHOULD support authentication with a - certificate as described in section 9.1. Together, these - can provide integrity and disclosure protection of - transmitted data, and authentication of client and server, - including protection against active intermediary attacks. - - If TLS is negotated, the client MUST discard all information about - the server fetched prior to the TLS negotiation. In particular, the - value of supportedSASLMechanisms MAY be different after TLS has been - negotiated (specifically, the EXTERNAL mechanism or the proposed - PLAIN mechanism are likely to only be listed after a TLS negotiation - has been performed). - - If a SASL security layer is negotiated, the client MUST discard all - information about the server fetched prior to SASL. In particular, if - the client is configured to support multiple SASL mechanisms, it SHOULD - fetch supportedSASLMechanisms both before and after the SASL security - layer is negotiated and verify that the value has not changed after the - SASL security layer was negotiated. This detects active attacks which - remove supported SASL mechanisms from the supportedSASLMechanisms list. - -7. Anonymous authentication - - Directory operations which modify entries or access protected - attributes or entries generally require client authentication. - Clients which do not intend to perform any of these operations - typically use anonymous authentication. - - LDAP implementations MUST support anonymous authentication, as - defined in section 7.1. - - LDAP implementations MAY support anonymous authentication with TLS, - as defined in section 7.2. - - While there MAY be access control restrictions to prevent access to - directory entries, an LDAP server SHOULD allow an anonymously-bound - client to retrieve the supportedSASLMechanisms attribute of the root - DSE. - - - -Wahl, Alvestrand, Hodges, Morgan Page 6 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - An LDAP server MAY use other information about the client provided - by the lower layers or external means to grant or deny access even - to anonymously authenticated clients. - -7.1. Anonymous authentication procedure - - An LDAP client which has not successfully completed a bind operation - on a connection is anonymously authenticated. - - An LDAP client MAY also specify anonymous authentication in a bind - request by using a zero-length OCTET STRING with the simple - authentication choice. - -7.2. Anonymous authentication and TLS - - An LDAP client MAY use the Start TLS operation [5] to negotiate the - use of TLS security [6]. If the client has not bound beforehand, - then until the client uses the EXTERNAL SASL mechanism to negotiate - the recognition of the client's certificate, the client is - anonymously authenticated. - - Recommendations on TLS ciphersuites are given in section 12. - - An LDAP server which requests that clients provide their certificate - during TLS negotiation MAY use a local security policy to determine - whether to successfully complete TLS negotiation if the client did not - present a certificate which could be validated. - -8. Password-based authentication - - LDAP implementations MUST support authentication with a password using - the DIGEST-MD5 mechanism for password protection, as defined in section - 8.1. - - LDAP implementations SHOULD support authentication with the "simple" - password choice when the connection is protected against eavesdropping - using TLS, as defined in section 8.2. - -8.1. Digest authentication - - An LDAP client MAY determine whether the server supports this - mechanism by performing a search request on the root DSE, requesting - the supportedSASLMechanisms attribute, and checking whether the - string "DIGEST-MD5" is present as a value of this attribute. - - In the first stage of authentication, when the client is performing - an "initial authentication" as defined in section 2.1 of [4], the - client sends a bind request in which the version number is 3, the - authentication choice is sasl, the sasl mechanism name is "DIGEST-MD5", - and the credentials are absent. The client then waits for a response - from the server to this request. - -Wahl, Alvestrand, Hodges, Morgan Page 7 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - The server will respond with a bind response in which the resultCode - is saslBindInProgress, and the serverSaslCreds field is present. The - contents of this field is a string defined by "digest-challenge" in - section 2.1.1 of [4]. The server SHOULD include a realm indication and - MUST indicate support for UTF-8. - - The client will send a bind request with a distinct mesage id, in which - the version number is 3, the authentication choice is sasl, the sasl - mechanism name is "DIGEST-MD5", and the credentials contain the string - defined by "digest-response" in section 2.1.2 of [4]. The serv-type - is "ldap". - - The server will respond with a bind response in which the resultCode - is either success, or an error indication. If the authentication is - successful and the server does not support subsequent authentication, - then the credentials field is absent. If the authentication is - successful and the server supports subsequent authentication, then - the crendentials field contains the string defined by "response-auth" - in section 2.1.3 of [4]. Support for subsequent authentication is - OPTIONAL in clients and servers. - -8.2. "simple" authentication choice under TLS encryption - - A user who has a directory entry containing a userPassword attribute - MAY authenticate to the directory by performing a simple password - bind sequence following the negotiation of a TLS ciphersuite - providing connection confidentiality [6]. - - The client will use the Start TLS operation [5] to negotiate the - use of TLS security [6] on the connection to the LDAP server. The - client need not have bound to the directory beforehand. - - For this authentication procedure to be successful, the client and - server MUST negotiate a ciphersuite which contains a bulk encryption - algorithm of appropriate strength. Recommendations on cipher - suites are given in section 12. - - Following the successful completion of TLS negotiation, the client - MUST send an LDAP bind request with the version number of 3, the - name field containing the name of the user's entry, and the "simple" - authentication choice, containing a password. - - The server will, for each value of the userPassword attribute in - the named user's entry, compare these for case-sensitive equality - with the client's presented password. If there is a match, then the - server will respond with resultCode success, otherwise the server will - respond with resultCode invalidCredentials. - - - - - -Wahl, Alvestrand, Hodges, Morgan Page 8 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - -8.3. Other authentication choices with TLS - - It is also possible to perform a SASL authentication exchange of - passwords following the negotiation of TLS. In this case the - client and server need not negotiate a ciphersuite which provides - confidentiality if the only service required is data integrity. - -9. Certificate-based authentication - - LDAP implementations SHOULD support authentication via a client - certificate in TLS, as defined in section 9.1. - -9.1. Certificate-based authentication with TLS - - A user who has a public/private key pair in which the public key has - been signed by a Certification Authority may use this key pair to - authenticate to the directory server if the user's certificate is - requested by the server. The user's certificate subject field - SHOULD be the name of the user's directory entry, and the - Certification Authority must be sufficiently trusted by the - directory server to have issued the certificate in order that the - server can process the certificate. The means by which servers - validate certificate paths is outside the scope of this document. - - A server MAY support mappings for certificates in which the subject - field name is different from the name of the user's directory entry. - A server which supports mappings of names MUST be capable of being - configured to support certificates for which no mapping is required. - - The client will use the Start TLS operation [5] to negotiate the - use of TLS security [6] on the connection to the LDAP server. The - client need not have bound to the directory beforehand. - - In the TLS negotiation, the server MUST request a certificate. The - client will provide its certificate to the server, and MUST perform - a private key-based encryption, proving it has it private key - associated with the certificate. - - As deployments will require protection of sensitive data in transit, - the client and server MUST negotiate a ciphersuite which contains a - bulk encryption algorithm of appropriate strength. Recommendations - of cipher suites are given in section 12. - - The server MUST verify that the client's certificate is valid. - The server will normally check that the certificate is issued by a - known CA, and that none of the certificates on the client's - certificate chain are invalid or revoked. There are several - procedures by which the server can perform these checks. - - Following the successful completion of TLS negotiation, the client - will send an LDAP bind request with the SASL "EXTERNAL" mechanism. - -Wahl, Alvestrand, Hodges, Morgan Page 9 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - -10. Other mechanisms - - The LDAP "simple" authentication choice is not suitable for - authentication on the Internet where there is no network or transport - layer confidentiality. - - As LDAP includes a native anonymous and plaintext authentication - methods, the "ANONYMOUS" and "PLAIN" SASL mechanisms are not used - with LDAP. If an authorization identity of a form different from - a DN is requested by the client, a mechanism that protects the - password in transit SHOULD be used. - - The following SASL-based mechanisms are not considered in this - document: KERBEROS_V4, GSSAPI and SKEY. - - The "EXTERNAL" SASL mechanism can be used to request the LDAP server - make use of security credentials exchanged by a lower layer. If a - TLS session has not been established between the client and server - prior to making the SASL EXTERNAL Bind request and there is no other - external source of authentication credentials (e.g. IP-level - security [8]), or if, during the process of establishing the - TLS session, the server did not request the client's authentication - credentials, the SASL EXTERNAL bind MUST fail with a result code of - inappropriateAuthentication. Any authentication identity and - authorization identity, as well as TLS connection, which were in - effect prior to making the Bind request, MUST remain in force. - -11. Authorization Identity - - The authorization identity is carried as part of the SASL credentials - field in the LDAP Bind request and response. - - When the "EXTERNAL" mechanism is being negotiated, if the - credentials field is present, it contains an authorization identity - of the authzId form described below. - - Other mechanisms define the location of the authorization - identity in the credentials field. - - The authorization identity is a string in the UTF-8 character set, - corresponding to the following ABNF [7]: - - ; Specific predefined authorization (authz) id schemes are - ; defined below -- new schemes may be defined in the future. - - authzId = dnAuthzId / uAuthzId - - ; distinguished-name-based authz id. - dnAuthzId = "dn:" dn - dn = utf8string ; with syntax defined in RFC 2253 - - -Wahl, Alvestrand, Hodges, Morgan Page 10 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - ; unspecified userid, UTF-8 encoded. - uAuthzId = "u:" userid - userid = utf8string ; syntax unspecified - - A utf8string is defined to be the UTF-8 encoding of one or more - ISO 10646 characters. - - All servers which support the storage of authentication credentials, - such as passwords or certificates, in the directory MUST support the - dnAuthzId choice. - - The uAuthzId choice allows for compatibility with client applications - which wish to authenticate to a local directory but do not know their - own Distinguished Name or have a directory entry. The format of the - string is defined as only a sequence of UTF-8 encoded ISO 10646 - characters, and further interpretation is subject to prior agreement - between the client and server. - - For example, the userid could identify a user of a specific directory - service, or be a login name or the local-part of an RFC 822 email - address. In general a uAuthzId MUST NOT be assumed to be globally - unique. - - Additional authorization identity schemes MAY be defined in future - versions of this document. - -12. TLS Ciphersuites - - The following ciphersuites defined in [6] MUST NOT be used for - confidentiality protection of passwords or data: - - TLS_NULL_WITH_NULL_NULL - TLS_RSA_WITH_NULL_MD5 - TLS_RSA_WITH_NULL_SHA - - The following ciphersuites defined in [6] can be cracked easily - (less than a week of CPU time on a standard CPU in 1997). The - client and server SHOULD carefully consider the value of the - password or data being protected before using these ciphersuites: - - TLS_RSA_EXPORT_WITH_RC4_40_MD5 - TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 - TLS_RSA_EXPORT_WITH_DES40_CBC_SHA - TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA - TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA - TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA - TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA - TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 - TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA - - - -Wahl, Alvestrand, Hodges, Morgan Page 11 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - The following ciphersuites are vulnerable to man-in-the-middle - attacks, and SHOULD NOT be used to protect passwords or sensitive - data, unless the network configuration is such that the danger of - a man-in-the-middle attack is tolerable: - - TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 - TLS_DH_anon_WITH_RC4_128_MD5 - TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA - TLS_DH_anon_WITH_DES_CBC_SHA - TLS_DH_anon_WITH_3DES_EDE_CBC_SHA - - A client or server that supports TLS MUST support at least - TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA. - -13. SASL service name for LDAP - - For use with SASL [2], a protocol must specify a service name to be - used with various SASL mechanisms, such as GSSAPI. For LDAP, the - service name is "ldap", which has been registered with the IANA - as a GSSAPI service name. - -14. Security Considerations - - Security issues are discussed throughout this memo; the - (unsurprising) conclusion is that mandatory security is important, - and that session encryption is required when snooping is a - problem. - - Servers are encouraged to prevent modifications by anonymous - users. Servers may also wish to minimize denial of service attacks - by timing out idle connections, and returning the unwillingToPerform - result code rather than performing computationally expensive - operations requested by unauthorized clients. - - A connection on which the client has not performed the Start TLS - operation or negotiated a suitable SASL mechanism for connection - integrity and encryption services is subject to man-in-the-middle - attacks to view and modify information in transit. - - Additional security considerations relating to the EXTERNAL - EXTERNAL mechanism to negotiate TLS can be found in [2], [5] - and [6]. - -15. Acknowledgements - - This document is a product of the LDAPEXT Working Group of the - IETF. The contributions of its members is greatly appreciated. - - - - - -Wahl, Alvestrand, Hodges, Morgan Page 12 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - -16. Bibliography - - [1] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access - Protocol (v3)", Dec. 1997, RFC 2251. - - [2] J. Myers, "Simple Authentication and Security Layer (SASL)", - Oct. 1997, RFC 2222. - - [3] S. Bradner, "Key words for use in RFCs to Indicate Requirement - Levels", RFC 2119. - - [4] P. Leach, C. Newman, "Using Digest Authentication as a SASL - Mechanism", INTERNET DRAFT . - - [5] J. Hodges, RL Morgan, M. Wahl, "LDAPv3 Extension for Transport - Layer Security", Oct. 1998, INTERNET DRAFT - . - - [6] T. Diers, C. Allen, "The TLS Protocol Version 1.0", Jan. 1999, - RFC 2246. - - [7] D. Crocker, Ed., P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", RFC 2234. - - [8] S. Kent, R. Atkinson, "Security Architecture for the Internet - Protocol", Nov. 1998, RFC 2401. - -17. Authors Address - - Mark Wahl - Innosoft International, Inc. - 8911 Capital of Texas Hwy, Suite 4140 - Austin, TX 78759 - USA - Phone: +1 512 231 1600 - EMail: Mark.Wahl@innosoft.com - - Harald Tveit Alvestrand - EMail: Harald.Alvestrand@maxware.no - - Jeff Hodges - Computing & Communication Services - Stanford University - Pine Hall - 241 Panama Street - Stanford, CA 94305-4122 - USA - Phone: +1-650-723-2452 - EMail: Jeff.Hodges@Stanford.edu - - - -Wahl, Alvestrand, Hodges, Morgan Page 13 - -INTERNET-DRAFT Authentication Methods for LDAP June 1999 - - RL "Bob" Morgan - Computing & Communication Services - Stanford University - Pine Hall - 241 Panama Street - Stanford, CA 94305-4122 - USA - Phone: +1-650-723-9711 - EMail: Bob.Morgan@Stanford.edu - -Full Copyright Statement - - Copyright (C) The Internet Society (1998). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - -Wahl, Alvestrand, Hodges, Morgan Page 14 - diff --git a/doc/drafts/draft-ietf-ldapext-ldap-c-api-xx.txt b/doc/drafts/draft-ietf-ldapext-ldap-c-api-xx.txt index 6fd89dd23e..74fdf7327e 100644 --- a/doc/drafts/draft-ietf-ldapext-ldap-c-api-xx.txt +++ b/doc/drafts/draft-ietf-ldapext-ldap-c-api-xx.txt @@ -1,8 +1,8 @@ Network Working Group M. Smith, Editor INTERNET-DRAFT Netscape Communications Corp. Intended Category: Standards Track T. Howes -Obsoletes: RFC 1823 Netscape Communications Corp. -Expires: 2 December 1999 A. Herron +Obsoletes: RFC 1823 +Expires: 8 April 2000 A. Herron Microsoft Corp. M. Wahl Innosoft International, Inc. @@ -10,10 +10,10 @@ Expires: 2 December 1999 A. Herron Microsoft Corp. - 2 June 1999 + 8 October 1999 The C LDAP Application Program Interface - + 1. Status of this Memo @@ -49,10 +49,10 @@ information. -Expires: 2 December 1999 [Page 1] +Expires: 8 April 2000 [Page 1] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 2. Introduction @@ -65,6 +65,10 @@ LDAP protocol. New extended operation functions were added to support LDAPv3 features such as controls. In addition, other LDAP API changes were made to support information hiding and thread safety. +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in RFC 2119[1]. + The C LDAP API is designed to be powerful, yet simple to use. It defines compatible synchronous and asynchronous interfaces to LDAP to suit a wide variety of applications. This document gives a brief overview of @@ -82,97 +86,99 @@ list of changes made since the last revision of this document. 2. Introduction...................................................2 3. Table of Contents..............................................2 4. Overview of the LDAP Model.....................................4 -5. Overview of LDAP API Use.......................................4 -6. Header File Requirements.......................................6 -7. Common Data Structures.........................................7 -8. Retrieving Information About the API Implementation............8 -8.1. Retrieving Information at Compile Time......................9 -8.2. Retrieving Information During Execution.....................10 -9. LDAP Error Codes...............................................13 -10. Performing LDAP Operations.....................................14 -10.1. Initializing an LDAP Session................................14 -10.2. LDAP Session Handle Options.................................15 -10.3. Working With Controls.......................................20 -10.3.1. A Client Control That Governs Referral Processing........22 -10.4. Authenticating to the directory.............................22 -10.5. Closing the session.........................................25 -10.6. Searching...................................................26 -10.7. Reading an Entry............................................29 -10.8. Listing the Children of an Entry............................30 -10.9. Comparing a Value Against an Entry..........................30 -10.10. Modifying an entry..........................................32 -10.11. Modifying the Name of an Entry..............................34 -10.12. Adding an entry.............................................36 - - - -Expires: 2 December 1999 [Page 2] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -10.13. Deleting an entry...........................................38 -10.14. Extended Operations.........................................39 -11. Abandoning An Operation........................................41 -12. Obtaining Results and Peeking Inside LDAP Messages.............42 -13. Handling Errors and Parsing Results............................44 -14. Stepping Through a List of Results.............................46 -15. Parsing Search Results.........................................47 -15.1. Stepping Through a List of Entries or References............48 -15.2. Stepping Through the Attributes of an Entry.................49 -15.3. Retrieving the Values of an Attribute.......................50 -15.4. Retrieving the name of an entry.............................51 -15.5. Retrieving controls from an entry...........................52 -15.6. Parsing References..........................................53 -16. Encoded ASN.1 Value Manipulation...............................54 -16.1. General.....................................................54 -16.2. Encoding....................................................55 -16.3. Encoding Example............................................58 -16.4. Decoding....................................................59 -16.5. Decoding Example............................................61 -17. Security Considerations........................................64 -18. Acknowledgements...............................................64 -19. Copyright......................................................64 -20. Bibliography...................................................65 -21. Authors' Addresses.............................................66 -22. Appendix A - Sample C LDAP API Code............................66 -23. Appendix B - Namespace Consumed By This Specification..........68 -24. Appendix C - Summary of Requirements for API Extensions........68 -24.1. Compatibility...............................................69 -24.2. Style.......................................................69 -24.3. Dependence on Externally Defined Types......................69 -24.4. Compile Time Information....................................69 -24.5. Runtime Information.........................................69 -24.6. Values Used for Session Handle Options......................70 -25. Appendix D - Known Incompatibilities with RFC 1823.............70 -25.1. Opaque LDAP Structure.......................................70 -25.2. Additional Error Codes......................................70 -25.3. Freeing of String Data with ldap_memfree()..................71 -25.4. Changes to ldap_result()....................................71 -25.5. Changes to ldap_first_attribute() and ldap_next_attribute...71 -25.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions......71 -25.7. Changes to the berval structure.............................71 -25.8. API Specification Clarified.................................72 -25.9. Deprecated Functions........................................72 -26. Appendix E - Data Types and Legacy Implementations.............72 -27. Appendix F - Changes Made Since Last Document Revision.........73 -27.1. API Changes.................................................73 -27.2. Editorial Changes...........................................74 -28. Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api-.74 -28.1. API Changes.................................................74 -28.2. Editorial changes...........................................75 - -Expires: 2 December 1999 [Page 3] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 +5. Overview of LDAP API Use and General Requirements..............4 +6. Header Requirements............................................6 +7. Common Data Structures and Types...............................7 +8. Memory Handling Overview.......................................9 +9. Retrieving Information About the API Implementation............9 +9.1. Retrieving Information at Compile Time......................9 +9.2. Retrieving Information During Execution.....................11 +10. LDAP Error Codes...............................................14 +11. Performing LDAP Operations.....................................15 +11.1. Initializing an LDAP Session................................15 +11.2. LDAP Session Handle Options.................................16 +11.3. Working With Controls.......................................22 +11.3.1. A Client Control That Governs Referral Processing........23 +11.4. Authenticating to the directory.............................24 +11.5. Closing the session.........................................26 +11.6. Searching...................................................27 +11.7. Reading an Entry............................................31 + + + +Expires: 8 April 2000 [Page 2] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + +11.8. Listing the Children of an Entry............................31 +11.9. Comparing a Value Against an Entry..........................31 +11.10. Modifying an entry..........................................33 +11.11. Modifying the Name of an Entry..............................36 +11.12. Adding an entry.............................................38 +11.13. Deleting an entry...........................................40 +11.14. Extended Operations.........................................41 +12. Abandoning An Operation........................................43 +13. Obtaining Results and Peeking Inside LDAP Messages.............43 +14. Handling Errors and Parsing Results............................45 +15. Stepping Through a List of Results.............................48 +16. Parsing Search Results.........................................49 +16.1. Stepping Through a List of Entries or References............49 +16.2. Stepping Through the Attributes of an Entry.................51 +16.3. Retrieving the Values of an Attribute.......................52 +16.4. Retrieving the name of an entry.............................53 +16.5. Retrieving controls from an entry...........................54 +16.6. Parsing References..........................................55 +17. Encoded ASN.1 Value Manipulation...............................56 +17.1. BER Data Structures and Types...............................56 +17.2. Memory Disposal and Utility Functions.......................57 +17.3. Encoding....................................................58 +17.4. Encoding Example............................................61 +17.5. Decoding....................................................62 +17.6. Decoding Example............................................65 +18. Security Considerations........................................67 +19. Acknowledgements...............................................68 +20. Copyright......................................................68 +21. Bibliography...................................................68 +22. Authors' Addresses.............................................69 +23. Appendix A - Sample C LDAP API Code............................70 +24. Appendix B - Namespace Consumed By This Specification..........72 +25. Appendix C - Summary of Requirements for API Extensions........72 +25.1. Compatibility...............................................72 +25.2. Style.......................................................73 +25.3. Dependence on Externally Defined Types......................73 +25.4. Compile Time Information....................................73 +25.5. Runtime Information.........................................73 +25.6. Values Used for Session Handle Options......................73 +26. Appendix D - Known Incompatibilities with RFC 1823.............74 +26.1. Opaque LDAP Structure.......................................74 +26.2. Additional Error Codes......................................74 +26.3. Freeing of String Data with ldap_memfree()..................74 +26.4. Changes to ldap_result()....................................75 +26.5. Changes to ldap_first_attribute() and ldap_next_attribute...75 +26.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions......75 +26.7. Changes to the berval structure.............................75 +26.8. API Specification Clarified.................................75 +26.9. Deprecated Functions........................................76 + + + +Expires: 8 April 2000 [Page 3] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + +27. Appendix E - Data Types and Legacy Implementations.............76 +28. Appendix F - Changes Made Since Last Document Revision.........77 +28.1. API Changes.................................................77 +28.2. Editorial Changes...........................................79 + 4. Overview of the LDAP Model LDAP is the lightweight directory access protocol, described in [2] and -[6]. It can provide a lightweight frontend to the X.500 directory [1], +[3]. It can provide a lightweight frontend to the X.500 directory [4], or a stand-alone service. In either mode, LDAP is based on a client- server model in which a client makes a TCP connection to an LDAP server, over which it sends requests and receives responses. @@ -198,7 +204,7 @@ is constructed by concatenating the sequence of RDNs from the entry up to the root of the tree. For example, if Babs worked for the University of Michigan, the DN of her U-M entry might be "cn=Barbara Jensen, o=University of Michigan, c=US". The DN format used by LDAP is defined -in [4]. +in [5]. Operations are provided to authenticate, search for and retrieve infor- mation, modify information, and add and delete entries from the tree. @@ -207,24 +213,25 @@ descriptions of the LDAP API calls that implement all of these func- tions. -5. Overview of LDAP API Use +5. Overview of LDAP API Use and General Requirements An application generally uses the C LDAP API in four simple steps. - 1. Initialize an LDAP session with a primary LDAP server. The - ldap_init() function returns a handle to the session, allowing - multiple connections to be open at once. - 2. Authenticate to the LDAP server. The ldap_sasl_bind() function - and friends support a variety of authentication methods. +Expires: 8 April 2000 [Page 4] + -Expires: 2 December 1999 [Page 4] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 + 1. Initialize an LDAP session with a primary LDAP server. The + ldap_init() function returns a handle to the session, allowing + multiple connections to be open at once. + 2. Authenticate to the LDAP server. The ldap_sasl_bind() function + and friends support a variety of authentication methods. 3. Perform some LDAP operations and obtain some results. ldap_search() and friends return results which can be parsed by @@ -250,7 +257,7 @@ entries and attributes returned, etc. Routines are also provided to interpret errors. Later sections of this document describe these rou- tines in more detail. -LDAP version 3 servers may return referrals and references to other +LDAP version 3 servers can return referrals and references to other servers. By default, implementations of this API will attempt to follow referrals automatically for the application. This behavior can be dis- abled globally (using the ldap_set_option() call) or on a per-request @@ -259,41 +266,46 @@ basis through the use of a client control. All DN and string attribute values passed into or produced by this C LDAP API are represented using the character set of the underlying LDAP protocol version in use. When this API is used with LDAPv3, DN and -string values are represented as UTF-8[10] characters. When this API is -used with LDAPv2, the US-ASCII[12] or T.61[12] character set are used. -Future documents may specific additional APIs supporting other character +string values are represented as UTF-8[6] characters. When this API is +used with LDAPv2, the US-ASCII[7] or T.61[7] character set are used. +Future documents MAY specify additional APIs supporting other character sets. For compatibility with existing applications, implementations of this API will by default use version 2 of the LDAP protocol. Applications that intend to take advantage of LDAP version 3 features will need to -use the ldap_set_option() call with a LDAP_OPT_PROTOCOL_VERSION to -switch to version 3. -Note that this API is designed for use in environments where the 'int' -type is at least 32 bits in size. +Expires: 8 April 2000 [Page 5] + +C LDAP API C LDAP Application Program Interface 8 October 1999 -Expires: 2 December 1999 [Page 5] +use the ldap_set_option() call with a LDAP_OPT_PROTOCOL_VERSION to +switch to version 3. +Unless otherwise indicated, conformant implementations of this specifi- +cation MUST implement all of the C LDAP API functions as described in +this document, and they MUST use the function prototypes, macro defini- +tions, and types defined in this document. -C LDAP API C LDAP Application Program Interface 2 June 1999 +Note that this API is designed for use in environments where the 'int' +type is at least 32 bits in size. -6. Header File Requirements +6. Header Requirements -To promote portability of applications, implementations of this C LDAP -API must conform to the following requirements of the header files used -by applications to access the services of this API: +To promote portability of applications, the following requirements are +imposed on the headers used by applications to access the services of +this API: Name and Inclusion - Applications are only required to include a single header file - named ldap.h to access all of the API services described in this - document. Therefore, the following C source program must com- - pile without errors: + Applications only need to include a single header named ldap.h + to access all of the API services described in this document. + Therefore, the following C source program MUST compile without + errors: #include @@ -303,67 +315,68 @@ Name and Inclusion return 0; } - Note that it is permissible for the ldap.h header file to - include other implementation-specific header files. + The ldap.h header MAY include other implementation-specific + headers. -Implementations SHOULD also provide a header file named lber.h to faci- -late development of applications desiring compatibility with older LDAP -implementations. The lber.h header file may be empty. +Implementations SHOULD also provide a header named lber.h to facilitate +development of applications desiring compatibility with older LDAP +implementations. The lber.h header MAY be empty. Old applications that +include lber.h in order to use BER facilities will need to include +ldap.h. Idempotence - All header files should be idempotent; that is, if they are - included more than once the effect is as if they had only been - included once. + All headers SHOULD be idempotent; that is, if they are included + more than once the effect is as if they had only been included + once. Must Be Included Before API Is Used - An application must include the ldap.h header file before - referencing any of the function or type definitions described in - this API specification. -Mutual Independence - If possible, header files should be mutually independent with - minimal dependence on system or any other header files. -Use of the 'const' Keyword - This API specification is defined in terms of ISO C[13]. It - makes use of function prototypes and the 'const' keyword. The - use of 'const' in this specification is limited to simple, non- - array function parameters to avoid forcing applications to - declare parameters and variables that accept return values from +Expires: 8 April 2000 [Page 6] -Expires: 2 December 1999 [Page 6] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 + An application MUST include the ldap.h header before referencing + any of the function or type definitions described in this API + specification. +Mutual Independence + Headers SHOULD be mutually independent with minimal dependence + on system or any other headers. +Use of the 'const' Keyword + This API specification is defined in terms of ISO C[8]. It + makes use of function prototypes and the 'const' keyword. The + use of 'const' in this specification is limited to simple, non- + array function parameters to avoid forcing applications to + declare parameters and variables that accept return values from LDAP API functions as 'const.' Implementations specifically - designed to be used with non-ISO C translators may provide func- - tion declarations without prototypes or function prototypes + designed to be used with non-ISO C translators SHOULD provide + function declarations without prototypes or function prototypes without specification of 'const' arguments. Definition of 'struct timeval' This API specification uses the 'struct timeval' type. Imple- - mentations of this API should ensure that the struct timeval - type is by default defined as a consequence of including the - ldap.h header file. Because struct timeval is usually defined - in one or more system header files, it is possible for header - file conflicts to occur if ldap.h also defines it or arranges - for it to be defined by including another header file. There- - fore, applications may want to arrange for struct timeval to be - defined before they include ldap.h. To support this, the ldap.h - header file must not itself define struct timeval if the prepro- - cessor symbol LDAP_TYPE_TIMEVAL_DEFINED is defined before ldap.h - is included. + mentations of this API MUST ensure that the struct timeval type + is by default defined as a consequence of including the ldap.h + header. Because struct timeval is usually defined in one or + more system headers, it is possible for header conflicts to + occur if ldap.h also defines it or arranges for it to be defined + by including another header. Therefore, applications MAY want + to arrange for struct timeval to be defined before they include + ldap.h. To support this, the ldap.h header MUST NOT itself + define struct timeval if the preprocessor symbol + LDAP_TYPE_TIMEVAL_DEFINED is defined before ldap.h is included. -7. Common Data Structures +7. Common Data Structures and Types -Some data structures that are common to several LDAP API functions are -defined here: +Data structures and types that are common to several LDAP API functions +are defined here: typedef struct ldap LDAP; @@ -371,40 +384,38 @@ defined here: typedef struct berelement BerElement; - typedef ber_len_t; /* actual definition is implementation-specific */ + typedef impl_len_t ber_len_t; - typedef ber_tag_t; /* actual definition is implementation-specific */ - - struct berval { + typedef struct berval { ber_len_t bv_len; - char *bv_val; - }; - struct timeval { - long tv_sec; - long tv_usec; - }; -The LDAP structure is an opaque data type that represents an LDAP ses- -sion Typically this corresponds to a connection to a single server, but -it may encompass several server connections in the face of LDAPv3 +Expires: 8 April 2000 [Page 7] -Expires: 2 December 1999 [Page 7] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 + char *bv_val; + } BerValue; + struct timeval { + impl_sec_t tv_sec; + impl_usec_t tv_usec; + }; -referrals. +The LDAP structure is an opaque data type that represents an LDAP ses- +sion Typically this corresponds to a connection to a single server, but +it MAY encompass several server connections in the face of LDAPv3 refer- +rals. The LDAPMessage structure is an opaque data type that is used to return entry, reference, result, and error information. An LDAPMessage struc- -ture may represent the beginning of a list, or chain of messages that +ture can represent the beginning of a list, or chain of messages that consists of a series of entries, references, and result messages as returned by LDAP operations such as search. LDAP API functions such as -ldap_parse_result() that operate on message chains that may contain more +ldap_parse_result() that operate on message chains that can contain more than one result message always operate on the first result message in the chain. See the "Obtaining Results and Peeking Inside LDAP Messages" section of this document for more information. @@ -414,16 +425,16 @@ data and state information about encoded data. It is described in more detail in the section "Encoded ASN.1 Value Manipulation" later in this document. -The ber_len_t type is an unsigned integral data type that is large +The `ber_len_t' type is an unsigned integral data type that is large enough to contain the length of the largest piece of data supported by -the API implementation. Similarly, the ber_tag_t type is an unsigned -integral data type that is large enough to hold the largest BER tag sup- -ported by the API implementation. Both of these types should be at -least 32 bits in size. See the appendix "Data Types and Legacy Imple- -mentations" for additional considerations. +the API implementation. The `impl_len_t' in the `ber_len_t' typedef +MUST be replaced with an appropriate type. The width (number of signi- +ficant bits) of `ber_len_t' MUST be at least 32 and no larger than that +of `unsigned long'. See the appendix "Data Types and Legacy Implementa- +tions" for additional considerations. -The berval structure is used to represent arbitrary binary data and its -fields have the following meanings: +The BerValue structure is used to represent arbitrary binary data and +its fields have the following meanings: bv_len Length of data in bytes. @@ -435,32 +446,72 @@ fields have the following meanings: tv_sec Seconds component of time interval. + + +Expires: 8 April 2000 [Page 8] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + tv_usec Microseconds component of time interval. -See the earlier section "Header File Requirements" for more information -on struct timeval. +Note that because the struct timeval definition typically is derived +from a system header, the types used for the tv_sec and tv_usec com- +ponents are implementation-specific integral types. Therefore, +`impl_sec_t' and `impl_usec_t' in the struct timeval definition MUST be +replaced with appropriate types. See the earlier section "Header +Requirements" for more information on struct timeval. + + +8. Memory Handling Overview + +All memory that is allocated by a function in this C LDAP API and +returned to the caller SHOULD be disposed of by calling the appropriate +"free" function provided by this API. The correct "free" function to +call is documented in each section of this document where a function +that allocates memory is described. +Memory that is allocated through means outside of the C LDAP API MUST +NOT be disposed of using a function provided by this API. -8. Retrieving Information About the API Implementation +If a pointer value passed to one of the C LDAP API "free" functions is +NULL, graceful failure (i.e, ignoring of the NULL pointer) MUST occur. + +The complete list of "free" functions that are used to dispose of allo- +cated memory is: + + ber_bvecfree() + ber_bvfree() + ber_free() + ldap_control_free() + ldap_controls_free() + ldap_memfree() + ldap_msgfree() + ldap_value_free() + ldap_value_free_len() + + +9. Retrieving Information About the API Implementation Applications developed to this specification need to be able to deter- mine information about the particular API implementation they are using +both at compile time and during execution. +9.1. Retrieving Information at Compile Time -Expires: 2 December 1999 [Page 8] +All conformant implementations MUST include the following five -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 9] -both at compile time and during execution. +C LDAP API C LDAP Application Program Interface 8 October 1999 -8.1. Retrieving Information at Compile Time -All conformant implementations MUST include the following five defini- -tions in a header file so compile time tests can be done by LDAP +definitions in a header so compile time tests can be done by LDAP software developers: #define LDAP_API_VERSION level @@ -478,7 +529,7 @@ where: ported by the implementation. max-version is replaced with the highest LDAP protocol version sup- - ported by the implementation. This should be 3. + ported by the implementation. This SHOULD be 3. "vend-name" is replaced with a text string that identifies the party that supplies the API implementation. @@ -486,9 +537,9 @@ where: "vend-version" is a supplier-specific version number multiplied times 100. -Note that the LDAP_VENDOR_NAME macro may be defined as "" if no vendor -name is available and the LDAP_VENDOR_VERSION macro may be defined as 0 -if no vendor-specific version information is available. +Note that the LDAP_VENDOR_NAME macro SHOULD be defined as "" if no ven- +dor name is available and the LDAP_VENDOR_VERSION macro SHOULD be +defined as 0 if no vendor-specific version information is available. For example, if this specification is published as RFC 88888, Netscape Communication's version 4.0 implementation that supports LDAPv2 and v3 @@ -503,22 +554,23 @@ might include macro definitions like these: and application code can test the C LDAP API version level using a construct such as this one: + #if (LDAP_API_VERSION >= 88888) + /* use features supported in RFC 88888 or later */ + #endif + +Until such time as this document is published as an RFC, implementations -Expires: 2 December 1999 [Page 9] +Expires: 8 April 2000 [Page 10] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 - #if (LDAP_API_VERSION >= 88888) - /* use features supported in RFC 88888 or later */ - #endif -Until such time as this document is published as an RFC, implementations -should use the value 2000 plus the revision number of this draft for +SHOULD use the value 2000 plus the revision number of this draft for LDAP_API_VERSION. For example, the correct value for LDAP_API_VERSION -for revision 03 of this draft is 2003. +for revision 04 of this draft is 2004. Documents that extend this specification SHOULD define a macro of the form: @@ -536,13 +588,21 @@ tations to define a macro like this: #define LDAP_API_FEATURE_TLS 99999 -Private or experimental API extensions may be indicated by defining a +Private or experimental API extensions SHOULD be indicated by defining a macro of this same form where "x" (the extension's name) begins with the string "X_" and "level" is replaced with a integer number that is specific to the extension. +It is RECOMMENDED that private or experimental API extensions use only +the following prefixes for macros, types, and function names: + LDAP_X_ + LBER_X_ + ldap_x_ + ber_x_ +and that these prefixes not be used by standard extensions. + -8.2. Retrieving Information During Execution +9.2. Retrieving Information During Execution The ldap_get_option() call (described in greater detail later in this document) can be used during execution in conjunction with an option @@ -550,24 +610,24 @@ parameter value of LDAP_OPT_API_INFO (0x00) to retrieve some basic information about the API and about the specific implementation being used. The ld parameter to ldap_get_option() can be either NULL or a valid LDAP session handle which was obtained by calling ldap_init(). -The optdata parameter to ldap_get_option() MUST be the address of an +The optdata parameter to ldap_get_option() SHOULD be the address of an LDAPAPIInfo structure which is defined as follows: typedef struct ldapapiinfo { int ldapai_info_version; /* version of this struct (1) */ int ldapai_api_version; /* revision of API supported */ - int ldapai_protocol_version; /* highest LDAP version supported */ - char **ldapai_extensions; /* names of API extensions */ - char *ldapai_vendor_name; /* name of supplier */ -Expires: 2 December 1999 [Page 10] +Expires: 8 April 2000 [Page 11] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 + int ldapai_protocol_version; /* highest LDAP version supported */ + char **ldapai_extensions; /* names of API extensions */ + char *ldapai_vendor_name; /* name of supplier */ int ldapai_vendor_version; /* supplier-specific version times 100 */ } LDAPAPIInfo; @@ -577,7 +637,7 @@ ition: #define LDAP_API_INFO_VERSION 1 Note that the ldapai_info_version field of the LDAPAPIInfo structure -should be set to the value LDAP_API_INFO_VERSION (1) before calling +SHOULD be set to the value LDAP_API_INFO_VERSION (1) before calling ldap_get_option() so that it can be checked for consistency. All other fields are set by the ldap_get_option() function. @@ -585,7 +645,7 @@ The members of the LDAPAPIInfo structure are: ldapai_info_version A number that identifies the version of the LDAPAPIInfo struc- - ture. This should be set to the value LDAP_API_INFO_VERSION + ture. This SHOULD be set to the value LDAP_API_INFO_VERSION (1) before calling ldap_get_option(). If the value received is not recognized by the API implementation, the ldap_get_option() function sets ldapai_info_version to a valid @@ -595,7 +655,7 @@ ldapai_info_version ldapai_api_version A number that matches that assigned to the C LDAP API RFC sup- - ported by the API implementation. This should match the value + ported by the API implementation. This SHOULD match the value of the LDAP_API_VERSION macro defined earlier. ldapai_protocol_version @@ -613,21 +673,22 @@ ldapai_extensions API extensions. If no API extensions are supported, this field will be set to NULL. The caller is responsible for disposing of the memory occupied by this array by passing it - to ldap_value_free() which is described later in this docu- - ment. To retrieve more information about a particular exten- - sion, the ldap_get_option() call can be used with an option -Expires: 2 December 1999 [Page 11] +Expires: 8 April 2000 [Page 12] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 + to ldap_value_free() which is described later in this docu- + ment. To retrieve more information about a particular exten- + sion, the ldap_get_option() call can be used with an option parameter value of LDAP_OPT_API_FEATURE_INFO (0x15). The opt- - data parameter to the ldap_get_option() MUST be the address of - an LDAPAPIFeatureInfo structure which is defined as follows: + data parameter to the ldap_get_option() SHOULD be the address + of an LDAPAPIFeatureInfo structure which is defined as fol- + lows: typedef struct ldap_apifeature_info { int ldapaif_info_version; /* version of this struct (1) */ @@ -641,9 +702,9 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 #define LDAP_FEATURE_INFO_VERSION 1 Note that the ldapaif_info_version field of the LDAPAPI- - FeatureInfo structure should be set to the value + FeatureInfo structure SHOULD be set to the value LDAP_FEATURE_INFO_VERSION (1) and the ldapaif_name field - should be set to the extension name string as described below + SHOULD be set to the extension name string as described below before ldap_get_option() is called. The call will fill in the ldapaif_version field of the LDAPAPIFeatureInfo structure. @@ -651,7 +712,7 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 ldapaif_info_version A number that identifies the version of the LDAPAPI- - FeatureInfo structure. This should be set to the value + FeatureInfo structure. This SHOULD be set to the value LDAP_FEATURE_INFO_VERSION (1) before calling ldap_get_option(). If the value received is not recognized by the API implementation, the ldap_get_option() function @@ -669,24 +730,26 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 ldap_get_option(). It is a number that matches that assigned to the C LDAP API extension RFC supported for this extension. For private or experimental API extensions, the - value is extension-specific. In either case, the value of - ldapaxi_ext_version should be identical to the value of the - LDAP_API_FEATURE_x macro defined for the extension - (described above). -Expires: 2 December 1999 [Page 12] +Expires: 8 April 2000 [Page 13] + +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 + + value is extension-specific. In either case, the value of + ldapaxi_ext_version SHOULD be identical to the value of the + LDAP_API_FEATURE_x macro defined for the extension + (described above). -9. LDAP Error Codes +10. LDAP Error Codes Many of the LDAP API routines return LDAP error codes, some of which -indicate local errors and some of which may be returned by servers. All -of the LDAP error codes returned will be positive integers. Supported +indicate local errors and some of which are returned by servers. All of +the LDAP error codes returned will be non-negative integers. Supported error codes are (hexadecimal values are given in parentheses after the constant): @@ -724,21 +787,21 @@ constant): LDAP_LOOP_DETECT (0x36) LDAP_NAMING_VIOLATION (0x40) LDAP_OBJECT_CLASS_VIOLATION (0x41) - LDAP_NOT_ALLOWED_ON_NONLEAF (0x42) - LDAP_NOT_ALLOWED_ON_RDN (0x43) - LDAP_ALREADY_EXISTS (0x44) - LDAP_NO_OBJECT_CLASS_MODS (0x45) - LDAP_RESULTS_TOO_LARGE (0x46) -- reserved for CLDAP - LDAP_AFFECTS_MULTIPLE_DSAS (0x47) -- new in LDAPv3 -Expires: 2 December 1999 [Page 13] +Expires: 8 April 2000 [Page 14] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 + LDAP_NOT_ALLOWED_ON_NONLEAF (0x42) + LDAP_NOT_ALLOWED_ON_RDN (0x43) + LDAP_ALREADY_EXISTS (0x44) + LDAP_NO_OBJECT_CLASS_MODS (0x45) + LDAP_RESULTS_TOO_LARGE (0x46) -- reserved for CLDAP + LDAP_AFFECTS_MULTIPLE_DSAS (0x47) -- new in LDAPv3 LDAP_OTHER (0x50) LDAP_SERVER_DOWN (0x51) LDAP_LOCAL_ERROR (0x52) @@ -759,7 +822,7 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 LDAP_REFERRAL_LIMIT_EXCEEDED (0x61) -10. Performing LDAP Operations +11. Performing LDAP Operations This section describes each LDAP operation API call in detail. All func- tions take a "session handle," a pointer to an LDAP structure containing @@ -768,7 +831,7 @@ sage structure. These structures and others are described as needed below. -10.1. Initializing an LDAP Session +11.1. Initializing an LDAP Session ldap_init() initializes a session with an LDAP server. The server is not actually contacted until an operation is performed that requires it, @@ -781,32 +844,33 @@ allowing various options to be set after initialization. Use of the following routine is deprecated: - LDAP *ldap_open( - const char *hostname, - int portno - ); -Unlike ldap_init(), ldap_open() attempts to make a server connection -before returning to the caller. -Expires: 2 December 1999 [Page 14] +Expires: 8 April 2000 [Page 15] + +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 + LDAP *ldap_open( + const char *hostname, + int portno + ); +Unlike ldap_init(), ldap_open() attempts to make a server connection +before returning to the caller. A more complete description can be +found in RFC 1823. Parameters are: 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 can include an optional - port number which is separated from the host itself with a - colon (:) character. The hosts will be tried in the order - listed, stopping with the first one to which a successful con- - nection is made. + connect to. Each hostname in the list MAY include a port number + which is separated from the host itself with a colon (:) char- + acter. The hosts will be tried in the order listed, stopping + with the first one to which a successful connection is made. - Note: A suitable representation for including a literal IPv6[11] + Note: A suitable representation for including a literal IPv6[10] address in the hostname parameter is desired, but has not yet been determined or implemented in practice. @@ -816,13 +880,13 @@ portno Contains the TCP port number to connect to. The default LDAP ter is ignored. ldap_init() and ldap_open() both return a "session handle," a pointer to -an opaque structure that should be passed to subsequent calls pertaining +an opaque structure that MUST be passed to subsequent calls pertaining to the session. These routines return NULL if the session cannot be ini- tialized in which case the operating system error reporting mechanism can be checked to see why the call failed. Note that if you connect to an LDAPv2 server, one of the LDAP bind calls -described below must be completed before other operations can be per- +described below SHOULD be completed before other operations can be per- formed on the session. LDAPv3 does not require that a bind operation be completed before other operations can be performed. @@ -830,7 +894,7 @@ The calling program can set various attributes of the session by calling the routines described in the next section. -10.2. LDAP Session Handle Options +11.2. LDAP Session Handle Options The LDAP session handle returned by ldap_init() is a pointer to an opaque data type representing an LDAP session. In RFC 1823 this data @@ -838,21 +902,20 @@ type was a structure exposed to the caller, and various fields in the structure could be set to control aspects of the session, such as size and time limits on searches. -In the interest of insulating callers from inevitable changes to this -structure, these aspects of the session are now accessed through a pair -of accessor functions, described below. - -ldap_get_option() is used to access the current value of various -session-wide parameters. ldap_set_option() is used to set the value of +Expires: 8 April 2000 [Page 16] -Expires: 2 December 1999 [Page 15] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 +In the interest of insulating callers from inevitable changes to this +structure, these aspects of the session are now accessed through a pair +of accessor functions, described below. +ldap_get_option() is used to access the current value of various +session-wide parameters. ldap_set_option() is used to set the value of these parameters. Note that some options are READ-ONLY and cannot be set; it is an error to call ldap_set_option() and attempt to set a READ-ONLY option. @@ -886,7 +949,7 @@ ld The session handle. If this is NULL, a set of global defaults is defaults. option The name of the option being accessed or set. This parameter - should be one of the following constants, which have the indi- + SHOULD be one of the following constants, which have the indi- cated meanings. After the constant the actual hexadecimal value of the constant is listed in parentheses. @@ -896,248 +959,260 @@ option The name of the option being accessed or set. This parameter Type for outvalue parameter: LDAPAPIInfo * + + +Expires: 8 April 2000 [Page 17] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + Description: Used to retrieve some basic information about the LDAP API implementation at execution time. See the section "Retriev- ing Information About the API Implementation" above for more information. This option is READ-ONLY and cannot be set. + LDAP_OPT_DEREF (0x02) + Type for invalue parameter: int * + Type for outvalue parameter: int * -Expires: 2 December 1999 [Page 16] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 + Description: + Determines how aliases are handled during search. It SHOULD + have one of the following values: LDAP_DEREF_NEVER (0x00), + LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or + LDAP_DEREF_ALWAYS (0x03). The LDAP_DEREF_SEARCHING value + means aliases are dereferenced during the search but not when + locating the base object of the search. The + LDAP_DEREF_FINDING value means aliases are dereferenced when + locating the base object but not during the search. The + default value for this option is LDAP_DEREF_NEVER. + LDAP_OPT_SIZELIMIT (0x03) + Type for invalue parameter: int * - LDAP_OPT_DESC (0x01) - Type for invalue parameter: not applicable (option is READ- - ONLY) + Type for outvalue parameter: int * - Type for outvalue parameter: int * + Description: + A limit on the number of entries to return from a search. A + value of LDAP_NO_LIMIT (0) means no limit. The default value + for this option is LDAP_NO_LIMIT. - Description: - The underlying socket descriptor corresponding to the pri- - mary LDAP connection. This option is READ-ONLY and cannot - be set. + LDAP_OPT_TIMELIMIT (0x04) + Type for invalue parameter: int * - LDAP_OPT_DEREF (0x02) - Type for invalue parameter: int * + Type for outvalue parameter: int * - Type for outvalue parameter: int * + Description: + A limit on the number of seconds to spend on a search. A + value of LDAP_NO_LIMIT (0) means no limit. This value is + passed to the server in the search request only; it does not + affect how long the C LDAP API implementation itself will + wait locally for search results. The timeout parameter + passed to ldap_search_ext_s() or ldap_result() -- both of + which are described later in this document -- can be used to + specify both a local and server side time limit. The default + value for this option is LDAP_NO_LIMIT. - Description: - Determines how aliases are handled during search. It can - have one of the following values: LDAP_DEREF_NEVER (0x00), - LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or - LDAP_DEREF_ALWAYS (0x03). The LDAP_DEREF_SEARCHING value - means aliases should be dereferenced during the search but - not when locating the base object of the search. The - LDAP_DEREF_FINDING value means aliases should be derefer- - enced when locating the base object but not during the - search. - LDAP_OPT_SIZELIMIT (0x03) - Type for invalue parameter: int * - Type for outvalue parameter: int * - Description: - A limit on the number of entries to return from a search. - A value of LDAP_NO_LIMIT (0) means no limit. +Expires: 8 April 2000 [Page 18] - LDAP_OPT_TIMELIMIT (0x04) - Type for invalue parameter: int * - Type for outvalue parameter: int * +C LDAP API C LDAP Application Program Interface 8 October 1999 - Description: - A limit on the number of seconds to spend on a search. A - value of LDAP_NO_LIMIT (0) means no limit. This value is - passed to the server in the search request only; it does - not affect how long the C LDAP API implementation itself - will wait locally for search results. The timeout parame- - ter passed to ldap_search_ext_s() or ldap_result() -- both + LDAP_OPT_REFERRALS (0x08) + Type for invalue parameter: void * (LDAP_OPT_ON or LDAP_OPT_OFF) + Type for outvalue parameter: int * -Expires: 2 December 1999 [Page 17] + Description: + Determines whether the LDAP library automatically follows + referrals returned by LDAP servers or not. It MAY be set to + one of the constants LDAP_OPT_ON or LDAP_OPT_OFF; any non- + NULL pointer value passed to ldap_set_option() enables this + option. When reading the current setting using + ldap_get_option(), a zero value means OFF and any non-zero + value means ON. By default, this option is ON. + LDAP_OPT_RESTART (0x09) + Type for invalue parameter: void * (LDAP_OPT_ON or LDAP_OPT_OFF) -C LDAP API C LDAP Application Program Interface 2 June 1999 + Type for outvalue parameter: int * + Description: + Determines whether LDAP I/O operations are automatically res- + tarted if they abort prematurely. It MAY be set to one of the + constants LDAP_OPT_ON or LDAP_OPT_OFF; any non-NULL pointer + value passed to ldap_set_option() enables this option. When + reading the current setting using ldap_get_option(), a zero + value means OFF and any non-zero value means ON. This option + is useful if an LDAP I/O operation can be interrupted prema- + turely, for example by a timer going off, or other interrupt. + By default, this option is OFF. - of which are described later in this document -- can be - used to specify both a local and server side time limit. + LDAP_OPT_PROTOCOL_VERSION (0x11) + Type for invalue parameter: int * - LDAP_OPT_REFERRALS (0x08) - Type for invalue parameter: void * (LDAP_OPT_ON or - LDAP_OPT_OFF) + Type for outvalue parameter: int * - Type for outvalue parameter: int * + Description: + This option indicates the version of the LDAP protocol used + when communicating with the primary LDAP server. It SHOULD be + one of the constants LDAP_VERSION2 (2) or LDAP_VERSION3 (3). + If no version is set the default is LDAP_VERSION2 (2). - Description: - Determines whether the LDAP library automatically follows - referrals returned by LDAP servers or not. It can be set - to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF; any - non-NULL pointer value passed to ldap_set_option() enables - this option. When reading the current setting using - ldap_get_option(), a zero value means off and any non-zero - value means on. + LDAP_OPT_SERVER_CONTROLS (0x12) + Type for invalue parameter: LDAPControl ** - LDAP_OPT_RESTART (0x09) - Type for invalue parameter: void * (LDAP_OPT_ON or - LDAP_OPT_OFF) + Type for outvalue parameter: LDAPControl *** - Type for outvalue parameter: int * + Description: + A default list of LDAP server controls to be sent with each - Description: - Determines whether LDAP I/O operations should automati- - cally be restarted if they abort prematurely. It should be - set to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF; - any non-NULL pointer value passed to ldap_set_option() - enables this option. When reading the current setting - using ldap_get_option(), a zero value means off and any - non-zero value means on. This option is useful if an LDAP - I/O operation may be interrupted prematurely, for example - by a timer going off, or other interrupt. - LDAP_OPT_PROTOCOL_VERSION (0x11) - Type for invalue parameter: int * - Type for outvalue parameter: int * +Expires: 8 April 2000 [Page 19] - Description: - This option indicates the version of the LDAP protocol - used when communicating with the primary LDAP server. It - must be one of the constants LDAP_VERSION2 (2) or - LDAP_VERSION3 (3). If no version is set the default is - LDAP_VERSION2 (2). - LDAP_OPT_SERVER_CONTROLS (0x12) +C LDAP API C LDAP Application Program Interface 8 October 1999 + request. See the Working With Controls section below. -Expires: 2 December 1999 [Page 18] + LDAP_OPT_CLIENT_CONTROLS (0x13) + Type for invalue parameter: LDAPControl ** + Type for outvalue parameter: LDAPControl *** -C LDAP API C LDAP Application Program Interface 2 June 1999 + Description: + A default list of client controls that affect the LDAP ses- + sion. See the Working With Controls section below. + LDAP_OPT_API_FEATURE_INFO (0x15) + Type for invalue parameter: not applicable (option is READ-ONLY) - Type for invalue parameter: LDAPControl ** + Type for outvalue parameter: LDAPAPIFeatureInfo * - Type for outvalue parameter: LDAPControl *** + Description: + Used to retrieve version information about LDAP API extended + features at execution time. See the section "Retrieving + Information About the API Implementation" above for more + information. This option is READ-ONLY and cannot be set. - Description: - A default list of LDAP server controls to be sent with - each request. See the Working With Controls section - below. + LDAP_OPT_HOST_NAME (0x30) + Type for invalue parameter: char * - LDAP_OPT_CLIENT_CONTROLS (0x13) - Type for invalue parameter: LDAPControl ** + Type for outvalue parameter: char ** - Type for outvalue parameter: LDAPControl *** + Description: + The host name (or list of hosts) for the primary LDAP server. + See the definition of the hostname parameter to ldap_init() + for the allowed syntax. - Description: - A default list of client controls that affect the LDAP - session. See the Working With Controls section below. + LDAP_OPT_ERROR_NUMBER (0x31) + Type for invalue parameter: int * - LDAP_OPT_API_FEATURE_INFO (0x15) - Type for invalue parameter: not applicable (option is READ- - ONLY) + Type for outvalue parameter: int * - Type for outvalue parameter: LDAPAPIFeatureInfo * + Description: + The code of the most recent LDAP error that occurred for this + session. - Description: - Used to retrieve version information about LDAP API - extended features at execution time. See the section - "Retrieving Information About the API Implementation" - above for more information. This option is READ-ONLY and - cannot be set. + LDAP_OPT_ERROR_STRING (0x32) + Type for invalue parameter: char * - LDAP_OPT_HOST_NAME (0x30) - Type for invalue parameter: char * + Type for outvalue parameter: char ** - Type for outvalue parameter: char ** + Description: + The message returned with the most recent LDAP error that - Description: - The host name (or list of hosts) for the primary LDAP - server. See the definition of the hostname parameter to - ldap_init() for the allowed syntax. - LDAP_OPT_ERROR_NUMBER (0x31) - Type for invalue parameter: int * - Type for outvalue parameter: int * +Expires: 8 April 2000 [Page 20] - Description: - The code of the most recent LDAP error that occurred for +C LDAP API C LDAP Application Program Interface 8 October 1999 -Expires: 2 December 1999 [Page 19] + occurred for this session. + LDAP_OPT_MATCHED_DN (0x33) + Type for invalue parameter: char * -C LDAP API C LDAP Application Program Interface 2 June 1999 + Type for outvalue parameter: char ** + Description: + The matched DN value returned with the most recent LDAP error + that occurred for this session. + + +outvalue The address of a place to put the value of the option. The + actual type of this parameter depends on the setting of the + option parameter. For outvalues of type char ** and LDAPCon- + trol **, a copy of the data that is associated with the LDAP + session ld is returned; callers should dispose of the memory by + calling ldap_memfree() or ldap_controls_free(), depending on + the type of data returned. + +invalue A pointer to the value the option is to be given. The actual + type of this parameter depends on the setting of the option + parameter. The data associated with invalue is copied by the + API implementation to allow callers of the API to dispose of or + otherwise change their copy of the data after a successful call + to ldap_set_option(). If a value passed for invalue is invalid + or cannot be accepted by the implementation, ldap_set_option() + should return -1 to indicate an error. - this session. +Both ldap_get_option() and ldap_set_option() return 0 if successful and +-1 if an error occurs. If -1 is returned by either function, a specific +error code MAY be retrieved by calling ldap_get_option() with an option +value of LDAP_OPT_ERROR_NUMBER. Note that there is no way to retrieve a +more specific error code if a call to ldap_get_option() with an option +value of LDAP_OPT_ERROR_NUMBER fails. + +When a call to ldap_get_option() succeeds, the API implementation MUST +NOT change the state of the LDAP session handle or the state of the +underlying implementation in a way that affects the behavior of future +LDAP API calls. When a call to ldap_get_option() fails, the only ses- +sion handle change permitted is setting the LDAP error code (as returned +by the LDAP_OPT_ERROR_NUMBER option). + +When a call to ldap_set_option() fails, it MUST NOT change the state of +the LDAP session handle or the state of the underlying implementation in +a way that affects the behavior of future LDAP API calls. - LDAP_OPT_ERROR_STRING (0x32) - Type for invalue parameter: char * +Standards track documents that extend this specification and specify new - Type for outvalue parameter: char ** - Description: - The message returned with the most recent LDAP error that - occurred for this session. +Expires: 8 April 2000 [Page 21] - outvalue The address of a place to put the value of the option. The - actual type of this parameter depends on the setting of the - option parameter. For outvalues of type char ** and LDAP- - Control **, a copy of the data that is associated with the - LDAP session ld is returned; callers should dispose of the - memory by calling ldap_memfree() or ldap_controls_free(). - invalue A pointer to the value the option is to be given. The actual - type of this parameter depends on the setting of the option - parameter. The data associated with invalue is copied by the - API implementation to allow callers of the API to dispose of - or otherwise change their copy of the data after a success- - ful call to ldap_set_option(). If a value passed for - invalue is invalid or cannot be accepted by the implementa- - tion, ldap_set_option() should return -1 to indicate an - error. +C LDAP API C LDAP Application Program Interface 8 October 1999 -Both ldap_get_option() and ldap_set_option() return 0 if successful and --1 if an error occurs. -Standards track documents that extend this specification and specify new -options MUST use values for option macros that are between 0x1000 and -0x3FFF inclusive. Private and experimental extensions MUST use values +options SHOULD use values for option macros that are between 0x1000 and +0x3FFF inclusive. Private and experimental extensions SHOULD use values for the option macros that are between 0x4000 and 0x7FFF inclusive. All values below 0x1000 and above 0x7FFF that are not defined in this docu- -ment are reserved and MUST NOT be used. +ment are reserved and SHOULD NOT be used. The following macro MUST be +defined by C LDAP API implementations to aid extension implementors: + #define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x4000 /* to 0x7FFF inclusive */ + -10.3. Working With Controls +11.3. Working With Controls LDAPv3 operations can be extended through the use of controls. Controls -may be sent to a server or returned to the client with any LDAP message. +can be sent to a server or returned to the client with any LDAP message. These controls are referred to as server controls. The LDAP API also supports a client-side extension mechanism through the use of client controls. These controls affect the behavior of the LDAP - - - -Expires: 2 December 1999 [Page 20] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - API only and are never sent to a server. A common data structure is used to represent both types of controls: @@ -1145,7 +1220,7 @@ used to represent both types of controls: char *ldctl_oid; struct berval ldctl_value; char ldctl_iscritical; - } LDAPControl, *PLDAPControl; + } LDAPControl; The fields in the ldapcontrol structure have the following meanings: @@ -1169,8 +1244,17 @@ Some LDAP API calls allocate an ldapcontrol structure or a NULL- terminated array of ldapcontrol structures. The following routines can be used to dispose of a single control or an array of controls: + + +Expires: 8 April 2000 [Page 22] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + void ldap_control_free( LDAPControl *ctrl ); void ldap_controls_free( LDAPControl **ctrls ); +If the ctrl or ctrls parameter is NULL, these calls do nothing. A set of controls that affect the entire session can be set using the ldap_set_option() function (see above). A list of controls can also be @@ -1181,21 +1265,14 @@ terminated array of pointers to ldapcontrol structures. Server controls are defined by LDAPv3 protocol extension documents; for example, a control has been proposed to support server-side sorting of -search results [7]. +search results [11]. One client control is defined in this document (described in the follow- -ing section). Other client controls may be defined in future revisions +ing section). Other client controls MAY be defined in future revisions of this document or in documents that extend this API. - -Expires: 2 December 1999 [Page 21] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -10.3.1. A Client Control That Governs Referral Processing +11.3.1. A Client Control That Governs Referral Processing As described previously in the section "LDAP Session Handle Options," applications can enable and disable automatic chasing of referrals on a @@ -1208,50 +1285,50 @@ ral chasing on per-request basis. A client control with an OID of #define LDAP_CONTROL_REFERRALS "1.2.840.113556.1.4.616" /* Flags for referrals client control value */ - #define LDAP_CHASE_SUBORDINATE_REFERRALS 0x00000020 - #define LDAP_CHASE_EXTERNAL_REFERRALS 0x00000040 + #define LDAP_CHASE_SUBORDINATE_REFERRALS 0x00000020U + #define LDAP_CHASE_EXTERNAL_REFERRALS 0x00000040U To create a referrals client control, the ldctl_oid field of an LDAPCon- -trol structure should be set to LDAP_CONTROL_REFERRALS -("1.2.840.113556.1.4.616") and the ldctl_value field should be set to a +trol structure MUST be set to LDAP_CONTROL_REFERRALS +("1.2.840.113556.1.4.616") and the ldctl_value field MUST be set to a 4-octet value that contains a set of flags. The ldctl_value.bv_len -field should always be set to 4. The ldctl_value.bv_val field should -point to a 4-octet integer flags value. This flags value can be set to -zero to disable automatic chasing of referrals and LDAPv3 references -altogether. Alternatively, the flags value can be set to the value -LDAP_CHASE_SUBORDINATE_REFERRALS (0x00000020) to indicate that only -LDAPv3 search continuation references should be automatically chased by +field MUST always be set to 4. The ldctl_value.bv_val field MUST point +to a 4-octet integer flags value. This flags value can be set to zero +to disable automatic chasing of referrals and LDAPv3 references alto- +gether. Alternatively, the flags value can be set to the value +LDAP_CHASE_SUBORDINATE_REFERRALS (0x00000020U) to indicate that only +LDAPv3 search continuation references are to be automatically chased by the API implementation, to the value LDAP_CHASE_EXTERNAL_REFERRALS -(0x00000040) to indicate that only LDAPv3 referrals should be automati- -cally chased, or the logical OR of the two flag values (0x00000060) to -indicate that both referrals and references should be automatically -chased. +(0x00000040U) to indicate that only LDAPv3 referrals are to be -10.4. Authenticating to the directory -The following functions are used to authenticate an LDAP client to an -LDAP directory server. +Expires: 8 April 2000 [Page 23] -The ldap_sasl_bind() and ldap_sasl_bind_s() functions can be used to do -general and extensible authentication over LDAP through the use of the -Simple Authentication Security Layer [8]. The routines both take the dn -to bind as, the method to use, as a dotted-string representation of an -OID identifying the method, and a struct berval holding the credentials. -The special constant value LDAP_SASL_SIMPLE (NULL) can be passed to -request simple authentication, or the simplified routines -ldap_simple_bind() or ldap_simple_bind_s() can be used. - int ldap_sasl_bind( +C LDAP API C LDAP Application Program Interface 8 October 1999 +automatically chased, or the logical OR of the two flag values +(0x00000060U) to indicate that both referrals and references are to be +automatically chased. -Expires: 2 December 1999 [Page 22] +11.4. Authenticating to the directory -C LDAP API C LDAP Application Program Interface 2 June 1999 +The following functions are used to authenticate an LDAP client to an +LDAP directory server. +The ldap_sasl_bind() and ldap_sasl_bind_s() functions can be used to do +general and extensible authentication over LDAP through the use of the +Simple Authentication Security Layer [12]. The routines both take the +dn to bind as, the method to use, as a dotted-string representation of +an OID identifying the method, and a struct berval holding the creden- +tials. The special constant value LDAP_SASL_SIMPLE (NULL) can be passed +to request simple authentication, or the simplified routines +ldap_simple_bind() or ldap_simple_bind_s() can be used. + int ldap_sasl_bind( LDAP *ld, const char *dn, const char *mechanism, @@ -1280,10 +1357,20 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 int ldap_simple_bind_s( LDAP *ld, const char *dn, + + + +Expires: 8 April 2000 [Page 24] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + const char *passwd ); - The use of the following routines is deprecated: + The use of the following routines is deprecated and more complete + descriptions can be found in RFC 1823: int ldap_bind( LDAP *ld, const char *dn, const char *cred, int method ); @@ -1301,14 +1388,6 @@ ld The session handle. dn The name of the entry to bind as. - - -Expires: 2 December 1999 [Page 23] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - mechanism Either LDAP_SASL_SIMPLE (NULL) to get simple authentica- tion, or a text string identifying the SASL method. @@ -1330,12 +1409,20 @@ msgidp This result parameter will be set to the message id of the servercredp This result parameter will be filled in with the creden- tials passed back by the server for mutual authentication, if given. An allocated berval structure is returned that - should be disposed of by calling ber_bvfree(). NULL may be - passed to ignore this field. + SHOULD be disposed of by calling ber_bvfree(). NULL SHOULD + be passed to ignore this field. Additional parameters for the deprecated routines are not described. Interested readers are referred to RFC 1823. + + +Expires: 8 April 2000 [Page 25] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + The ldap_sasl_bind() function initiates an asynchronous bind operation and returns the constant LDAP_SUCCESS if the request was successfully sent, or another LDAP error code if not. See the section below on error @@ -1357,17 +1444,8 @@ LDAP_SUCCESS if the operation was successful, or another LDAP error code if it was not. See the section below on error handling for more informa- tion about possible errors and how to interpret them. - - - -Expires: 2 December 1999 [Page 24] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - Note that if an LDAPv2 server is contacted, no other operations over the -connection should be attempted before a bind call has successfully com- +connection can be attempted before a bind call has successfully com- pleted. Subsequent bind calls can be used to re-authenticate over the same con- @@ -1375,7 +1453,7 @@ nection, and multistep SASL sequences can be accomplished through a sequence of calls to ldap_sasl_bind() or ldap_sasl_bind_s(). -10.5. Closing the session +11.5. Closing the session The following functions are used to unbind from the directory, close open connections, and dispose of the session handle. @@ -1393,6 +1471,15 @@ ld The session handle. serverctrls List of LDAP server controls. + + + +Expires: 8 April 2000 [Page 26] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + clientctrls List of client controls. The ldap_unbind_ext(), ldap_unbind() and ldap_unbind_s() all work syn- @@ -1414,16 +1501,7 @@ trol sent with an unbind request. - - - -Expires: 2 December 1999 [Page 25] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -10.6. Searching +11.6. Searching The following functions are used to search the LDAP directory, returning a requested set of attributes for each entry matched. There are five @@ -1450,6 +1528,15 @@ variations. const char *filter, char **attrs, int attrsonly, + + + +Expires: 8 April 2000 [Page 27] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + LDAPControl **serverctrls, LDAPControl **clientctrls, struct timeval *timeout, @@ -1471,15 +1558,6 @@ variations. const char *base, int scope, const char *filter, - - - -Expires: 2 December 1999 [Page 26] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - char **attrs, int attrsonly, LDAPMessage **res @@ -1506,61 +1584,80 @@ scope One of LDAP_SCOPE_BASE (0x00), LDAP_SCOPE_ONELEVEL (0x01), or LDAP_SCOPE_SUBTREE (0x02), indicating the scope of the search. -filter A character string as described in [3], representing the +filter A character string as described in [13], representing the + + + +Expires: 8 April 2000 [Page 28] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + search filter. The value NULL can be passed to indicate that the filter "(objectclass=*)" which matches all entries - should be used. Note that if the caller of the API is - using LDAPv2, only a subset of the filter functionality - described in [3] can be successfully used. + is to be used. Note that if the caller of the API is using + LDAPv2, only a subset of the filter functionality described + in [13] can be successfully used. attrs A NULL-terminated array of strings indicating which attri- butes to return for each matching entry. Passing NULL for this parameter causes all available user attributes to be retrieved. The special constant string LDAP_NO_ATTRS - ("1.1") can be used as the only string in the array to - indicate that no attribute types should be returned by the + ("1.1") MAY be used as the only string in the array to + indicate that no attribute types are to be returned by the server. The special constant string LDAP_ALL_USER_ATTRS ("*") can be used in the attrs array along with the names of some operational attributes to indicate that all user - attributes plus the listed operational attributes should be + attributes plus the listed operational attributes are to be returned. -attrsonly A boolean value that should be zero if both attribute types - and values are to be returned, non-zero if only types are - wanted. - - - -Expires: 2 December 1999 [Page 27] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - +attrsonly A boolean value that MUST be zero if both attribute types + and values are to be returned, and non-zero if only types + are wanted. timeout For the ldap_search_st() function, this specifies the local search timeout value (if it is NULL, the timeout is infin- - ite). For the ldap_search_ext() and ldap_search_ext_s() - functions, this specifies both the local search timeout - value and the operation time limit that is sent to the - server within the search request. For the - ldap_search_ext() and ldap_search_ext_s() functions, pass- - ing a NULL value for timeout causes the global default - timeout stored in the LDAP session handle (set by using + ite). If a zero timeout (where tv_sec and tv_usec are both + zero) is passed, API implementations SHOULD return + LDAP_PARAM_ERROR. + + For the ldap_search_ext() and ldap_search_ext_s() func- + tions, the timeout parameter specifies both the local + search timeout value and the operation time limit that is + sent to the server within the search request. Passing a + NULL value for timeout causes the global default timeout + stored in the LDAP session handle (set by using ldap_set_option() with the LDAP_OPT_TIMELIMIT parameter) to be sent to the server with the request but an infinite - local search timeout to be used. + local search timeout to be used. If a zero timeout (where + tv_sec and tv_usec are both zero) is passed in, API imple- + mentations SHOULD return LDAP_PARAM_ERROR. If a zero value + for tv_sec is used but tv_usec is non-zero, an operation + time limit of 1 SHOULD be passed to the LDAP server as the + operation time limit. For other values of tv_sec, the + tv_sec value itself SHOULD be passed to the LDAP server. sizelimit For the ldap_search_ext() and ldap_search_ext_s() calls, this is a limit on the number of entries to return from the search. A value of LDAP_NO_LIMIT (0) means no limit. -res For the synchronous calls, this is a result parameter which - will contain the results of the search upon completion of - the call. If no results are returned, *res is set to NULL. -serverctrls List of LDAP server controls. -clientctrls List of client controls. + +Expires: 8 April 2000 [Page 29] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +res For the synchronous calls, this is a result parameter which + will contain the results of the search upon completion of + the call. If no results are returned, *res is set to NULL. + +serverctrls List of LDAP server controls. + +clientctrls List of client controls. msgidp This result parameter will be set to the message id of the request if the ldap_search_ext() call succeeds. @@ -1583,20 +1680,11 @@ LDAP_OPT_TIMELIMIT LDAP_OPT_DEREF One of LDAP_DEREF_NEVER (0x00), LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or LDAP_DEREF_ALWAYS - (0x03), specifying how aliases should be handled during the - search. The LDAP_DEREF_SEARCHING value means aliases should - - - -Expires: 2 December 1999 [Page 28] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - - be dereferenced during the search but not when locating the + (0x03), specifying how aliases are handled during the + search. The LDAP_DEREF_SEARCHING value means aliases are + dereferenced during the search but not when locating the base object of the search. The LDAP_DEREF_FINDING value - means aliases should be dereferenced when locating the base + means aliases are dereferenced when locating the base object but not during the search. The ldap_search_ext() function initiates an asynchronous search opera- @@ -1610,8 +1698,17 @@ can be parsed using the result parsing routines described in detail later. Similar to ldap_search_ext(), the ldap_search() function initiates an -asynchronous search operation and returns the message id of the opera- -tion initiated. As for ldap_search_ext(), a subsequent call to +asynchronous search operation and returns the message id of the + + + +Expires: 8 April 2000 [Page 30] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +operation initiated. As for ldap_search_ext(), a subsequent call to ldap_result(), described below, can be used to obtain the result of the bind. In case of error, ldap_search() will return -1, setting the ses- sion error parameters in the LDAP structure appropriately. @@ -1623,8 +1720,8 @@ another LDAP error code if it was not. See the section below on error handling for more information about possible errors and how to interpret them. Entries returned from the search (if any) are contained in the res parameter. This parameter is opaque to the caller. Entries, attri- -butes, values, etc., should be extracted by calling the parsing routines -described below. The results contained in res should be freed when no +butes, values, etc., can be extracted by calling the parsing routines +described below. The results contained in res SHOULD be freed when no longer in use by calling ldap_msgfree(), described later. The ldap_search_ext() and ldap_search_ext_s() functions support LDAPv3 @@ -1637,24 +1734,15 @@ tion will wait for a search to complete. After the local search timeout expires, the API implementation will send an abandon operation to abort the search operation. -10.7. Reading an Entry +11.7. Reading an Entry LDAP does not support a read operation directly. Instead, this operation is emulated by a search with base set to the DN of the entry to read, scope set to LDAP_SCOPE_BASE, and filter set to "(objectclass=*)" or - - - -Expires: 2 December 1999 [Page 29] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - NULL. attrs contains the list of attributes to return. -10.8. Listing the Children of an Entry +11.8. Listing the Children of an Entry LDAP does not support a list operation directly. Instead, this operation is emulated by a search with base set to the DN of the entry to list, @@ -1662,52 +1750,53 @@ scope set to LDAP_SCOPE_ONELEVEL, and filter set to "(objectclass=*)" or NULL. attrs contains the list of attributes to return for each child entry. -10.9. Comparing a Value Against an Entry +11.9. Comparing a Value Against an Entry The following routines are used to compare a given attribute value assertion against an LDAP entry. There are four variations: int ldap_compare_ext( - LDAP *ld, - const char *dn, - const char *attr, - struct berval *bvalue - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp + + + +Expires: 8 April 2000 [Page 31] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + + LDAP *ld, + const char *dn, + const char *attr, + const struct berval *bvalue, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp ); int ldap_compare_ext_s( - LDAP *ld, - const char *dn, - const char *attr, - struct berval *bvalue, - LDAPControl **serverctrls, - LDAPControl **clientctrls + LDAP *ld, + const char *dn, + const char *attr, + const struct berval *bvalue, + LDAPControl **serverctrls, + LDAPControl **clientctrls ); int ldap_compare( - LDAP *ld, - const char *dn, - const char *attr, - const char *value + LDAP *ld, + const char *dn, + const char *attr, + const char *value ); int ldap_compare_s( - LDAP *ld, - const char *dn, - const char *attr, - const char *value + LDAP *ld, + const char *dn, + const char *attr, + const char *value ); - - -Expires: 2 December 1999 [Page 30] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - Parameters are: ld The session handle. @@ -1724,6 +1813,15 @@ bvalue The attribute value to compare against those found in the value A string attribute value to compare against, used by the ldap_compare() and ldap_compare_s() functions. Use ldap_compare_ext() or ldap_compare_ext_s() if you need to + + + +Expires: 8 April 2000 [Page 32] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + compare binary values. serverctrls List of LDAP server controls. @@ -1758,14 +1856,7 @@ The ldap_compare_ext() and ldap_compare_ext_s() functions support LDAPv3 server controls and client controls. - -Expires: 2 December 1999 [Page 31] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -10.10. Modifying an entry +11.10. Modifying an entry The following routines are used to modify an existing LDAP entry. There are four variations: @@ -1773,12 +1864,21 @@ are four variations: typedef struct ldapmod { int mod_op; char *mod_type; - union { + union mod_vals_u { char **modv_strvals; struct berval **modv_bvals; } mod_vals; } LDAPMod; #define mod_values mod_vals.modv_strvals + + + +Expires: 8 April 2000 [Page 33] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + #define mod_bvalues mod_vals.modv_bvals int ldap_modify_ext( @@ -1814,14 +1914,6 @@ Parameters are: ld The session handle. - - -Expires: 2 December 1999 [Page 32] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - dn The name of the entry to modify. mods A NULL-terminated array of modifications to make to the @@ -1836,7 +1928,15 @@ msgidp This result parameter will be set to the message id of the The fields in the LDAPMod structure have the following meanings: -mod_op The modification operation to perform. It should be one of + + +Expires: 8 April 2000 [Page 34] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +mod_op The modification operation to perform. It MUST be one of LDAP_MOD_ADD (0x00), LDAP_MOD_DELETE (0x01), or LDAP_MOD_REPLACE (0x02). This field also indicates the type of values included in the mod_vals union. It is logi- @@ -1846,7 +1946,7 @@ mod_op The modification operation to perform. It should be one of mod_type The type of the attribute to modify. mod_vals The values (if any) to add, delete, or replace. Only one of - the mod_values or mod_bvalues variants should be used, + the mod_values or mod_bvalues variants can be used, selected by ORing the mod_op field with the constant LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of zero-terminated strings and mod_bvalues is a NULL- @@ -1858,7 +1958,7 @@ entry, creating the attribute if necessary. For LDAP_MOD_DELETE modifications, the given values are deleted from the entry, removing the attribute if no values remain. If the entire attri- -bute is to be deleted, the mod_vals field should be set to NULL. +bute is to be deleted, the mod_vals field can be set to NULL. For LDAP_MOD_REPLACE modifications, the attribute will have the listed values after the modification, having been created if necessary, or @@ -1870,15 +1970,6 @@ tion and returns the constant LDAP_SUCCESS if the request was success- fully sent, or another LDAP error code if not. See the section below on error handling for more information about possible errors and how to interpret them. If successful, ldap_modify_ext() places the message id - - - -Expires: 2 December 1999 [Page 33] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - of the request in *msgidp. A subsequent call to ldap_result(), described below, can be used to obtain the result of the modify. @@ -1892,14 +1983,23 @@ sion error parameters in the LDAP structure appropriately. The synchronous ldap_modify_ext_s() and ldap_modify_s() functions both return the result of the operation, either the constant LDAP_SUCCESS if the operation was successful, or another LDAP error code if it was not. -See the section below on error handling for more information about pos- -sible errors and how to interpret them. +See the section below on error handling for more information about + + + +Expires: 8 April 2000 [Page 35] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +possible errors and how to interpret them. The ldap_modify_ext() and ldap_modify_ext_s() functions support LDAPv3 server controls and client controls. -10.11. Modifying the Name of an Entry +11.11. Modifying the Name of an Entry In LDAPv2, the ldap_modrdn(), ldap_modrdn_s(), ldap_modrdn2(), and ldap_modrdn2_s() routines were used to change the name of an LDAP entry. @@ -1927,21 +2027,13 @@ cated. const char *dn, const char *newrdn, const char *newparent, - - - -Expires: 2 December 1999 [Page 34] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - int deleteoldrdn, LDAPControl **serverctrls, LDAPControl **clientctrls ); - Use of the following routines is deprecated. + The use of the following routines is deprecated and more complete + descriptions can be found in RFC 1823: int ldap_modrdn( LDAP *ld, @@ -1949,6 +2041,15 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 const char *newrdn ); int ldap_modrdn_s( + + + +Expires: 8 April 2000 [Page 36] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + LDAP *ld, const char *dn, const char *newrdn @@ -1976,26 +2077,16 @@ newrdn The new RDN to give the entry. newparent The new parent, or superior entry. If this parameter is NULL, only the RDN of the entry is changed. The root DN - may be specified by passing a zero length string, "". The - newparent parameter should always be NULL when using ver- - sion 2 of the LDAP protocol; otherwise the server's + SHOULD be specified by passing a zero length string, "". + The newparent parameter SHOULD always be NULL when using + version 2 of the LDAP protocol; otherwise the server's behavior is undefined. deleteoldrdn This parameter only has meaning on the rename routines if newrdn is different than the old RDN. It is a boolean - value, if non-zero indicating that the old RDN value(s) - - - -Expires: 2 December 1999 [Page 35] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - - should be removed, if zero indicating that the old RDN - value(s) should be retained as non-distinguished values of - the entry. + value, if non-zero indicating that the old RDN value(s) is + to be removed, if zero indicating that the old RDN value(s) + is to be retained as non-distinguished values of the entry. serverctrls List of LDAP server controls. @@ -2007,6 +2098,15 @@ msgidp This result parameter will be set to the message id of the The ldap_rename() function initiates an asynchronous modify DN operation and returns the constant LDAP_SUCCESS if the request was successfully sent, or another LDAP error code if not. See the section below on error + + + +Expires: 8 April 2000 [Page 37] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + handling for more information about possible errors and how to interpret them. If successful, ldap_rename() places the DN message id of the request in *msgidp. A subsequent call to ldap_result(), described below, @@ -2022,7 +2122,7 @@ The ldap_rename() and ldap_rename_s() functions both support LDAPv3 server controls and client controls. -10.12. Adding an entry +11.12. Adding an entry The following functions are used to add entries to the LDAP directory. There are four variations: @@ -2041,15 +2141,6 @@ There are four variations: const char *dn, LDAPMod **attrs, LDAPControl **serverctrls, - - - -Expires: 2 December 1999 [Page 36] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - LDAPControl **clientctrls ); @@ -2065,6 +2156,14 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 LDAPMod **attrs ); + + +Expires: 8 April 2000 [Page 38] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + Parameters are: ld The session handle. @@ -2073,7 +2172,7 @@ dn The name of the entry to add. attrs The entry's attributes, specified using the LDAPMod struc- ture defined for ldap_modify(). The mod_type and mod_vals - fields should be filled in. The mod_op field is ignored + fields MUST be filled in. The mod_op field is ignored unless ORed with the constant LDAP_MOD_BVALUES, used to select the mod_bvalues case of the mod_vals union. @@ -2098,15 +2197,6 @@ can be used to obtain the result of the add. Similar to ldap_add_ext(), the ldap_add() function initiates an asyn- chronous add operation and returns the message id of the operation ini- tiated. As for ldap_add_ext(), a subsequent call to ldap_result(), - - - -Expires: 2 December 1999 [Page 37] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - described below, can be used to obtain the result of the add. In case of error, ldap_add() will return -1, setting the session error parameters in the LDAP structure appropriately. @@ -2122,7 +2212,16 @@ controls and client controls. -10.13. Deleting an entry + + + +Expires: 8 April 2000 [Page 39] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +11.13. Deleting an entry The following functions are used to delete a leaf entry from the LDAP directory. There are four variations: @@ -2156,14 +2255,6 @@ Parameters are: ld The session handle. - - -Expires: 2 December 1999 [Page 38] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - dn The name of the entry to delete. serverctrls List of LDAP server controls. @@ -2177,13 +2268,22 @@ Note that the entry to delete must be a leaf entry (i.e., it must have no children). Deletion of entire subtrees in a single operation is not supported by LDAP. -The ldap_delete_ext() function initiates an asynchronous delete opera- -tion and returns the constant LDAP_SUCCESS if the request was success- -fully sent, or another LDAP error code if not. See the section below on -error handling for more information about possible errors and how to -interpret them. If successful, ldap_delete_ext() places the message id -of the request in *msgidp. A subsequent call to ldap_result(), described -below, can be used to obtain the result of the delete. +The ldap_delete_ext() function initiates an asynchronous delete + + + +Expires: 8 April 2000 [Page 40] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +operation and returns the constant LDAP_SUCCESS if the request was suc- +cessfully sent, or another LDAP error code if not. See the section +below on error handling for more information about possible errors and +how to interpret them. If successful, ldap_delete_ext() places the mes- +sage id of the request in *msgidp. A subsequent call to ldap_result(), +described below, can be used to obtain the result of the delete. Similar to ldap_delete_ext(), the ldap_delete() function initiates an asynchronous delete operation and returns the message id of the opera- @@ -2202,39 +2302,38 @@ The ldap_delete_ext() and ldap_delete_ext_s() functions support LDAPv3 server controls and client controls. -10.14. Extended Operations +11.14. Extended Operations The ldap_extended_operation() and ldap_extended_operation_s() routines allow extended LDAP operations to be passed to the server, providing a general protocol extensibility mechanism. int ldap_extended_operation( - LDAP *ld, - const char *requestoid, - struct berval *requestdata, + LDAP *ld, + const char *requestoid, + const struct berval *requestdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp + ); + int ldap_extended_operation_s( + LDAP *ld, + const char *requestoid, + const struct berval *requestdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + char **retoidp, + struct berval **retdatap + ); -Expires: 2 December 1999 [Page 39] +Expires: 8 April 2000 [Page 41] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_extended_operation_s( - LDAP *ld, - const char *requestoid, - struct berval *requestdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - char **retoidp, - struct berval **retdatap - ); Parameters are: @@ -2242,7 +2341,7 @@ ld The session handle. requestoid The dotted-OID text string naming the request. -requestdata The arbitrary data required by the operation (if NULL, no +requestdata The arbitrary data needed by the operation (if NULL, no data is sent to the server). serverctrls List of LDAP server controls. @@ -2254,12 +2353,12 @@ msgidp This result parameter will be set to the message id of the retoidp Pointer to a character string that will be set to an allo- cated, dotted-OID text string returned by the server. This - string should be disposed of using the ldap_memfree() func- + string SHOULD be disposed of using the ldap_memfree() func- tion. If no OID was returned, *retoidp is set to NULL. retdatap Pointer to a berval structure pointer that will be set an allocated copy of the data returned by the server. This - struct berval should be disposed of using ber_bvfree(). If + struct berval SHOULD be disposed of using ber_bvfree(). If no data is returned, *retdatap is set to NULL. The ldap_extended_operation() function initiates an asynchronous @@ -2269,15 +2368,6 @@ tion below on error handling for more information about possible errors and how to interpret them. If successful, ldap_extended_operation() places the message id of the request in *msgidp. A subsequent call to ldap_result(), described below, can be used to obtain the result of the - - - -Expires: 2 December 1999 [Page 40] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - extended operation which can be passed to ldap_parse_extended_result() to obtain the OID and data contained in the response. @@ -2293,7 +2383,16 @@ The ldap_extended_operation() and ldap_extended_operation_s() functions both support LDAPv3 server controls and client controls. -11. Abandoning An Operation + + + +Expires: 8 April 2000 [Page 42] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +12. Abandoning An Operation The following calls are used to abandon an operation in progress: @@ -2327,28 +2426,29 @@ ldap_abandon() is identical to ldap_abandon_ext() except that it does not accept client or server controls and it returns zero if the abandon was successful, -1 otherwise. - - -Expires: 2 December 1999 [Page 41] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - After a successful call to ldap_abandon() or ldap_abandon_ext(), results with the given message id are never returned from a subsequent call to ldap_result(). There is no server response to LDAP abandon operations. -12. Obtaining Results and Peeking Inside LDAP Messages +13. Obtaining Results and Peeking Inside LDAP Messages ldap_result() is used to obtain the result of a previous asynchronously initiated operation. Note that depending on how it is called, -ldap_result() may actually return a list or "chain" of result messages. +ldap_result() can actually return a list or "chain" of result messages. The ldap_result() function only returns messages for a single request, so for all LDAP operations other than search only one result message is -expected; that is, the only time the "result chain" may contain more +expected; that is, the only time the "result chain" can contain more than one message is if results from a search operation are returned. + + + +Expires: 8 April 2000 [Page 43] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + Once a chain of messages has been returned to the caller, it is no longer tied in any caller-visible way to the LDAP request that produced it. Therefore, a chain of messages returned by calling ldap_result() or @@ -2382,17 +2482,9 @@ Parameters are: ld The session handle. msgid The message id of the operation whose results are to be - returned, or the constant LDAP_RES_ANY (-1) if any result is - - - -Expires: 2 December 1999 [Page 42] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - - desired. + returned, the constant LDAP_RES_UNSOLICITED (0) if an unsoli- + cited result is desired, or or the constant LDAP_RES_ANY (-1) + if any result is desired. all Specifies how many messages will be retrieved in a single call to ldap_result(). This parameter only has meaning for search @@ -2400,11 +2492,20 @@ all Specifies how many messages will be retrieved in a single call message at a time. Pass LDAP_MSG_ALL (0x01) to request that all results of a search be received before returning all results in a single chain. Pass LDAP_MSG_RECEIVED (0x02) to - indicate that all messages retrieved so far should be returned + indicate that all messages retrieved so far are to be returned in the result chain. timeout A timeout specifying how long to wait for results to be returned. A NULL value causes ldap_result() to block until + + + +Expires: 8 April 2000 [Page 44] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + results are available. A timeout value of zero seconds speci- fies a polling behavior. @@ -2434,28 +2535,19 @@ ldap_result() returns 0 if the timeout expired and -1 if an error occurs, in which case the error parameters of the LDAP session handle will be set accordingly. -ldap_msgfree() frees the result structure pointed to by res and returns -the type of the message it freed. If res is NULL, nothing is done and -the value zero is returned. +ldap_msgfree() frees each message in the result chain pointed to by res +and returns the type of the last message in the chain. If res is NULL, +nothing is done and the value zero is returned. ldap_msgtype() returns the type of the LDAP message it is passed as a parameter. The type will be one of the types listed above, or -1 on - - - -Expires: 2 December 1999 [Page 43] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - error. ldap_msgid() returns the message ID associated with the LDAP message -passed as a parameter. +passed as a parameter, or -1 on error. -13. Handling Errors and Parsing Results +14. Handling Errors and Parsing Results The following calls are used to extract information from results and handle errors returned by other LDAP API routines. Note that @@ -2463,6 +2555,14 @@ ldap_parse_sasl_bind_result() and ldap_parse_extended_result() must typ- ically be used in addition to ldap_parse_result() to retrieve all the result information from SASL Bind and Extended Operations respectively. + + +Expires: 8 April 2000 [Page 45] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + int ldap_parse_result( LDAP *ld, LDAPMessage *res, @@ -2489,23 +2589,17 @@ result information from SASL Bind and Extended Operations respectively. int freeit ); + #define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" + char *ldap_err2string( int err ); - The use of the following routines is deprecated. + The use of the following routines is deprecated and more complete + descriptions can be found in RFC 1823: int ldap_result2error( LDAP *ld, LDAPMessage *res, int freeit - - - -Expires: 2 December 1999 [Page 44] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - ); void ldap_perror( LDAP *ld, const char *msg ); @@ -2518,34 +2612,43 @@ res The result of an LDAP operation as returned by ldap_result() or one of the synchronous API operation calls. + + +Expires: 8 April 2000 [Page 46] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + errcodep This result parameter will be filled in with the LDAP error code field from the LDAPMessage message. This is the indi- cation from the server of the outcome of the operation. - NULL may be passed to ignore this field. + NULL SHOULD be passed to ignore this field. matcheddnp In the case of a return of LDAP_NO_SUCH_OBJECT, this result parameter will be filled in with a DN indicating how much - of the name in the request was recognized. NULL may be - passed to ignore this field. The matched DN string should + of the name in the request was recognized. NULL SHOULD be + passed to ignore this field. The matched DN string SHOULD be freed by calling ldap_memfree() which is described later in this document. errmsgp This result parameter will be filled in with the contents of the error message field from the LDAPMessage message. - The error message string should be freed by calling + The error message string SHOULD be freed by calling ldap_memfree() which is described later in this document. - NULL may be passed to ignore this field. + NULL SHOULD be passed to ignore this field. referralsp This result parameter will be filled in with the contents of the referrals field from the LDAPMessage message, indi- cating zero or more alternate LDAP servers where the - request should be retried. The referrals array should be + request is to be retried. The referrals array SHOULD be freed by calling ldap_value_free() which is described later - in this document. NULL may be passed to ignore this field. + in this document. NULL SHOULD be passed to ignore this + field. serverctrlsp This result parameter will be filled in with an allocated array of controls copied out of the LDAPMessage message. - The control array should be freed by calling + The control array SHOULD be freed by calling ldap_controls_free() which was described earlier. freeit A boolean that determines whether the res parameter is @@ -2554,34 +2657,38 @@ freeit A boolean that determines whether the res parameter is tion. This is provided as a convenience; you can also use ldap_msgfree() to free the result later. If freeit is non-zero, the entire chain of messages represented by res + is disposed of. +servercredp For SASL bind results, this result parameter will be filled + in with the credentials passed back by the server for + mutual authentication, if given. An allocated berval struc- + ture is returned that SHOULD be disposed of by calling + ber_bvfree(). NULL SHOULD be passed to ignore this field. +retoidp For extended results, this result parameter will be filled + in with the dotted-OID text representation of the name of + the extended operation response. This string SHOULD be -Expires: 2 December 1999 [Page 45] -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 47] - is disposed of. +C LDAP API C LDAP Application Program Interface 8 October 1999 -servercredp For SASL bind results, this result parameter will be filled - in with the credentials passed back by the server for - mutual authentication, if given. An allocated berval struc- - ture is returned that should be disposed of by calling - ber_bvfree(). NULL may be passed to ignore this field. -retoidp For extended results, this result parameter will be filled - in with the dotted-OID text representation of the name of - the extended operation response. This string should be - disposed of by calling ldap_memfree(). NULL may be passed - to ignore this field. + disposed of by calling ldap_memfree(). NULL SHOULD be + passed to ignore this field. The + LDAP_NOTICE_OF_DISCONNECTION macro is defined as a conveni- + ence for clients that wish to check an OID to see if it + matches the one used for the unsolicited Notice of Discon- + nection (defined in RFC 2251[2] section 4.4.1). retdatap For extended results, this result parameter will be filled in with a pointer to a struct berval containing the data in - the extended operation response. It should be disposed of - by calling ber_bvfree(). NULL may be passed to ignore this - field. + the extended operation response. It SHOULD be disposed of + by calling ber_bvfree(). NULL SHOULD be passed to ignore + this field. err For ldap_err2string(), an LDAP error code, as returned by ldap_parse_result() or another LDAP API call. @@ -2589,43 +2696,43 @@ err For ldap_err2string(), an LDAP error code, as returned by Additional parameters for the deprecated routines are not described. Interested readers are referred to RFC 1823. -All three of the ldap_parse_*_result() routines skip over messages of -type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERENCE when looking -for a result message to parse. They return the constant LDAP_SUCCESS if -the result was successfully parsed and another LDAP error code if not. -Note that the LDAP error code that indicates the outcome of the opera- -tion performed by the server is placed in the errcodep -ldap_parse_result() parameter. If a chain of messages that contains -more than one result message is passed to these routines they always -operate on the first result in the chain. +The ldap_parse_result(), ldap_parse_sasl_bind_result(), and +ldap_parse_extended_result() functions all skip over messages of type +LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERENCE when looking for a +result message to parse. They return the constant LDAP_SUCCESS if the +result was successfully parsed and another LDAP error code if not. Note +that the LDAP error code that indicates the outcome of the operation +performed by the server is placed in the errcodep ldap_parse_result() +parameter. If a chain of messages that contains more than one result +message is passed to these routines they always operate on the first +result in the chain. ldap_err2string() is used to convert a numeric LDAP error code, as -returned by one of the three ldap_parse_*_result() routines, or one of -the synchronous API operation calls, into an informative zero-terminated -character string message describing the error. It returns a pointer to -static data. +returned by ldap_parse_result(), ldap_parse_sasl_bind_result(), +ldap_parse_extended_result() or one of the synchronous API operation +calls, into an informative zero-terminated character string message +describing the error. It returns a pointer to static data. -14. Stepping Through a List of Results +15. Stepping Through a List of Results The ldap_first_message() and ldap_next_message() routines are used to step through the list of messages in a result chain returned by -ldap_result(). For search operations, the result chain may actually - +ldap_result(). For search operations, the result chain can actually +include referral messages, entry messages, and result messages. +ldap_count_messages() is used to count the number of messages returned. +The ldap_msgtype() function, described above, can be used to distinguish +between the different message types. + LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res ); -Expires: 2 December 1999 [Page 46] -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 48] -include referral messages, entry messages, and result messages. -ldap_count_messages() is used to count the number of messages returned. -The ldap_msgtype() function, described above, can be used to distinguish -between the different message types. +C LDAP API C LDAP Application Program Interface 8 October 1999 - LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res ); LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *msg ); @@ -2647,44 +2754,43 @@ returned if an error occurs while stepping through the entries, in which case the error parameters in the session handle ld will be set to indi- cate the error. -ldap_count_messages() returns the number of messages contained in a -chain of results. It can also be used to count the number of messages -that remain in a chain if called with a message, entry, or reference -returned by ldap_first_message(), ldap_next_message(), -ldap_first_entry(), ldap_next_entry(), ldap_first_reference(), -ldap_next_reference(). +If successful, ldap_count_messages() returns the number of messages con- +tained in a chain of results; if an error occurs such as the res parame- +ter being invalid, -1 is returned. The ldap_count_messages() call can +also be used to count the number of messages that remain in a chain if +called with a message, entry, or reference returned by +ldap_first_message(), ldap_next_message(), ldap_first_entry(), +ldap_next_entry(), ldap_first_reference(), ldap_next_reference(). -15. Parsing Search Results +16. Parsing Search Results The following calls are used to parse the entries and references returned by ldap_search() and friends. These results are returned in an -opaque structure that should only be accessed by calling the routines -described below. Routines are provided to step through the entries and -references returned, step through the attributes of an entry, retrieve -the name of an entry, and retrieve the values associated with a given -attribute in an entry. - - +opaque structure that MAY be accessed by calling the routines described +below. Routines are provided to step through the entries and references +returned, step through the attributes of an entry, retrieve the name of +an entry, and retrieve the values associated with a given attribute in +an entry. +16.1. Stepping Through a List of Entries or References +The ldap_first_entry() and ldap_next_entry() routines are used to step +through and retrieve the list of entries from a search result chain. +The ldap_first_reference() and ldap_next_reference() routines are used +to step through and retrieve the list of continuation references from a +search result chain. ldap_count_entries() is used to count the number +of entries returned. ldap_count_references() is used to count the number -Expires: 2 December 1999 [Page 47] +Expires: 8 April 2000 [Page 49] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -15.1. Stepping Through a List of Entries or References -The ldap_first_entry() and ldap_next_entry() routines are used to step -through and retrieve the list of entries from a search result chain. -The ldap_first_reference() and ldap_next_reference() routines are used -to step through and retrieve the list of continuation references from a -search result chain. ldap_count_entries() is used to count the number -of entries returned. ldap_count_references() is used to count the number of references returned. LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *res ); @@ -2720,26 +2826,29 @@ case the error parameters in the session handle ld will be set to indi- cate the error. ldap_count_entries() returns the number of entries contained in a chain -of entries. It can also be used to count the number of entries that -remain in a chain if called with a message, entry or reference returned -by ldap_first_message(), ldap_next_message(), ldap_first_entry(), -ldap_next_entry(), ldap_first_reference(), ldap_next_reference(). +of entries; if an error occurs such as the res parameter being invalid, +-1 is returned. The ldap_count_entries() call can also be used to count +the number of entries that remain in a chain if called with a message, +entry or reference returned by ldap_first_message(), +ldap_next_message(), ldap_first_entry(), ldap_next_entry(), +ldap_first_reference(), ldap_next_reference(). +ldap_count_references() returns the number of references contained in a +chain of search results; if an error occurs such as the res parameter +being invalid, -1 is returned. The ldap_count_references() call can +also be used to count the number of references that remain in a chain. -Expires: 2 December 1999 [Page 48] -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 50] -ldap_count_references() returns the number of references contained in a -chain of search results. It can also be used to count the number of -references that remain in a chain. +C LDAP API C LDAP Application Program Interface 8 October 1999 -15.2. Stepping Through the Attributes of an Entry +16.2. Stepping Through the Attributes of an Entry The ldap_first_attribute() and ldap_next_attribute() calls are used to step through the list of attribute types returned with an entry. @@ -2775,41 +2884,40 @@ ptr In ldap_first_attribute(), the address of a pointer used inter- mem A pointer to memory allocated by the LDAP library, such as the attribute type names returned by ldap_first_attribute() and ldap_next_attribute, or the DN returned by ldap_get_dn(). If mem - is NULL, nothing is done. + is NULL, the ldap_memfree() call does nothing. ldap_first_attribute() and ldap_next_attribute() will return NULL when the end of the attributes is reached, or if there is an error, in which case the error parameters in the session handle ld will be set to indi- cate the error. +Both routines return a pointer to an allocated buffer containing the +current attribute name. This SHOULD be freed when no longer in use by +calling ldap_memfree(). +ldap_first_attribute() will allocate and return in ptr a pointer to a -Expires: 2 December 1999 [Page 49] +Expires: 8 April 2000 [Page 51] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -Both routines return a pointer to an allocated buffer containing the -current attribute name. This should be freed when no longer in use by -calling ldap_memfree(). -ldap_first_attribute() will allocate and return in ptr a pointer to a -BerElement used to keep track of the current position. This pointer -should be passed in subsequent calls to ldap_next_attribute() to step -through the entry's attributes. After a set of calls to -ldap_first_attribute() and ldap_next_attribute(), if ptr is non-NULL, it -should be freed by calling ber_free( ptr, 0 ). Note that it is very -important to pass the second parameter as 0 (zero) in this call, since -the buffer associated with the BerElement does not point to separately -allocated memory. +BerElement used to keep track of the current position. This pointer MAY +be passed in subsequent calls to ldap_next_attribute() to step through +the entry's attributes. After a set of calls to ldap_first_attribute() +and ldap_next_attribute(), if ptr is non-NULL, it SHOULD be freed by +calling ber_free( ptr, 0 ). Note that it is very important to pass the +second parameter as 0 (zero) in this call, since the buffer associated +with the BerElement does not point to separately allocated memory. The attribute type names returned are suitable for passing in a call to ldap_get_values() and friends to retrieve the associated values. -15.3. Retrieving the Values of an Attribute +16.3. Retrieving the Values of an Attribute ldap_get_values() and ldap_get_values_len() are used to retrieve the values of a given attribute from an entry. ldap_count_values() and @@ -2840,19 +2948,20 @@ Parameters are: ld The session handle. +entry The entry from which to retrieve values, as returned by + ldap_first_entry() or ldap_next_entry(). +attr The attribute whose values are to be retrieved, as returned by + ldap_first_attribute() or ldap_next_attribute(), or a caller- -Expires: 2 December 1999 [Page 50] -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 52] -entry The entry from which to retrieve values, as returned by - ldap_first_entry() or ldap_next_entry(). +C LDAP API C LDAP Application Program Interface 8 October 1999 + -attr The attribute whose values are to be retrieved, as returned by - ldap_first_attribute() or ldap_next_attribute(), or a caller- supplied string (e.g., "mail"). vals The values returned by a previous call to ldap_get_values() or @@ -2868,12 +2977,15 @@ found for attr or if an error occurs. ldap_count_values() and ldap_count_values_len() return -1 if an error occurs such as the vals parameter being invalid. -Note that the values returned are dynamically allocated and should be +If a NULL vals parameter is passed to ldap_value_free() or +ldap_value_free_len(), nothing is done. + +Note that the values returned are dynamically allocated and SHOULD be freed by calling either ldap_value_free() or ldap_value_free_len() when no longer in use. -15.4. Retrieving the name of an entry +16.4. Retrieving the name of an entry ldap_get_dn() is used to retrieve the name of an entry. ldap_explode_dn() and ldap_explode_rdn() are used to break up a name @@ -2897,45 +3009,46 @@ entry The entry whose name is to be retrieved, as returned by dn The dn to explode, such as returned by ldap_get_dn(). +rdn The rdn to explode, such as returned in the components of the + -Expires: 2 December 1999 [Page 51] +Expires: 8 April 2000 [Page 53] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -rdn The rdn to explode, such as returned in the components of the array returned by ldap_explode_dn(). notypes A boolean parameter, if non-zero indicating that the dn or rdn - components should have their type information stripped off + components are to have their type information stripped off (i.e., "cn=Babs" would become "Babs"). ldap_get_dn() will return NULL if there is some error parsing the dn, setting error parameters in the session handle ld to indicate the error. -It returns a pointer to newly allocated space that the caller should +It returns a pointer to newly allocated space that the caller SHOULD free by calling ldap_memfree() when it is no longer in use. Note the -format of the DNs returned is given by [4]. +format of the DNs returned is given by [5]. ldap_explode_dn() returns a NULL-terminated char * array containing the RDN components of the DN supplied, with or without types as indicated by the notypes parameter. The components are returned in the order they -appear in the dn. The array returned should be freed when it is no +appear in the dn. The array returned SHOULD be freed when it is no longer in use by calling ldap_value_free(). ldap_explode_rdn() returns a NULL-terminated char * array containing the components of the RDN supplied, with or without types as indicated by the notypes parameter. The components are returned in the order they -appear in the rdn. The array returned should be freed when it is no +appear in the rdn. The array returned SHOULD be freed when it is no longer in use by calling ldap_value_free(). ldap_dn2ufn() converts the DN into the user friendly format described in -[5]. The UFN returned is newly allocated space that should be freed by a -call to ldap_memfree() when no longer in use. +[14]. The UFN returned is newly allocated space that SHOULD be freed by +a call to ldap_memfree() when no longer in use. -15.5. Retrieving controls from an entry +16.5. Retrieving controls from an entry ldap_get_entry_controls() is used to extract LDAP controls from an entry. @@ -2956,15 +3069,16 @@ entry The entry to extract controls from, as returned by -Expires: 2 December 1999 [Page 52] +Expires: 8 April 2000 [Page 54] -C LDAP API C LDAP Application Program Interface 2 June 1999 + +C LDAP API C LDAP Application Program Interface 8 October 1999 serverctrlsp This result parameter will be filled in with an allocated array of controls copied out of entry. The control array - should be freed by calling ldap_controls_free(). If ser- + SHOULD be freed by calling ldap_controls_free(). If ser- verctrlsp is NULL, no controls are returned. ldap_get_entry_controls() returns an LDAP error code that indicates @@ -2973,7 +3087,7 @@ goes well). -15.6. Parsing References +16.6. Parsing References ldap_parse_reference() is used to extract referrals and controls from a SearchResultReference message. @@ -2997,13 +3111,13 @@ ref The reference to parse, as returned by ldap_result(), referralsp This result parameter will be filled in with an allocated array of character strings. The elements of the array are the referrals (typically LDAP URLs) contained in ref. The - array should be freed when no longer in used by calling + array SHOULD be freed when no longer in used by calling ldap_value_free(). If referralsp is NULL, the referral URLs are not returned. serverctrlsp This result parameter will be filled in with an allocated array of controls copied out of ref. The control array - should be freed by calling ldap_controls_free(). If ser- + SHOULD be freed by calling ldap_controls_free(). If ser- verctrlsp is NULL, no controls are returned. freeit A boolean that determines whether the ref parameter is @@ -3013,10 +3127,10 @@ freeit A boolean that determines whether the ref parameter is -Expires: 2 December 1999 [Page 53] +Expires: 8 April 2000 [Page 55] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 ldap_msgfree() to free the result later. @@ -3026,9 +3140,9 @@ the reference could be successfully parsed (LDAP_SUCCESS if all goes well). -16. Encoded ASN.1 Value Manipulation +17. Encoded ASN.1 Value Manipulation -This section describes routines which may be used to encode and decode +This section describes routines which MAY be used to encode and decode BER-encoded ASN.1 values, which are often used inside of control and extension values. @@ -3036,19 +3150,74 @@ With the exceptions of two new functions ber_flatten() and ber_init(), these functions are compatible with the University of Michigan LDAP 3.3 implementation of BER. +Note that the functions defined in this section all provide a method for +determining success or failure but generally do not provide access to +specific error codes. Therefore, applications that require precise +error information when encoding or decoding ASN.1 values SHOULD NOT use +these functions. + + +17.1. BER Data Structures and Types + +The following additional integral types are defined for use in manipula- +tion of BER encoded ASN.1 values: + typedef impl_tag_t ber_tag_t; /* for BER tags */ + + typedef impl_int_t ber_int_t; /* for BER ints, enums, and Booleans */ + + typedef impl_unit_t ber_uint_t; /* unsigned equivalent of ber_int_t */ + + typedef impl_slen_t ber_slen_t; /* signed equivalent of ber_len_t */ + +Note that the actual definition for these four integral types is imple- +mentation specific; that is, `impl_tag_t', `impl_int_t', `impl_uint_t', +and `impl_slen_t' MUST each be replaced with an appropriate +implementation-specific type. + +The `ber_tag_t' type is an unsigned integral data type that is large +enough to hold the largest BER tag supported by the API implementation. +The width (number of significant bits) of `ber_tag_t' MUST be at least +32, greater than or equal to that of `unsigned int' (so that integer +promotions won't promote it to `int'), and no wider than that of +`unsigned long'. + + + + +Expires: 8 April 2000 [Page 56] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + -16.1. General +The `ber_int_t' and `ber_uint_t' types are the signed and unsigned vari- +ants of an integral type that is large enough to hold integers for pur- +poses of BER encoding and decoding. The width of `ber_int_t' MUST be at +least 32 and no larger than that of `long'. The width (number of signi- +ficant bits) of `ber_uint_t' MUST be at least 32 and no larger than that +of `unsigned long'. Note that the `ber_uint_t' type is not used +directly in the C LDAP API but is provided for the convenience of appli- +cation developers and for use by extensions to the API. - struct berval { +The `ber_slen_t' type is the signed variant of the `ber_len_t' integral +type that is large enough to contain the length of the largest piece of +data supported by the API implementation. The `impl_slen_t' in the +`ber_len_t' typedef MUST be replaced with an appropriate type. The +width of `ber_slen_t' MUST be at least 32 and no larger than that of +`unsigned long'. Note that `ber_slen_t' is not used directly in the C +LDAP API but is provided for the convenience of application developers +and for use by extensions to the API. + + typedef struct berval { ber_len_t bv_len; char *bv_val; - }; + } BerValue; -As defined earlier in the section "Common Data Structures", a struct -berval contains an arbitrary sequence of bytes and an indication of its -length. The bv_len element is an unsigned integer. The bv_val is not -necessarily zero-terminated. Applications may allocate their own berval -structures. +As defined earlier in the section "Common Data Structures", a berval +structure contains an arbitrary sequence of bytes and an indication of +its length. The bv_len element is an unsigned integer. The bv_val is +not necessarily zero-terminated. Applications MAY allocate their own +berval structures. As defined earlier in the section "Common Data Structures", the BerEle- ment structure is an opaque structure: @@ -3058,56 +3227,60 @@ ment structure is an opaque structure: It contains not only a copy of the encoded value, but also state infor- mation used in encoding or decoding. Applications cannot allocate their own BerElement structures. The internal state is neither thread- -specific nor locked, so two threads should not manipulate the same +specific nor locked, so two threads SHOULD NOT manipulate the same BerElement value simultaneously. A single BerElement value cannot be used for both encoding and decoding. +17.2. Memory Disposal and Utility Functions + void ber_bvfree( struct berval *bv ); -ber_bvfree() frees a berval returned from this API. Both the bv->bv_val -string and the berval itself are freed. Applications should not use +ber_bvfree() frees a berval structure returned from this API. Both the +bv->bv_val string and the berval structure itself are freed. If bv is -Expires: 2 December 1999 [Page 54] +Expires: 8 April 2000 [Page 57] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -ber_bvfree() with bervals which the application has allocated. +NULL, this call does nothing. void ber_bvecfree( struct berval **bv ); -ber_bvecfree() frees an array of bervals returned from this API. Each -of the bervals in the array are freed using ber_bvfree(), then the array -itself is freed. +ber_bvecfree() frees an array of berval structures returned from this +API. Each of the berval structures in the array are freed using +ber_bvfree(), then the array itself is freed. If bv is NULL, this call +does nothing. struct berval *ber_bvdup( const struct berval *bv ); -ber_bvdup() returns a copy of a berval. The bv_val field in the -returned berval points to a different area of memory than the bv_val -field in the argument berval. The NULL pointer is returned on error -(e.g. out of memory). +ber_bvdup() returns a copy of a berval structure. The bv_val field in +the returned berval structure points to a different area of memory than +the bv_val field in the bv argument. The NULL pointer is returned on +error (e.g. out of memory). void ber_free( BerElement *ber, int fbuf ); ber_free() frees a BerElement which is returned from the API calls -ber_alloc_t() or ber_init(). Each BerElement must be freed by the -caller. The second argument fbuf should always be set to 1 to ensure +ber_alloc_t() or ber_init(). Each BerElement SHOULD be freed by the +caller. The second argument fbuf SHOULD always be set to 1 to ensure that the internal buffer used by the BER functions is freed as well as -the BerElement container itself. +the BerElement container itself. If ber is NULL, this call does noth- +ing. -16.2. Encoding +17.3. Encoding BerElement *ber_alloc_t( int options ); ber_alloc_t() constructs and returns BerElement. The NULL pointer is returned on error. The options field contains a bitwise-or of options which are to be used when generating the encoding of this BerElement. -One option is defined and must always be supplied: +One option is defined and SHOULD always be supplied: #define LBER_USE_DER 0x01 @@ -3122,16 +3295,16 @@ put as defined in X.509 and X.680 can be produced. Unrecognized option bits are ignored. The BerElement returned by ber_alloc_t() is initially empty. Calls to -ber_printf() will append bytes to the end of the ber_alloc_t(). +Expires: 8 April 2000 [Page 58] -Expires: 2 December 1999 [Page 55] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 +ber_printf() will append bytes to the end of the ber_alloc_t(). int ber_printf( BerElement *ber, const char *fmt, ... ) @@ -3139,113 +3312,116 @@ The ber_printf() routine is used to encode a BER element in much the same way that sprintf() works. One important difference, though, is that state information is kept in the ber argument so that multiple calls can be made to ber_printf() to append to the end of the BER ele- -ment. ber must be a pointer to a BerElement returned by ber_alloc_t(). +ment. ber MUST be a pointer to a BerElement returned by ber_alloc_t(). ber_printf() interprets and formats its arguments according to the for- mat string fmt. ber_printf() returns -1 if there is an error during -encoding and a positive number if successful. As with sprintf(), each -character in fmt refers to an argument to ber_printf(). +encoding and a non-negative number if successful. As with sprintf(), +each character in fmt refers to an argument to ber_printf(). The format string can contain the following format characters: 't' Tag. The next argument is a ber_tag_t specifying the tag to override the next element to be written to the ber. This works - across calls. The integer tag value must contain the tag class, - constructed bit, and tag value. For example, a tag of "[3]" for - a constructed type is 0xA3. All implementations must support - tags that fit in a single octet (i.e., where the tag value is - less than 32) and they may support larger tags. - -'b' Boolean. The next argument is an int, containing either 0 for - FALSE or 0xff for TRUE. A boolean element is output. If this - format character is not preceded by the 't' format modifier, the - tag 0x01 is used for the element. - -'i' Integer. The next argument is an int, containing the integer in - the host's byte order. An integer element is output. If this - format character is not preceded by the 't' format modifier, the - tag 0x02 is used for the element. - -'X' Bitstring. The next two arguments are a char * pointer to the - start of the bitstring, followed by an int containing the number - of bits in the bitstring. A bitstring element is output, in - primitive form. If this format character is not preceded by the - 't' format modifier, the tag 0x03 is used for the element. - -'n' Null. No argument is required. An ASN.1 NULL element is out- - put. If this format character is not preceded by the 't' format - modifier, the tag 0x05 is used for the element. + across calls. The integer tag value SHOULD contain the tag + class, constructed bit, and tag value. For example, a tag of + "[3]" for a constructed type is 0xA3U. All implementations MUST + support tags that fit in a single octet (i.e., where the tag + value is less than 32) and they MAY support larger tags. -'o' Octet string. The next two arguments are a char *, followed by - an int with the length of the string. The string may contain - null bytes and need not be zero-terminated. An octet string - element is output, in primitive form. If this format character - is not preceded by the 't' format modifier, the tag 0x04 is used - for the element. +'b' Boolean. The next argument is an ber_int_t, containing either 0 + for FALSE or 0xff for TRUE. A boolean element is output. If + this format character is not preceded by the 't' format modif- + ier, the tag 0x01U is used for the element. + +'e' Enumerated. The next argument is a ber_int_t, containing the + enumerated value in the host's byte order. An enumerated ele- + ment is output. If this format character is not preceded by the + 't' format modifier, the tag 0x0AU is used for the element. + +'i' Integer. The next argument is a ber_int_t, containing the + integer in the host's byte order. An integer element is output. + If this format character is not preceded by the 't' format + modifier, the tag 0x02U is used for the element. + +'B' Bitstring. The next two arguments are a char * pointer to the + start of the bitstring, followed by a ber_len_t containing the + number of bits in the bitstring. A bitstring element is output, + in primitive form. If this format character is not preceded by + the 't' format modifier, the tag 0x03U is used for the element. +'n' Null. No argument is needed. An ASN.1 NULL element is output. + If this format character is not preceded by the 't' format + modifier, the tag 0x05U is used for the element. -Expires: 2 December 1999 [Page 56] +Expires: 8 April 2000 [Page 59] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +'o' Octet string. The next two arguments are a char *, followed by + a ber_len_t with the length of the string. The string MAY con- + tain null bytes and are do not have to be zero-terminated. An + octet string element is output, in primitive form. If this for- + mat character is not preceded by the 't' format modifier, the + tag 0x04U is used for the element. 's' Octet string. The next argument is a char * pointing to a zero-terminated string. An octet string element in primitive form is output, which does not include the trailing '\0' (null) byte. If this format character is not preceded by the 't' format - modifier, the tag 0x04 is used for the element. + modifier, the tag 0x04U is used for the element. 'v' Several octet strings. The next argument is a char **, an array of char * pointers to zero-terminated strings. The last element - in the array must be a NULL pointer. The octet strings do not + in the array MUST be a NULL pointer. The octet strings do not include the trailing '\0' (null) byte. Note that a construct - like '{v}' is required to get an actual SEQUENCE OF octet - strings. The 't' format modifier cannot be used with this for- - mat character. + like '{v}' is used to get an actual SEQUENCE OF octet strings. + The 't' format modifier cannot be used with this format charac- + ter. -'V' Several octet strings. A NULL-terminated array of berval *'s is - supplied. Note that a construct like '{V}' is required to get an - actual SEQUENCE OF octet strings. The 't' format modifier cannot - be used with this format character. +'V' Several octet strings. A NULL-terminated array of struct berval + *'s is supplied. Note that a construct like '{V}' is used to + get an actual SEQUENCE OF octet strings. The 't' format modifier + cannot be used with this format character. -'{' Begin sequence. No argument is required. If this format char- - acter is not preceded by the 't' format modifier, the tag 0x30 - is used. +'{' Begin sequence. No argument is needed. If this format charac- + ter is not preceded by the 't' format modifier, the tag 0x30U is + used. -'}' End sequence. No argument is required. The 't' format modifier +'}' End sequence. No argument is needed. The 't' format modifier cannot be used with this format character. -'[' Begin set. No argument is required. If this format character - is not preceded by the 't' format modifier, the tag 0x31 is - used. +'[' Begin set. No argument is needed. If this format character is + not preceded by the 't' format modifier, the tag 0x31U is used. -']' End set. No argument is required. The 't' format modifier can- - not be used with this format character. +']' End set. No argument is needed. The 't' format modifier cannot + be used with this format character. -Each use of a '{' format character must be matched by a '}' character, +Each use of a '{' format character SHOULD be matched by a '}' character, either later in the format string, or in the format string of a subse- quent call to ber_printf() for that BerElement. The same applies to the '[' and ']' format characters. -Sequences and sets nest, and implementations of this API must maintain +Sequences and sets nest, and implementations of this API MUST maintain internal state to be able to properly calculate the lengths. - int ber_flatten( const BerElement *ber, struct berval **bvPtr ); + int ber_flatten( BerElement *ber, struct berval **bvPtr ); -The ber_flatten routine allocates a struct berval whose contents are a -BER encoding taken from the ber argument. The bvPtr pointer points to -the returned berval, which must be freed using ber_bvfree(). This rou- -tine returns 0 on success and -1 on error. +Expires: 8 April 2000 [Page 60] -Expires: 2 December 1999 [Page 57] +C LDAP API C LDAP Application Program Interface 8 October 1999 -C LDAP API C LDAP Application Program Interface 2 June 1999 - +The ber_flatten routine allocates a struct berval whose contents are a +BER encoding taken from the ber argument. The bvPtr pointer points to +the returned berval structure, which SHOULD be freed using ber_bvfree(). +This routine returns 0 on success and -1 on error. The ber_flatten API call is not present in U-M LDAP 3.3. @@ -3254,7 +3430,7 @@ modifiers have not been properly matched is an error (i.e., -1 will be returned by ber_flatten() if this situation is exists). -16.3. Encoding Example +17.4. Encoding Example The following is an example of encoding the following ASN.1 data type: @@ -3265,7 +3441,8 @@ The following is an example of encoding the following ASN.1 data type: } - int encode_example1(const char *s,int val1,int val2,struct berval **bvPtr) + int encode_example1(const char *s, ber_int_t val1, ber_int_t val2, + struct berval **bvPtr) { BerElement *ber; int rc = -1; @@ -3279,7 +3456,7 @@ The following is an example of encoding the following ASN.1 data type: } if (val2 != 0) { - if (ber_printf(ber,"ti",0x80,val2) == -1) { + if (ber_printf(ber,"ti",(ber_tag_t)0x80,val2) == -1) { goto done; } } @@ -3290,26 +3467,34 @@ The following is an example of encoding the following ASN.1 data type: rc = ber_flatten(ber,bvPtr); - done: - ber_free(ber,1); - return rc; - } +Expires: 8 April 2000 [Page 61] + +C LDAP API C LDAP Application Program Interface 8 October 1999 -Expires: 2 December 1999 [Page 58] + done: + ber_free(ber,1); + return rc; + } -C LDAP API C LDAP Application Program Interface 2 June 1999 +17.5. Decoding -16.4. Decoding +The following two macros are available to applications: LBER_ERROR and +LBER_DEFAULT. Both of these macros MUST be #define'd as integer con- +stants that are both compatible with the ber_tag_t type and for which +all bits have the value one. For example, ISO C guarantees that these +definitions will work: -The following two symbols are available to applications. + #define LBER_ERROR ((ber_tag_t)-1) + #define LBER_DEFAULT ((ber_tag_t)-1) - #define LBER_ERROR (ber_tag_t)0xffffffff - #define LBER_DEFAULT (ber_tag_t)0xffffffff +The intent is that LBER_ERROR and LBER_DEFAULT are both defined as the +integer value that has all bits set to 1, as such a value is not a valid +BER tag. BerElement *ber_init( const struct berval *bv ); @@ -3323,7 +3508,7 @@ The ber_scanf() routine is used to decode a BER element in much the same way that sscanf() works. One important difference, though, is that some state information is kept with the ber argument so that multiple calls can be made to ber_scanf() to sequentially read from the BER element. -The ber argument must be a pointer to a BerElement returned by +The ber argument SHOULD be a pointer to a BerElement returned by ber_init(). ber_scanf interprets the bytes according to the format string fmt, and stores the results in its additional arguments. ber_scanf() returns LBER_ERROR on error, and a different value on suc- @@ -3333,110 +3518,134 @@ The format string contains conversion specifications which are used to direct the interpretation of the BER element. The format string can contain the following characters: -'a' Octet string. A char ** argument should be supplied. Memory is +'a' Octet string. A char ** argument MUST be supplied. Memory is allocated, filled with the contents of the octet string, zero- terminated, and the pointer to the string is stored in the argu- - ment. The returned value must be freed using ldap_memfree. The - tag of the element must indicate the primitive form (constructed - strings are not supported) but is otherwise ignored and dis- - carded during the decoding. This format cannot be used with - octet strings which could contain null bytes. + ment. The returned value SHOULD be freed using ldap_memfree. + The tag of the element MUST indicate the primitive form + + -'O' Octet string. A struct berval ** argument should be supplied, +Expires: 8 April 2000 [Page 62] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + + (constructed strings are not supported) but is otherwise ignored + and discarded during the decoding. This format cannot be used + with octet strings which could contain null bytes. + +'O' Octet string. A struct berval ** argument MUST be supplied, which upon return points to an allocated struct berval contain- - ing the octet string and its length. ber_bvfree() must be + ing the octet string and its length. ber_bvfree() SHOULD be called to free the allocated memory. The tag of the element - must indicate the primitive form (constructed strings are not + MUST indicate the primitive form (constructed strings are not supported) but is otherwise ignored during the decoding. -'b' Boolean. A pointer to an int should be supplied. The int value - stored will be 0 for FALSE or nonzero for TRUE. The tag of the - element must indicate the primitive form but is otherwise +'b' Boolean. A pointer to a ber_int_t MUST be supplied. The + ber_int_t value stored will be 0 for FALSE or nonzero for TRUE. + The tag of the element MUST indicate the primitive form but is + otherwise ignored during the decoding. + +'e' Enumerated. A pointer to a ber_int_t MUST be supplied. The + enumerated value stored will be in host byte order. The tag of + the element MUST indicate the primitive form but is otherwise + ignored during the decoding. ber_scanf() will return an error + if the value of the enumerated value cannot be stored in a + ber_int_t. +'i' Integer. A pointer to a ber_int_t MUST be supplied. The + ber_int_t value stored will be in host byte order. The tag of + the element MUST indicate the primitive form but is otherwise + ignored during the decoding. ber_scanf() will return an error + if the integer cannot be stored in a ber_int_t. +'B' Bitstring. A char ** argument MUST be supplied which will point + to the allocated bits, followed by a ber_len_t * argument, which + will point to the length (in bits) of the bitstring returned. + ldap_memfree SHOULD be called to free the bitstring. The tag of + the element MUST indicate the primitive form (constructed bit- + strings are not supported) but is otherwise ignored during the + decoding. -Expires: 2 December 1999 [Page 59] +'n' Null. No argument is needed. The element is verified to have a + zero-length value and is skipped. The tag is ignored. +'t' Tag. A pointer to a ber_tag_t MUST be supplied. The ber_tag_t + value stored will be the tag of the next element in the BerEle- + ment ber, represented so it can be written using the 't' format + of ber_printf(). The decoding position within the ber argument + is unchanged by this; that is, the fact that the tag has been + retrieved does not affect future use of ber. -C LDAP API C LDAP Application Program Interface 2 June 1999 +'v' Several octet strings. A char *** argument MUST be supplied, - ignored during the decoding. -'i' Integer. A pointer to an int should be supplied. The int value - stored will be in host byte order. The tag of the element must - indicate the primitive form but is otherwise ignored during the - decoding. ber_scanf() will return an error if the integer can- - not be stored in an int. +Expires: 8 April 2000 [Page 63] -'B' Bitstring. A char ** argument should be supplied which will - point to the allocated bits, followed by a ber_len_t * argument, - which will point to the length (in bits) of the bitstring - returned. ldap_memfree must be called to free the bitstring. - The tag of the element must indicate the primitive form (con- - structed bitstrings are not supported) but is otherwise ignored - during the decoding. -'n' Null. No argument is required. The element is verified to have - a zero-length value and is skipped. The tag is ignored. +C LDAP API C LDAP Application Program Interface 8 October 1999 + -'v' Several octet strings. A char *** argument should be supplied, which upon return points to an allocated NULL-terminated array of char *'s containing the octet strings. NULL is stored if the - sequence is empty. ldap_memfree must be called to free each + sequence is empty. ldap_memfree SHOULD be called to free each element of the array and the array itself. The tag of the sequence and of the octet strings are ignored. 'V' Several octet strings (which could contain null bytes). A - struct berval *** should be supplied, which upon return points - to a allocated NULL-terminated array of struct berval *'s con- - taining the octet strings and their lengths. NULL is stored if - the sequence is empty. ber_bvecfree() can be called to free the + struct berval *** MUST be supplied, which upon return points to + a allocated NULL-terminated array of struct berval *'s contain- + ing the octet strings and their lengths. NULL is stored if the + sequence is empty. ber_bvecfree() can be called to free the allocated memory. The tag of the sequence and of the octet strings are ignored. 'x' Skip element. The next element is skipped. No argument is - required. + needed. -'{' Begin sequence. No argument is required. The initial sequence +'{' Begin sequence. No argument is needed. The initial sequence tag and length are skipped. -'}' End sequence. No argument is required. +'}' End sequence. No argument is needed. -'[' Begin set. No argument is required. The initial set tag and +'[' Begin set. No argument is needed. The initial set tag and length are skipped. -']' End set. No argument is required. - - ber_tag_t ber_peek_tag( const BerElement *ber, - - - -Expires: 2 December 1999 [Page 60] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - +']' End set. No argument is needed. + ber_tag_t ber_peek_tag( BerElement *ber, ber_len_t *lenPtr ); ber_peek_tag() returns the tag of the next element to be parsed in the BerElement argument. The length of this element is stored in the *lenPtr argument. LBER_DEFAULT is returned if there is no further data -to be read. The ber argument is not modified. +to be read. The decoding position within the ber argument is unchanged +by this call; that is, the fact that ber_peek_tag() has been called does +not affect future use of ber. ber_tag_t ber_skip_tag( BerElement *ber, ber_len_t *lenPtr ); ber_skip_tag() is similar to ber_peek_tag(), except that the state pointer in the BerElement argument is advanced past the first tag and length, and is pointed to the value part of the next element. This rou- -tine should only be used with constructed types and situations when a +tine SHOULD only be used with constructed types and situations when a BER encoding is used as the value of an OCTET STRING. The length of the value is stored in *lenPtr. ber_tag_t ber_first_element( BerElement *ber, ber_len_t *lenPtr, char **opaquePtr ); + + +Expires: 8 April 2000 [Page 64] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + ber_tag_t ber_next_element( BerElement *ber, ber_len_t *lenPtr, char *opaque ); @@ -3449,11 +3658,11 @@ ber_next_element() positions the state at the start of the next element in the constructed type. LBER_DEFAULT is returned if there are no further values. -The len and opaque values should not be used by applications other than +The len and opaque values SHOULD NOT be used by applications other than as arguments to ber_next_element(), as shown in the example below. -16.5. Decoding Example +17.6. Decoding Example The following is an example of decoding an ASN.1 data type: @@ -3466,34 +3675,34 @@ The following is an example of decoding an ASN.1 data type: tonly BOOLEAN, attrs SEQUENCE OF OCTET STRING, -- must be printable [0] SEQUENCE OF SEQUENCE { - - - -Expires: 2 December 1999 [Page 61] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - type OCTET STRING -- must be printable, crit BOOLEAN DEFAULT FALSE, value OCTET STRING } OPTIONAL } - #define TAG_CONTROL_LIST 0xA0L /* context specific cons 0 */ + #define TAG_CONTROL_LIST 0xA0U /* context specific cons 0 */ int decode_example2(struct berval *bv) { BerElement *ber; ber_len_t len; ber_tag_t res; - int scope, ali, size, time, tonly; + ber_int_t scope, ali, size, time, tonly; char *dn = NULL, **attrs = NULL; int i,rc = 0; ber = ber_init(bv); if (ber == NULL) { fputs("ERROR ber_init failed\n", stderr); + + + +Expires: 8 April 2000 [Page 65] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + return -1; } @@ -3523,19 +3732,10 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 tag != LBER_DEFAULT; tag = ber_next_element (ber,&len,opaque)) { - - - -Expires: 2 December 1999 [Page 62] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - ber_len_t tlen; ber_tag_t ttag; char *type; - int crit; + ber_int_t crit; struct berval *value; if (ber_scanf(ber,"{a",&type) == LBER_ERROR) { @@ -3546,15 +3746,24 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 ldap_memfree(type); ttag = ber_peek_tag(ber,&tlen); - if (ttag == 0x01) { /* boolean */ + if (ttag == 0x01U) { /* boolean */ if (ber_scanf(ber,"b", &crit) == LBER_ERROR) { fputs("ERROR cannot parse crit\n", stderr); + + + +Expires: 8 April 2000 [Page 66] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + rc = -1; break; } - } else if (ttag == 0x04) { /* octet string */ + } else if (ttag == 0x04U) { /* octet string */ crit = 0; } else { fputs("ERROR extra field in controls\n", @@ -3572,7 +3781,11 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 } } - ber_scanf(ber,"}"); + if ( rc == 0 ) { /* no errors so far */ + if (ber_scanf(ber,"}") == LBER_ERROR) { + rc = -1; + } + } ber_free(ber,1); @@ -3581,29 +3794,30 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 - - -Expires: 2 December 1999 [Page 63] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -17. Security Considerations +18. Security Considerations LDAPv2 supports security through protocol-level authentication using -clear-text passwords. LDAPv3 adds support for SASL [8] (Simple Authen- +clear-text passwords. LDAPv3 adds support for SASL [12] (Simple Authen- tication Security Layer) methods. LDAPv3 also supports operation over a secure transport layer using Transport Layer Security TLS [9]. Readers are referred to the protocol documents for discussion of related secu- rity considerations. -Implementations of this API should be cautious when handling authentica- +Implementations of this API SHOULD be cautious when handling authentica- tion credentials. In particular, keeping long-lived copies of creden- tials without the application's knowledge is discouraged. -18. Acknowledgements + + + +Expires: 8 April 2000 [Page 67] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + +19. Acknowledgements Many members of the IETF ASID and LDAPEXT working groups as well as members of the Internet at large have provided useful comments and @@ -3615,7 +3829,7 @@ The original material upon which this specification is based was sup- ported by the National Science Foundation under Grant No. NCR-9416667. -19. Copyright +20. Copyright Copyright (C) The Internet Society (1997-1999). All Rights Reserved. @@ -3637,89 +3851,94 @@ revoked by the Internet Society or its successors or assigns. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK +FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT- +NESS FOR A PARTICULAR PURPOSE. +21. Bibliography -Expires: 2 December 1999 [Page 64] +[1] Bradner, S., "Key words for use in RFCs to Indicate Requirement + Levels", RFC 2119, March 1997. +[2] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol + (v3)", RFC 2251, December 1997. -C LDAP API C LDAP Application Program Interface 2 June 1999 -FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT -INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT- -NESS FOR A PARTICULAR PURPOSE. +Expires: 8 April 2000 [Page 68] -20. Bibliography -[1] The Directory: Selected Attribute Syntaxes. CCITT, Recommendation - X.520. +C LDAP API C LDAP Application Program Interface 8 October 1999 + -[2] M. Wahl, A. Coulbeck, T. Howes, S. Kille, W. Yeong, C. Robbins, +[3] M. Wahl, A. Coulbeck, T. Howes, S. Kille, W. Yeong, C. Robbins, "Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions", RFC 2252, December 1997. -[3] T. Howes, "The String Representation of LDAP Search Filters," RFC - 2254, December 1997. +[4] The Directory: Selected Attribute Syntaxes. CCITT, Recommendation + X.520. -[4] M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol +[5] M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol (v3): A UTF-8 String Representation of Distinguished Names", RFC 2253, December 1997. -[5] S. Kille, "Using the OSI Directory to Achieve User Friendly Nam- - ing," RFC 1781, March 1995. +[6] F. Yergeau, "UTF-8, a transformation format of Unicode and ISO + 10646", RFC 2044, October 1996. -[6] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol - (v3)", RFC 2251, December 1997. +[7] K. Simonsen, "Character Mnemonics and Character Sets," RFC 1345, + June 1992. -[7] A. Herron, T. Howes, M. Wahl, C. Weider, A. Anantha, "LDAP Control - Extension for Server Side Sorting of Search Results", INTERNET- - DRAFT , 7 August 1998. +[8] "Programming Languages - C", ANSI/ISO Standard 9899, revised 1997. -[8] J. Meyers, "Simple Authentication and Security Layer (SASL)", RFC - 2222, October 1997. +[9] J. Hodges, R. Morgan, M. Wahl, "Lightweight Directory Access Proto- + col (v3): Extension for Transport Layer Security", INTERNET-DRAFT + (work in progress) , June + 1999. + +[10] R. Hinden, S. Deering, "IP Version 6 Addressing Architecture," RFC + 1884, December 1995. -[9] "Lightweight Directory Access Protocol (v3): Extension for Tran- - sport Layer Security", INTERNET-DRAFT , November 1998. +[11] A. Herron, T. Howes, M. Wahl, A. Anantha, "LDAP Control Extension + for Server Side Sorting of Search Results", INTERNET-DRAFT (work in + progress) , 5 April 1999. -[10] "UTF-8, a transformation format of Unicode and ISO 10646", RFC - 2044, October 1996. +[12] J. Meyers, "Simple Authentication and Security Layer (SASL)", RFC + 2222, October 1997. -[11] "IP Version 6 Addressing Architecture,", RFC 1884, December 1995. +[13] T. Howes, "The String Representation of LDAP Search Filters," RFC + 2254, December 1997. -[12] "Character Mnemonics and Character Sets," RFC 1345, June 1992. +[14] S. Kille, "Using the OSI Directory to Achieve User Friendly Nam- + ing," RFC 1781, March 1995. -[13] "Programming Languages - C", ANSI/ISO Standard 9899, revised 1997. +22. Authors' Addresses + Mark Smith (document editor) + Netscape Communications Corp. + 501 E. Middlefield Rd., Mailstop MV068 + Mountain View, CA 94043 + USA -Expires: 2 December 1999 [Page 65] +Expires: 8 April 2000 [Page 69] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -21. Authors' Addresses - Mark Smith (document editor) - Netscape Communications Corp. - 501 E. Middlefield Rd., Mailstop MV068 - Mountain View, CA 94043 - USA +1 650 937-3477 mcs@netscape.com Tim Howes - Netscape Communications Corp. - 501 E. Middlefield Rd., Mailstop MV068 - Mountain View, CA 94043 - USA - +1 650 937-3419 - howes@netscape.com + 1345 Fairway Dr. + Los Altos, CA 94024 + +1 650 787-5384 + timhowes@yahoo.com Andy Herron Microsoft Corp. @@ -3746,20 +3965,11 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 anoopa@microsoft.com -22. Appendix A - Sample C LDAP API Code +23. Appendix A - Sample C LDAP API Code #include #include - - - -Expires: 2 December 1999 [Page 66] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - main() { LDAP *ld; @@ -3769,6 +3979,15 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 BerElement *ptr; char **vals; + + + +Expires: 8 April 2000 [Page 70] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + /* open an LDAP session */ if ( (ld = ldap_init( "dotted.host.name", LDAP_PORT )) == NULL ) return 1; @@ -3808,15 +4027,6 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 /* print each value */ vals = ldap_get_values( ld, e, a ); - - - -Expires: 2 December 1999 [Page 67] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - for ( i = 0; vals[i] != NULL; i++ ) { printf( "\t\tvalue: %s\n", vals[i] ); } @@ -3826,6 +4036,15 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 if ( ptr != NULL ) { ber_free( ptr, 0 ); } + + + +Expires: 8 April 2000 [Page 71] + + +C LDAP API C LDAP Application Program Interface 8 October 1999 + + } /* free the search results */ ldap_msgfree( res ); @@ -3837,7 +4056,7 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 } -23. Appendix B - Namespace Consumed By This Specification +24. Appendix B - Namespace Consumed By This Specification The following 2 prefixes are used in this specification to name func- tions: @@ -3860,50 +4079,55 @@ macros: mod_ -24. Appendix C - Summary of Requirements for API Extensions +25. Appendix C - Summary of Requirements for API Extensions As the LDAP protocol is extended, this C LDAP API will need to be extended as well. For example, an LDAPv3 control extension has already -been defined for server-side sorting of search results [7]. This +been defined for server-side sorting of search results [7]. This appen- +dix summarizes the requirements for extending this API. +25.1. Compatibility +Extensions to this document SHOULD NOT, by default, alter the behavior +of any of the APIs specified in this document. If an extension option- +ally changes the behavior of any existing C LDAP API function calls, the +behavior change MUST be well documented. -Expires: 2 December 1999 [Page 68] -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 72] -appendix summarizes the requirements for extending this API. -24.1. Compatibility +C LDAP API C LDAP Application Program Interface 8 October 1999 -Extensions to this document should not, by default, alter the behavior -of any of the APIs specified in this document. If an extension option- -ally changes the behavior of any existing C LDAP API function calls, the -behavior change must be well documented. -24.2. Style +25.2. Style -Extensions to this API should follow the general style and naming con- -ventions used in this document. For example, function names should +Extensions to this API SHOULD follow the general style and naming con- +ventions used in this document. For example, function names SHOULD start with "ldap_" or "ber_" and consist entirely of lowercase letters, -digits, and underscore ('_') characters. More information can be found -in the preceding appendix called "Namespace Consumed By This Specifica- -tion." - -24.3. Dependence on Externally Defined Types - -Extensions to this API should minimize dependencies on types and macros -that are defined in system header files and generally use only intrinsic +digits, and underscore ('_') characters. It is RECOMMENDED that private +and experimental extensions use only the following prefixes for macros, +types, and function names: + LDAP_X_ + LBER_X_ + ldap_x_ + ber_x_ +and that these prefixes not be used by standard extensions. + +25.3. Dependence on Externally Defined Types + +Extensions to this API SHOULD minimize dependencies on types and macros +that are defined in system headers and generally use only intrinsic types that are part of the C language, types defined in this specifica- tion, or types defined in the extension document itself. -24.4. Compile Time Information +25.4. Compile Time Information -Extensions to this API should conform to the requirements contained in +Extensions to this API SHOULD conform to the requirements contained in the "Retrieving Information at Compile Time" section of this document. -That is, extensions should define a macro of the form: +That is, extensions SHOULD define a macro of the form: #define LDAP_API_FEATURE_x level @@ -3911,30 +4135,30 @@ so that applications can detect the presence or absence of the extension at compile time and also test the version or level of the extension pro- vided by an API implementation. -24.5. Runtime Information +25.5. Runtime Information -Extensions to this API should conform to the requirements contained in +Extensions to this API SHOULD conform to the requirements contained in the "Retrieving Information During Execution" section of this document. -That is, each extension should be given a character string name and that -name should appear in the ldapai_extensions array field of the LDAPAPI- +That is, each extension SHOULD be given a character string name and that +name SHOULD appear in the ldapai_extensions array field of the LDAPAPI- Info structure following a successful call to ldap_get_option() with an option parameter value of LDAP_OPT_API_INFO. In addition, information -about the extension should be available via a call to ldap_get_option() +about the extension SHOULD be available via a call to ldap_get_option() with an option parameter value of LDAP_OPT_API_FEATURE_INFO. +25.6. Values Used for Session Handle Options +Extensions to this API that add new session options (for use with the +ldap_get_option() and ldap_set_option() functions) SHOULD meet the -Expires: 2 December 1999 [Page 69] +Expires: 8 April 2000 [Page 73] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -24.6. Values Used for Session Handle Options -Extensions to this API that add new session options (for use with the -ldap_get_option() and ldap_set_option() functions) should meet the requirements contained in the last paragraph of the "LDAP Session Handle Options" section of this document. Specifically, standards track docu- ments MUST use values for option macros that are between 0x1000 and @@ -3942,14 +4166,14 @@ ments MUST use values for option macros that are between 0x1000 and for the option macros that are between 0x4000 and 0x7FFF inclusive. -25. Appendix D - Known Incompatibilities with RFC 1823 +26. Appendix D - Known Incompatibilities with RFC 1823 This appendix lists known incompatibilities between this API specifica- tion and the one contained in RFC 1823, beyond the additional API func- tions added in support of LDAPv3. -25.1. Opaque LDAP Structure +26.1. Opaque LDAP Structure In RFC 1823, some fields in the LDAP structure were exposed to applica- tion programmers. To provide a cleaner interface and to make it easier @@ -3959,7 +4183,7 @@ opaque. The new ldap_set_option() and ldap_get_option() calls can be used to manipulate per-session and global options. -25.2. Additional Error Codes +26.2. Additional Error Codes The following new error code macros were introduced to support LDAPv3: LDAP_REFERRAL @@ -3977,26 +4201,22 @@ The following new error code macros were introduced to support LDAPv3: LDAP_REFERRAL_LIMIT_EXCEEDED +26.3. Freeing of String Data with ldap_memfree() +All strings received from the API (e.g., those returned by the +ldap_get_dn() or ldap_dn2ufn() functions) SHOULD be freed by calling +ldap_memfree() not free(). RFC 1823 did not define an ldap_memfree() +function. +Expires: 8 April 2000 [Page 74] -Expires: 2 December 1999 [Page 70] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -25.3. Freeing of String Data with ldap_memfree() -All strings received from the API (e.g., those returned by the -ldap_get_dn() or ldap_dn2ufn() functions) should be freed by calling -ldap_memfree() not free(). RFC 1823 did not define an ldap_memfree() -function. +C LDAP API C LDAP Application Program Interface 8 October 1999 -25.4. Changes to ldap_result() +26.4. Changes to ldap_result() The meaning of the all parameter to ldap_result has changed slightly. Nonzero values from RFC 1823 correspond to LDAP_MSG_ALL (0x01). There @@ -4007,20 +4227,20 @@ LDAP_RES_MODRDN. The actual value for these two macros is the same (0x6D). -25.5. Changes to ldap_first_attribute() and ldap_next_attribute +26.5. Changes to ldap_first_attribute() and ldap_next_attribute -Each non-NULL return value should be freed by calling ldap_memfree() +Each non-NULL return value SHOULD be freed by calling ldap_memfree() after use. In RFC 1823, these two functions returned a pointer to a per-session buffer, which was not very thread-friendly. After the last call to ldap_first_attribute() or ldap_next_attribute(), -the value set in the ptr parameter should be freed by calling ber_free( -ptr, 0 ). RFC 1823 did not mention that the ptr value should be freed. +the value set in the ptr parameter SHOULD be freed by calling ber_free( +ptr, 0 ). RFC 1823 did not mention that the ptr value SHOULD be freed. The type of the ptr parameter was changed from void * to BerElement *. -25.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions +26.6. Changes to ldap_modrdn() and ldap_modrdn_s() Functions In RFC 1823, the ldap_modrdn() and ldap_modrdn_s() functions include a parameter called deleteoldrdn. This does not match the great majority @@ -4030,33 +4250,33 @@ functions that support deleteoldrdn and are widely implemented as well were added to this specification: ldap_modrdn2() and ldap_modrdn2_s(). -25.7. Changes to the berval structure +26.7. Changes to the berval structure In RFC 1823, the bv_len element of the berval structure was defined as -an unsigned long. In this specification, the type is implementation- -specific, although it must be an unsigned integral type that is at least -32 bits in size. See the appendix "Data Types and Legacy +an `unsigned long'. In this specification, the type is implementation- +specific, although it MUST be an unsigned integral type that is at least +32 bits in size. See the appendix "Data Types and Legacy Implementa- +tions" for additional considerations. +26.8. API Specification Clarified -Expires: 2 December 1999 [Page 71] +RFC 1823 left many things unspecified, including behavior of various +memory disposal functions when a NULL pointer is presented, requirements +for headers, values of many macros, and so on. This specification is -C LDAP API C LDAP Application Program Interface 2 June 1999 +Expires: 8 April 2000 [Page 75] -Implementations" for additional considerations. +C LDAP API C LDAP Application Program Interface 8 October 1999 -25.8. API Specification Clarified -RFC 1823 left many things unspecified, including behavior of various -memory disposal functions when a NULL pointer is presented, requirements -for header files, values of many macros, and so on. This specification -is more complete and generally tighter than the one in RFC 1823. +more complete and generally tighter than the one in RFC 1823. -25.9. Deprecated Functions +26.9. Deprecated Functions A number of functions that are in RFC 1823 are labeled as "deprecated" in this specification. In most cases, a replacement that provides @@ -4088,36 +4308,39 @@ are: Use ldap_parse_result() instead. -26. Appendix E - Data Types and Legacy Implementations +27. Appendix E - Data Types and Legacy Implementations -The data types associated with the length of a ber value (ber_len_t) and -the tag (ber_tag_t) have been defined in this specification as unsigned -integral types of implementation-specific size. This was done so that +The data types associated with the length of a ber value (ber_len_t), +and the tag (ber_tag_t) have been defined in this specification as +unsigned integral types of implementation-specific size. The data type +used for encoding and decoding ber integer, enumerated, and boolean +values has been defined in this specification as a signed integral type +of implementation-specific size. This was done so that source and +binary compatibility of the C LDAP API can be maintained across ILP32 +environments (where int, long, and pointers are all 32 bits in size) and +LP64 environments (where ints remain 32 bits but longs and pointers grow +to 64 bits). -Expires: 2 December 1999 [Page 72] +Expires: 8 April 2000 [Page 76] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 -source and binary compatibility of the C LDAP API can be maintained -across ILP32 environments (where int, long, and pointers are all 32 bits -in size) and LP64 environments (where ints remain 32 bits but longs and -pointers grow to 64 bits). In older implementations of the C LDAP API, such as those based on RFC -1823, implementors may have chosen to use an unsigned long for these -types. If a long data type was used, a port of an application to a 64- -bit operating system using the LP64 data model would find the size of -the BER length and tag types used by the C LDAP API to increase. Also, -if the legacy implementation had chosen to implement the types as an -unsigned int, adoption of a specification that mandated use of unsigned -longs would cause a source incompatibility in an LP64 application. By -using an implementation-specific data type, the C LDAP API implementa- -tion is free to choose the correct data type and the ability to maintain -source compatibility. +1823, implementors may have chosen to use an `unsigned long' for length +and tag values. If a long data type was used for either of these items, +a port of an application to a 64-bit operating system using the LP64 +data model would find the size of the types used by the C LDAP API to +increase. Also, if the legacy implementation had chosen to implement +the tag and types as an unsigned int, adoption of a specification that +mandated use of unsigned longs would cause a source incompatibility in +an LP64 application. By using implementation-specific data types, the C +LDAP API implementation is free to choose the correct data type and the +ability to maintain source compatibility. For example, suppose a legacy implementation chose to define the return value of ber_skip_tag() as an unsigned long but wishes to have the @@ -4125,308 +4348,199 @@ library return a 32-bit quantity in both ILP32 and LP64 data models. The following typedefs for ber_tag_t will provide a fixed sized data structure while preserving existing ILP32 source -- all without generat- ing compiler warnings: - #if defined(_LP64) + #include /* provides UINT_MAX in ISO C */ + #if UINT_MAX >= 0xffffffffU typedef unsigned int ber_tag_t; #else typedef unsigned long ber_tag_t; #endif -The above assumes that the the preprocessor symbol _LP64 is defined if -and only if the code is being compiled in an LP64 environment. Similar -code can be used to define an appropriate ber_len_t type. - - -27. Appendix F - Changes Made Since Last Document Revision - -The previous version of this document was draft-ietf-ldapext-ldap-c- -api-02.txt, dated 23 February, 1999. This appendix lists all of the -changes made to that document to produce this one. - -27.1. API Changes - Types: added the ber_len_t and ber_tag_t implementation-specific - unsigned integral data types to support source and binary compatibil- - ity between ILP32 and LP64 environments. Changes were made to the - "Common Data Structures" and "Encoded ASN.1 Value Manipulation" sec- - tions of this document. +Similar code can be used to define appropriate ber_len_t and ber_int_t +types. +28. Appendix F - Changes Made Since Last Document Revision +The previous version of this document was draft-ietf-ldapext-ldap-c- +api-03.txt, dated 2 June 1999. This appendix lists all of the changes +made to that document to produce this one. +28.1. API Changes -Expires: 2 December 1999 [Page 73] - - -C LDAP API C LDAP Application Program Interface 2 June 1999 - - -27.2. Editorial Changes - - General: Added Appendix E - Data Types and Legacy Implementations; - moved list of recent document changes to Appendices F and G. + Types: Added BerValue typedef for struct berval. Clarified width + requirements for integral types. Made it clear that the types for + the fields within struct timeval are implementation-specific. - "Retrieving Information During Execution" section: removed misplaced - ldapai_vendor_name and ldapai_vendor_version from the LDAPAPI- - FeatureInfo structure description. + Namespace: Added recommendation that private and experimental exten- + sions use the LDAP_X_, LBER_X_, ldap_x_, and ber_x_ portions of the + namespace only. - "Extended Operations" section: changed the names of the "requestoid" - and "requestdata" parameters in the function prototypes to match the - parameter descriptions. The old names were "exoid" and "exdata." + Macro-defined constants: Added missing 'U' suffix to unsigned + integral values. - Appendix D - "Appendix D - Known Incompatibilities with RFC 1823 ": - Added note about changes to the berval structure. -28. Appendix G - Changes Made Since draft-ietf-ldapext-ldap-c-api- -01.txt -The version of this document that preceded draft-ietf-ldapext-ldap-c- -api-02.txt was draft-ietf-ldapext-ldap-c-api-01.txt, dated 7 August -1998. This appendix lists all of the changes made to that document to -produce draft-ietf-ldapext-ldap-c-api-02.txt. +Expires: 8 April 2000 [Page 77] -28.1. API Changes +C LDAP API C LDAP Application Program Interface 8 October 1999 - General: added the 'const' keyword to function prototypes where - appropriate. - Added two new sections that specify additional features and require- - ments for API implementors: - "Header File Requirements" - "A Client Control That Governs Referral Processing" + "LDAP Error Codes" section: Corrected text to say that LDAP error + codes are non-negative integers (used to say "positive integers" + which excluded LDAP_SUCCESS). + "LDAP Session Handle Option" section: Removed LDAP_OPT_DESC because + the definition was insufficient to allow interoperable use. Added + new option LDAP_OPT_MATCHED_DN. Documented the defaults for options. + Added text to specify required behavior with respect to state in the + session handle when a call to ldap_get_option() or ldap_set_option() + succeeds or fails. Added the LDAP_OPT_PRIVATE_EXTENSION_BASE macro. - LDAP_VERSION_MAX, LDAP_VENDOR_NAME, and LDAP_VENDOR_VERSION macros. - Corrected LDAP_API_VERSION example code to use >= instead of >. - Added note about what value to use for LDAP_API_VERSION prior to pub- - lication of this draft as an RFC (2000 + draft revision number). + "Working With Controls" section: Removed PLDAPControl typedef (was a + pointer to an LDAPControl, but was not used anywhere in the API). - "Retrieving Information During Execution" section: added - LDAP_API_INFO_VERSION macro and clarified the text to explain the - behavior when there is a mismatch between LDAPAPIInfo structure ver- - sions. Added LDAP_OPT_API_FEATURE_INFO to allow applications to - retrieve version information about API extended features. + "Searching" section: Added text to describe how the operation timel- + imit that is passed to the LDAP server for an LDAP search operation + is derived from the timeout parameter that is passed to + ldap_search_ext() and ldap_search_ext_s(). + "Comparing a Value Against an Entry" section: Added `const' to + declarations of `bvalue' in ldap_compare_ext() and + ldap_compare_ext_s(). Also added missing trailing commas in proto- + types. + "Extended Operations" section: Added `const' to declarations of + `requestdata' in ldap_extended_operation() and + ldap_extended_operation_s() prototypes. + "Obtaining Results and Peeking Inside LDAP Messages" section: Added + LDAP_RES_UNSOLICITED macro for use as the `msgid' parameter to + ldap_result(). Added text to indicate that ldap_msgid() returns -1 + on error. -Expires: 2 December 1999 [Page 74] + "Handling Errors and Parsing Results" section: Added + LDAP_NOTICE_OF_DISCONNECTION macro. + "Stepping Through a List of Results" section: Added text to indicate + that ldap_count_messages(), ldap_count_entries(), and + ldap_count_references() return -1 if an error occurs. -C LDAP API C LDAP Application Program Interface 2 June 1999 + "Encoded ASN.1 Value Manipulation" section: Added ber_int_t, + ber_uint_t, and ber_slen_t integral types. Changed functions to use + ber_int_t where appropriate. Added support for encoding and decoding + enumerated values (format 'e'). Added support for the 't' format to + ber_scanf() (works like ber_peek_tag()). Changed the format specif- + ier for Bitstring in ber_printf() from 'X' to 'B' to match + ber_scanf(). Corrected text to say that ber_printf() returns a non- + negative number if successful (used to say positive, but zero is a - "LDAP Session Handle Options" section: Added macro definitions for - LDAP_OPT_ON and LDAP_OPT_OFF and changed the "invalue" type for - Boolean options from "int" to "void *". For consistency, we now - require that applications dispose of "char *" and "LDAPControl *" - values that are returned. Added note about which option value ranges - are to be used for various purposes. - "Closing the session" section: added new function ldap_unbind_ext() - to allow controls to be used with unbind operations. +Expires: 8 April 2000 [Page 78] - "Searching" section: added requirement that *res be set to NULL by - synchronous calls that fail to return any results. - "Modifying the Name of an Entry" section: added function prototypes - for ldap_modrdn2() and ldap_modrdn2_s() and corrected the ones for - ldap_modrdn() and ldap_modrdn_s() to match the most widely imple- - mented APIs. +C LDAP API C LDAP Application Program Interface 8 October 1999 - "Obtaining Results and Peeking Inside LDAP Messages" section: added - requirement that "*res" be set to NULL when ldap_result() fails to - return any results. Added requirement that ldap_msgfree() accept a - NULL "res" parameter. - "Stepping Through the Attributes of an Entry" section: added - requirement that ldap_memfree() accept a NULL "mem" parameter. + valid return value). Removed `const' qualifier from BerElement + parameters in ber_flatten() and ber_peek_tag() function prototypes + and added note about preserving the state of the underlying BerEle- + ment when ber_peek_tag() is called. Revised LBER_ERROR and + LBER_DEFAULT macros to use more portable definitions. Updated exam- + ples to reflect changes. - "Encoded ASN.1 Value Manipulation - Encoding" section: added note - that implementations may support tags with a value larger than 32 - (but this is not required). - "Encoded ASN.1 Value Manipulation - Decoding" section: changed the - LBER_ERROR and LBER_DEFAULT macros to end in "UL" instead of "L" - since all the functions that return these two values return an - "unsigned long" value. +28.2. Editorial Changes + General: Changed document to reference RFC 2119 ("Key words for use + in RFCs to Indicate Requirement Levels") and to use the key words + consistently. Reordered references to list them in the order they + appear in the document. Added text for deprecated functions to indi- + cate that more complete descriptions can be found in RFC 1823. -28.2. Editorial changes + Section names: Renamed "Overview of LDAP API Use" to "Overview of + LDAP API Use and General Requirements." Renamed "Header File + Requirements" to "Header Requirements." Renamed "Common Data Struc- + tures" to "Common Data Structures and Types." Renamed "General" sec- + tion within "Encoded ASN.1 Value Manipulation" section to "BER Data + Structures and Types." + Types: Modified implementation-specific typedefs to use `impl_XXX_t' + convention. Moved definition of `ber_tag_t' from "Common Data Struc- + tures and Types" section to "Encoded ASN.1 Value Manipulation" sec- + tion. - Removed section: "Appendix - Outstanding Issues." + "Overview of LDAP API Use and General Requirements" section: added + note that conformant implementations MUST implement all of the func- + tions and so on defined in this specification. - Added two new editorial sections: - "Appendix - Summary of Requirements for API Extensions" - "Appendix - Known Incompatibilities with RFC 1823". + "Header Requirements" section: Removed all references to the term + "header file(s)" and replaced with the simpler and less restrictive + term "header(s)." - General: replaced all occurrences of "LDAP C API" with "C LDAP API" - for consistency. + "Memory Handling Overview" section: New section added. Also cleaned + up text throughout the document to consistently state that "free" + routines do nothing when a NULL pointer is passed in. + "LDAP Session Handle Options" section: Clarified text to better indi- + cate whether ldap_memfree() or ldap_controls_free() should be used to + dispose of char * and LDAPControl * values returned by + ldap_get_option(). + "Handling Errors and Parsing Results" section: Removed confusing use + of ldap_parse_*_result() pattern (all function names are spelled out + now). -Expires: 2 December 1999 [Page 75] +Expires: 8 April 2000 [Page 79] -C LDAP API C LDAP Application Program Interface 2 June 1999 +C LDAP API C LDAP Application Program Interface 8 October 1999 - "Status of Memo" section: added a statement that this document is in - full conformance with all provisions of Section 10 of RFC2026. Also - revised the text about the Internet Draft current and shadow direc- - tories to match the latest I-D guidelines. - Document authors: removed Chris Weider from the list of authors (at - his own request) and added an explicit mention of him in the "Ack- - nowledgements" section. Updated Mark Wahl's company affiliation in - document preface. Added "(document editor)" after Mark Smith's name - in the "Authors' Addresses" section. + "Encoded ASN.1 Value Manipulation" section: Added note about lack of + specific error codes from BER functions. Cleaned up references to + berval to always say "struct berval" or "berval structure." - Copyright: updated the year to 1999. + "Authors" section: Updated Tim Howes' contact information. - "Introduction" section: expanded the sentence that mentioned the sam- - ple code appendix to mention all of the appendices. - "Overview of LDAP API Use" section: numbered the four simple steps - for using the API. Added mention of the referrals client control. - Clarified the text on character sets. Replaced mention of - ldap_bind() with ldap_sasl_bind() because the former is deprecated. - Added note that this API is designed for use in environments where - the 'int' type is at least 32 bits in size. - "Common Data Structures" section: added definition of BerElement so - it is defined before it is used. Added reference back to "Header - File Requirements" for "struct timeval" related considerations. - "Initializing an LDAP Session" section: moved note about ldap_open() - attempting to make a server connection closer to the ldap_open() - function prototype. Added note that using literal IPv6 addresses in - the "hostname" parameter is not yet supported. - "LDAP Session Handle Options" section: replaced one instance of - "Formerly" with "In RFC 1823." Added note about inheritance of - options when automatic referral following is enabled. Added - LDAP_OPT_API_INFO and LDAP_OPT_API_FEATURE_INFO for completeness (not - previously included in this section). Replaced erroneous references - to the "Using Controls" section with references to the "Working With - Controls" section. In the text describing the LDAP_OPT_HOST_NAME - option, added a reference to the "hostname" parameter of ldap_init() - for the syntax of the option value. Clarified that ldap_set_option() - makes a copy of the "invalue" data. - "Working With Controls" section: added a note to remind the reader - that server controls that are marked critical should not be used with - unbind and abandon operations since those two operations have no - server response. -Expires: 2 December 1999 [Page 76] -C LDAP API C LDAP Application Program Interface 2 June 1999 - "Closing the session" section: made it clear that all open connec- - tions associated with a session handle are closed when any of the - unbind API functions are called. - "Searching" section: added note that only a subset of the filter - functionality is available when communicating with an LDAPv2 server. - Clarified text to explain when a local timeout is used and when it is - not. - "Abandoning An Operation" section: removed some redundant text from - the paragraph that explains the differences between ldap_abandon() - and ldap_abandon_ext(). - "Obtaining Results and Peeking Inside LDAP Messages" section: clari- - fied that ldap_result() only returns messages for one request at a - time. - "Handling Errors and Parsing Results" section: replace a few - occurrences of LDAPResult with LDAPMessage (there is no type called - LDAPResult). Changed the names of the "resultoidp" and "resultdatap" - parameters to "retoidp" and "retdatap" to avoid confusion with LDAP - result messages. - "Stepping Through a List of Entries or References" section: added "or - References" to the section name to better reflect its contents. - Added missing description of "ref" parameter. Added mention of - ldap_first_reference() and ldap_next_reference() in sentence about - function return values. - "Stepping Through the Attributes of an Entry" section: added forward - reference for BerElement type. - "Parsing References" section: in the description of the "ref" parame- - ter, changed the phrase "these routines" to the more accurate "this - routine." - "Encoded ASN.1 Value Manipulation - General" section: changed text to - make sense given that the definition of BerElement now appears first - in the "Common Data Structures" section. - "Encoded ASN.1 Value Manipulation - Encoding" section: Changed the - style of function prototypes to better match the rest of the docu- - ment. Corrected a typo in the ber_bvdup() description ("as the" - replaced with "than the"). Changed "null" to "NULL" where appropri- - ate to be consistent with use elsewhere in the document. Removed - mention of sequences from the discussion of the LBER_USE_DER option. - Fixed some truncated sentences (by adding some missing '\' characters - to the nroff document source). -Expires: 2 December 1999 [Page 77] -C LDAP API C LDAP Application Program Interface 2 June 1999 - "Encoded ASN.1 Value Manipulation - Encoding Example" section: sim- - plified the error handling in the example code through the use of a - 'goto' statement. - "Encoded ASN.1 Value Manipulation - Decoding" section: Changed the - style of function prototypes to better match the rest of the docu- - ment. Changed "null" to "NULL" and "null-terminated" to "zero- - terminated" where appropriate to be consistent with use elsewhere in - the document. Fixed a typo (the text now says "an allocated" instead - of "a allocated."). Clarified the description of the 'n' format - character for ber_scanf(). - "Encoded ASN.1 Value Manipulation - Decoding Example" section: - changed code to not define a macro that begins with "LDAP" since that - prefix is reserved for the API. Removed an extra 'i' from the format - string used in the first call to ber_scanf(). Changed error report- - ing code to send messages to stderr instead of stdout. Changed - declaration of "res" local variable from "int" to "unsigned long" and - corrected one test of the ber_scanf() return value to test against - LBER_ERROR instead of -1. Fixed improperly rendered strings (by - adding '\' characters to the nroff source for this document so that - '\t' and '\n' are correctly rendered). - "Acknowledgements" section: added the mention of Chris Weider. - Rephrased the text that gives credit to the National Science Founda- - tion (it now says "The original material upon which this specifica- - tion is based was supported by ..." instead of "This original - material upon which this revision is based was based upon work sup- - ported by ..." - In the "Bibliography" section: Added a reference to RFC 1345 and - ANSI/ISO C. Updated the LDAPv3 TLS and Sorting references to point - to the latest revisions of those documents. - "Appendix - Sample C LDAP API Code": added #include to the - sample code. Changed the code to demonstrate good error handling by - freeing all memory and calling ldap_unbind() before returning. - Replaced calls to exit() with return statements. Fixed improperly - rendered strings (by adding '\' characters to the nroff source for - this document so that '\t' and '\n' are correctly rendered). @@ -4438,6 +4552,6 @@ C LDAP API C LDAP Application Program Interface 2 June 1999 -Expires: 2 December 1999 [Page 78] +Expires: 8 April 2000 [Page 80] diff --git a/doc/drafts/draft-ietf-ldapext-ldapv3-vlv-xx.txt b/doc/drafts/draft-ietf-ldapext-ldapv3-vlv-xx.txt new file mode 100644 index 0000000000..e7bb99ef8a --- /dev/null +++ b/doc/drafts/draft-ietf-ldapext-ldapv3-vlv-xx.txt @@ -0,0 +1,655 @@ + +INTERNET-DRAFT David Boreham, Netscape + Jim Sermersheim, Novell + Anoop Anantha, Microsoft + Michael Armijo, Microsoft +ldapext Working Group 6 April, 2000 + + + LDAP Extensions for Scrolling View Browsing of Search Results + + draft-ietf-ldapext-ldapv3-vlv-04.txt + This document expires on 5 October 2000 + +1. Status of this Memo + +This document is an Internet-Draft and is in full conformance with all +provisions of Section 10 of RFC2026. Internet-Drafts are working docu- +ments of the Internet Engineering Task Force (IETF), its areas, and its +working groups. Note that other groups may also distribute working +documents as Internet-Drafts. + +Internet-Drafts are draft documents valid for a maximum of six months +and may be updated, replaced, or obsoleted by other documents at any +time. It is inappropriate to use Internet- Drafts as reference material +or to cite them other than as "work in progress." + +The list of current Internet-Drafts can be accessed at +http://www.ietf.org/ietf/1id-abstracts.txt + +The list of Internet-Draft Shadow Directories can be accessed at +http://www.ietf.org/shadow.html. + +2. Abstract + +This document describes a Virtual List View control extension for the +LDAP Search operation. This control is designed to allow the "virtual +list box" feature, common in existing commercial e-mail address book +applications, to be supported efficiently by LDAP servers. LDAP servers' +inability to support this client feature is a significant impediment to +LDAP replacing proprietary protocols in commercial e-mail systems. + +The control allows a client to specify that the server return, for a +given LDAP search with associated sort keys, a contiguous subset of the +search result set. This subset is specified in terms of offsets into the +ordered list, or in terms of a greater than or equal comparison value. + +3. Background + +A Virtual List is a graphical user interface technique employed where + + + +Boreham et al [Page 1] + + + + + +RFC DRAFT April 2000 + + +ordered lists containing a large number of entries need to be displayed. +A window containing a small number of visible list entries is drawn. The +visible portion of the list may be relocated to different points within +the list by means of user input. This input can be to a scroll bar +slider; from cursor keys; from page up/down keys; from alphanumeric keys +for "typedown". The user is given the impression that they may browse +the complete list at will, even though it may contain millions of +entries. It is the fact that the complete list contents are never +required at any one time that characterizes Virtual List View. Rather +than fetch the complete list from wherever it is stored (typically from +disk or a remote server), only that information which is required to +display the part of the list currently in view is fetched. The subject +of this document is the interaction between client and server required +to implement this functionality in the context of the results from a +sorted LDAP search request. + +For example, suppose an e-mail address book application displays a list +view onto the list containing the names of all the holders of e-mail +accounts at a large university. The list is sorted alphabetically. +While there may be tens of thousands of entries in this list, the +address book list view displays only 20 such accounts at any one time. +The list has an accompanying scroll bar and text input window for type- +down. When first displayed, the list view shows the first 20 entries in +the list, and the scroll bar slider is positioned at the top of its +range. Should the user drag the slider to the bottom of its range, the +displayed contents of the list view should be updated to show the last +20 entries in the list. Similarly, if the slider is positioned somewhere +in the middle of its travel, the displayed contents of the list view +should be updated to contain the 20 entries located at that relative +position within the complete list. Starting from any display point, if +the user uses the cursor keys or clicks on the scroll bar to request +that the list be scrolled up or down by one entry, the displayed con- +tents should be updated to reflect this. Similarly the list should be +displayed correctly when the user requests a page scroll up or down. +Finally, when the user types characters in the type-down window, the +displayed contents of the list should "jump" or "seek" to the appropri- +ate point within the list. For example, if the user types "B", the +displayed list could center around the first user with a name beginning +with the letter "B". When this happens, the scroll bar slider should +also be updated to reflect the new relative location within the list. + +This document defines a request control which extends the LDAP search +operation. Always used in conjunction with the server side sorting +control[SSS], this allows a client to retrieve selected portions of +large search result set in a fashion suitable for the implementation of +a virtual list view. + +The key words "MUST", "SHOULD", and "MAY" used in this document are to + + + +Boreham et al [Page 2] + + + + + +RFC DRAFT April 2000 + + +be interpreted as described in [Bradner97]. + +4. Client-Server Interaction + +The Virtual List View control extends a regular LDAP Search operation +which must also include a server-side sorting control[SSS]. Rather than +returning the complete set of appropriate SearchResultEntry messages, +the server is instructed to return a contiguous subset of those entries, +taken from the sorted result set, centered around a particular target +entry. Henceforth, in the interests of brevity, the sorted search result +set will be referred to as "the list". + +The sort control MAY contain any sort specification valid for the +server. The attributeType field in the first SortKeyList sequence ele- +ment has special significance for "typedown". + +The desired target entry, and the number of entries to be returned both +before, and after, that target entry in the list, are determined by the +client's VirtualListViewRequest control. + +When the server returns the set of entries to the client, it attaches a +VirtualListViewResponse control to the SearchResultDone message. The +server returns in this control: its current estimate for the list con- +tent count, the location within the list corresponding to the target +entry, and any error codes. + +The target entry is specified in the VirtualListViewRequest control by +one of two methods. The first method is for the client to indicate the +target entry's offset within the list. The second way is for the client +to supply an attribute assertion value. The value is compared against +the values of the attribute specified as the primary sort key in the +sort control attached to the search operation. The first sort key in +the SortKeyList is the primary sort key. The target entry is the first +entry in the list with value greater than or equal to (in the primary +sort order), the presented value. The order is determined by rules +defined in [SSS]. Selection of the target entry by this means is +designed to implement "typedown". Note that it is possible that no +entry satisfies these conditions, in which case there is no target +entry. This condition is indicated by the server returning the special +value contentCount + 1 in the target position field. + +Because the server may not have an accurate estimate of the number of +entries in the list, and to take account of cases where the list size is +changing during the time the user browses the list, and because the +client needs a way to indicate specific list targets "beginning" and +"end", offsets within the list are transmitted between client and server +as ratios---offset to content count. The server sends its latest esti- +mate as to the number of entries in the list (content count) to the + + + +Boreham et al [Page 3] + + + + + +RFC DRAFT April 2000 + + +client in every response control. The client sends its assumed value +for the content count in every request control. The server examines the +content count and offsets presented by the client and computes the +corresponding offsets within the list, based on its own idea of the con- +tent count. + + Si = Sc * (Ci / Cc) + + Where: + Si is the actual list offset used by the server + Sc is the server's estimate for content count + Ci is the client's submitted offset + Cc is the client's submitted content count + The result is rounded to the nearest integer. + +If the content count is stable, and the client returns to the server the +content count most recently received, Cc = Sc and the offsets transmit- +ted become the actual server list offsets. + +The following special cases are allowed: a client sending a content +count of zero (Cc = 0) means "client has no idea what the content count +is, server MUST use its own content count estimate in place of the +client's". An offset value of one (Ci = 1) always means that the target +is the first entry in the list. Client specifying an offset which equals +the content count specified in the same request control (Ci = Cc) means +that the target is the last entry in the list. Ci may only equal zero +when Cc is also zero. This signifies the last entry in the list. + +Because the server always returns contentCount and targetPosition, the +client can always determine which of the returned entries is the target +entry. Where the number of entries returned is the same as the number +requested, the client is able to identify the target by simple arith- +metic. Where the number of entries returned is not the same as the +number requested (because the requested range crosses the beginning or +end of the list, or both), the client must use the target position and +content count values returned by the server to identify the target +entry. For example, suppose that 10 entries before and 10 after the tar- +get were requested, but the server returns 13 entries, a content count +of 100 and a target position of 3. The client can determine that the +first entry must be entry number 1 in the list, therefore the 13 entries +returned are the first 13 entries in the list, and the target is the +third one. + +A server-generated context identifier MAY be returned to clients. A +client receiving a context identifier SHOULD return it unchanged in a +subsequent request which relates to the same list. The purpose of this +interaction is to enhance the performance and effectiveness of servers +which employ approximate positioning. + + + +Boreham et al [Page 4] + + + + + +RFC DRAFT April 2000 + + +5. The Controls + +Support for the virtual list view control extension is indicated by the +presence of the OID "2.16.840.1.113730.3.4.9" in the supportedControl +attribute of a server's root DSE. + +5.1. Request Control + +This control is included in the SearchRequest message as part of the +controls field of the LDAPMessage, as defined in Section 4.1.12 of +[LDAPv3]. The controlType is set to "2.16.840.1.113730.3.4.9". The cri- +ticality SHOULD be set to TRUE. If this control is included in a Sear- +chRequest message, a Server Side Sorting request control [SSS] MUST also +be present in the message. The controlValue is an OCTET STRING whose +value is the BER-encoding of the following SEQUENCE: + + VirtualListViewRequest ::= SEQUENCE { + beforeCount INTEGER (0..maxInt), + afterCount INTEGER (0..maxInt), + CHOICE { + byoffset [0] SEQUENCE { + offset INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt) }, + greaterThanOrEqual [1] AssertionValue }, + contextID OCTET STRING OPTIONAL } + +beforeCount indicates how many entries before the target entry the +client wants the server to send. afterCount indicates the number of +entries after the target entry the client wants the server to send. +offset and contentCount identify the target entry as detailed in section +4. greaterThanOrEqual is an attribute assertion value defined in +[LDAPv3]. If present, the value supplied in greaterThanOrEqual is used +to determine the target entry by comparison with the values of the +attribute specified as the primary sort key. The first list entry who's +value is no less than (less than or equal to when the sort order is +reversed) the supplied value is the target entry. If present, the con- +textID field contains the value of the most recently received contextID +field from a VirtualListViewResponse control. The type AssertionValue +and value maxInt are defined in [LDAPv3]. contextID values have no +validity outwith the connection on which they were received. That is, a +client should not submit a contextID which it received from another con- +nection, a connection now closed, or a different server. + + +5.2. Response Control + +This control is included in the SearchResultDone message as part of the +controls field of the LDAPMessage, as defined in Section 4.1.12 of + + + +Boreham et al [Page 5] + + + + + +RFC DRAFT April 2000 + + +[LDAPv3]. + +The controlType is set to "2.16.840.1.113730.3.4.10". The criticality is +FALSE (MAY be absent). The controlValue is an OCTET STRING, whose value +is the BER encoding of a value of the following SEQUENCE: + + VirtualListViewResponse ::= SEQUENCE { + targetPosition INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt), + virtualListViewResult ENUMERATED { + success (0), + operationsError (1), + unwillingToPerform (53), + insufficientAccessRights (50), + busy (51), + timeLimitExceeded (3), + adminLimitExceeded (11), + sortControlMissing (60), + offsetRangeError (61), + other (80) }, + contextID OCTET STRING OPTIONAL } + +targetPosition gives the list offset for the target entry. contentCount +gives the server's estimate of the current number of entries in the +list. Together these give sufficient information for the client to +update a list box slider position to match the newly retrieved entries +and identify the target entry. The contentCount value returned SHOULD be +used in a subsequent VirtualListViewRequest control. contextID is a +server-defined octet string. If present, the contents of the contextID +field SHOULD be returned to the server by a client in a subsequent Vir- +tualListViewRequest control. + +The virtualListViewResult codes which are common to the LDAP sear- +chResponse (adminLimitExceeded, timeLimitExceeded, busy, operationsEr- +ror, unwillingToPerform, insufficientAccessRights) have the same mean- +ings as defined in [LDAPv3], but they pertain specifically to the VLV +operation. For example, the server could exceed an administration limit +processing a SearchRequest with a VirtualListViewRequest control. How- +ever, the same administration limit would not be exceeded should the +same SearchRequest be submitted by the client without the VirtualList- +ViewRequest control. In this case, the client can determine that an +administration limit has been exceeded in servicing the VLV request, and +can if it chooses resubmit the SearchRequest without the VirtualList- +ViewRequest control. + +insufficientAccessRights means that the server denied the client permis- +sion to perform the VLV operation. + + + + +Boreham et al [Page 6] + + + + + +RFC DRAFT April 2000 + + +If the server determines that the results of the search presented exceed +the range provided by the 32-bit offset values, it MUST return +offsetRangeError. + +6. Protocol Example + +Here we walk through the client-server interaction for a specific vir- +tual list view example: The task is to display a list of all 78564 peo- +ple in the US company "Ace Industry". This will be done by creating a +graphical user interface object to display the list contents, and by +repeatedly sending different versions of the same virtual list view +search request to the server. The list view displays 20 entries on the +screen at a time. + +We form a search with baseDN "o=Ace Industry, c=us"; search scope sub- +tree; filter "objectClass=inetOrgPerson". We attach a server sort order +control to the search, specifying ascending sort on attribute "cn". To +this base search, we attach a virtual list view request control with +contents determined by the user activity and send the search to the +server. We display the results from each search in the list window and +update the slider position. + +When the list view is first displayed, we want to initialize the con- +tents showing the beginning of the list. Therefore, we set beforeCount = +0, afterCount = 19, contentCount = 0, offset = 1 and send the request to +the server. The server duly returns the first 20 entries in the list, +plus the content count = 78564 and targetPosition = 1. We therefore +leave the scroll bar slider at its current location (the top of its +range). + +Say that next the user drags the scroll bar slider down to the bottom of +its range. We now wish to display the last 20 entries in the list, so +we set beforeCount = 19, afterCount = 0, contentCount = 78564, offset = +78564 and send the request to the server. The server returns the last 20 +entries in the list, plus the content count = 78564 and targetPosition = +78564. + +Next the user presses a page up key. Our page size is 20, so we set +beforeCount = 0, afterCount = 19, contentCount = 78564, offset = +78564-19-20 and send the request to the server. The server returns the +preceding 20 entries in the list, plus the content count = 78564 and +targetPosition = 78525. + +Now the user grabs the scroll bar slider and drags it to 68% of the way +down its travel. 68% of 78564 is 53424 so we set beforeCount = 9, after- +Count = 10, contentCount = 78564, offset = 53424 and send the request to +the server. The server returns the preceding 20 entries in the list, +plus the content count = 78564 and targetPosition = 53424. + + + +Boreham et al [Page 7] + + + + + +RFC DRAFT April 2000 + + +Lastly, the user types the letter "B". We set beforeCount = 9, after- +Count = 10 and greaterThanOrEqual = "B". The server finds the first +entry in the list not less than "B", let's say "Babs Jensen", and +returns the nine preceding entries, the target entry, and the proceeding +10 entries. The server returns content count = 78564 and targetPosition += 5234 and so the client updates its scroll bar slider to 6.7% of full +scale. + +7. Notes for Implementers + +While the feature is expected to be generally useful for arbitrary +search and sort specifications, it is specifically designed for those +cases where the result set is very large. The intention is that this +feature be implemented efficiently by means of pre-computed indices per- +taining to a set of specific cases. For example, an offset relating to +"all the employees in the local organization, sorted by surname" would +be a common case. + +The intention for client software is that the feature should fit easily +with the host platform's graphical user interface facilities for the +display of scrolling lists. Thus the task of the client implementers +should be one of reformatting up the requests for information received +from the list view code to match the format of the virtual list view +request and response controls. + +Client implementers should note that any offset value returned by the +server may be approximate. Do not design clients > which only operate +correctly when offsets are exact. + +Server implementers using indexing technology which features approximate +positioning should consider returning context identifiers to clients. +The use of a context identifier will allow the server to distinguish +between client requests which relate to different displayed lists on the +client. Consequently the server can decide more intelligently whether to +reposition an existing database cursor accurately to within a short dis- +tance of its current position, or to reposition to an approximate posi- +tion. Thus the client will see precise offsets for "short" repositioning +(e.g. paging up or down), but approximate offsets for a "long" reposi- +tion (e.g. a slider movement). + +Server implementers are free to return status code unwillingToPerform +should their server be unable to service any particular VLV search. +This might be because the resolution of the search is computationally +infeasible, or because excessive server resources would be required to +service the search. + +Client implementers should note that this control is only defined on a +client interaction with a single server. If a server returns referrals + + + +Boreham et al [Page 8] + + + + + +RFC DRAFT April 2000 + + +as a part of its response to the search request, the client is responsi- +ble for deciding when and how to apply this control to the referred-to +servers, and how to collate the results from multiple servers. + + +8. Relationship to "Simple Paged Results" + +These controls are designed to support the virtual list view, which has +proved hard to implement with the Simple Paged Results mechanism +[SPaged]. However, the controls described here support any operation +possible with the Simple Paged Results mechanism. The two mechanisms are +not complementary, rather one has a superset of the other's features. +One area where the mechanism presented here is not a strict superset of +the Simple Paged Results scheme is that here we require a sort order to +be specified. No such requirement is made for paged results. + + +9. Security Considerations + +Server implementers may wish to consider whether clients are able to +consume excessive server resources in requesting virtual list opera- +tions. Access control to the feature itself; configuration options lim- +iting the feature's use to certain predetermined search base DNs and +filters; throttling mechanisms designed to limit the ability for one +client to soak up server resources, may be appropriate. + +Consideration should be given as to whether a client will be able to +retrieve the complete contents, or a significant subset of the complete +contents of the directory using this feature. This may be undesirable in +some circumstances and consequently it may be necessary to enforce some +access control. + +Clients can, using this control, determine how many entries are con- +tained within a portion of the DIT. This may constitute a security +hazard. Again, access controls may be appropriate. + +Server implementers SHOULD exercise caution concerning the content of +the contextID. Should the contextID contain internal server state, it +may be possible for a malicious client to use that information to gain +unauthorized access to information. + +10. Acknowledgements + +Chris Weider of Microsoft co-authored a previous version of this docu- +ment. + + + + + + +Boreham et al [Page 9] + + + + + +RFC DRAFT April 2000 + + +11. References + +[LDAPv3] + Wahl, M, S. Kille and T. Howes, "Lightweight Directory Access Pro- + tocol (v3)", Internet Standard, December, 1997. RFC2251. + +[SPaged] + Weider, C, A. Herron, A. Anantha, and T. Howes, "LDAP Control + Extension for Simple Paged Results Manipulation", September + 1999. RFC2696 + +[SSS]Wahl, M, A. Herron and T. Howes, "LDAP Control Extension for Server + Side Sorting of Search Results", Internet Draft, April, 1999. + Available as draft-ietf-asid-ldapv3-sorting-02.txt. + +[Bradner97] + Bradner, S., "Key Words for use in RFCs to Indicate Requirement + Levels", BCP 14, RFC 2119, March 1997. + +12. Authors' Addresses + + David Boreham + iPlanet e-commerce solutions + 501 E. Middlefield Road + Mountain View, CA 94043, USA + +1 650 937-5206 + dboreham@netscape.com + + Jim Sermersheim + Novell + 122 East 1700 South + Provo, Utah 84606, USA + jimse@novell.com + + Anoop Anantha + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052, USA + +1 425 882-8080 + anoopa@microsoft.com + + Michael Armijo + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052, USA + +1 425 882-8080 + micharm@microsoft.com + This document expires on 5 October 2000 + + + +Boreham et al [Page 10] + + + + + +RFC DRAFT April 2000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Boreham et al [Page 11] + + diff --git a/doc/drafts/draft-ietf-ldapext-locate-xx.txt b/doc/drafts/draft-ietf-ldapext-locate-xx.txt new file mode 100644 index 0000000000..3fb0d19a6d --- /dev/null +++ b/doc/drafts/draft-ietf-ldapext-locate-xx.txt @@ -0,0 +1,205 @@ +INTERNET-DRAFT Michael P. Armijo + Levon Esibov +April, 2000 Paul Leach +Expires: October, 2000 Microsoft Corporation + R.L. Morgan + University of Washington + + Discovering LDAP Services with DNS + +Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet- Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + Distribution of this memo is unlimited. It is filed as , and expires on October 15, 2000. + Please send comments to the authors. + + +1. Abstract + + A Lightweight Directory Access Protocol (LDAP) request must be + directed to an appropriate server for processing. This document + specifies a method for discovering such servers using information in + the Domain Name System. + + +2. Introduction + + The LDAPv3 protocol [1] is designed to be a lightweight access + protocol for directory services supporting X.500 models. As a + distributed directory service, the complete set of directory + information (known as the Directory Information Base) is spread + across many different servers. Hence there is the need to + determine, when initiating or processing a request, which servers + hold the relevant information. In LDAP, the Search, Modify, Add, + Delete, ModifyDN, and Compare operations all specify a Distinguished + Name (DN) [2] on which the operation is performed. A client, or a + server acting on behalf of a client, must be able to determine the + server(s) that hold the naming context containing that DN, since + that server (or one of that set of servers) must receive and process + the request. This determination process is called "server + location". To support dynamic distributed operation, the + information needed to support server location must be available via + lookups done at request processing time, rather than, for example, + as static data configured into each client or server. + + It is possible to maintain the information needed to support server + location in the directory itself, and X.500 directory deployments + typically do so. In practice, however, this only permits location + of servers within a limited X.500-connected set. LDAP-specific + methods of maintaining server location information in the directory + have not yet been standardized. This document defines an + alternative method of managing server location information using the + Domain Name System. This method takes advantage of the global + deployment of the DNS, by allowing LDAP server location information + for any existing DNS domain to be published by creating the records + described below. A full discussion of the benefits and drawbacks of + the various directory location and naming methods is beyond the + scope of this document. + + RFC 2247[3] defines an algorithm for mapping DNS domain names into + DNs. This document defines the inverse mapping, from DNs to DNS + domain names, based on the conventions in [3], for use in this + server location method. The server location method described in + this document is only defined for DNs that can be so mapped, i.e., + those DNs that are based on domain names. In practice this is + reasonable because many objects of interest are named with domain + names, and use of domain-name-based DNs is becoming common. + + +3. Mapping Distinguished Names into Domain Names + + This section defines a method of converting a DN into a DNS domain + name for use in the server location method described below. Some + DNs cannot be converted into a domain name. + + The output domain name is initially empty. For each RDN component + of the DN, beginning with the first, if the attribute type is "DC", + then the attribute value is used as a domain name component (label). + The first such value becomes the most significant (i.e., rightmost) + domain name component, and successive values occupy less significant + positions (i.e., extending leftward), in order. If the attribute + type is not "DC", then processing stops. If the first RDN component + of the DN is not of type "DC" then the DN cannot be converted to a + domain name. + + +4. Locating LDAP servers through DNS + + LDAP server location information is to be stored using DNS Service + Location Record (SRV)[5]. The data in a SRV record contains the DNS + name of the server that provides the LDAP service, corresponding + Port number, and parameters that enable the client to choose an + appropriate server from multiple servers according to the algorithm + described in [5]. The name of this record has the following format: + + _._. + + where is always "ldap", and is a protocol that can + be either "udp" or "tcp". is the domain name formed by + converting the DN of a naming context mastered by the LDAP Server + into a domain name using the algorithm in Section 2. Note that + "ldap" is the symbolic name for the LDAP service in Assigned + Numbers[6], as required by [5]. + + Presence of such records enables clients to find the LDAP servers + using standard DNS query [4]. A client (or server) seeking an LDAP + server for a particular DN converts that DN to a domain name using + the algorithm of Section 2, does a SRV record query using the DNS + name formed as described in the preceding paragraph, and interprets + the response as described in [5] to determine a host (or hosts) to + contact. As an example, a client that searches for an LDAP server + for the DN "ou=foo,dc=example,dc=net" that supports the TCP protocol + will submit a DNS query for a set of SRV records with owner name: + + _ldap._tcp.example.net. + + The client will receive the list of SRV records published in DNS + that satisfy the requested criteria. The following is an example of + such a record: + + _ldap._tcp.example.net. IN SRV 0 0 389 phoenix.example.net. + + The set of returned records may contain multiple records in the case + where multiple LDAP servers serve the same domain. + + + +5. Security Considerations + + This document describes a method that uses DNS SRV records to + discover LDAP servers. All security considerations related to DNS + SRV records are inherited by this document. See the security + considerations section in [6] for more details. + + +6. References + + [1] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access + Protocol(v3)", RFC 2251, December 1997. + + [2] Wahl, M., Kille, S. and T. Howes, "Lightweight Directory Access + Protocol (v3): UTF-8 String Representation of Distinguished + Names", RFC 2253, December 1997. + + [3] Kille, S. and M. Wahl, "Using Domains in LDAP/X.500 + Distinguished Names", RFC 2247, January 1998. + + [4] Mockapetris, P., "DOMAIN NAMES - CONCEPTS AND FACILITIES", RFC + 1034, STD 13, November 1987. + + [5] Gulbrandsen, A., Vixie, P. and L. Esibov, "A DNS RR for + specifying the location of services (DNS SRV)", RFC 2782, + February 2000. + + [6] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC + 1700, October 1994. + + +6. Authors' Addresses + + Michael P. Armijo + One Microsoft Way + Redmond, WA 98052 + micharm@microsoft.com + + Paul Leach + One Microsoft Way + Redmond, WA 98052 + paulle@microsoft.com + + Levon Esibov + One Microsoft Way + Redmond, WA 98052 + levone@microsoft.com + + RL "Bob" Morgan + University of Washington + 4545 15th Ave NE + Seattle, WA 98105 + US + + Phone: +1 206 221 3307 + EMail: rlmorgan@washington.edu + URI: http://staff.washington.edu/rlmorgan/ + + Expires October, 2000 + diff --git a/doc/drafts/draft-ietf-ldapext-sorting-xx.txt b/doc/drafts/draft-ietf-ldapext-sorting-xx.txt new file mode 100644 index 0000000000..8a7b99f128 --- /dev/null +++ b/doc/drafts/draft-ietf-ldapext-sorting-xx.txt @@ -0,0 +1,303 @@ + +Network Working Group A. Herron, Microsoft +INTERNET DRAFT T. Howes, Netscape +Expire in six months M. Wahl, Critical Angle Inc + A. Anantha, Microsoft + April 5, 1999 + + LDAP Control Extension for Server Side Sorting of Search Results + draft-ietf-ldapext-sorting-02.txt + + +1. Status of this Memo + +This document is an Internet-Draft. Internet-Drafts are working docu- +ments of the Internet Engineering Task Force (IETF), its areas, and its +working groups. Note that other groups may also distribute working +documents as Internet-Drafts. + +Internet-Drafts are draft documents valid for a maximum of six months +and may be updated, replaced, or obsoleted by other documents at any +time. It is inappropriate to use Internet- Drafts as reference material +or to cite them other than as ``work in progress.'' + +To learn the current status of any Internet-Draft, please check the +``1id-abstracts.txt'' listing contained in the Internet- Drafts Shadow +Directories on ds.internic.net (US East Coast), nic.nordu.net (Europe), +ftp.isi.edu (US West Coast), or munnari.oz.au (Pacific Rim). + +This document expires on October 5, 1999. + +2. Abstract + +This document describes two LDAPv3 control extensions for server side +sorting of search results. These controls allows a client to specify the +attribute types and matching rules a server should use when returning +the results to an LDAP search request. The controls may be useful when +the LDAP client has limited functionality or for some other reason +cannot sort the results but still needs them sorted. Other permissible +controls on search operations are not defined in this extension. + +The sort controls allow a server to return a result code for the sorting +of the results that is independent of the result code returned for the +search operation. + +The key words "MUST", "SHOULD", and "MAY" used in this document are to +be interpreted as described in [bradner97]. + +3. The Controls + +3.1 Request Control + +This control is included in the searchRequest message as part of the +controls field of the LDAPMessage, as defined in Section 4.1.12 of +[LDAPv3]. + +The controlType is set to "1.2.840.113556.1.4.473". The criticality +MAY be either TRUE or FALSE (where absent is also equivalent to +FALSE) at the client's option. The controlValue is an OCTET STRING, +whose value is the BER encoding of a value of the following SEQUENCE: + + SortKeyList ::= SEQUENCE OF SEQUENCE { + attributeType AttributeDescription, + orderingRule [0] MatchingRuleId OPTIONAL, + reverseOrder [1] BOOLEAN DEFAULT FALSE } + +The SortKeyList sequence is in order of highest to lowest sort key +precedence. + +The MatchingRuleID SHOULD be one that is valid for the attribute type +it applies to. If it is not, the server MUST return unwillingToPerform. + +Each attributeType should only occur in the SortKeyList once. If an +attributeType is included in the sort key list multiple times, the +server should return an error in the sortResult of unwillingToPerform. + +If the orderingRule is omitted, the ordering MatchingRule defined for use +with this attribute MUST be used. + +Any conformant implementation of this control MUST allow a sort key +list with at least one key. + +3.2 Response Control + +This control is included in the searchResultDone message as part of the +controls field of the LDAPMessage, as defined in Section 4.1.12 of +[LDAPv3]. + +The controlType is set to "1.2.840.113556.1.4.474". The criticality is +FALSE (MAY be absent). The controlValue is an OCTET STRING, whose +value is the BER encoding of a value of the following SEQUENCE: + + SortResult ::= SEQUENCE { + sortResult ENUMERATED { + success (0), -- results are sorted + operationsError (1), -- server internal failure + timeLimitExceeded (3), -- timelimit reached before + -- sorting was completed + strongAuthRequired (8), -- refused to return sorted + -- results via insecure + -- protocol + adminLimitExceeded (11), -- too many matching entries + -- for the server to sort + noSuchAttribute (16), -- unrecognized attribute + -- type in sort key + inappropriateMatching (18), -- unrecognized or inappro- + -- priate matching rule in + -- sort key + insufficientAccessRights (50), -- refused to return sorted + -- results to this client + busy (51), -- too busy to process + unwillingToPerform (53), -- unable to sort + other (80) + }, + attributeType [0] AttributeDescription OPTIONAL } + +4. Client-Server Interaction + +The sortKeyRequestControl specifies one or more attribute types and +matching rules for the results returned by a search request. The server +SHOULD return all results for the search request in the order specified +by the sort keys. If the reverseOrder field is set to TRUE, then the +entries will be presented in reverse sorted order for the specified +key. + +There are six possible scenarios that may occur as a result of the sort +control being included on the search request : + +1 - If the server does not support this sorting control and the client +specified TRUE for the control's criticality field, then the server +MUST return unavailableCriticalExtension as a return code in the +searchResultDone message and not send back any other results. This +behavior is specified in section 4.1.12 of [LDAPv3]. + +2 - If the server does not support this sorting control and the client +specified FALSE for the control's criticality field, then the server +MUST ignore the sort control and process the search request as if it +were not present. This behavior is specified in section 4.1.12 of +[LDAPv3]. + +3 - If the server supports this sorting control but for some reason +cannot sort the search results using the specified sort keys and the +client specified TRUE for the control's criticality field, then the +server SHOULD do the following: return unavailableCriticalExtension as +a return code in the searchResultDone message; include the +sortKeyResponseControl in the searchResultDone message, and not send +back any search result entries. + +4 - If the server supports this sorting control but for some reason +cannot sort the search results using the specified sort keys and the +client specified FALSE for the control's criticality field, then the +server should return all search results unsorted and include the +sortKeyResponseControl in the searchResultDone message. + +5 - If the server supports this sorting control and can sort the search +results using the specified sort keys, then it should include the +sortKeyResponseControl in the searchResultDone message with a +sortResult of success. + +6 - If the search request failed for any reason and/or there are no +searchResultEntry messages returned for the search response, then the +server SHOULD omit the sortKeyResponseControl from the +searchResultDone message. + +The client application is assured that the results are sorted in the +specified key order if and only if the result code in the +sortKeyResponseControl is success. If the server omits the +sortKeyResponseControl from the searchResultDone message, the client +SHOULD assume that the sort control was ignored by the server. + +The sortKeyResponseControl, if included by the server in the +searchResultDone message, should have the sortResult set to either +success if the results were sorted in accordance with the keys +specified in the sortKeyRequestControl or set to the appropriate error +code as to why it could not sort the data (such as noSuchAttribute or +inappropriateMatching). Optionally, the server MAY set the +attributeType to the first attribute type specified in the SortKeyList +that was in error. The client SHOULD ignore the attributeType field if +the sortResult is success. + +The server may not be able to sort the results using the specified sort +keys because it may not recognize one of the attribute types, the +matching rule associated with an attribute type is not applicable, or +none of the attributes in the search response are of these types. +Servers may also restrict the number of keys allowed in the control, +such as only supporting a single key. + +Servers that chain requests to other LDAP servers should ensure that +the server satisfying the client's request sort the entire result set +prior to sending back the results. + +4.1 Behavior in a chained environment + +If a server receives a sort request, the client expects to receive a +set of sorted results. If a client submits a sort request to a server +which chains the request and gets entries from multiple servers, and +the client has set the criticality of the sort extension to TRUE, the +server MUST merge sort the results before returning them to the client +or MUST return unwillingToPerform. + +4.2 Other sort issues + +An entry that meets the search criteria may be missing one or more of +the sort keys. In that case, the entry is considered to have a value of +NULL for that key. This standard considers NULL to be a larger value +than all other valid values for that key. For example, if only one key +is specified, entries which meet the search criteria but do not have +that key collate after all the entries which do have that key. If the +reverseOrder flag is set, and only one key is specified, entries which +meet the search criteria but do not have that key collate BEFORE all +the entries which do have that key. + +If a sort key is a multi-valued attribute, and an entry happens to have +multiple values for that attribute and no other controls are present that +affect the sorting order, then the server SHOULD use the least value +(according to the ORDERING rule for that attribute). + +5. Interaction with other search controls + +When the sortKeyRequestControl control is included with the +pagedResultsControl control as specified in [LdapPaged], then the +server should send the searchResultEntry messages sorted according to +the sort keys applied to the entire result set. The server should not +simply sort each page, as this will give erroneous results to the +client. + +The sortKeyList must be present on each searchRequest message for the +paged result. It also must not change between searchRequests for the +same result set. If the server has sorted the data, then it SHOULD +send back a sortKeyResponseControl control on every searchResultDone +message for each page. This will allow clients to quickly determine +if the result set is sorted, rather than waiting to receive the entire +result set. + + +6. Security Considerations + +Implementors and administrators should be aware that allowing sorting +of results could enable the retrieval of a large number of records from +a given directory service, irregardless of administrative limits set on +the maximum number of records to return. + +A client that desired to pull all records out of a directory service +could use a combination of sorting and updating of search filters to +retrieve all records in a database in small result sets, thus +circumventing administrative limits. + +This behavior can be overcome by the judicious use of permissions on +the directory entries by the administrator and by intelligent +implementations of administrative limits on the number of records +retrieved by a client. + + +7. References + +[LDAPv3] + Wahl, M, S. Kille and T. Howes, "Lightweight Directory Access +Pro- + tocol (v3)", RFC 2251, December, 1997. + +[Bradner97] + Bradner, Scott, "Key Words for use in RFCs to Indicate +Requirement + Levels", RFC 2119, March, 1997. + +[LdapPaged] + C. Weider, A. Herron, and T. Howes, "LDAP Control Extension for + Simple Paged Results Manipulation", Internet Draft, February, 1997. + Available as draft-ietf-asid-ldapv3-simplepaged-00.txt. + + +8. Author's Address + + Anoop Anantha + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052 + USA + Anoopa@microsoft.com + +1 425 882-8080 + + Andy Herron + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052 + USA + andyhe@microsoft.com + +1 425 882-8080 + + Tim Howes + Netscape Communications Corp. + 501 E. Middlefield Road + Mountain View, CA 94043 + USA + howes@netscape.com + +1 415 937-2600 + + Mark Wahl + Critical Angle Inc. + 4815 W Braker Lane #502-385 + Austin, TX 78759 + USA + M.Wahl@critical-angle.com + diff --git a/doc/drafts/draft-ietf-ldup-framing-xx.txt b/doc/drafts/draft-ietf-ldup-framing-xx.txt new file mode 100644 index 0000000000..404e8ac603 --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-framing-xx.txt @@ -0,0 +1,340 @@ + +Extended Operations for Framing LDAP Operations +Internet-Draft +Intended Category: Standards Track +Expires: September 10, 2000 + + + Ellen Stokes + IBM Corporation + + Roger Harrison + Novell, Inc. + + Gordon Good + Netscape Communications Corp. + + March 10, 2000 + + Extended Operations for Framing LDAP Operations + Filename: draft-ietf-ldup-framing-00.txt + +Table of Contents + +1. Status of this Memo.............................................2 +2. Abstract........................................................2 +3. Overview........................................................2 +4. Protocol element definitions....................................3 +4.1 StartFramedProtocolRequest Extended Operation...................3 +4.2 StartFramedProtocolResponse Extended Operation..................3 +4.3 EndFramedProtocolRequest Extended Operation.....................4 +4.4 EndFramedProtocolResponse Extended Operation....................4 +5. Acknowledgments.................................................5 +6. References......................................................5 +7. Author's Addresses..............................................5 + + + + + + + + + + + + + + + + + + + + +Stokes, Harrison and Good [Page 1] + +Internet-Draft LDUP Workgroup March 10, 2000 + + +1. Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that other + groups may also distribute working documents as Internet-Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet- Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + +. + + This Internet Draft expires September 10, 2000. + + +2. Abstract + + Certain types of LDAP applications can benefit from the ability to + specify the beginning and end of a related group of operations. For + example, the LDUP multimaster update protocol [ARCHITECTURE] requires + that two servers agree to begin a session to transfer pending + replication updates. This document provides a framework for + constructing protocols that feature a framed set of related + operations. It defines a pair of LDAPv3 extended operations that + provide begin-end framing, and a pair of extended operations used to + respond the begin-end framing operations. The nature of the actual + LDAP operations carried inside these framing operations is not + specified in this document. + + All protocol elements described here are LDAP Version 3 extended + operations. LDAP Version 3 is described in RFC 2251 [LDAPv3]. + + Certain terms used in this document are defined in the document "LDAP + Replication Architecture" [ARCHITECTURE]. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are + to be interpreted as described in RFC 2119 [KEYWORDS]. + +3. Overview + + This document describes two LDAPv3 Extended Operations that are used + to signal the beginning and end of a set of grouped operations, and + + + +Stokes, Harrison and Good [Page 2] + +Internet-Draft LDUP Workgroup March 10, 2000 + + + two LDAPv3 extended operations that are used to respond to these + operations. These extended operations provide a framework that may be + used when developing a protocol that requires begin-end framing. + +4. Protocol element definitions + +4.1 StartFramedProtocolRequest Extended Operation + + The StartFramedProtocolRequest extended operation indicates that the + initiator wishes to begin transmission of a set of related LDAP + operations. The requestValue of the StartFramedProtocolRequest + extended operation contains an OID that describes the specific framed + protocol being initiated, and a protocol-specific payload. + + An LDAPv3 Extended Request is defined in [LDAPv3] as follows: + + ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + requestName [0] LDAPOID, + requestValue [1] OCTET STRING OPTIONAL + } + + The requestName portion of the StartFramedProtocolRequest must be the + OID "2.16.840.1.113719.1.142.100.1". + + The requestValue of the StartFramedProtocolRequest must be set to the + BER-encoding of the following: + + StartFramedProtocolRequestValue ::= SEQUENCE { + framedProtocolOID LDAPOID, + framedProtocolPayload OPTIONAL OCTET STRING + } + + The parameters in the requestValue of the StartFramedProtocolRequest + are: + + - framedProtocolOID: An OID that uniquely identifies the protocol + framed by this operation. - framedProtocolPayload: An octet + string that contains protocol-specific + information. + + +4.2 StartFramedProtocolResponse Extended Operation + + The StartFramedProtocolResponse extended operation is sent in + response to a StartFramedProtocolResponse extended operation. + + An LDAPv3 Extended Response is defined in [LDAPv3] as follows: + + + + +Stokes, Harrison and Good [Page 3] + +Internet-Draft LDUP Workgroup March 10, 2000 + + + ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + COMPONENTS of LDAPResult, + responseName [10] LDAPOID OPTIONAL, + response [11] OCTET STRING OPTIONAL + } + + The responseName of the StartFramedProtocolResponse must be the OID + "2.16.840.1.113719.1.142.100.2". + + The response of the StartFramedProtocolResponse is set to the BER- + encoding of a protocol-specific response. + +4.3 EndFramedProtocolRequest Extended Operation + + The EndFramedProtocolRequest extended operation indicates the end a + set of related LDAP operations. The requestValue of the + EndFramedProtocolRequest extended operation contains a protocol- + specific payload. + + An LDAPv3 Extended Request is defined in [LDAPv3] as follows: + + ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + requestName [0] LDAPOID, + requestValue [1] OCTET STRING OPTIONAL + } + + The requestName of the EndFramedProtocolRequest must be the OID + "2.16.840.1.113719.1.142.100.4". + + The requestValue of the EndFramedProtocolRequest is set to the BER- + encoding of a protocol-specific response. + +4.4 EndFramedProtocolResponse Extended Operation + + The EndFramedProtocolResponse extended operation is sent in response + to an EndFramedProtocolRequest. + + An LDAPv3 Extended Response is defined in [LDAPv3] as follows: + + ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + COMPONENTS of LDAPResult, + responseName [10] LDAPOID OPTIONAL, + response [11] OCTET STRING OPTIONAL + } + + The responseName of the EndFramedProtocolResponse must be the OID + "2.16.840.1.113719.1.142.100.5". + + + + +Stokes, Harrison and Good [Page 4] + +Internet-Draft LDUP Workgroup March 10, 2000 + + + The response of the EndFramedProtocolResponse is set to the BER- + encoding of a protocol-specific response. + +5. Acknowledgments + +The authors gratefully acknowledge the contributions of the IETF LDUP +working group. + +6. References + + +[KEYWORDS] + S. Bradner, "Key Words for use in RFCs to Indicate Requirement Lev- + els", Harvard University, RFC 2119, March 1997. + + +[ARCHITECTURE] + J. Merrells, E. Reed, U. Srinivasan, "LDAP Replication Architec- + ture", Internet-Draft, draft-ietf-ldup-model-02.txt, October 1999. + + +[LDAPv3] + M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol + (v3)", RFC 2251, December 1997. + +7. Author's Addresses + + Ellen Stokes + IBM + 11400 Burnet Rd + Austin, TX 78758 + USA + EMail: stokes@austin.ibm.com + phone: +1 512 838 3725 + fax: +1 512 838 0156 + + Roger Harrison + Novell, Inc. + 122 E. 1700 S. + Provo, UT 84606 + USA + EMail: roger_harrison@novell.com + Phone: +1 801 861 2642 + + Gordon Good + Netscape Communications Corp. + 501 E. Middlefield Rd. + Mailstop MV068 + + + +Stokes, Harrison and Good [Page 5] + +Internet-Draft LDUP Workgroup March 10, 2000 + + + Mountain View, CA 94043 + USA + EMail: ggood@netscape.com + Phone: +1 650 937-3825 + + +Appendix A - Complete ASN.1 Definition + +StartFramedProtocolRequest ::= ExtendedRequest + +StartFramedProtocolRequestValue ::= SEQUENCE { + framedProtocolOID LDAPOID, + framedProtocolPayload OPTIONAL OCTET STRING +} + +StartFramedProtocolResponse ::= ExtendedResponse + +EndFramedProtocolRequest ::= ExtendedRequest + +EndFramedProtocolResponse ::= ExtendedResponse + +Full Copyright Statement + +Copyright (C) The Internet Society (1999). All Rights Reserved. + +This document and translations of it may be copied and furnished to oth- +ers, and derivative works that comment on or otherwise explain it or +assist in its implementation may be prepared, copied, published and dis- +tributed, in whole or in part, without restriction of any kind, provided +that the above copyright notice and this paragraph are included on all +such copies and derivative works. However, this document itself may not +be modified in any way, such as by removing the copyright notice or +references to the Internet Society or other Internet organizations, +except as needed for the purpose of developing Internet standards in +which case the procedures for copyrights defined in the Internet Stan- +dards process must be followed, or as required to translate it into +languages other than English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an "AS +IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK +FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT- +NESS FOR A PARTICULAR PURPOSE. + + + + +Stokes, Harrison and Good [Page 6] diff --git a/doc/drafts/draft-ietf-ldup-infomod-xx.txt b/doc/drafts/draft-ietf-ldup-infomod-xx.txt new file mode 100644 index 0000000000..b1e5ab1aac --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-infomod-xx.txt @@ -0,0 +1,1021 @@ +INTERNET-DRAFT +draft-ietf-ldup-infomod-01.txt + Ed Reed + Reed-Matthews, Inc. + March 9, 2000 + + LDUP Replication Information Model + + +1. Status of this Memo + +This document is an Internet-Draft and is in full conformance with all +provisions of Section 10 of RFC2026. + +Internet-Drafts are working documents of the Internet Engineering Task +Force (IETF), its areas, and its working groups. Note that other +groups may also distribute working documents as Internet-Drafts. + +Internet-Drafts are draft documents valid for a maximum of six months +and may be updated, replaced, or obsoleted by other documents at any +time. It is inappropriate to use Internet-Drafts as reference material +or to cite them other than as "work in progress." + +The list of current Internet-Drafts can be accessed at +http://www.ietf.org/ietf/1id-abstracts.txt. + +The list of Internet-Draft Shadow Directories can be accessed at +http://www.ietf.org/shadow.html. + +This Internet-Draft expires on May 11, 1999. + + +2. Abstract + +[LDUP Model] describes the architectural approach to replication of +LDAP directory contents. This document describes the information +model and schema elements which support LDAP Replication Services +which conform to [LDUP Model]. + +Directory schema is extended to provide object classes, subentries, +and attributes to describe areas of the namespace which are under +common administrative authority, units of replication (ie, subtrees, +or partitions of the namespace, which are replicated), servers which +hold replicas of various types for the various partitions of the +namespace, which namespaces are held on given servers, and the +progress of various namespace management and replication operations. +Among other things, this knowledge of where directory content is + + + +Reed [Page 1] + Expires September 9, 2000 + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +located will provide the basis for dynamic generation of LDAP +referrals for clients who can follow them. + +The controlling framework by which the relationships, types, and +health of replicas of the directory content will be defined so that, +as much as possible, directory content is itself used to monitor and +control the environment. + +Security information, including access control policy identifiers and +information will be treated as directory content by the replication +protocols when specified by the LDAPEXT group. + +The information model will describe required and optional house- +keeping duties for compliant systems to implement, such as garbage +collection of deleted objects, reconciliation of moved and renamed +objects, update sequencing and transaction bracketing of changes, etc. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in RFC 2119 [RFC2119]. The +sections below reiterate these definitions and include some additional +ones. + + +2.1 Changes in this version + +LDAP Subentry definition is moved to its own document [SUBENTRY]. + +LDAP Schedule Subentry definition is defined. + +LDAP Access Point removed in favor of just using the DN of the server +holding the replica (so a new syntax isn't required). + +LDAP Change Sequence Number syntax eleminated in favor of just calling +it a CaseIgnoreString, so new comparison rules aren't required. + +Deleted ldapSearchFilter definition from here. Sparse replicas is +deferred. Might sparse be supported for single-master configurations +(read-only, of course). + +Fractional are okay in multi-master configurations, but again, only on +read-only replicas. + +Changed the naming convention upper-lower case usage to look less +weird. + +Note: + + +Reed [Page 2] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +Consistency discussion + +Schema document must clearly indicate that clients can and should +inspect the replica subentries to understand the single-master/multi- +master nature of the naming context to which they're talking. + +The paradigm change, to distributed data, needs to be exhaustively +discussed in the profile documents. How old applications which assume +single-master behave or misbehave in a multi-master environment is +critical to make clear. Draw examples from SMP pre-emptive +programming practices, from DNS vs host file models, etc. + + + +Decisions from wash ietf_ + +1) define two simple schema classes _ event driven histeresis + buckets, and cron-like thing. Then, the replica has a single + value pointer to a schedule. More schedule things can be + defined in the future. + +2) Create attribute ReplicaURI to provide service access point for + that replica. No DSA entry requirement. + +3) Replica id table discussion should move to protocol spec. + +To do: +1) define the cron schedule subentry class +2) define the rest of the attributes used in the classes +3) verify LDUP OID number with Novell (!) one more time +4) verify all OIDs assigned +5) verify all OIDs documented at the end of the document +6) scrub editorial comments +7) cross reference with arch document on schema element names + + + + + + + + + + + + + + + +Reed [Page 3] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +Table of Contents +1. Status of this Memo .............................................1 +2. Abstract 1 +2.1 Changes in this version........................................2 +3. Introduction ....................................................4 +3.1 Scope 4 +3.2 Terms and Definitions..........................................5 +4. Data design: ....................................................5 +5. Directory Knowledge .............................................5 +6. Schema 6 +6.1 Data Structure Definitions.....................................6 +6.1.1 ldapChangeSequenceNumber..................................6 +6.2 Attribute Definitions..........................................7 +6.2.1 attributeExclusionFilter..................................7 +6.2.2 attributeInclusionFilter..................................8 +6.2.3 replicaURI................................................8 +6.2.4 replicationStatus.........................................9 +6.2.5 replicaType...............................................9 +6.2.6 SecsToWait Attributes....................................11 +6.2.6.1 secsToWaitCat1 ........................................11 +6.2.6.2 secsToWaitCat2 ........................................11 +6.2.6.3 secsToWaitCat3 ........................................11 +6.2.6.4 secsToWaitCat4 ........................................11 +6.2.6.5 secsToWaitCat5 ........................................11 +6.2.7 updateVector.............................................12 +6.3 Class Definitions.............................................12 +6.3.1 nameContext..............................................12 +6.3.2 replicaSubentry..........................................12 +6.3.3 replicaAgreementSubentry.................................13 +6.3.4 eventScheduledSubentry Class.............................14 +6.3.5 timeScheduledSubentry Class..............................15 +7. Object Identifier Assignments ..................................15 +8. Security Considerations ........................................16 +9. References .....................................................16 +10. Copyright Notice ...............................................17 +11. Acknowledgements ...............................................17 +12. Author's Address ...............................................18 + + +3. Introduction + + +3.1 Scope + +This document describes schema of subentries representing replicas, +replication agreements and their dependencies. + + + +Reed [Page 4] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +Management and status schema elements may be defined if there is +sufficient consensus. + +Semantic interpretation of schema elements, including any special +handling expectations are to be provided here. + + +3.2 Terms and Definitions + +Definitions are provided in [LDUP Requirements], and may be reproduced +here for the convenience of the reader. + + + +4. Data design: + +As described in [LDUP Model], knowledge of replicated portions of the +directory information tree (DIT) is stored in the directory itself. + +An auxiliary class is defined to designate containers, or nodes, in +the DIT which are the root-most, or base, of naming contexts +[RFC2251]. Directory subentries [X501] are used to hold information +about replicas and replica agreements. + + + +5. Directory Knowledge + +Information about what replicas exist, what they contain, their types, +where they are stored, and how they may be contacted inevitably +provides the basis for distributed directory knowledge. As namespaces +from stand-alone servers are inter-connected with one another, this +replica information can and will be used by name resolution operations +to locate servers holding copies of specific objects, and to optimize +distributed searches which span multiple Naming Contexts. + +However, the focus of this document is NOT to fully enable such +distributed directory uses. Instead, we are focused on how portions +of the namespace (Directory Information Tree - DIT) may be replicated, +and how those replicas are configured and related to one another via +Replication Agreements. + +As such, the following high level description (from [LDUP Model])of +the information model envisioned is provided as reference for the +reader before presenting the detailed specifications. + +Generally, the DSE Naming Context attribute of an LDAPv3 server names +the Naming Contexts for which there are replicas on that server. + +Reed [Page 5] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +The Naming Context Auxiliary Class (nameContext) is added to container +objects which may have separately defined replication policy. + +Immediately subordinate to a Naming Context object are the Replica +Subentry containers which identify where the identified replica +resides (ie, its LDAP Access Point), its type (Primary, Updateable, +ReadOnly), if it is sparse, the LDAP search filter which defines what +object classes it holds, and if it is fractional, the attributes it +does or does not hold. + +Immediately subordinate in the namespace to a Replica Subentry are +Replication Agreement leaf entries which each identify another +Replica, the scheduling policy for replication operations (including +times when replication is to be performed, when it is not to be +performed, or the policies governing event-driven replication +initiation). + + + +6. Schema + + +6.1 Data Structure Definitions + +For the purposes of defining the encoding rules for attribute +structures, the BNF definitions in section 4.1 of [RFC2252] will be +used. They are based on the BNF styles of [RFC822]. + +To avoid requiring new syntax support to be added unnecessarily to +existing LDAPv3 directory service implementations (and the +accompanying matching rules, etc. they would entail), a string +encoding is defined for ldapChangeSequenceNumber which can use +CaseIgnoreString matching rules for ordering and equality. + +6.1.1 ldapChangeSequenceNumber + +( 1.3.6.1.4.1.1466.115.121.1.TBD DESC 'LDAP Change Sequence Number' ) + +Values in this syntax are encoded according to the following BNF. +Note there MUST NOT be any whitespace separators, unless they are in +replicaID, which must be encoded according to the instructions below. + +This encoding is specified so that the CaseIgnoreString equality and +ordering rules will work correctly when replicaNumber is used. + +When replicaID is used, CaseIgnoreString comparison rules will not +work unless each replicaID is exactly the same length with no padded + + +Reed [Page 6] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +white spaces (because CaseIgnoreString suppresses duplicate adjacent +white space when it compares two strings). + +LDAPChangeSequenceNumber = GeneralizedZTime "#" S1 "#" replicaID + "#" S2 +GeneralizedZTime = yyyy | mm | dd | hh | mi | ss | "Z" +yyyy = dddd +mm = dd +dd = dd +hh = dd +mi = dd +ss = dd +replicaID = dstring +S1, S2 = numericstring + +The GeneralizedTime is used as described (cf. [X680] section 39.3 case +b) without separators or whitespace, and representing a coordinated +universal time (i.e., Greenwich Mean Time, or GMT). All times +referenced by this syntax MUST be normalized to GMT - no local times, +nor time zone offsets are permitted. To simplify comparisons of two +CSNs, the "Z" MUST be the UTF-8 capital-Z character. + +The ReplicaID represents the specific Replica of this Naming Context +where the event associated with this LDAPChangeSequenceNumber +occurred. Note that in actual transfer, the ReplicaID MAY be +represented by a number (see the specification of the +replicaLookupTable, above). + +S1 and S2 are sequence numbers which are used to order two events with +the same Generalized Time and ReplicaID. In order to use string +matching rules for equality and ordering with values with this +encoding, the length of each field must be consistent. Thus, all +instances of S1 MUST be represented with the same number of digits, +using leading zeros as necessary. The same with S2 and replicaID. + + + + +6.2 Attribute Definitions + + +6.2.1 attributeExclusionFilter + +( 2.16.840.1.113719.142.4.1 NAME 'attributeExclusionFilter' + SYNTAX OCTET STRING + SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation ) + + + +Reed [Page 7] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +The attributeExclusionFilter is intended to contain a list of +attributes in the form of an AttributeDescriptionList as described in +section 4.5.1. Search Request of [RFC2251] with the following +interpretation: an empty attributeExclusionFilter means that no +attributes are excluded; the special values "*" and "1.1" mean that +ALL attributes are excluded. + +A non-empty attributeExclusionFilter attribute on a replica subEntry +describes the attributes NOT PRESENT on entries held by that replica. +Replicas MUST NOT accept changes for attributes they're not permitted +to hold, per the attributeInclusionFilter and attributeExclusionFilter +attributes on their replica subEntry. + +A non-empty attributeExclusionFilter attribute on a +replicationAgreement subEntry describes which additional attributes +are to be excluded from the updates to be sent from the supplier +replica to the consumer replica. + + +6.2.2 attributeInclusionFilter + +( {2.16.840.1.113719.142.4.2 NAME 'attributeInclusionFilter' + SYNTAX OCTET STRING + SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation ) + +The attributeInclusionFilter is intended to contain a list of +attributes in the form of an AttributeDescriptionList as described in +section 4.5.1. Search Request of [RFC2251] with the following +interpretation: an empty attributeInclusionFilter means that all +attributes are included; the special value "*" means that ALL +attributes are included; the special value "1.1" is meaningless and is +ignored in this usage. + +A non-empty attributeInclusionFilter attribute on a replica subEntry +describes the attributes that may be PRESENT on entries held by that +replica. Replicas MUST NOT accept changes for attributes they're not +permitted to hold, per the attributeIncludionFilter and +attributeExclusionFilter attributes on their replica subEntry. + + +6.2.3 replicaURI + +(2.16.840.1.113719.142.4.x NAME `replicaURI' + DESC `how to connect to this replica' + SYNTAX ldapURI + USAGE dSAOperation ) + + + +Reed [Page 8] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +6.2.4 replicationStatus + +(2.16.840.1.113719.142.4.3 NAME 'replicationStatus' + DESC 'human readable status of last replication attempt' + SYNTAX DirectoryString + SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation ) + + +The replicationStatus attribute MAY be used to hold a human readable +message describing the most recent replication session attempt for a +replicationAgreement. + +For example, such a messages might include + +1) 19980805162203Z # Success # + +2) 19980805162322Z # Failure # Server too busy, try again + +3) 19980805170215Z # Failure # Unable to connect to DSA + +4) 19980806002301Z # Failure # Authentication failed + +5) 19980806003201Z # Failure # lost connection, reset by peer + +It is suggested, but not required, that the time of a replication +attempt (completion, if successful or failure, if not), the result of +the attempt, and any additional information about a failure be +included in the string message. + +It is suggested, but not required, that the messages be stored with +language tags (English, French, German, Japanese, Chinese, per [LANG +TAG]) particularly if multiple translations of the error messages are +available to the DSA implementers. + +Note that this is a single-valued attribute. Sequences of status +entries SHOULD be written to log files or other persistent storage, or +in multi-valued replication history attributes, but are not specified +here. + + +6.2.5 replicaType + +(2.16.840.1.113719.142.4.4 NAME 'replicaType' + DESC 'Enum: 0-reserved, 1-Primary, 2-Updateable, 3-ReadOnly, all +others reserved' + EQUALITY integerMatch + SYNTAX INTEGER + SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation ) + +Reed [Page 9] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +ReplicaType is a simple enumeration, used to identify what kind of +replica is being described in a Replica object entry. + +A ReadOnly replica only accepts LDAP Search operations (to Read +entries, list containers, and search for entries). Because no updates +ever originate from ReadOnly replicas, they never have changes to send +to another replica. However, a ReadOnly replica may be designated a +supplier DSA in a replica agreement, if it is simply passing along +information it receives from other Updateable replicas about entries +and their changes. + +ReadOnly replicas may be incomplete replicas. + +An Updateable replica may accept both LDAP Search operations (to read, +list, or search entries), as well as modification operations (to add, +modify, or delete entries). + +The consequences of having incomplete updateable replicas are not +fully understood. LDAP DSAs MAY require updateable replicas to be +complete replicas. + +A Primary replica is an Updateable replica, but it is "more special" +than other Updateable replicas. When LDAP application want to direct +their operations to a single replica, so that the application can be +sure that all application LDAP modification (add, delete, modify) +operations will be immediately visible to application readers, the +Primary replica is a good choice. Such a use would be consistent with +High Confidence DAP option [X518]. One such application might be a +management application which creates new naming contexts or joins two +naming contexts into a single naming context. Another application +might be one which creates new replicas, or replication agreements. + +There SHOULD be only one Primary replica defined for a naming context +at any time. If applications, expecting there to be a Primary replica +discover, by search or inspection of ReplicaType attributes of the +defined Replicas of a naming context, find more than one _ they should +realize that something is wrong. + +There MAY be NO primary replica defined for a naming context. + +Primary replicas MAY NOT be incomplete replicas. + +The way in which replicas change their type, as from ReadOnly to +Updateable, or Updateable to Primary is outside the scope of this +document. + +Section 5.1 "Replica Type" of [LDUP MODEL] details the permissible +combinations of replica types and sparse/fractional replicas. + +Reed [Page 10] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +6.2.6 SecsToWait Attributes + +The secsToWait attributes document the number of seconds a replica is +to wait after the occurrence of a "category n" change event before +initiating a new replication session for replicationAgreements +governed by an eventScheduledSubentry. The definition of a "category +n" change event is implementation dependent, and may be defined +differently by different directory servers. The absence of a value +for any of these attributes MUST be interpreted as meaning "do not +initiate a replication session for change events of this category". + + +6.2.6.1 secsToWaitCat1 + +( 2.16.840.1.113719.142.4.5.1 NAME 'secsToWaitCat1' + SYNTAX INTEGER + USAGE dSAOperation ) + + +6.2.6.2 secsToWaitCat2 + +( 2.16.840.1.113719.142.4.5.2 NAME 'secsToWaitCat2' + SYNTAX INTEGER + USAGE dSAOperation ) + + +6.2.6.3 secsToWaitCat3 + +( 2.16.840.1.113719.142.4.5.3 NAME 'secsToWaitCat3' + SYNTAX INTEGER + USAGE dSAOperation ) + + +6.2.6.4 secsToWaitCat4 + +( 2.16.840.1.113719.142.4.5.4 NAME 'secsToWaitCat4' + SYNTAX INTEGER + USAGE dSAOperation ) + + +6.2.6.5 secsToWaitCat5 + +( 2.16.840.1.113719.142.4.5.5 NAME 'secsToWaitCat5' + SYNTAX INTEGER + USAGE dSAOperation ) + + + + +Reed [Page 11] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +6.2.7 updateVector + +( 2.16.840.1.113719.142.4.6 NAME 'updateVector' + SYNTAX ldapChangeSequenceNumberSyntax + NO-USER-MODIFICATION USAGE dSAOperation ) + +The attribute updateVector is a multi-valued attribute which contains +information for a replica describing the latest changes received by +the replica from other replicas. + +There may be only one ldapChangeSequenceNumber entry from each replica +in the updateVector. That is to say, there is a unique value +constraint on the ReplicaID component of entries in the list. + + +6.3 Class Definitions + + +6.3.1 nameContext + +( 2.16.840.1.113719.142.6.2.1 NAME 'nameContext' SUP top AUXILIARY ) + + +The nameContext auxiliary class, when present on an object, indicates +the beginning, or root, of a naming context. The naming context is +said to be rooted at the entry with the nameContext auxiliary class in +its list of object classes. The root-most entry of a naming context +is the entry with the nameContext auxiliary class in its list of +object classes. + +Characteristics of the replication topology of a naming context are +defined in the replicaSubentry sub-entries associated with the naming +context. + +The attribute accessControlPolicyOID has been removed from here, and +should be published as an ldapSubEntry subordinate to the nameContext, +instead. + +The attribute nameContextCreationTimestamp used here in previous +drafts has been eliminated as redundant. The ldapChangeSequenceNumber +associated with the nameContext value in the list of objectClasses +attribute serves the same purpose. + + +6.3.2 replicaSubentry + +( 2.16.840.1.113719.142.6.3.1 NAME 'replicaSubentry' SUP ldapSubEntry + STRUCTURAL + +Reed [Page 12] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + + MUST (cn, replicaURI, replicaType) + MAY (attributeExclusionFilter, attributeInclusionFilter, +description, updateVector) ) + +Entries of type replicaSubentry MAY be named by their cn attribute. + +The attributes attributeExclusionFilter and attributeInclusionFilter, +if present, govern which entries and attributes from the local naming +context are to be sent (or not sent) to the replica named in replicaDN +of replica agreements for this replica. The attributeExclusionFilter +names attributes which SHOULD NOT be sent. The +attributeInclusionFilter names attributes which SHOULD be sent. + +The attribute replicaURI contains information in ldapURI format that +can be used to contact (ie, open a connection to) this replica. + +The attribute description contains a human-readable description of the +sub-entry. + +The attribute updateVector contains a set of +ldapChangeSequenceNumbers, one for each of the other replicas for this +naming context, which records, from this replicas perspective, the +last change event received from the other indicated replica. + + +6.3.3 replicaAgreementSubentry + +( 2.16.840.1.113719.142.6.4.1 NAME 'replicaAgreementSubentry' + SUP ldapSubEntry STRUCTURAL + MUST ( cn ) + MAY ( attributeExclusionFilter, description, replicaDN, +replicationMechanismOID, replicationStatus, scheduleDN ) ) + +Entries of type replicaAgreementSubentry MAY be named by their cn +attribute. + +The attributes attributeExclusionFilter, and ldapSearchFilter, if +present, govern which entries and attributes from the local naming +context are to be sent (or not sent) to the replica named in +replicaDN. The attributeExclusionFilter names attributes SHOULD NOT be +sent. Note there is no attributeInclusionFilter, because the list of +attributes that may be sent may not be extended beyond those +documented in the attributeInclusionFilter on the replicaSubentry. + +Processing of allowable changes to be sent is as follows: + +1) the attributeInclusionFilter from the replica subentry defines a + set of attributes which SHOULD be sent, less exclusions; + +Reed [Page 13] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +2) the union of attributes excluded by the attributeExclusionFilter + from the replicasubentry and the attributeExclusionFilter from the + replicaAgreementSubentry defines a set of attributes which SHOULD + NOT be sent; + +3) the subtraction of attributes which SHOULD NOT be sent by (2) from + the attributes which SHOULD be sent by (1) constitute the set of + attributes for which changes MAY be sent. + +The attribute description contains a human-readable description of the +sub-entry. + +The attribute replicaDN of syntax DN names another sub-entry of type +replicaSubentry to whom changes are to be sent. If there is no value +for the replicaDN attribute on a replicaAgreementSubentry, the +replicaAgreementSubentry is ignored. Absence of a value may occur +briefly when replicas and replica agreements are first being created, +or when the replica to which a replica agreement applies is being +deleted. + +The attribute replicationStatus MAY be used to record the most recent +result of an attempt to send changes to the replica named in +replicaDN, whether success, or if failure, the nature of the problem +encountered. + +The attribute schedule, if present, names one or more entries of type +scheduleSubentry which govern the schedule for replication attempts. +If not present, replication MUST be attempted when there are changes +to be sent. + + +6.3.4 eventScheduledSubentry Class + +( 2.16.840.1.113719.142.6.1.1 NAME 'eventScheduledSubentry' + SUP ldapSubEntry STRUCTURAL + MUST ( cn ) + MAY ( description, secsToWaitCat1, secsToWaitCat2, secsToWaitCat3, +secsToWaitCat4, secsToWaitCat5 ) ) + +Note that replication agreements using eventScheduledSubentry policy +are, by definition, supplier-initiated. + +The description attribute may be used by the administrator to document +or comment on this subentry. + +The secsToWaitCat1 attribute documents the number of seconds a replica +is to wait after the occurrence of a "category 1" change event before +initiating a new replication session for replicationAgreements + +Reed [Page 14] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +governed by this eventScheduledSubentry. The definition of a +"category 1" change event is implementation dependent, and may be +defined differently by different directory servers. The absence of a +value for this attribute MUST be interpreted as meaning "do not +initiate a replication session for change events of this category". + +The secsToWaitCat2 _ secsToWaitCat5 attributes are similarly defined +for their respective categoriess of change events. + +6.3.5 timeScheduledSubentry Class + +( 2.16.840.1.113719.142.6.5.1 NAME 'timeScheduledSubentry' + SUP ldapSubEntry STRUCTURAL + MUST ( cn ) + MAY ( description ) ) + + + + +7. Object Identifier Assignments + +The LDUP OID prefix is + +ID ::= OBJECT IDENTIFIER + +ldup ID ::= { joint-iso-ccitt(2) country(16) us(840) + organization(1) novell(113719) ldup(142) } + +The OID assignments defined in this document are: + +Attributes: +attributeExclusionFilter ID ::= 2.16.840.1.113719.142.4.1 +attributeInclusionFilter ID ::= 2.16.840.1.113719.142.4.2 +replicationStatus ID ::= 2.16.840.1.113719.142.4.3 +replicaType ID ::= 2.16.840.1.113719.142.4.4 +secsToWaitClass1 ID ::= 2.16.840.1.113719.142.4.5.1 +secsToWaitClass2 ID ::= 2.16.840.1.113719.142.4.5.2 +secsToWaitClass3 ID ::= 2.16.840.1.113719.142.4.5.3 +secsToWaitClass4 ID ::= 2.16.840.1.113719.142.4.5.4 +secsToWaitClass5 ID ::= 2.16.840.1.113719.142.4.5.5 +updateVector ID ::= 2.16.840.1.113719.142.4.6 + +Object Classes: +eventScheduledSubentry ID ::= 2.16.840.1.113719.142.6.1.1 +nameContext ID ::= 2.16.840.1.113719.142.6.2.1 +replicaSubentry ID ::= 2.16.840.1.113719.142.6.3.1 +replicaAgreementSubentry ID ::= 2.16.840.1.113719.142.6.4.1 +timeScheduledSubentry ID ::= 2.16.840.1.113719.142.6.5.1 + +Reed [Page 15] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + + +Note: Object Class OIDs have version numbers, Attribute OIDs don't. + + +8. Security Considerations + +Many of the attributes and object classes described in this document +should be considered _security sensitive_, and protected from +unintended modification by LDAP servers. Generally, creating Naming +Contexts, Replicas and Replica Agreement entries should only be +allowed by directory administrators who are authorized to do so. + +The values of attributes defined here are intended to control the +behavior of the directory service agents, themselves. Unintended +modification of their values may result in incomplete replication of +data (if ldapSearchFilter or attributeExclusionFilter are changed), +inappropriate disclosure of information (if attributeInclusionFilter +is changed), or updates may be lost (if updateVector is changed). + +To avoid depending to much on the ldapAccessPoint values for other +replicas, connections between LDAP servers for the purpose of +replication MUST ALWAYS be authenticated using an authentication +mechanism appropriate for the nature of information to be exchanged. + + + +9. References + +[LANG TAG] _ M. Wahl, T. Howes, _Use of Language Codes in LDAP_, +Internet draft, draft-ietf-ldapext-lang-01.txt + +[LDUP Model] - J. Merrells, E. Reed, U. Srinivisan, _An Abstract Model +of LDAP Replication_, Internet draft, draft-merrells-ldup-model-01.txt + +[LDUP Requirements] - R. Weiser, E. Stokes _LDAP Replication +Requirements_, Internet draft, draft-weiser-replica-req-02.txt, April +1998 + +[RFC2251] _ M. Wahl, T. Howes, S. Kille, _Lightweight Directory Access +Protocol (v3)_, December 1997, RFC 2251 + +[RFC2252] _ M. Wahl, A. Coulbeck, T. Howes, S. Kille, _Lightweight +Directory Access Protocol (v3): Attribute Syntax Definitions_, +December 1997, RFC 2252 + +[X525] - ITU-T Recommendation X.525 (1997) | ISO/IEC 9594-9:1997, +Information Technology _ Open Systems Interconnection _ The Directory: +Replication + +Reed [Page 16] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +[X680] - ITU-T Recommendation X.680 (1994) | ISO/IEC 8824-1:1995, +Information technology _ Abstract Syntax Notation One (ASN.1): +Specification of Basic Notation + + + +10. Copyright Notice + +Copyright (C) The Internet Society (1999). All Rights Reserved. + +This document and translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it +or assist in its implmentation may be prepared, copied, published and +distributed, in whole or in part, without restriction of any kind, +provided that the above copyright notice and this paragraph are +included on all such copies and derivative works. However, this +document itself may not be modified in any way, such as by removing +the copyright notice or references to the Internet Society or other +Internet organizations, except as needed for the purpose of developing +Internet standards in which case the procedures for copyrights defined +in the Internet Standards process must be followed, or as required to +translate it into languages other than English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an +"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING +TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN +WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE." + + +11. Acknowledgements + +The use of subEntry object class to store Replica and Replication +Agreement information is due primarily to the lucid explanation by +Mark Wahl, Innosoft, of how they could be used and extended. + +The IETF takes no position regarding the validity or scope of any +intellectual property or other rights that might be claimed to pertain +to the implementation or use of the technology described in this +document or the extent to which any license under such rights might or +might not be available; neither does it represent that it has made any +effort to identify any such rights. Information on the IETF's +procedures with respect to rights in standards-track and standards- +related documentation can be found in BCP-11. Copies of claims of + +Reed [Page 17] + Expires September 9, 2000 + + + +INTERNET-DRAFT 9 March 2000 + LDUP Replication Information Model + +rights made available for publication and any assurances of licenses +to be made available, or the result of an attempt made to obtain a +general license or permission for the use of such proprietary rights +by implementors or users of this specification can be obtained from +the IETF Secretariat. + +The IETF invites any interested party to bring to its attention any +copyrights, patents or patent applications, or other proprietary +rights which may cover technology that may be required to practice +this standard. Please address the information to the IETF Executive +Director. + + + +12. Author's Address + + Edwards E. Reed + Reed-Matthews, Inc. + 1064 East 140 North + Lindon, UT 84042 + USA + E-mail: eer@oncalldba.com + + LDUP Mailing List: ietf-ldup@idc.org + + + + + + + + + + + + + + + + + + + + + + + + + +Reed [Page 18] + Expires September 9, 2000 + diff --git a/doc/drafts/draft-ietf-ldup-model-xx.txt b/doc/drafts/draft-ietf-ldup-model-xx.txt new file mode 100644 index 0000000000..1567971548 --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-model-xx.txt @@ -0,0 +1,2468 @@ +INTERNET-DRAFT + +draft-ietf-ldup-model-03.txt + + + John Merrells + Netscape Communications Corp. + Ed Reed + Reed-Matthews, Inc. + Uppili Srinivasan + Oracle, Inc. + March 10, 2000 + + LDAP Replication Architecture + +Copyright (C) The Internet Society (1998,1999, 2000). +All Rights Reserved. + +Status of this Memo + +This document is an Internet-Draft and is in full conformance with all +provisions of Section 10 of RFC2026. + +Internet-Drafts are working documents of the Internet Engineering Task +Force (IETF), its areas, and its working groups. Note that other +groups may also distribute working documents as Internet-Drafts. + +Internet-Drafts are draft documents valid for a maximum of six months +and may be updated, replaced, or made obsolete by other documents at +any time. It is inappropriate to use Internet-Drafts as reference +material or to cite them other than as "work in progress." + +The list of current Internet-Drafts can be accessed at +http://www.ietf.org/ietf/1id-abstracts.txt + +The list of Internet-Draft Shadow Directories can be accessed at +http://www.ietf.org/shadow.html. + +This draft, file name draft-ietf-ldup-model-03.txt, is intended to be +become a Proposed Standard RFC, to be published by the IETF Working +Group LDUP. Distribution of this document is unlimited. Comments +should be sent to the LDUP Replication mailing list or +to the authors. + +This Internet-Draft expires on 10 September 2000. + + + + + + + +Merrells, Reed, Srinivasan [Page 1] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + + + + + + +1 Abstract + +This architectural document outlines a suite of schema and protocol +extensions to LDAPv3 that enables the robust, reliable, server-to- +server exchange of directory content and changes. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in RFC 2119 [RFC2119]. The +sections below reiterate these definitions and include some additional +ones. + + +2 Table of Contents + +1 Abstract......................................................2 +2 Table of Contents.............................................2 +3 Introduction..................................................4 +3.1 Scope.........................................................4 +3.2 Document Objectives...........................................5 +3.3 Document Non-Objectives.......................................6 +3.4 Existing Implementations......................................6 +3.4.1 Replication Log Implementations.........................6 +3.4.2 State-Based Implementations.............................7 +3.5 Terms and Definitions.........................................7 +3.6 Consistency Models............................................8 +3.7 LDAP Constraints..............................................9 +4 Directory Model..............................................10 +4.1 Replica Type.................................................10 +4.1.1 Primary Replica........................................10 +4.1.2 Updatable Replica......................................10 +4.1.3 Read-Only Replica......................................10 +4.1.4 Fractional Replicas....................................10 +4.2 Sub-Entries..................................................11 +4.3 Glue Entries.................................................11 +4.4 Unique Identifiers...........................................11 +4.5 Change Sequence Number.......................................11 +4.5.1 CSN Composition........................................11 +4.5.2 CSN Representation.....................................12 +4.5.3 CSN Generation.........................................12 +4.6 State Change Information.....................................13 +4.1.1 Entry Change State Storage and Representation..........13 +4.1.2 Attribute Change State Storage.........................14 + +Merrells, Reed, Srinivasan [Page 2] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +4.1.3 Attribute Value Change State Storage...................14 +4.2 LDAP Update Operations.......................................14 +5 Information Model............................................15 +5.1 Entries, + Semantics and Relationships............................15 +5.2 Root DSE Attributes..........................................15 +5.3 Naming Context...............................................15 +5.4 Replica Object Class and Entries.............................16 +5.5 Lost and Found Entry.........................................16 +5.6 Replication Agreement Object Class and Entries...............16 +5.6.1 Replication Schedule...................................17 +6 Policy Information...........................................18 +6.1 Schema Knowledge.............................................18 +7 LDUP Update Transfer Protocol Framework......................18 +7.1 Replication Session Initiation...............................19 +7.1.1 Authentication.........................................19 +7.1.2 Consumer Initiated.....................................19 +7.1.3 Supplier Initiated.....................................19 +7.2 Start Replication Session....................................20 +7.2.1 Start Replication Request..............................20 +7.2.2 Start Replication Response.............................20 +7.3 Update Transfer..............................................20 +7.4 End Replication Session......................................20 +7.5 Integrity & Confidentiality..................................21 +8 LDUP Update Protocols........................................21 +8.1 Replication Updates and Update Primitives....................21 +8.2 Fractional Updates...........................................21 +9 LDUP Full Update Transfer Protocol...........................22 +9.1 Full Update Transfer.........................................22 +9.2 Replication Update Generation................................22 +9.3 Replication Update Consumption...............................22 +9.4 Full Update, End Replication Session.........................22 +9.5 Interrupted Transmission.....................................23 +10 LDUP Incremental Update Transfer Protocol....................23 +10.1 Update Vector................................................23 +10.2 Supplier Initiated, Incremental Update, + Start Replication Session................................24 +10.3 Replication Update Generation................................24 +10.3.1 Replication Log Implementation.......................25 +10.3.2 State-Based Implementation...........................25 +10.4 Replication Update Consumption...............................25 +10.5 Update Resolution Procedures.................................25 +10.5.1 URP: Distinguished Names.............................26 +10.5.2 URP: Orphaned Entries................................26 +10.5.3 URP: Distinguished Not Present.......................26 +10.5.4 URP: Schema - Single Valued Attributes...............26 +10.5.5 URP: Schema - Required Attributes....................27 +10.5.6 URP: Schema - Extra Attributes.......................27 + + +Merrells, Reed, Srinivasan [Page 3] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +10.5.7 URP: Duplicate Attribute Values......................27 +10.5.8 URP: Ancestry Graph Cycle............................27 +10.6 Incremental Update, End Replication Session..................27 +10.7 Interrupted Transmission.....................................28 +11 Purging State Information....................................28 +11.1 Purge Vector.................................................28 +11.2 Purging Deleted Entries, Attributes, and Attribute Values....29 +12 Replication Configuration and Management.....................29 +13 Time.........................................................30 +14 Security Considerations......................................31 +15 Acknowledgements.............................................31 +16 References...................................................32 +17 Intellectual Property Notice.................................32 +18 Copyright Notice.............................................33 +19 Authors' Address.............................................33 +20 Appendix A - LDAP Constraints................................34 +20.1 LDAP Constraints Clauses.....................................34 +20.2 LDAP Data Model Constraints..................................35 +20.3 LDAP Operation Behaviour Constraints.........................36 +20.4 New LDAP Constraints.........................................37 +20.4.1 New LDAP Data Model Constraints......................37 +20.4.2 New LDAP Operation Behaviour Constraints.............37 + + + + + + +3 Introduction + + +3.1 Scope + +This architectural document provides an outline of an LDAP based +replication scheme. Further detailed design documents will draw +guidance from here. + +The design proceeds from prior work in the industry, including +concepts from the ITU-T Recommendation X.525 (1993, 1997) Directory +Information Shadowing Protocol (DISP) [X525], experience with widely +deployed distributed directories in network operating systems, +electronic mail address books, and other database technologies. The +emphasis of the design is on: + +1. Simplicity of operation. + +2. Flexibility of configuration. + +3. Manageability of replica operations among mixed heterogeneous + vendor LDAP servers under common administration. + + +Merrells, Reed, Srinivasan [Page 4] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +4. Security of content and configuration information when LDAP servers + from more than one administrative authority are interconnected. + +A range of deployment scenarios are supported, including multi-master +and single-master topologies. Replication networks may include +transitive and redundant relationships between LDAP servers. + +The controlling framework used to define the relationships, types, and +state of replicas of the directory content is defined. In this way the +directory content can itself be used to monitor and control the +replication network. The directory schema is extended to define object +classes, auxiliary classes, and attributes that describe areas of the +namespace which are replicated, LDAP servers which hold replicas of +various types for the various partitions of the namespace, LDAP Access +Points (network addresses) where such LDAP servers may be contacted, +which namespaces are held on given LDAP servers, and the progress of +replication operations. Among other things, this knowledge of where +directory content is located could serve as the basis for dynamic +generation of LDAP referrals. + +An update transfer protocol, which actually brings a replica up to +date with respect to changes in directory content at another replica, +is defined using LDAPv3 protocol extensions. The representation of +directory content and changes will be defined by the LDAP Replication +Update Transfer Protocol sub-team. Incremental and full update +transfer mechanisms are described. Replication protocols are required +to include initial population, change updates, and removal of +directory content. + +Security information, including access control policy will be treated +as directory content by the replication protocols. Confidentiality +and integrity of replication information is required to be provided by +lower-level transport/session protocols such as IPSEC and/or TLS. + + + +3.2 Document Objectives + +The objectives of this document are: + +a) To define the architectural foundations for LDAP Replication, so + that further detailed design documents may be written. For + instance, the Information Model, Update Transfer Protocol, and + Update Resolution Procedures documents. + +b) To provide an architectural solution for each clause of the + requirements document [LDUP Requirements]. + +c) To preserve the LDAP Data Model and Operation Behavior +constraints + defined for LDAP in RFC 2251 [See Appendix A] + +d) To avoid tying the LDUP working group to the schedule of any other + working group. + +e) Not to infringe upon known registered intellectual property rights. + + +Merrells, Reed, Srinivasan [Page 5] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + + + +3.3 Document Non-Objectives + +This document does not address the following issues, as they are +considered beyond the scope of the Working Group. + +a) How LDAP becomes a distributed directory. There are many issues + beyond replication that should be considered. Such as, support for + external references, algorithms for computing referrals from the + distributed directory knowledge, etc. + +b) Specifying management protocols to create naming contexts or new + replicas. LDAP may be sufficient for this. The document describes + how new replicas and naming contexts are represented, in the + directory, as entries, attributes, and attribute values. + +c) How transactions will be replicated. However, the architecture + should not knowingly prevent or impede them, given the Working + Group's incomplete understanding of the issues at this time. + +d) The mapping or merging of disparate Schema definitions. + +e) Support of overlapping replicated regions. + +f) The case where separate attributes of an entry may be mastered by + different LDAP servers. This might be termed a 'Split Primary'. + Replica roles are defined in section 4.1. + +g) The specification of a replication system that supports Sparse + Replication. A Sparse Replica contains a subset of the naming + context entries, being modified by an Entry Selection Filter + criteria associated with the replica. An Entry Selection Filter is + an LDAP filter expression that describes the entries to be + replicated. The design and implementation of this functionality is + not yet well enough understood to specify here. + + + +3.4 Existing Implementations + +In order to define a standard replication scheme that may be readily +implemented we must consider the architectures of current LDAP server +implementations. Existing systems currently support proprietary +replication schemes based on one of two general approaches: log-based +or state-based. Some sections of this text may specifically address +the concerns of one approach. They will be clearly marked. + + + +3.4.1R + eplication Log Implementations + +Implementations based on the original University of Michigan LDAP +server code record LDAP operations to a operation log. During a +replication session operations are replayed from this log to bring the + +Merrells, Reed, Srinivasan [Page 6] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +Consumer replica up to date. Example implementations of this type at +this time are the Innosoft, Netscape, and Open LDAP Directory Servers. + + + +3.4.2S + tate-Based Implementations + +Directory Server implementations from Novell and Microsoft at this +time do not replay LDAP operations from a operation log. When a +replication session occurs each entry in the Replicated Area is +considered in turn, compared against the update state of the Consumer, +and any resultant changes transmitted. These changes are a set of +assertions about the presence or absence of entries, attributes, and +their values. + + + +3.5 Terms and Definitions + +The definitions from the Replication Requirements document have been +copied here and extended. + +For brevity, an LDAP server implementation is referred to throughout +as 'the server'. + +The LDAP update operations; Add, Delete, Modify, Modify RDN (LDAPv2) +and Modify DN (LDAPv3), are collectively referred to as LDAP Update +Operations. + +A Naming Context is a subtree of entries in the Directory Information +Tree (DIT). There may be multiple Naming Contexts stored on a single +server. Naming Contexts are defined in section 17 of [X501]. + +A Naming Context is based at an entry identified as its root and +includes all its subordinate entries down the tree until another +Naming Context is encountered. + +A Replica is an instance of a replicated Naming Context. + +A replicated Naming Context is said to be single-mastered if there is +only one Replica where it may be updated, and multi-mastered if there +is more than one Replica where it may be updated. + +A Replication Relationship is established between two or more Replicas +that are hosted on servers that cooperate to service a common area of +the DIT. + +A Replication Agreement is defined between two parties of a +Replication Relationship. The properties of the agreement codify the +Unit of Replication, the Update Transfer Protocol to be used, and the +Replication Schedule of a Replication Session. + +A Replication Session is an LDAP session between the two servers +identified by a replication agreement. Interactions occur between the +two servers, resulting in the transfer of updates from the supplier +replica to the consumer replica. + +Merrells, Reed, Srinivasan [Page 7] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +The Initiator of a Replication Session is the initiating server. + +A Responder server responds to the replication initiation request from +the Initiator server. + +A Supplier server is the source of the updates to be transferred. + +A Consumer server is the recipient of the update sequence. + +The Update Transfer Protocol is the means by which the Replication +Session proceeds. It defines the protocol for exchanging updates +between the Replication Relationship partners. + +A Replication Update is an LDAP Extended Operation that contains +updates to be applied to the DIT. The Update Transfer Protocol carries +a sequence of these messages from the Supplier to the Consumer. + +The Update Resolution Procedures repair constraint violations that +occur when updates to a multi-mastered Replica collide. + +A Fractional Entry Specification is a list of entry attributes to be +included, or a list of attributes to be excluded in a replica. An +empty specification implies that all entry attributes are included. + +A Fractional Entry is an entry that contains only a subset of its +original attributes. It results from the replication of changes +governed by a Fractional Entry +Specification. + +A Fractional Replica is a replica that holds Fractional Entries of its +naming context. + + + +3.6 Consistency Models + +This replication architecture supports a loose consistency model +between replicas of a naming context. It does not attempt to provide +the appearance of a single copy of a replica. The contents of each +replica may be different, but over time they will be converging +towards the same state. This architecture is not intended to support +LDAP Clients that require a tight consistency model, where the state +of all replicas is always equivalent. + +Three levels of consistency are available to LDAP Clients, which are +characterized by their deployment topologies. Single-Server, where +there is just the naming context and no replicas. Single-master, where +there are replicas, but only one may be updated. And, multi-master, +where there is more than one replica to which LDAP update operations +may be directed. The consistency properties of each model are rooted +in their serialization of read and write operations. + +1) A single-server deployment of a naming context provides tight +consistency to LDAP applications. LDAP Clients have no choice but to +direct all their operations to a single server, serializing both read + + +Merrells, Reed, Srinivasan [Page 8] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +and write operations. + +2) A single-mastered deployment of a naming context provides both +tight and loose consistency to LDAP applications. LDAP Clients must +direct all write operations to the single updateable replica, but may +direct their reads to any of the replicas. A client experiences tight +consistency by directing all its operations to the single updatable +replica, and loose consistency by directing any read operations to any +other replica. + +3) A multi-mastered deployment of a naming context can provide only +loose consistency to LDAP applications. Across the system writes and +reads are not serialized. An LDAP Client could direct their read and +write operations to a single updateable replica, but they will not +receive tight consistency as interleaved writes could be occurring at +another replica. + +Tight consistency can be achieved in a multi-master deployment for a +particular LDAP application if and only if all instances of its client +are directed towards the same updateable replica, and the application +data is not updated by any other LDAP application. Introducing these +constraints to an application and deployment of a naming-context +ensures that writes are serialized providing tight consistency for the +application. + +Future work could make use of the architecture proposed in this +document as a basis for allowing clients to request session guarantees +from a server when establishing a connection. + + + +3.7 LDAP Constraints + +The LDAP-v3 Internet RFC [LDAPv3] defines a set of Data Model and +Operation Behaviour constraints that a compliant LDAP server must +enforce. The server must reject an LDAP Update Operation if its +application to the target entry would violate any one of these LDAP +Constraints. [Appendix A B contains the original text clauses from RFC +2251, and also a summary.] + +In the case of a single-server or single-mastered naming context all +LDAP Constraints are immediately enforced at the single updateable +replica. An error result code is returned to an LDAP Client that +presents an operation that would violate the constraints. + +In the case of a multi-mastered naming context not all LDAP +Constraints can be immediately enforced at the updateable replica to +which the LDAP Update Operation is applied. This loosely consistent +replication architecture ensures that at each replica all constraints +are imposed, but as updates are replicated constraint violations may +arise +that can not be reported to the appropriate client. Any constraint +violations that occur are repaired by a set of update resolution +procedures. + +Any LDAP client that has been implemented to expect immediate + + +Merrells, Reed, Srinivasan [Page 9] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +enforcement of all LDAP Constraints may not behave as expected +against a multi-mastered naming context. + + + +4 Directory Model + + +This section describes extensions to the LDAP Directory Model that are +required by this replication architecture. + + + +4.1 Replica Type + +Each Replica is characterized with a replica type. This may be +Primary, Updatable, or Read-Only. A Read-Only Replica may be further +defined as being Fractional. + + + +4.1.1 + Primary Replica + +The Primary Replica is a full copy of the Replica, to which all +applications that require tight consistency should direct their LDAP +Operations. There can be only one Primary Replica within the set of +Replicas of a given Naming Context. It is also permissible for none +of the Replicas to be designated the Primary. The Primary Replica MUST +NOT be a Fractional Replica. + + +4.1.2 + Updatable Replica + +An Updatable Replica is a Replica that accepts all the LDAP Update +Operations, but is not the Primary Replica. There could be none, one, +or many Updatable Replicas within the set of Replicas of a given +Naming Context. An Updatable Replica MUST NOT be a Fractional Replica. + + + +4.1.3 + Read-Only Replica + +A Read-Only Replica will accept only non-modifying LDAP operations. +All modification operations shall be referred to an updateable +Replica. The server referred to would usually be a Supplier of this +Replica. + + + +4.1.4 + Fractional Replicas + +Fractional Replicas must always be Read-Only. All LDAP Update +Operations must be referred to an Updatable Replica. The server +referred to would usually be a Supplier of this Fractional Replica. + + +Merrells, Reed, Srinivasan [Page 10] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +4.2 Sub-Entries + +Replication management entries are to be stored at the base of the +replicated naming context. They will be of a 'ldapSubentry' +objectclass +to exclude them from regular searches. Entries with the objectclass +subentry are not returned as the result of a search unless the filter +component "(objectclass=ldapSubentry)" is included in the search +filter. + + + +4.3 Glue Entries + +A glue entry is an entry that contains knowledge of its name only. No +other information is held with it. Such glue entries will be +distinguished through a special object class defined for that purpose. +Glue entries may be created during a replication session to repair a +constraint violation. + + +4.4 Unique Identifiers + +Distinguished names can change, so are therefore unreliable as +identifiers. A Unique Identifier must therefore be assigned to each +entry as it is created. This identifier will be stored as an +operational attribute of the entry, named 'entryUUID'. The entryUUID +attribute is single valued. A consistent algorithm for generating such +unique identifiers should be defined for use in the LDUP standards +documents that detail the LDUP information model and LDUP protocols. + + +4.5 Change Sequence Number + +Change Sequence Numbers (CSNs) are used to impose a total ordering +upon the causal sequence of updates applied to all the replicas of a +naming context. Every LDAP Update Operation is assigned at least one +CSN. A Modify operation MUST be assigned one CSN per modification. + + + +4.5.1 + CSN Composition + +A CSN is formed of four components. In order of significance they +are; the time, a change count, a Replica Identifier, and a +modification number. The CSN is composed thus to ensure the uniqueness +of every generated CSN. When CSNs are compared to determine their +ordering they are compared component by component. First the time, +then the change count, then the replica identifier, and finally the +modification number. + +The time component is a year-2000-safe representation of the real +world time, with a granularity of one second. + +Because many LDAP Update Operations, at a single replica, may be + +Merrells, Reed, Srinivasan [Page 11] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +applied to the same data in a single second, the change count +component of the CSN is provided to further order the changes. Each +replica maintains a count of LDAP update operations applied against +it. It is reset to zero at the start of each second, and is +monotonically increasing within that second, incremented for each and +every update operation. Should LDAP Update Operations occur at +different replicas, to the same data, within the same single second, +and happen to be assigned the same change count number, then the +Replica Identifier is used to further order the changes. + +The Replica Identifier is the value of the RDN attribute on the +Replica Subentry. The Replica Identifier could be assigned +programmatically or administratively, in either case short values are +advised to minimise resource usage. The IA5CaseIgnoreString syntax is +used to compare and order Replica Identifier values. + +The fourth and final CSN component, the modification number, is used +for ordering the modifications within an LDAP Modify operation. + + + +4.5.2 + CSN Representation + +The preferred CSN representation is: + yyyy mm dd hh:mi:ssz # 0xSSSS # replica id # 0xssss + +The 'z' in the time stipulates that the time is expressed in GMT +without any daylight savings time offsets permitted, and the 0xssss +represents the hexadecimal representation of an unsigned +integer. +Implementations must support 16 bit change counts and should support +longer ones (32, 64, or 128 bits). + +An example CSN would be " 1998081018:44:31z#0x000F#1#0x0000 ". The +update assigned this CSN would have been applied at time +1998081018:44:31z happened to be the 16th operation which was applied +in that second, was made against the replica with identifier '1', and +was the first modification of the operation that caused the change. + + + +4.5.3 + CSN Generation + +Because Change Sequence Numbers are primarily based on timestamps, +clock differences between servers can cause unexpected change +ordering. The synchronization of server clocks is not required, though +it is preferable that clocks are accurate. If timestamps are not +accurate, and a server consistently produces timestamps which are +significantly older than those of other servers, its updates will not +have effect and the real world time ordering of updates will not be +maintained. + +However, an implementation may choose to require clock +synchronisation. The Network Time Protocol [NTP] [SNTP] offers a +protocol means by which heterogeneous server hosts may be time +synchronised. + +Merrells, Reed, Srinivasan [Page 12] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +The modifications which made up an LDAP Modify operation are presented +in a sequence. This must be preserved when the resultant changes of +this operation are replicated. + + + + +4.5.3.1 CSN Generation - Log Based Implementation + + +The modification number component may not be required, since the +ordering of the modifications within an LDAP Modify operation have +been preserved in the operation log. + + +4.5.3.2 CSN Generation - State Based Implementation + + +The modification number component may be needed to ensure that the +order of the modifications within an LDAP Modify operation are +faithfully replicated. + + +4.6 State Change Information + +State changes can be introduced via either LDAP Update Operations or +via Replication Updates. A CSN is included with all changes made to an +entry, its attributes, and attribute values. This state information +must be recorded for the entry to enable a total ordering of updates. +The CSN recorded is the CSN assigned to the state change at the server +where the state change was first made. CSNs are only assigned to state +changes that originate from LDAP Update Operations. + +Each of the LDAP Update Operations change their target entry in +different ways, and record the CSN of the change differently. The +state information for the resultant state changes are recorded at +three levels. The entry level, attribute level, and attribute value +level. The state change may be shown through. + +1) The creation of a deletion CSN for the entry, an attribute, or an + attribute value. + +2) In the addition of a new entry, attribute or attribute value, and + its existence CSN. + +3) An update to an existing attribute, attribute value, entry + distinguished name, or entry superior name, and its update CSN. + + + +4.1.1 + Entry Change State Storage and Representation + +When an entry is created, with the LDAP Add operation, the CSN of the +change is added to the entry as the value of an operational attribute + + +Merrells, Reed, Srinivasan [Page 13] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +named 'createdEntryCSN', of syntax type LDAPChangeSequenceNumber. + + createdEntryCSN ::= csn + +Deleted entries are marked as deleted by the addition of the object +class 'deletedEntry'. The attribute 'deletedEntryCSN', of syntax type +LDAP Change Sequence Number, is added to record where and when the +entry was deleted. Deleted entries are not visible to LDAP clients - +they may not be read, they don't appear in lists or search results, +and they may not be changed once deleted. Names of deleted entries +are available for reuse by new entries immediately after the deleted +entry is so marked. It may be desirable to allow deleted entries to be +accessed and manipulated by management and data recovery applications, +but that is outside the scope of this document. + + deletedEntryCSN ::= csn + +A CSN is recorded for both the RDN, and the Superior DN of the entry. + + +4.1.2A + ttribute Change State Storage + +When all values of an attribute have been deleted, the attribute is +marked as deleted and the CSN of the deletion is recorded. The deleted +state and CSN are stored by the server, but have no representation on +the entry, and may not be the subject of a search operation. This +state information must be stored to enable the Update Resolution +Procedures to be performed. + + + +4.1.3 + Attribute Value Change State Storage + +The Modification CSN for each value is to be set by the server when it +accepts a modification request to the value, or when a new value with +a later Modification CSN is received via Replication. The modified +value and the Modification CSN changes are required to be atomic, so +that the value and its Modification CSN cannot be out of synch on a +given server. The state information is stored by the server, but it +has no representation on the entry, and may not be the subject of a +search operation. + +When the value of an attribute is deleted the state of its deletion +must be recorded, with the CSN of the modifying change. It must be +stored to enable the Update Resolution Procedures to be performed. + + + +4.2 LDAP Update Operations + +The server must reject LDAP client update operations with a CSN that +is older than the state information that would be replaced if the +operation were performed. This could occur in a replication topology +where the difference between the clocks of updateable replicas was too +large. Result code 72, serverClocksOutOfSync, is returned to the +client. + +Merrells, Reed, Srinivasan [Page 14] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +5 Information Model + + +This section describes the object classes of the entries that +represent the replication topology. The operational information for +replication are administered through these entries. The LDUP Working +Group will work towards defining an Internet standard to fully detail +all these schema elements. + + +5.1 Entries, Semantics and Relationships + +This section defines the organization of operational data for directory +replication in terms of the relative placement of the entries that +represent Naming Contexts, its Replicas, and their associated +Replication agreements. This section also describes the purpose of +these objects and abstractly describes their content. +A Naming Context defines an area of DIT with independent replication +policies. There are many mechanisms available to identify the set of +Naming Contexts in a Directory, including through special auxiliary +classes or through operational attributes in root DSE pointing to +such entries. The LDUP information model standards will detail an +appropriate mechanism. + +Entries representing the set of Replicas associated with a Naming +Context are created immediately below (children) the Naming Context +entries. Replica entries are defined as subentries and are +intended to hold attributes that identify the Replica's LDAP Access +Point, its Replica Type, and if it is a Fractional Replica, the +attributes it does or does not hold. The attribute value of the entry's +Relative Distinguished Name (RDN) is termed the Replica Identifier and +is used as a component of each CSN associated with the replica. + +Immediately subordinate to each Replica Subentry are the entries +representing the Replication Agreements between this replica and +another replica on some other server in the network. A Replication +Agreement entry is associated with exactly one remote replica. +These entries are defined to hold attributes identifying +the remote Replica associated with this agreement, the scheduling +policy for replication operations, including times when replication is +to be performed, when it is not to be performed, or the policies +governing event-driven replication initiation another Replica, the +scheduling policy for replication operations, including times when +replication is to be performed, when it is not to be performed, or the +policies governing event-driven replication initiation. + + + +5.2 Root DSE Attributes + +LDUP information model will define Root DSE attributes to identify the +set of naming Contexts and replicas present in an LDAP server. + +5.3 Naming Context + +The LDUP Information Model will implement schema elements for + +Merrells, Reed, Srinivasan [Page 15] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +representing configuration and policy information common for all +replicas of the Naming Context. Attributes for recording the location +and time of creation of naming contexts may also be identified by the +information model. + +In future LDAP Access Control standards would define mechanisms for +identifying the ACL policy associated with a Naming Context as well as +the syntax and semantics of its representation. + + +5.4 Replica Object Class and Entries + +Each Replica is characterized by a replica type. This may be Primary, +Updatable, or Read-Only. The latter two types may be further defined +as being Fractional. The Replica entry will include a Fractional Entry +Specification for a Fractional Replica. + +There is a need to represent network addresses of servers holding +replicas participating in Replication Agreements. For this, +the LDUP information model will define an attribute with an +appropriate syntax to represent an LDAP server addresses with which to +contact replicas. + + +An Update Vector describes the point to which the Replica has been +updated, in respect to all the other Replicas of the Naming Context. +The vector is used at the initiation of a replication session to +determine the sequence of updates that should be transferred. + +Enabling LDAP to be a fully distributed service is not an objective +for the design of LDUP information model, though the information stored +in replica entries could facilitate certain distributed operations. + + +5.5 Lost and Found Entry + +When replicating operations between servers, conflicts may arise that +cause a parent entry to be removed causing its child entries to become +orphaned. In this case the Update Resolution Procedures will make the +Lost and Found Entry the child's new superior. + +Each Replica Entry names it's Lost and Found Entry, which would +usually be an entry below the Replica Entry itself. This well known +place allows administrators, and their tools, to find and repair +abandoned entries. + + + +5.6 Replication Agreement Object Class and Entries + +The Replication Agreement defines: + +1. The schedule for Replication Sessions initiation. + +2. The server that initiates the Replication Session, either the + Consumer or the Supplier. + +Merrells, Reed, Srinivasan [Page 16] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +3. The authentication credentials that will be presented between + servers. + +4. The network/transport security scheme that will be employed in + order to ensure data confidentiality. + +5. The replication protocols and relevant protocol parameters to be + used for Full and Incremental updates. An OID is used to identify + the update transfer protocol, thus allowing for future extensions + or bilaterally agreed upon alternatives. + +6. If the Replica is Fractional, the Fractional Entry Specification for +the attributes to be included or excluded + +Permission to participate in replication sessions will be controlled, +at least in part, by the presence and content of replica agreements. + +The Supplier must be subject to the access control policy enforced by +the Consumer. Since the access control policy information is stored +and replicated as directory content, the access control imposed on the +Supplier by the Consumer must be stored in the Consumer's Replication +Agreement. + + + +5.6.1 + Replication Schedule + +There are two broad mechanisms for initiating replication sessions: +(1) scheduled event driven and (2) change event driven. The mechanism +used to schedule replication operations between two servers is +determined by the Schedule information that is part of the Replication +Agreement governing the Replicas on those two servers. Because each +Replication Agreement describes the policy for one direction of the +relationship, it is possible that events propagate via scheduled +events in one direction, and by change events in the other. + +Change event driven replication sessions are, by their nature, +initiated by suppliers of change information. The server, which the +change is made against, schedules a replication session in response to +the change itself, so that notification of the change is passed on to +other Replicas. + +Scheduled event driven replication sessions can be initiated by either +consumers or suppliers of change information. The schedule defines a +calendar of time periods during which Replication Sessions should be +initiated. + +Schedule information may include both scheduled and change event +driven mechanisms. For instance, one such policy may be to begin +replication within 15 seconds of any change event, or every 30 minutes +if no change events are received. + + + + + +Merrells, Reed, Srinivasan [Page 17] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +6 Policy Information + + +Administrative policy information governs the behavior of the server +This policy information needs to be consistently known and +applied by all replicas of a Naming Context. It may be +represented in the DIT as sub-entries, attributes, and attribute +values. Auxiliary classes are a convenient way to hold such +policy information and to uniformly replicate them among all its +replicas. For a naming context to be faithfully reproduced, all +applicable prescriptive policy information represented among its +ancestral entries must also be replicated. In all cases such +policy information is transmitted as if it were an element of +the Replica root entry. + +Policy information is always replicated in the same manner as any +other entries, attributes, and attribute values. + + + +6.1 Schema Knowledge + +Schema subentries should be subordinate to the naming contexts to +which they apply. Given our model, a single server may hold replicas +of several naming contexts. It is therefore essential that schema +should not be considered to be a server-wide policy, but rather to be +scoped by the namespace to which it applies. + +Schema modifications replicate in the same manner as other directory +data. Given the strict ordering of replication events, schema +modifications will naturally be replicated prior to entry creations +which use them, and subsequent to data deletions which eliminate +references to schema elements to be deleted. Servers MUST NOT +replicate information about entries which are not defined in the +schema. Servers should not replicate modifications to existing schema +definitions for which there are existing entries and/or attributes +which rely on the schema element. + +Should a schema change cause an entry to be in violation of the new +schema, it is recommended that the server preserve the entry for +administrative repair. The server could add a known object class to +make the entry valid and to mark the entry for maintenance. + + + +7 LDUP Update Transfer Protocol Framework + + +A Replication Session occurs between a Supplier server and Consumer +server over an LDAP connection. This section describes the process by +which a Replication Session is initiated, started and stopped. + +The session initiator, termed the Initiator, could be either the +Supplier or Consumer. The Initiator sends an LDAP extended operation +to the Responder identifying the replication agreement being acted on. +The Supplier then sends a sequence of updates to the Consumer. + +Merrells, Reed, Srinivasan [Page 18] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +All transfers are in one direction only. A two way exchange requires +two replication sessions; one session in each direction. + + +7.1 Replication Session Initiation + +The Initiator starts the Replication Session by opening an LDAP +connection to its Responder. The Initiator binds using the +authentication credentials provided in the Replication Agreement. +The LDUP Update Transfer Protocol will define the LDAP extended +operation the Initiator should perform to initialize an LDUP session. +For the sake of convenience, this extended LDAP operation for +initializing a replication session is referred to as the "Start +Replication" operation. Among other things, this operation will +identify the role each +server will perform, and what type of replication is to be performed. + +One server is to be the Consumer, the other the Supplier, and the +replication may be either Full or Incremental. + + + +7.1.1 + Authentication + + +The initiation of a Replication Session is to be restricted to +privileged clients. The identity and the credentials for the client +eligible for initiating a replication session will be defined as +attributes within Replication Agreements. + +7.1.2 + Consumer Initiated + +The Consumer binds to the Supplier using the authentication +credentials provided in the Replication Agreement. The Consumer sends +the "Start Replication" extended request to begin the Replication +Session. The Supplier returns a "Start Replication" extended response +containing a response code. The Consumer then disconnects from the +Supplier. If the Supplier has agreed to the replication session +initiation, it binds to the Consumer and behaves just as if the +Supplier initiated the replication. + + + +7.1.3 + Supplier Initiated + +The Supplier binds to the Consumer using the authentication +credentials provided in the Replication Agreement. The Supplier sends +the "Start Replication" extended request to begin the +Replication Session. The Consumer returns a "Start Replication" +extended +response containing a response code, and possibly its Update Vector. +If the Consumer has agreed to the Replication Session initiation, then +the transfer protocol begins. + + + +Merrells, Reed, Srinivasan [Page 19] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + + +7.2 Start Replication Session + +7.2.1S + tart Replication Request + + +The LDUP Update Transfer Protocol would define an LDAP Extended +Request, referred to in this document as "Start Replication Request", +that is sent from the Initiator to Responder. The parameters of the +"Start Replication Request" would identify the Replication Agreement +associated with the session, the Update Transfer Protocol associated \ +with the replication session, and other state information necessary +to resume replication between the two servers. + + +7.2.2S + tart Replication Response + + +The LDUP Update Transfer Protocol would define an LDAP Extended +Response, "Start Replication Response", sent in reply to a Start +Replication Request, from the Responder to the Initiator. The +parameters of the Start Replication Response include an response code, +and an optional Update Vector. + + + +7.3 Update Transfer + +Each Update Transfer Protocol is identified by an OID. An LDUP +conformant server implementation must support those update protocols +that are +defined as mandatory in the Update Transfer Protocol standard , and +may support many others. A server will advertise its +protocols in the Root DSE multi-valued attribute +'supportedReplicationProtocols'. + +The Update Transfer Protocol would define the mechanisms for a +Consumer to receive a complete (full) update or incremental update +based on the current state of replication represented in the Update +Vector. A full update is necessary for initializing a consumer +replica upon establishment of replication agreements. + + + +7.4 End Replication Session + +A Replication Session is terminated by the "End Replication Request" +initiated by the supplier. The purpose of this request and response +is to secure the state of the Update Vector associated with the two +replicas that participated in replication. This is necessary for +proper resumption of replication during subsequent LDUP sessions + + + + +Merrells, Reed, Srinivasan [Page 20] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +7.5 Integrity & Confidentiality + +Data integrity (ie, protection from unintended changes) and +confidentiality (ie, protection from unintended disclosure to +eavesdroppers) SHOULD be provided by appropriate selection of +underlying transports, for instance TLS, or IPSEC. Replication MUST +be supported across TLS LDAP connections. Servers MAY be configured +to refuse replication connections over unprotected TCP connections. + + + + +8 LDUP Update Protocols + + +This Internet-Draft defines two transfer protocols for the supplier to +push changes to the consumer. Other protocols could be defined to +transfer changes, including those which pull changes from the supplier +to the consumer, but those are left for future work. + + + +8.1 Replication Updates and Update Primitives + +Both LDUP Update Protocols define how Replication Updates are +transferred from the Supplier to the Consumer. Each Replication Update +consists of a set of Update Primitives that describe the state changes +that have been made to a single entry. Each Replication Update is +associated with a single entry identified by its UUID. + + + The Update Transfer Protocol would define a set of Update Primitives +each of which codifies an assertion about the state change of an entry +that resulted from a directory update operation. The primitives will +include sufficient data to allow recreation of corresponding state +changes on the consumer's replica. An assertion based approach has +been chosen in such a way that the Primitives are idempotent, meaning +that re-application of a Primitive to an Entry will cause no change to +the entry. This is desirable as it provides some resilience against +some kinds of system failures. + +Each Update Primitive contains a CSN that represents an ordering among +all such primitives generated anywhere in the +network. This ordering information is used by the consumer to reconcile +among those primitives that lead to consistency violation +ier. + + +8.2 Fractional Updates + +When fully populating or incrementally bringing up to date a +Fractional Replica each of the Replication Updates must only contain +updates to the attributes in the Fractional Entry Specification. + + + +Merrells, Reed, Srinivasan [Page 21] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +9 LDUP Full Update Transfer Protocol + + + + +9.1 Full Update Transfer + +This Full Update Protocol provides a bulk transfer of the replica +contents for the initial population of new replicas, and the +refreshing of existing replicas. The LDUP Update Transfer protocol +standard will define the ways for this transfer is initiated. + +The Consumer must replace its entire replica contents with that sent +from the Supplier. + +The Consumer need not service any requests for this Naming Context +whilst the full update is in progress. The Consumer could instead +return a +referral to another replica, possibly the supplier. + + + +9.2 Replication Update Generation + +The entire state of a Replicated Area can be mapped onto a sequence of +Replication Updates, each of which contains a sequence of Update +Primitives that describe the entire state of a single entry. + +The sequence of Replication Updates must be ordered such that no entry +is created before its parent. + + + +9.3 Replication Update Consumption + +A Consumer will receive the Replication Updates, extract the sequence +of Update Primitives, and must apply them to the DIB in the order +provided. + + + +9.4 Full Update, End Replication Session + + +A Full Update should also result in the replication of all appropriate +LDUP meta data (which are part of the replicated naming context), such +as the sub-entry representing the Replica being updated and the Update +Vector associated with it. +The Supplier could be accepting updates whilst the update is in +progress. Once the Full Update has completed, an Incremental Update +should be performed to transfer these changes. + + + + + +Merrells, Reed, Srinivasan [Page 22] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +9.5 Interrupted Transmission + +If the Replication Session terminates before the End Replication +Request is sent, then the Replica could be in an inconsistent state. + Until the replica is restored to a consistent +state, the consumer might not permit LDAP Clients to access the +incomplete replica. The Consumer could refer the Client to the +Supplier Replica, or return an error result code. + + + +10 LDUP Incremental Update Transfer Protocol + + +For efficiency, the Incremental Update Protocol transmits only those +changes that have been made to the Supplier replica that the Consumer +has not already received. In a replication topology with transitive +redundant replication agreements, changes may propagate through the +replica network via different routes. + +The Consumer must not support multiple concurrent replication sessions +with more than one Supplier for the same Naming Context. A Supplier +that attempts to initiate a Replication Session with a Consumer +already participating as a Consumer in another Replication Session +will receive appropriate error. . + + + +10.1 Update Vector + +The Supplier uses the Consumer's Update Vector to determine the +sequence of updates that should be sent to the Consumer. + +Each Replica entry includes an Update Vector to record the point to +which the replica has been updated. The vector is a set of CSN values, +one value for each known updateable Replica. Each CSN value in the +vector corresponds to the most recent change that occurred in an +updateable replica that has been replicated to the replica whose +replication state this Update Vector represents. + +For example, consider two updatable replicas of a naming context, one +is assigned replica identifier '1', the other replica identifier '2'. +Each is responsible for maintaining its own update vector, which will +contain two CSNs, one for each replica. So, if both replicas are +identical they will have equivalent update vectors. + +Both Update Vectors = + +{1998081018:44:31z#0x000F#1#0x0000, 1998081018:51:20z#0x0001#2#0x0000} + +Subsequently, at 7pm, an update is applied to replica '2', so its +update vector is updated. + +Replica '1' Update Vector = + +{1998081018:44:31z#0x000F#1#0x0000, 1998081018:51:20z#0x0001#2#0x0000} + +Merrells, Reed, Srinivasan [Page 23] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +Replica '2' Update Vector = + +{1998081018:44:31z#0x000F#1#0x0000, 1998081019:00:00z#0x0000#2#0x0000} + +Since the Update Vector records the state to which the replica has +been updated, a supplier server, during Replication Session +initiation, can determine the sequence of updates that should be sent +to the consumer. From the example above no updates need to be sent +from replica '1' to replica '2', but there is an update pending from +replica '2' to replica '1'. + +Because the Update Vector embodies knowledge of updates made at all +known replicas it supports replication topologies that include +transitive and redundant connections between replicas. It ensures that +changes are not transferred to a consumer multiple times even though +redundant replication agreements may exist. It also ensures that +updates are passed across the replication network between replicas +that are not directly linked to each other. + +It may be the case that a CSN for a given replica is absent, for one +of two reasons. + +1. CSNs for Read-Only replicas might be absent because no changes will + have ever been applied to that Replica, so there are no changes to + replicate. + +2. CSNs for newly created replicas may be absent because no changes to + that replica have yet been propagated. + +An Update Vector might also contain a CSN for a replica that no longer +exists. The replica may have been temporarily taken out of service, +or may have been removed from the replication topology permanently. An +implementation may choose to retire a CSN after some configurable time +period. + + + +10.2 Supplier Initiated, Incremental Update, Start Replication Session + +The Consumer Responder must return its Update Vector to the Supplier +Initiator. The Supplier uses this to determine the sequence of +Replication Updates that need to be sent to the Consumer. + + + +10.3 Replication Update Generation + +The Supplier generates a sequence of Replication Updates to be sent to +the consumer. To enforce LDAP Constraint 20.1.6, that the LDAP Modify +must be applied atomically, each Replication Update must contain the +entire sequence of Update Primitives for all the LDAP Operations for +which the Replication Update contains Update Primitives. Stated less +formally, for each primitive the update contains, it must also contain +all the other primitives that came from the same operation. + + +Merrells, Reed, Srinivasan [Page 24] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + + +10.3.1 Replication Log Implementation + +A log-based implementation might take the approach of mapping LDAP +Operations onto an equivalent sequence of Update Primitives. A +systematic procedure for achieving this will be fully described in the +standard document defining Update Reconciliation Procedures. + +The Consumer Update Vector is used to determine the sequence of LDAP +Operations in the operation log that the Consumer has not yet seen. + + + +10.3.2 State-Based Implementation + +A state-based implementation might consider each entry of the replica +in turn using the Update Vector of the consumer to find all the state +changes that need to be transferred. Each state change (entry, +attribute, or value - creation, deletion, or update) is mapped onto +the equivalent Update Primitive. All the Update Primitives for a +single entry might be collected into a single Replication Update. +Consequently, it could contain the resultant primitives of many LDAP +operations. + + + +10.4 Replication Update Consumption + +A Consumer will receive Replication Updates, extract the sequence of +Update Primitives, and must apply them to the DIB in the order +provided. LDAP Constraint 20.1.6 states that the modifications within +an LDAP Modify operation must be applied in the sequence provided. + +Those Update Primitives must be reconciled with the current replica +contents and any previously received updates. In short,, +updates are compared to the state information associated with the item +being operated on. If the change has a more recent CSN, then it is +applied to the directory contents. If the change has an older CSN it +is no longer relevant and its change must not be effected. + +If the consumer acts as a supplier to other replicas then the updates +are retained for forwarding. + + + +10.5 Update Resolution Procedures + +The LDAP Update Operations must abide by the constraints imposed by +the LDAP Data Model and LDAP Operational Behaviour, Appendix A. An +operation that would violate at least one of these constraints is +rejected with an error result code. + +The loose consistency model of this replication architecture and its +support for multiple updateable replicas of a naming context means + + +Merrells, Reed, Srinivasan [Page 25] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +that LDAP Update Operations could be valid at one replica, but not in +another. At the time of acceptance, the accepting +replica may not have received other updates that would cause a +constraint to be violated, and the operation to be rejected. + +Replication Updates must never be rejected because of a violation of +an LDAP Constraint. If the result of applying the Replication Update +causes a constraint violation to occur, then some remedial action must +be taken to satisfy the constraint. These Update Resolution Procedures +are introduced here will be fully defined withinLDUP Update Resolution +Procedures. + + + +10.5.1 URP: Distinguished Names + +LDAP Constraints 20.1.1 and 20.1.10 ensure that each entry in the +replicated area has a unique DN. A Replication Update could violate +this constraint producing two entries, with different unique +identifiers, but with the same DN. The resolution procedure is to +rename the most recently named entry so that its RDN includes its own +unique identifier. This ensures that the new DN of the entry shall be +unique. + + + +10.5.2 URP: Orphaned Entries + +LDAP Constraints 20.1.11 ensures that every entry must have a parent +entry. A Replication Update could violate this constraint producing an +entry with no parent entry. The resolution procedure is to create a +Glue Entry to take the place of the absent parent. The Glue Entry's +superior will be the Lost and Found Entry. This well known place +allows administrators and their tools to find and repair abandoned +entries. + + + +10.5.3 URP: Distinguished Not Present + +LDAP Constraints 20.1.8 and 20.1.9 ensure that the components of an +RDN appear as attribute values of the entry. A Replication Update +could violate this constraint producing an entry without its +distinguished values. The resolution procedure is to add the missing +attribute values, and mark them as distinguished not present, so that +they can be deleted when the attribute values are no longer +distinguished. + + + +10.5.4 URP: Schema - Single Valued Attributes + +LDAP Constraint 20.1.7 enforces the single-valued attribute schema +restriction. A Replication Update could violate this constraint +creating a multi-value single-valued attribute. The resolution + + +Merrells, Reed, Srinivasan [Page 26] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +procedure is to consider the value of a single-valued attribute as +always being equal. In this way the most recently added value will be +retained, and the older one discarded. + + + +10.5.5 URP: Schema - Required Attributes + +LDAP Constraint 20.1.7 enforces the schema objectclass definitions on +an entry. A Replication Update could violate this constraint creating +an entry that does not have attribute values for required attributes. +The resolution procedure is to ignore the schema violation and mark +the entry for administrative repair. + + + +10.5.6 URP: Schema - Extra Attributes + +LDAP Constraint 20.1.3 and 20.1.7 enforces the schema objectclass +definitions on an entry. A Replication Update could violate this +constraint creating an entry that has attribute values not allowed by +the objectclass values of the entry. The resolution procedure is to +ignore the schema violation and mark the entry for administrative +repair. + + + +10.5.7 URP: Duplicate Attribute Values + +LDAP Constraint 20.1.5 ensures that the values of an attribute +constitute a set of unique values. A Replication Update could violate +this constraint. The resolution procedure is to enforce this +constraint, recording the most recently assigned CSN with the value. + + + +10.5.8 URP: Ancestry Graph Cycle + +LDAP Constraint 20.4.2.1 prevents against a cycle in the DIT. A +Replication Update could violate this constraint causing an entry to +become it's own parent, or for it to appear even higher in it's +ancestry graph. The resolution procedure is to break the cycle by +changing the parent of the entry closest to be the lost and found +entry. + + + +10.6 Incremental Update, End Replication Session + +If the Supplier sent none of its own updates to the Consumer, then the +Supplier's CSN within the Supplier's update vector should be updated +with the earliest possible CSN that it could generate, to record the +time of the last successful replication session. The Consumer will +have received the Supplier's Update Vector in the replica sub-entry it +holds for the Supplier replica. + +Merrells, Reed, Srinivasan [Page 27] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +The Consumer's resultant Update Vector CSN values will be at least as +great as the Supplier's Update Vector. + +The Supplier may request that the Consumer return its resultant Update +Vector so that the Supplier can update its replica sub-entry for the +Consumer Replica. The Supplier requests this by setting a flag in the +End Replication Request. The default flag value is TRUE meaning the +Consumer Update Vector must be returned. + + + +10.7 Interrupted Transmission + +If the Replication Session terminates before the End Replication +Request is sent then the Consumer's Update Vector may or may not be +updated to reflect the updates received. The Start Replication request +includes a Replication Update Ordering flag which states whether the +updates were sent in CSN order per replica. + +If updates are sent in CSN order per replica then it is possible to +update the Consumer Update Vector to reflect that some portion of the +updates to have been sent have been received and successfully applied. +The next Incremental Replication Session will pick up where the failed +session left off. + +If updates are not sent in CSN order per replica then the Consumer +Update can not be updated. The next Incremental Replication Session +will begin where the failed session began. Some updates will be +replayed, but because the application of Replication Updates is +idempotent they will not cause any state changes. + + + +11 Purging State Information + + +The state information stored with each entry need not be stored +indefinitely. A server implementation may choose to periodically, or +continuously, remove state information that is no longer required. The +mechanism is implementation-dependent, but to ensure interoperability +between implementations, the state information must not be purged +until all known replicas have received and acknowledged the change +associated with a CSN. This is determined from the Purge Vector +[11.1]. + +All the CSNs stored that are lower than the Purge Vector may be +purged, because no changes with older CSNs can be replicated to this +replica. + + + +11.1 Purge Vector + +The Purge Vector is an Update Vector constructed from the Update +Vectors of all known replicas. Each replica has a sub-entry for each + +Merrells, Reed, Srinivasan [Page 28] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +known replica stored below its naming context. Each of those entries +contains the last known update vector for that replica. The lowest CSN +for each replica are taken from these update vectors to form the Purge +Vector. The Purge Vector is used to determine when state information +and updates need no longer be stored. + + + +11.2 Purging Deleted Entries, Attributes, and Attribute Values + +The following conditions must hold before an item can be deleted from +the Directory Information Base. + +1) The LDAP delete operation has been propagated to all replication +agreement partners. + +2) All the updates from all the other replicas with CSNs less than the +CSN on the deletion have been propagated to the server holding the +deleted entry (similarly for deleted attributes and attribute values). + +3) The CSN generator of the other Replicas must have advanced beyond +the deletion CSN of the deleted entry. Otherwise, it is possible for +one of those Replicas to generate operations with CSNs earlier than +the deleted entry. + + +12 Replication Configuration and Management + + +Replication management entries, such as replica or replication +agreement entries, can be altered on any updateable replica. These +entries are implicitly included in the directory entries governed by +any agreement associated with this naming context. As a result, all +servers with a replica of a naming context will have access to +information about all other replicas and associated agreements. + +The deployment and maintenance of a replicated directory network +involves the creation and management of all the replicas of a naming +context and replication agreements among these replicas. This section +outlines, through an example, the administrative actions necessary to +create a new replica and establish replication agreements. Typically, +administrative tools will guide the administrator and facilitate these +actions. The objective of this example is to illustrate the +architectural relationship among various replication related +operational information. + +A copy of an agreement should exist on both the supplier and consumer +side for the replication update transfer protocol to be able to start. +For this purpose, the root of the naming context, replica objects and +the replication agreement objects are created first on one of the +servers. A copy of these objects are then manually created on the +second server associated with the agreement. + +The scenario below starts with a server (named DSA1) that holds an +updateable replica of a naming context NC1. Procedures to establish +an updateable replica of the naming context on a second server (DSA2) + +Merrells, Reed, Srinivasan [Page 29] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +are outlined. + +On DSA1: + +1) Add the context prefix for NC1 to the Root DSE attribute + 'replicaRoot' if it does not already exist. + +2) Alter the 'ObjectClass' attribute of the root entry of NC1 to + include the "namingContext" auxiliary class. + +3) Create a replica object, NC1R1, (as a child of the root of NC1) to + represent the replica on DSA1. The attributes include replica type + (updateable, read-only etc.) and DSA1 access point information. + +4) Create a copy of the replica object NC1R2 (after it is created on + DSA2) + +5) Create a replication agreement, NC1R1-R2 to represent update + transfer from NC1R1 to NC1R2. This object is a child of NC1R1. + +On DSA2: + +1) Add NC1's context prefix to the Root DSE attribute 'replicaRoot'. + +2) Create a copy of the root entry of NC1 as a copy of the one in DSA1 + (including the namingContext auxiliary class) + +3) Create a copy of the replica object NC1R1 + +4) Create a second replica object, NC1R2 (as a sibling of NC1R1) to + represent the replica on DSA2. + +5) Create a copy of the replication agreement, NC1R1-R2 + +6) Create a replication agreement, NC1R2-R1, to represent update + transfer from NC1R2 to NC1R1. This object is a sibling of NC1R1- + R2. + +After these actions update transfer to satisfy either of the two +agreements can commence. + +If data already existed in one of the replicas, the update transfer +protocol should perform a complete update of the data associated with +the agreement before normal replication begins. + + + +13 Time + + +The server assigns a CSN for every LDAP update operation it receives. +Since the CSN is principally based on time, the CSN is susceptible to +the Replica clocks drifting in relation to each other (either forwards +or backwards). + +The server must never assign a CSN older than or equal to the last CSN +it assigned. + +Merrells, Reed, Srinivasan [Page 30] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + +The server must reject update operations, from any source, which would +result in setting a CSN on an entry or a value which is earlier than +the one that is there. The error code serverClocksOutOfSync (72) +should be returned. + + +14 Security Considerations + + +The preceding architecture discussion covers the server +authentication, session confidentiality, and session integrity in +sections 7.1.1 and 7.5 + +The internet draft "Authentication Methods" for LDAP, provides a +detailed LDAP security discussion. Its introductory passage is +paraphrased below. [AUTH] + +A Replication Session can be protected with the following security +mechanisms. + +1) Authentication by means of the SASL mechanism set, possibly backed + by the TLS credentials exchange mechanism, + +2) Authorization by means of access control based on the Initiators + authenticated identity, + +3) Data integrity protection by means of the TLS protocol or data- + integrity SASL mechanisms, + +4) Protection against snooping by means of the TLS protocol or data- + encrypting SASL mechanisms, + +The configuration entries that represent Replication Agreements may +contain authentication information. This information must never be +replicated between replicas. + +Updates to a multi-mastered entry may collide causing the Update +Resolution Procedures [10.5] to reject or reverse one of the changes +to the entry. The URP algorithms resolve conflicts by using the total +ordering of updates imposed by the assignment of CSNs for every +operation. As a consequence updates originating from system +administrators have no priority over updates originating from regular +system users. + + + +15 Acknowledgements + + +This document is a product of the LDUP Working Group of the IETF. The +contributions of its members is greatly appreciated. + + + + + +Merrells, Reed, Srinivasan [Page 31] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +16 References + + +[AUTH] - M. Wahl, H. Alvestrand, J. Hodges, RL "Bob" Morgan, +"Authentication Methods for LDAP", Internet Draft, draft-ietf-ldapext- +authmeth-02.txt, June 1998. + +[BCP-11] - R. Hovey, S. Bradner, "The Organizations Involved in the +IETF Standards Process", BCP 11, RFC 2028, October 1996. + +[LDAPv3] - M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access +Protocol (v3)", RFC 2251, December1997. + +[LDUP Requirements] - R. Weiser, E. Stokes 'LDAP Replication +Requirements', Internet Draft, draft-weiser-replica-req-02.txt, +October, 1999 + +[NTP] - D. L. Mills, "Network Time Protocol (Version 3)", RFC 1305, +March, 1992. + +[RFC2119] - S. Bradner, "Key words for use in RFCs to Indicate +Requirement Levels", RFC 2119. + +[RFC2252] - M. Wahl, A. Coulbeck, T. Howes, S. Kille, 'Lightweight +Directory Access Protocol (v3): Attribute Syntax Definitions', RFC +2252, December 1997. + +[SNTP] - D. L. Mills, "Simple Network Time Protocol (SNTP) Version 4 +for IPv4, IPv6 and OSI", RFC 2030, University of Delaware, October +1996. + +[TLS] - J. Hodges, R. L. "Bob" Morgan, M. Wahl, "Lightweight +Directory Access Protocol (v3): Extension for Transport +Layer Security", Internet draft, draft-ietf-ldapext-ldapv3-tls-01.txt, +June 1998. + +[X501] - ITU-T Recommendation X.501 (1993), ) | ISO/IEC 9594-2:1993, +Information Technology - Open Systems Interconnection - The Directory: +Models + +[X680] - ITU-T Recommendation X.680 (1994) | ISO/IEC 8824-1:1995, +Information technology - Abstract Syntax Notation One (ASN.1): +Specification of Basic Notation + +[X525] - ITU-T Recommendation X.525 (1997) | ISO/IEC 9594-9:1997, +Information Technology - Open Systems Interconnection - The Directory: +Replication + + +17 Intellectual Property Notice + + +The IETF takes no position regarding the validity or scope of any +intellectual property or other rights that might be claimed to +pertain to the implementation or use of the technology described in +this document or the extent to which any license under such rights + + +Merrells, Reed, Srinivasan [Page 32] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +might or might not be available; neither does it represent that it has +made any effort to identify any such rights. Information on the +IETF's procedures with respect to rights in standards-track and +standards-related documentation can be found in BCP-11. [BCP-11] +Copies of claims of rights made available for publication and any +assurances of licenses to be made available, or the result of an +attempt made to obtain a general license or permission for the use of +such proprietary rights by implementors or users of this specification +can be obtained from the IETF Secretariat. + +The IETF invites any interested party to bring to its attention any +copyrights, patents or patent applications, or other proprietary +rights which may cover technology that may be required to practice +this standard. Please address the information to the IETF Executive +Director. + + +18 Copyright Notice + + + Copyright (C) The Internet Society (1998,1999). All Rights Reserved. + +This document and translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it +or assist in its implementation may be prepared, copied, published and +distributed, in whole or in part, without restriction of any kind, +provided that the above copyright notice and this paragraph are +included on all such copies and derivative works. However, this +document itself may not be modified in any way, such as by removing +the copyright notice or references to the Internet Society or other +Internet organizations, except as needed for the purpose of +developing Internet standards in which case the procedures for +copyrights defined in the Internet Standards process must be followed, +or as required to translate it into languages other than English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an +"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING +TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN +WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +19 Authors' Address + + + John Merrells + Netscape Communications, Inc. + 501 East Middlefield Road + Mountain View + CA 94043 + USA + E-mail: merrells@netscape.com + + +Merrells, Reed, Srinivasan [Page 33] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + Phone: +1 650-937-5739 + + Edwards E. Reed + Reed-Matthews, Inc. + 1064 East 140 North + Lindon + UT 84042 + USA + E-mail: eer@oncalldba.com + Phone: +1 801-796-7065 + + Uppili Srinivasan + Oracle, Inc. + Redwood Shores + CA + USA + E-mail: usriniva@us.oracle.com + Phone: +1 650 506 3039 + + LDUP Engineering Mailing List: ldup-repl@external.cisco.com + LDUP Working Group Mailing List: ietf-ldup@imc.org + + +20 Appendix A - LDAP Constraints + + +20.1 LDAP Constraints Clauses + +This is an enumeration of the Data Model and Operation Behaviour +constraint clauses defined in RFC 2251. [LDAPv3] + +1) Data Model - Entries have names: one or more attribute values from + the entry form its relative distinguished name (RDN), which MUST be + unique among all its siblings. (p5) + +2) Data Model - Attributes of Entries - Each entry MUST have an + objectClass attribute. (p6) + +3) Data Model - Attributes of Entries - Servers MUST NOT permit + clients to add attributes to an entry unless those attributes are + permitted by the object class definitions. (p6) + +4) Relationship to X.500 - This document defines LDAP in terms of + X.500 as an X.500 access mechanism. An LDAP server MUST act in + accordance with the X.500 (1993) series of ITU recommendations when + providing the service. However, it is not required that an LDAP + server make use of any X.500 protocols in providing this service, + e.g. LDAP can be mapped onto any other directory system so long as + the X.500 data and service model as used in LDAP is not violated in + the LDAP interface. (p8) + +5) Elements of Protocol - Common Elements - Attribute - Each attribute + value is distinct in the set (no duplicates). (p14) + +6) Elements of Protocol - Modify Operation - The entire list of entry + modifications MUST be performed in the order they are listed, as a + +Merrells, Reed, Srinivasan [Page 34] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + single atomic operation. (p33) + +7) Elements of Protocol - Modify Operation - While individual + modifications may violate the directory schema, the resulting entry + after the entire list of modifications is performed MUST conform to + the requirements of the directory schema. (p33) + +8) Elements of Protocol - Modify Operation - The Modify Operation + cannot be used to remove from an entry any of its distinguished + values, those values which form the entry's relative distinguished + name. (p34) + +9) Elements of Protocol - Add Operation - Clients MUST include + distinguished values (those forming the entry's own RDN) in this + list, the objectClass attribute, and values of any mandatory + attributes of the listed object classes. (p35) + +10) Elements of Protocol - Add Operation - The entry named in the + entry field of the AddRequest MUST NOT exist for the AddRequest to + succeed. (p35) + +11) Elements of Protocol - Add Operation - The parent of the entry to + be added MUST exist. (p35) + +12) Elements of Protocol - Delete Operation - ... only leaf entries + (those with no subordinate entries) can be deleted with this + operation. (p35) + +13) Elements of Protocol - Modify DN Operation - If there was already + an entry with that name [the new DN], the operation would fail. + (p36) + +14) Elements of Protocol - Modify DN Operation - The server may not + perform the operation and return an error code if the setting of + the deleteoldrdn parameter would cause a schema inconsistency in + the entry. (p36) + + + +20.2 LDAP Data Model Constraints + +The LDAP Data Model Constraint clauses as written in RFC 2251 [LDAPv3] +may be summarised as follows. + +a) The parent of an entry must exist. (LDAP Constraint 11 & 12.) + +b) The RDN of an entry is unique among all its siblings. (LDAP + Constraint 1.) + +c) The components of the RDN must appear as attribute values of the + entry. (LDAP Constraint 8 & 9.) + +d) An entry must have an objectclass attribute. (LDAP Constraint 2 & + 9.) + +e) An entry must conform to the schema constraints. (LDAP Constraint + + +Merrells, Reed, Srinivasan [Page 35] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + + 3 & 7.) + +f) Duplicate attribute values are not permitted. (LDAP Constraint 5.) + + + +20.3 LDAP Operation Behaviour Constraints + +The LDAP Operation Behaviour Constraint clauses as written in RFC 2251 +[LDAPv3] may be summarised as follows. + +A) The Add Operation will fail if an entry with the target DN already +exists. (LDAP Constraint 10.) + +B) The Add Operation will fail if the entry violates data constraints: + + a - The parent of the entry does not exist. (LDAP Constraint 11.) + + b - The entry already exists. (LDAP Constraint 10.) + + c - The entry RDN components appear as attribute values on the + entry. (LDAP Constraint 9.) + + d - The entry has an objectclass attribute. (LDAP Constraint 9.) + + e - The entry conforms to the schema constraints. (LDAP + Constraint 9.) + + f - The entry has no duplicated attribute values. (LDAP +Constraint 5.) + +C) The modifications of a Modify Operation are applied in the order +presented. (LDAP Constraint 6.) + +D) The modifications of a Modify Operation are applied atomically. +(LDAP Constraint 6.) + +E) A Modify Operation will fail if it results in an entry that +violates data constraints: + + c - If it attempts to remove distinguished attribute values. + (LDAP Constraint 8.) + + d - If it removes the objectclass attribute. (LDAP Constraint 2.) + + e - If it violates the schema constraints. (LDAP Constraint 7.) + + f - If it creates duplicate attribute values. (LDAP Constraint + 5.) + +F) The Delete Operation will fail if it would result in a DIT that +violates data constraints: + + a - The deleted entry must not have any children. (LDAP +Constraint 12.) + + + +Merrells, Reed, Srinivasan [Page 36] + Expires 10 September 2000 + + + + + +INTERNET-DRAFT LDAP Replication Architecture March 10, 2000 + + +G) The ModDN Operation will fail if it would result in a DIT or entry +that violates data constraints: + + b - The new Superior entry must exist. (Derived LDAP Data Model + Constraint A) + + c - An entry with the new DN must not already exist. (LDAP + Constraint 13.) + + c - The new RDN components do not appear as attribute values on + the entry. (LDAP Constraint 1.) + + d - If it removes the objectclass attribute. (LDAP Constraint 2.) + + e - It is permitted for the operation to result in an entry that + violates the schema constraints. (LDAP Constraint 14.) + + + +20.4 New LDAP Constraints + +The introduction of support for multi-mastered entries, by the +replication scheme presented in this document, necessitates the +imposition of new constraints upon the Data Model and LDAP Operation +Behaviour. + + + +20.4.1 New LDAP Data Model Constraints + +1) Each entry shall have a unique identifier generated by the UUID +algorithm available through the 'entryUUID' operational attribute. The +entryUUID attribute is single valued. + + + +20.4.2 New LDAP Operation Behaviour Constraints + +1) The LDAP Data Model Constraints do not prevent cycles in the + ancestry graph. Existing constraints Data Model Constraint - 20.4.1 + - (a) and Operation Constraint - 20.4.2 - (B) would prevent this in + the single master case, but not in the presence of multiple + masters. + +2) The LDAP Data Model Constraints state that only the LDAP Modify + Operation is atomic. All other LDAP Update Operations are also + considered to be atomically applied to the DIB. + + + + + + + + + +Merrells, Reed, Srinivasan [Page 37] + Expires 10 September 2000 + + diff --git a/doc/drafts/draft-ietf-ldup-protocol-xx.txt b/doc/drafts/draft-ietf-ldup-protocol-xx.txt new file mode 100644 index 0000000000..9108794f06 --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-protocol-xx.txt @@ -0,0 +1,895 @@ + +LDUP Replication Update Protocol +Internet-Draft +Intended Category: Standards Track +Expires: September 10, 2000 + + + Ellen Stokes + IBM Corporation + + Gordon Good + Netscape Communications Corp. + + March 10 2000 + + The LDUP Replication Update Protocol + Filename: draft-ietf-ldup-protocol-01.txt + +Table of Contents + +1. Status of this Memo.............................................2 +2. Abstract........................................................2 +3. Overview of Protocol............................................2 +4. High-level Description of Protocol Flow.........................3 +4.1 Supplier-initiated incremental replication protocol.............3 +4.2. Consumer-initiated replication protocol......................4 +5. Replication protocol element definitions........................5 +5.1 StartFramedProtocolRequest Extended Operation...................5 +5.2 StartFramedProtocolResponse Extended Operation..................6 +5.3 ReplicationUpdate Extended Operation............................7 +5.3.1 UniqueIdentifier.............................................8 +5.3.2 ReplicationPrimitive.........................................8 +5.3.2.1 AddEntryPrimitive.........................................8 +5.3.2.2 MoveEntryPrimitive........................................9 +5.3.2.3 RenameEntryPrimitive......................................9 +5.3.2.4 RemoveEntryPrimitive......................................9 +5.3.2.5 AddAttributeValuePrimitive................................10 +5.3.2.6 RemoveAttributeValuePrimitive.............................10 +5.3.2.7 RemoveAttributePrimitive..................................10 +5.4 EndFramedProtocolRequest Extended Operation.....................11 +5.5 EndFramedProtocolResponse Extended Operation....................11 +5.6 ReplicationUpdateResponse Extended Operation....................12 +6. Semantics of Full and Incremental Update protocols..............13 +7. Summary of response codes.......................................13 +8. Implications for log-based and state-based servers..............13 +9. Replication of access control and schema information............13 +10. Security Considerations.........................................14 +11. Glossary of Terms...............................................14 +12. Acknowledgments.................................................14 +13. References......................................................14 +14. Author's Addresses..............................................15 + + + +Stokes and Good [Page 1] + +Internet-Draft LDUP Workgroup March 10 2000 + + +1. Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that other + groups may also distribute working documents as Internet-Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet- Drafts as reference + material or to cite them other than as "work in progress." + + To view the list Internet-Draft Shadow Directories, see + http://www.ietf.org/shadow.html. + + This Internet Draft expires September 10, 2000. + + +2. Abstract + + The protocol described in this document is designed to allow one LDAP + server to replicate its directory content to another LDAP server. The + protocol is designed to be used in a replication configuration where + multiple updatable servers are present. Provisions are made in the + protocol to carry information that allows the server receiving + updates to apply a total ordering to all updates in the replicated + system. This total ordering allows all replicas to correctly resolve + conflicts that arise when LDAP clients submit changes to different + servers that later replicate to one another. + + All protocol elements described here are LDAP Version 3 extended + operations. LDAP Version 3 is described in RFC 2251 [LDAPv3]. + + Certain terms used in this document are defined in the document "LDAP + Replication Architecture" (draft-ietf-ldup-model-00.txt). + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are + to be interpreted as described in RFC 2119 [KEYWORDS]. + +3. Overview of Protocol + + The LDAP Replication Architecture [ARCHITECTURE] describes the + overall approach used in ensuring consistency of multiple updatable + replicas of directory content. The protocol described in this + document implements the approach desribed in that document. + + + +Stokes and Good [Page 2] + +Internet-Draft LDUP Workgroup March 10 2000 + + + LDAP Version 3 extended operations are used to carry replicated + content from one server to another. The extended operations defined + in this document are used to initiate and end a replication session, + and to exchange updates. These updates carry with them information + that allows the receiving server to apply a total ordering to all of + the updates in a replicated system. All servers that receive + replication updates apply a consistent set of update resolution + policies, described in [URP]. Consistent application of the update + resolution policies ensures that all replicas eventually converge and + contain the same directory data. + + This protocol is based upon the extended operations defined in + [FRAMING]. + + This protocol is intended to meet the requirements set forth in + [REQ]. + +4. High-level Description of Protocol Flow + + The following section provides a high-level overview of the + replication protocol. Throughout this section, the supplier server is + indicated by the letter "S" and the consumer server by the letter + "C". The construct "S -> C" indicates that the supplier is sending an + LDAPv3 extended operation to the consumer, and "C -> S" indicates + that the consumer is sending an LDAPv3 extended operation to the + supplier. + +4.1 Supplier-initiated incremental replication protocol + + S -> C: LDAP bind operation (identity and credentials + used are implementation-defined) + + C -> S: Bind response + + S -> C: StartFramedProtocolRequest LDAPv3 extended + operation. The parameters are: + + 1) The OID for the LDUP incremental replication protocol or the + LDUP total update protocol, depending on whether an incremental + or complete refresh of the replica is to be performed. + 2) A protocol-specific payload containing: + a) The root of replicated area (unambiguously + identifies the replicated area) + b) The supplier's replicaID + c) The protocol initiation type - Supplier-Initiated + in this case. + + C -> S: StartFramedProtocolResponse LDAPv3 extended operation. The + + + +Stokes and Good [Page 3] + +Internet-Draft LDUP Workgroup March 10 2000 + + + parameters are: + + 1) A protocol-specific payload containing: + a) A response code (see section 7) + b) An optional update vector that is included + if and only if the response code is REPL_SUCCESS. + + S -> C: The supplier may send zero or more ReplicationUpdate LDAPv3 + extended operations. The parameters are: + + 1) The UUID of the entry being updated + 2) One or more Replication Primitives (The supplier + may send as many of these as required to bring + the consumer up to date) + + C -> S: At any time, the consumer may send an unsolicited + ReplicationUpdateResponse LDAPv3 extended operation. The + parameters are: + + 1) An optional update vector. If sent, this indicates that + the consumer has committed all updates whose CSNs are + covered by the transmitted update vector [see glossary + for a definition of "covered by"]. + 2) An optional AbortUpdate boolean flag. If a supplier + receives a ReplicationUpdateResponse from a consumer with + the AbortUpdate flag set to true, the supplier server MUST + immediately cease sending updates and terminate its + connection to the consumer. + + S -> C: After all required updates have been sent to the consumer, the + supplier sends an EndFramedProtocolRequest LDAPv3 extended + operation. + + C -> S: The consumer responds by sending an EndFramedProtocolResponse + LDAPv3 extended operation, and then closes the connection. + +4.2. Consumer-initiated replication protocol + + C -> S: LDAP bind operation (identity and credentials + used are implementation-defined) + + S -> C: Bind response + + C -> S: StartFramedProtocolRequest LDAPv3 extended + operation. The parameters are: + + 1) The OID for the LDUP incremental replication protocol or the + LDUP total update protocol, depending on whether an incremental + + + +Stokes and Good [Page 4] + +Internet-Draft LDUP Workgroup March 10 2000 + + + or complete refresh of the replica is to be performed. + 2) A protocol-specific payload containing: + a) The root of replicated area (unambiguously + identifies the replicated area) + b) The consumer's replicaID + c) The protocol initiation type - Consumer-Initiated + in this case. + + S -> C: StartFramedProtocolResponse LDAPv3 extended operation. The + parameters are: + + 1) A protocol-specific payload containing: + a) A response code (see section 7) + + S -> C: The supplier server disconnects from the consumer server, + and then connects to the consumer, beginning a Supplier- + Initiated protocol session (see section 4.1). + + +5. Replication protocol element definitions + +5.1 StartFramedProtocolRequest Extended Operation + + The StartFramedProtocolRequest extended operation is sent by a replication + initiator to a server to indicate that a replication session should + commence. For supplier-initiated replication, the supplier sends this + extended operation to the replication consumer to indicate that a + replication session should commence. For consumer-initiated + replication, the consumer sends this extended operation to the + replication supplier to indicate that the supplier should initiate a + replication session to the consumer as soon as possible. + + The StartFramedProtocolRequest extended operation is defined + in [FRAMING]. When signaling the beginning of a replication + session, then requestValue of the StartFramedProtocolRequest + is set to the following: + + requestValue ::= SEQUENCE { + framedProtocolOID LDAPOID, + framedProtocolPayload OPTIONAL OCTET STRING + } + + The framedProtocolOID of the StartReplicationRequest must be the OID + for the LDUP incremental replication protocol, + 2.16.840.1.113719.1.142.1.4.3, or the LDUP total update protocol, + 2.16.840.1.113719.1.142.1.4.4. See section 7 for information on the + semantic behavior of these update protocols. Implementations MUST + support the two update protocols defined in this document. + + + +Stokes and Good [Page 5] + +Internet-Draft LDUP Workgroup March 10 2000 + + + The framedProtocolPayload of the StartFramedProtocolRequestValue must + be set to the BER-encoding of the following: + + framedProtocolPayload ::= SEQUENCE { + replicaRoot LDAPDN, + replicaID LDAPString, + replicationInitiator ENUMERATED { + supplier (0), + consumer (1) + } + } + + The parameters in the framedProtocolPayload of the + StartFramedProtocolRequestValue are: + + - replicaRoot: the distinguished name of the entry at the top of + the replicated area, and uniquely identifies the unit of + replication. + + - replicaID: the replica identifier of the replication initiator. + Each replica of a given replicated area is identified by a unique + identifier, described in [ARCHITECTURE]. + + - replicationInitiator: used to differentiate between a supplier- + initiated session and a consumer-initiated session. If the + replicationInitiator contains the enumerated value , + then the initiator is the supplier, and the receiver of this + operation should prepare to receive a set of replication updates + (or should reject the operation is replication updates are not + permitted for some reasonm, perhaps due to access control + restrictions). If the replicationInitiator contains the + enumerated value , then the receiver should prepare to + establish a supplier-initiated replication session with the + consumer as soon as possible, updating the replicated are given by + replicaRoot and using the update protocol given by + replicationProtocolOID. + +5.2 StartFramedProtocolResponse Extended Operation + + The StartFramedProtocolResponse extended operation is sent in + response to a StartFramedProtocolRequest extended operation. + + For a supplier-initiated session, the response field of the + StartFramedProtocolResponse extended response indicates that the + consumer is or is not prepared to accept a set of updates. If the + consumer is prepared to accept updates, it sends a response field + containing a success code and the consumer's replica update vector. + If the consumer is unwilling or unable to accept updates, it sends a + + + +Stokes and Good [Page 6] + +Internet-Draft LDUP Workgroup March 10 2000 + + + response field containing an error code. + + For a consumer-initiated session, the response field of the + StartFramedProtocolResponse extended respons indicates that the + supplier is or is not prepared to send a set of updates to the + consumer. If the supplier is prepared to send updates to the + consumer, it sends a response field containing a success code. If the + supplier is unwilling or unable to send updates to the consumer, it + sends a response field containing an error code. In both cases, the + supplier disconnects from the consumer. If the supplier sent a + success code to the consumer, it opens a connection to the consumer + as soon as possible and initiates a supplier-initiated replication + session. + + The StartFramedProtocolResponse extended operation is defined in + [FRAMING]. When responding to a StartFramedProtocolRequest signaling + the beginning of an LDUP replication session, the response field of + the StartFramedProtocolResponse is set to the following: + + StartFramedProtocolResponseValue ::= SEQUENCE { + responseCode LDUPResponseCode, + replicaUpdateVector Attribute, + } + + LDUPResponseCodes are defined in section 8. + + The replicaUpdateVector contains a replica update vector, as defined + in [INFOMOD]. The update vector is encoded as a normal LDAP + attribute, defined in [LDAPv3]. + + +5.3 ReplicationUpdate Extended Operation + +The ReplicationUpdate extended operation carries a set of replication +primitives that represent the desired final state of a single entry. + +The ReplicationUpdate extended operation is defined as follows: + +An LDAPv3 Extended Request is defined in [LDAPv3] as follows: + + ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + requestName [0] LDAPOID + requestValue [1] OCTET STRING OPTIONAL + } + +The requestName of the ReplicationUpdate must be the OID +2.16.840.1.113719.1.142.100.3. + + + + +Stokes and Good [Page 7] + +Internet-Draft LDUP Workgroup March 10 2000 + + +The requestValue of the ReplicationUpdate must be set to the BER- +encoding of the following: + + requestValue ::= SEQUENCE { + uniqueID UniqueIdentifier, + updates SET OF ReplicationPrimitive + } + +5.3.1 UniqueIdentifier + + The Distinguished Name of an entry may be changed (by renaming the + entry), or the entry may not have a distinguished name (if it was + deleted). The Unique Identifier provides an immutable name, + independent of the current name or deletion status, for an entry. All + replicated operations address entries by their Unique Identifiers. + + UniqueIdentifier ::= LDAPString + + +5.3.2 ReplicationPrimitive + + A ReplicationPrimitive carries a single assertion about the the final + state of an entry, attribute, or attribute value. There are seven + types of primitives. + + ReplicationPrimitive ::= CHOICE { + addEntryPrimitive AddEntryPrimitive, + moveEntryPrimitive MoveEntryPrimitive, + renameEntryPrimitive RenameEntryPrimitive, + removeEntryPrimitive RemoveEntryPrimitive, + addAttributeValuePrimitive AddAttributeValuePrimitive, + removeAttributeValuePrimitive RemoveAttributeValuePrimitive, + removeAttributePrimitive RemoveAttributePrimitive + } + + Each primitive applies to the entry referred to by the + uniqueIdentifier in the enclosing ReplicationUpdate extended + operation. + + Each primitive carries an lLDAPChangeSequenceNumber that is used by + the consumer server to correctly resolve update conflicts. [URP] + describes the update reconciliation procedures. + +5.3.2.1 AddEntryPrimitive + + The AddEntryPrimitive is used to add a new entry. + + AddEntryPrimitive ::= [APPLICATION 0] SEQUENCE { + + + +Stokes and Good [Page 8] + +Internet-Draft LDUP Workgroup March 10 2000 + + + csn lDAPChangeSequenceNumber, + superior UniqueIdentifier, + rdn RelativeLDAPDN + } + + Parameters of the AddEntryPrimitive are: + + - csn: The change sequence number of the primitive. + + - superior: The unique identifier of the superior (parent) entry. + + - rdn: The relative distinguished name of the new entry. + +5.3.2.2 MoveEntryPrimitive + + The MoveEntryPrimitive is used to move an entry to a new location in + the DIT. + + MoveEntryPrimitive ::= [APPLICATION 1] SEQUENCE { + csn lDAPChangeSequenceNumber, + superior UniqueIdentifier + } + + Parameters of the MoveEntryPrimitive are: + + - csn: The change sequence number of the primitive. + + - superior: The unique identifier of the new superior (parent) + entry. + +5.3.2.3 RenameEntryPrimitive + + The RenameEntryPrimitive is used to change the RDN of an entry. + + RenameEntryPrimitive ::= [APPLICATION 2] SEQUENCE { + csn lDAPChangeSequenceNumber, + rdn RelativeLDAPDN + } + + Parameters of the RenameEntryPrimitive are: + + - csn: The change sequence number of the primitive. + + - rdn: The new relative distinguished name of the entry. + +5.3.2.4 RemoveEntryPrimitive + + The RemoveEntryPrimitive is used to delete an entry from the DIT. + + + +Stokes and Good [Page 9] + +Internet-Draft LDUP Workgroup March 10 2000 + + + RemoveEntryPrimitive ::= [APPLICATION 3] SEQUENCE { + csn lDAPChangeSequenceNumber + } + + Parameters of the RemoveEntryPrimitive are: + + - csn: The change sequence number of the primitive. + +5.3.2.5 AddAttributeValuePrimitive + + The AddAttributeValuePrimitive is use to add a new attribute value to + an entry. + + AddAttributeValuePrimitive ::= [APPLICATION 4] SEQUENCE { + csn lDAPChangeSequenceNumber, + type AttributeDescription, + value AttributeValue + } + + Parameters of the AddAttributeValuePrimitive are: + + - csn: The change sequence number of the primitive. + + - type: The type of the attribute being added. + + - value: The value being added. Multiple values are not permitted. + +5.3.2.6 RemoveAttributeValuePrimitive + + The RemoveAttributeValuePrimitive is used to remove a particular + attribute value from an entry. + + RemoveAttributeValuePrimitive ::= [APPLICATION 5] SEQUENCE { + csn lDAPChangeSequenceNumber, + type AttributeDescription, + value AttributeValue + } + + Parameters of the RemoveAttributeValuePrimitive are: + + - csn: The change sequence number of the primitive. + + - type: The type of the attribute being removed. + + - value: The value being removed. Multiple values are not + permitted. + +5.3.2.7 RemoveAttributePrimitive + + + +Stokes and Good [Page 10] + +Internet-Draft LDUP Workgroup March 10 2000 + + + The RemoveAttributePrimitive is used to remove an attribute and all + its values from an entry. + + RemoveAttributePrimitive ::= [APPLICATION 6] SEQUENCE { + csn lDAPChangeSequenceNumber, + type AttributeDescription + } + + Parameters of the RemoveAttributePrimitive are: + + - csn: The change sequence number of the primitive. + + - type: The type of the attribute being removed. + + +5.4 EndFramedProtocolRequest Extended Operation + + The EndFramedProtocolRequest extended operation is sent from the + replication supplier to the replication consumer to indicate the end + of the sequence of replication updates. In the event that the + supplier is sending a total update, the requestValue field of the + EndFramedProtocolRequest extended operation contains a replica update + vector. The consumer server must replace its replica update vector, + if present, with the one provided by the supplier. In the event that + the supplier is sending an incremental update, the replica update + vector is absent. + + The EndFramedProtocolRequest extended operation is defined in + [FRAMING]. When used to signal the termination of an LDUP incremental + or total update session, the requestValue field of the + EndFramedProtocolRequest is set to the following: + + requestValue ::= SEQUENCE { + replicaUpdateVector Attribute OPTIONAL, + returnConsumerUpdateVector BOOLEAN + } + + If returnConsumerUpdateVector is TRUE, the consumer server must + return its current update vector to the supplier in the response + field of the EndFramedProtocolResponse extended response (defined in + section 5.5). Typically, the supplier will request the consumer's + update vector for read-only replicas, since the read-only replica + will never initiate a replication session, and will therefore never + have the opportunity to provide its update vector to other servers. + + +5.5 EndFramedProtocolResponse Extended Operation + + + + +Stokes and Good [Page 11] + +Internet-Draft LDUP Workgroup March 10 2000 + + + The EndFramedProtocolResponse extended operation is defined in + [FRAMING]. It is used to respond to a EndFramedProtocolRequest. The + response field of the EndFramedProtocolResponse extended operation is + set to the following: + + response ::= SEQUENCE { + replicaUpdateVector Attribute OPTIONAL + } + + The replicaUpdateVector contains the consumer's current replica + update vector, and is optional. The consumer server should only send + the replicaUpdateVector if requested by the supplier server in the + EndReplicationRequest extended operation. + +5.6 ReplicationUpdateResponse Extended Operation + +The ReplicationUpdateResponse extended operation is sent, unsolicited, +by a consumer to a supplier when the consumer wishes the supplier to +stop sending updates. + +An LDAPv3 extended response is defined in [LDAPv3] as follows: + + ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + COMPONENTS of LDAPResult, + responseName [10] LDAPOID OPTIONAL, + response [11] OCTET STRING OPTIONAL + } + +The responseName of the ReplicationUpdateResponse must be the OID [OID +to be assigned]. + +The response field of the ReplicationUpdateResponse must be set to the +BER-encoding of the following: + + response ::= SEQUENCE { + replicaUpdateVector Attribute OPTIONAL + abortUpdate BOOLEAN + } + +The parameters of the ReplicationUpdateResponse are: + +- An optional update vector. If sent, this indicates that the consumer +has committed all updates whose CSNs are covered by the transmitted +update vector [see glossary for a definition of "covered by"]. - An +optional AbortUpdate boolean flag. If a supplier receives a +ReplicationUpdateResponse from a consumer with the AbortUpdate flag set +to true, the supplier server MUST immediately cease sending updates and +terminate its connection to the consumer. + + + +Stokes and Good [Page 12] + +Internet-Draft LDUP Workgroup March 10 2000 + + +6. Semantics of Full and Incremental Update protocols + +[To be written] + +7. Summary of response codes + +The following list describes the response codes that may be included in +the StartFramedProtocolResponse, EndFramedProtocolResponse, and +ReplicationUpdateResponse extended operations. + + LDUPResponseCode ::= SEQUENCE { + resultCode ENUMERATED { + success (0), + operationsError (1), + protocolError (2), + insufficientAccessRights (50), + busy (51), + excessiveCSNSkew (200), + + other (80) }, + errorMessage LDAPString } + +The meanings of the response codes are as follows: + + success..................... As defined in [LDAPv3]. + operationsError............. As defined in [LDAPv3]. + protocolError............... As defined in [LDAPv3]. + insufficientAccessRights.... Access denied. The identity that the + initiator provided in the bind request does + not have sufficient privileges to perform + the operation. + busy........................ The replica is temporarily unable to accept + updates. + excessiveCSNSkew............ The consumer server has detected that the + CSNs being generated by the supplier are + too small (perhaps because the supplier's + clock was set back). Updates from the + supplier will not be applied. + other....................... Some other error occurred. + +8. Implications for log-based and state-based servers + +To be written, or possibly incorporated into [ARCHITECTURE]. + +9. Replication of access control and schema information + +To be written, or possibly incorporated into [ARCHITECTURE]. + + + + +Stokes and Good [Page 13] + +Internet-Draft LDUP Workgroup March 10 2000 + + +10. Security Considerations + +To be written. + +11. Glossary of Terms + + Covered by: We say that a CSN is "covered by" an update vector if and + only if the CSN is less than or equal to the component of the update + vector corresponding to the replica ID in the CSN. In other words, + given a CSN with components and an update vector with CSNs + ,..., then the CSN is covered + by the RUV if and only if one of the following holds for some value + i: + a) r = ri and t < ti + b) r = ri and t = ti and S < Si + c) r = ri and t = ti and S = Si and s < si + + +12. Acknowledgments + +To be written. + +13. References + + +[ARCHITECTURE] + J. Merrells, E. Reed, U. Srinivasan, "LDAP Replication Architec- + ture", Internet-Draft, draft-ietf-ldup-model-02.txt, October 1999. + + +[FRAMING] + E. Stokes, G. Good, "Extended Operations for Framing LDAP Bulk + Update Operations", Internet-Draft, draft-ietf-ldup-framing-00.txt, + March 2000. + + +[INFOMOD] + E. Reed, "LDAP Replication Information Model", Internet-Draft, + draft-reed-ldup-infomod-00.txt, June 1999. + + +[KEYWORDS] + S. Bradner, "Key Words for use in RFCs to Indicate Requirement Lev- + els", Harvard University, RFC 2119, March 1997. + + +[LDAPv3] + M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol + + + +Stokes and Good [Page 14] + +Internet-Draft LDUP Workgroup March 10 2000 + + + (v3)", RFC 2251, December 1997. + + +[REQ]R. Weiser, E. Stokes, "LDAP V3 Replication Requirements", + Internet-Draft, draft-ietf-ldup-replica-req-02.txt, October 1999. + + +[URP]S. Legg, A. Payne, "LDUP Update Reconciliation Procedures", + Internet-Draft, draft-ietf-ldup-urp-02.txt, October 1999. + +14. Author's Addresses + + Ellen Stokes + IBM + 11400 Burnet Rd + Austin, TX 78758 + USA + EMail: stokes@austin.ibm.com + phone: +1 512 838 3725 + fax: +1 512 838 0156 + + Gordon Good + Netscape Communications Corp. + 501 E. Middlefield Rd. + Mailstop MV068 + Mountain View, CA 94043 + USA + EMail: ggood@netscape.com + Phone: +1 650 937-3825 + + 15. Document Revision History + (This section will be removed prior to this document's publication + as a proposed standard) + + Differences between draft-ietf-ldup-protocol-00.txt and + draft-ietf-ldup-protocol-01.txt: + + 1) The document was reworked to use the ldup framed protocol + draft [FRAMING]. + + +Appendix A - Complete ASN.1 Definition + +To be written. + +Full Copyright Statement + +Copyright (C) The Internet Society (1999). All Rights Reserved. + + + +Stokes and Good [Page 15] + +Internet-Draft LDUP Workgroup March 10 2000 + + +This document and translations of it may be copied and furnished to oth- +ers, and derivative works that comment on or otherwise explain it or +assist in its implementation may be prepared, copied, published and dis- +tributed, in whole or in part, without restriction of any kind, provided +that the above copyright notice and this paragraph are included on all +such copies and derivative works. However, this document itself may not +be modified in any way, such as by removing the copyright notice or +references to the Internet Society or other Internet organizations, +except as needed for the purpose of developing Internet standards in +which case the procedures for copyrights defined in the Internet Stan- +dards process must be followed, or as required to translate it into +languages other than English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an "AS +IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK +FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT- +NESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Stokes and Good [Page 16] diff --git a/doc/drafts/draft-ietf-ldup-replica-req-xx.txt b/doc/drafts/draft-ietf-ldup-replica-req-xx.txt new file mode 100644 index 0000000000..ac8a526837 --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-replica-req-xx.txt @@ -0,0 +1,1035 @@ + INTERNET-DRAFT Russel F. Weiser + Informational Draft Digital Signature Trust Co. + Expires 21 April 2000 Ellen Stokes + IBM + 21 October 1999 + + + + + + LDAP V3 Replication Requirements + + + + + + Status of this Memo + + + + This document is am Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + + Internet-Drafts are draft documents valid for a maximum of six + months and may be updated, replaced, or obsoleted by other documents + at any time. It is inappropriate to use Internet-Drafts as + reference material or to cite them other than as ``work in + progress.'' + + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/lid-abstracts.txt + + + The list of Internet-Drafts Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + + + + Abstract + + + This document discusses the fundamental requirements for replication + of data accessible via the LDAPv3 [RFC2251] protocol. It is intended + to be a gathering place for general replication requirements needed + to provide interoperability between informational directories. + + + The key words MUST, MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [RFC2119]. + + + + + + + + Weiser & Stokes 21 April 2000 [PAGE 1] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + + + Table of Contents + + + 1.Introduction.....................................................3 + 2. Terminology.....................................................3 + 3. Objective.......................................................5 + 4. Applicability Statement.........................................5 + 5. Replication Model..............................................10 + 6. Replication Protocol...........................................12 + 7. Schema.........................................................13 + 8. Administration and Management Considerations...................13 + 9. Acknowledgement................................................14 + 10. References....................................................15 + 11. Author's Address..............................................15 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Weiser & Stokes 21 April 2000 [Page 2] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + + + + + 1. Introduction + + + The ability to distribute directory information throughout the + network provides a two fold benefit to the network: (1) increasing + the reliability of the directory through fault tolerance, and + (2) brings the directory content closer to the clients using the + data. LDAPÆs acceptance as an access protocol for directory + information is driving the need to distribute LDAP directory content + among servers within enterprise and Internet. Currently LDAP does + not define a replication mechanism and only generally mentions LDAP + shadow servers (see [RFC2251] and [Changelog]) in passing. The + requirements for replication are critical to the successful + deployment and acceptance of LDAP in the market place. + + + + 2. Terminology + + + For the purposes of this document, the following terminology + definitions are used: + + + Area of replication - A whole or portion of a directory tree(DIT) + making up a distinct unit of data to be replicated. This may also be + known as "unit of replication". + + Atomic operation - The ability to treat and contain several updates + or attribute changes as a single operation for replication purposes + to guarantee that the several updates or attribute changes are + propagated to a replica as a single unit. + + Authoritative Master Replica - The Primary updateable replica of the + replicated information. + + + Conflict resolution - Deterministic procedures within replication + protocols, utilized to resolve change information conflicts that may + arise due to conflicting changes affecting a directory entry. + + + Fractional replication - The capability to replicate a subset of + attributes of any given entry. + + Incremental Update - The process of updating a replica, or copy, of + a naming context, by updating only those fields or objects which + have changed. + + + Master Slave, or Single Master Replication - Replication model that + assumes only one server, the master, allows write access to the + replicated data. Note that Master-Slave replication can be + considered a proper subset of multi-master replication. + + + + Weiser & Stokes 21 April 2000 [Page 3] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + + + Multi-Master Replication - A replication model where entries can be + written and updated on any of several updateable replica copies + without requiring communication with other updateable replicas + before the write or update is performed. + + + Naming Context - Suffix of a Sub-tree. A sub-tree of entries held in + a single server [X.500]. + + + One-way Replication - The process of synchronization in a single + direction where the authoritative source information is provided to + a replica. + + + Partial Replication - The capability to replicate some subset of + entries in a naming context. + + + Propagation behavior - The general behavior of the actual + synchronization process between a consumer and a provider of + replication information. + + Read-only Replica - A read-only copy of a replicated directory. A + read-only replica is assumed to be a slave replica of master slave + or single master replication definition. + + + Replica - A single instance of a whole or portion of the Directory + tree (DIT) as defined by area of replication. + + + Replica Ring - A set of servers, which hold in common the same DIT + information as, defined by ôArea of replicationö. These servers may + be managed under a single replication agreement that handles all + members of the set of servers as a group. + + + Replica Cycle - When a change or groups of changes need to be + propagated to the other member of a replica ring. The process of + contacting a replica member would be considered the beginning of a + replication cycle; the termination of communications with a replica + is the end of the cycle whether its due to an error or successful + exchange of update records. + + + Replication - The process of copying portions of naming context + information and content between multiple LDAP servers, such that + certain predefined portions of the information are available from + different servers. Replication can occur between either homogeneous + implementations across heterogeneous platforms (operating systems) + or heterogeneous implementations supporting identical replication + across heterogeneous platforms (operating systems). + + + Sparse Replica - A incomplete copy of a sub-tree which maybe + inclusive with updateable, or Read-only. See Partial replication and + + + + + Weiser & Stokes 21 April 2000 [Page 4] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + Fractional replication. + + + Topology - Refers to the shape of the directed graph describing the + relationships between replicas, as in the replicated directory + topology. + + + Two-way Replication - The process of synchronization where change + information may flow bi-directionally between two replica. + + Update Propagation - Protocol-based process by which directory + replicas are reconciled. + + + Updateable Replica - A Non-authoritative read-writeable copy of the + replicated information. Such that during conflict resolution a + authoritative master takes precedents in resolving conflicts. + + + + 3. Objective + + + The major objective is to provide an interoperable LDAP V3 directory + synchronization protocol which is simple, highly efficient and + flexible enough to support both multi-master and master-slave + replication operations to meet the needs of both the internet and + enterprise environments. + + + 4. Applicability Statement + + + Generally replication can be characterized by looking at data + consistency models across existing technologies. This may provide + insight to LDAP v3 replication requirements. The following is a + brief examination of the following data models. + + + Model 1: Tight Consistency -- Includes environments where all + replicas must always contain exactly the same directory content. Two + phase commit transaction models may be used to preserve transaction + consistency. + + + Model 2: Eventual Consistency or Transient Consistency -- Includes + X.500 Directories, Bayou [XEROX], and NDS (Novell Directory + Services) names service where definite knowledge of the global + replica topology is provided through predetermined replication + agreements. Such that every update propagates to every replica that + it can reach via a path of stepwise eventual connectivity. + Transaction consistency is preserved for transactions directed at + the master server in X.500 implementations. NDS additionally + provides deterministic consistency over time to all replicas due to + its inherent replication policies. + + + + + Weiser & Stokes 21 April 2000 [Page 5] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + Model 3: Limited Effort Eventual Consistency -- Includes Xerox + Clearinghouse [XEROX] that provides a statistical probability of + convergence with global knowledge of replica topology. Similar to + "Eventual Consistency", except where replicas may purge updates + therefore dropping propagation changes when some replica time + boundary is exceeded, thus leaving some changes replicated to a + portion of the replica topology. Transactional consistency is not + preserved, though some weaker constraints on consistency are + available. + + Model 4: Loosest Consistency -- Includes opportunistic or simple + cache where information is provided from the cache until stale. + + + Model 5: Ad hoc -- A copy of a date store where no follow up checks + are made for the accuracy/freshness of the data. + + + Consistency models 2, and 3 involve the use of prearranged + replication agreements or "Predefined Replication Agreements" + between cooperating servers. The complexity of Model 1's use of 2- + phase commit adds additional overhead that should not considered at + this time. Models 4 and 5 involve unregistered replicas which + "pull" updates from another directory server without that server's + knowledge. These models can be considered to violate a directory's + security policies. Therefore models 1, 4, and 5 are declared to be + out of scope of this working group. + + + So through further review of these consistency models two + application areas can then be derived with even further + characterizations of the data types usages. + + Eventual Consistency or Transient Consistency (Model 2) - This model + provides policy configuration through security management + parameters; the data is more dynamic and utilizes dynamic address + information. + + Limited Effort Eventual Consistency (Model 3) - This model matches a + white-pages environment which contains fairly static data and + address information. This model mainly replicates message + attributes. + + Therefore it is believed an LDAP replication should be flexible + enough to cover the above range of capabilities. The generalized use + of LDUP replication environment is to provide for the distribution + of LDAP directory information in order to improve accessibility and + consistency of the information held by the directory. + + + + 4.1 Replication Scenarios + + + + + + Weiser & Stokes 21 April 2000 [Page 6] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + The following directory deployment examples are intended to + substantiate and validate our replication requirements. It is + assumed in all cases that directory implementations from different + vendors are involved. + + 4.1.1 Extranet Example + + + A company has a trading partner to whom it wishes to provide + directory information. This information may be as simple as a + corporate telephone directory, or as complex as an extranet work + flow application. For performance reasons the company may wish to + have a replica of its directory within the Partner Company, rather + than simply exposed beyond its firewall. + + + The requirements, which follow from this scenario, are: + + - One-way replication, single mastered. + - Authentication of clients. + - Common access control and access control identification. + - Secure transmission of updates. + - Selective attribute replication (Fractional Replication), so that + only partial entries can be replicated. + + + + 4.1.2 Consolidation Example + + + Company A acquires company B. In the transition period, whilst the + organizations are merged, both directory services must coexist. + Company A may wish to attach company B's directory to its own. + + The requirements, which follow from this scenario, are: + + - Multi-Master replication. + - Common access control model. Access control model identification. + - Secure transmission of updates. + - Replication between DITs with potentially differing schema. + + + 4.1.3 Replication Heterogeneous Deployment Example + + An organization may deliberately deploy multiple directory services + within their enterprise to employ the differing benefits of each + service. In this case multi-master replication will be required to + ensure that the multiple updateable replicas of the DIT are + synchronized. Some vendors may provide directory clients, which are + tied to their own directory service. + + + The requirements, which follow from this scenario, are: + + + - Multi-Master replication + + + + Weiser & Stokes 21 April 2000 [Page 7] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + - Common access control model and Access control model + identification. + - Secure transmission of updates. + - Replication between DITs with potentially differing schemas. + + 4.1.4 Shared Name Space Example + + + Two organizations may choose to cooperate on some venture and need a + shared name space to manage their operation. Both organizations + will require administrative rights over the shared name space. + + The requirements, which follow from this scenario, are: + + - Multi-Master replication. + - Common access control model and Access control model + identification. + - Secure transmission of updates. + + 4.1.5 Supplier Initiated Replication + + A single master environment, which maintains a number of replicas of + the DIT by pushing changes, based on a defined schedule. + + + The requirements, which follow from this scenario, are: + + - Single-master environment. + - Supplier-initiated replication. + - Secure transmission of updates. + + + 4.1.6 Consumer Initiated Replication + + + Again a single mastered replication topology, but the replica + initiates the replication exchange rather than the master. An + example of this is a replica that resides on a laptop computer that + may run disconnected for a period of time. + + + The requirements, which follow from this scenario, are: + + - Single-master environment. + - Consumer initiated replication. + - Open scheduling (anytime). + + 4.1.7 Prioritized attribute replication + + + The password attribute can provide an example of the requirement for + prioritized attribute replication. A user is working in Utah and the + administrator resides in California. The user has forgotten his + password. So the user calls or emails the administrator to request a + new password. The administrator provides the updated password (a + change). Policy states that this attribute is critical and must be + + + + Weiser & Stokes 21 April 2000 [Page 8] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + available to the user for login immediately (e.g. shortly) after the + administrator changed it. Replication needs to occur immediately for + critical attributes/objects. + + + The requirements, which follow from this scenario, are: + + - Incremental replication of changes. + - Automatic replication on change of certain attributes. + - Replicate based on time/attribute semantics. + + 4.1.8 Bandwidth issues + + + The replication of Server (A) R/W replica (a) in Katmandu is handled + via a dial up phone link to Paris where server (B) R/W replica of + (a) resides. Server (C) R/W replica of(a) is connected by a T1 + connection to server (B). Each connection has a different + performance characteristic. + + + The requirements, which follow from this scenario, are: + + - Minimize repetitive updates when replicating from multiple + replication paths. + - Incremental replication of changes. + - Provide replication cycles to delay and/or retry when connections + can not be reached. + - Allowances for consumer initiated or supplier initiated + replication. + + + 4.1.9 Interoperable Administration and Management + + The administrator with administrative authority of the corporate + directory which is replicated by numerous geographically dispersed + LDAP servers from different vendors notices that the replication + process is not completing correctly as the change log is continuing + to grow and/or error message informs him. The administrator uses his + $19.95 RepCo LDAP directory replication diagnostics tools to look at + Root DSE replica knowledge on server 17 and determines that server + 42 made by LDAPÆRUS Inc. is not replicating properly due to an + Object conflict. Using his Repco Remote repair tools he connects to + server 42 and resolves the conflict on the remote server. + + + The requirements, which follow from this scenario, are: + + - Provides replication audit history. + - Provisions for managing conflict resolution. + - Provide LDAP access to predetermined agreements, topology and + policy attributes. + - Provide operations for comparing replicaÆs content for validity. + - Provide LDAP access to status and audit information. + + + + + Weiser & Stokes 21 April 2000 [Page 9] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + 4.1.10 Enterprise Directory Replication Mesh + + + A Corporation builds a mesh of directory servers within the + enterprise utilizing LDAP servers from various vendors. Five servers + are holding the same area of replication. The predetermined + replication agreement(s) for the enterprise mesh are under a single + management, and the security domain allows a single predetermined + replication agreement to manage the 5 servers replication. + + + The requirements, which follow from this scenario, are: + + - Predefined replication agreements that manage more than a single + area of replication that is held on numerous servers. + - Common support of replication management knowledge across vendor + implementation. + - Rescheduling and continuation of a replication cycle when one + server in a replica ring is busy and/or unavailable. + + 5. Replication Model + + + 5.1 LDAP Replication MUST be allowed to span different vendors + directory services in order to provide interoperability. + + 5.2 All replicas MUST eventually be updated with the changed + information, if specified by the replication policy. + + + 5.3 Replication schedules MUST be configurable to allow for + periodic replication, with the replication period determined by + administrator of the replicated system. + + + 5.4 Replication Model MUST enable replication cycle to be initiated + on change or based on the number of pending changes. + + 5.5 The replication model MUST allow for administrative + initiation of replication cycle for any replica that may have + just come back online or was unavailable during previous + replication cycles. + + 5.6 The replication model MUST support both master-slave and + authoritative multi-updateable replica relationships. + + + 5.7 All replicated information between the master database and its + replica databases MUST be identical including all non-user + modify operational attributes such as time stamps. Note this + does not imply that the entire database is identical from + replica to replica, but that the subset of data, chosen to + replicate is identical from replica to replica. Some + operational attributes may be dynamically evaluated; these + attributes will not necessarily appear to be identical. + + + + + + + Weiser & Stokes 21 April 2000 [Page 10] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + 5.8 In distributed multi-vendor environment, LDAP replication MUST + NOT require all copies of the replicated information be + complete copies of the replicated object. + + + 5.9 LDAP replication MUST encompass common schema objects and + attributes, access control, and name space information. + + + 5.10 Sub-tree Replication MUST be defined to allow for greater + flexibility in replication topologies of the DIT as defined by + the area of replication called partial replication. + + + 5.11 Replication of critical values MUST be synchronized and have + priority over non-critical values. An example of a critical + value might be a password or certificate value. + + 5.12 Replication activities MUST occur within the context of a + predefined replication agreement that addresses proper + knowledge of access requirements and credentials between the + synchronizing directories. Currently X.525 DISP [X.525] + discusses this as a shadowing agreement including such + information as unit of replication, update mode, and access + point defining many of the policies between the master and a + replica. + + + 5.13 The acceptance and usage of the Internet requires that LDAP + replication be available across disparate vendor directory + services. + + + 5.14 LDAP replication MUST provide scalability to both enterprise + and Internet environments, e.g. an LDAP server may provide + replication services to replicas within an enterprise as well + as across the Internet. + + + 5.15 The replication model MUST define deterministic policy such + that replication cycle startup time conflicts between two or + more competing master replicas may be resolved + programmatically. An example might be automatic submission and + rescheduling by one of the masters. In such a case, these + replication "conflicts" MUST be resolved by the replication + policy. + + + 5.16 Any replication capable LDAP server MUST allow replication + where the 2 replicating servers agree they can replicate. This + may be accomplished through administrative agreements assuming + compatible access control model and common schema are provided. + + + 5.17 The replication model MUST be able to handle convergence and + resurrection of attributes and objects. This is a consequence + of delete and move with respect to the replication process. + + + + + Weiser & Stokes 21 April 2000 [Page 11] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + 5.18 It is not realistic to assume that all vendors have cooperating + schemas, but that replication may be allowed between diverse + schema. The Model MAY allow for replication between divergent + schema of objects. + + + 6. Replication Protocol + + + 6.1 The act of replication SHOULD have minimal impact on both the + system and network performance. + + 6.2 The replica synchronization SHOULD be handled in such a manner + as to not saturate network with repetitive entry replication + from multiple synchronization providers points. + + + 6.3 Replication MUST only be allowed after the authentication and + verification of authorization of both the replica and the + source directory. + + + 6.4 The transport for LDAP synchronization MUST allow for the + integrity and confidentiality of each replicated server. + + + 6.5 Replicated data MUST be transferable in a secure manner. + + + 6.6 Replication protocol MUST provide for recovery and rescheduling + of a replication cycle due to a replication initiation + conflicts (e.g. consumer busy replicating with other servers) + and or loss of connection(e.g. supplier cannot reach a + replica). The replication protocol MUST include restarting at + the last acknowledged update prior to interruption rather than + re-sending updates it had already sent to a consuming replica. + + + 6.7 LDAP replication MUST allow for full update to facilitate + replica initialization and reset loading utilizing a + standardized format such as LDIF [LDIF] format. + + 6.8 The replication standard SHOULD NOT limit the size of a + replica. The area of replication is defined to be a whole or + portion of a DIT, also allowing a portion of a naming context + to be replicated. Incremental replication SHOULD be allowed. + + 6.9 The replication agreements MUST accommodate multiple servers + receiving the same replica under a single predefined agreement. + + + 6.10 The replication protocol MUST allow either a master or replica + to initiate the replication process. + + + 6.11 Additionally the initiator MUST be allowed to determine + whether it will become a consumer or supplier during the + synchronization startup process. This would allow a replica to + + + + Weiser & Stokes 21 April 2000 [Page 12] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + be periodically connected and synchronized from remote sites at + the local administrator's discretion. + + + 6.12 Multiple LDAP changes to a single server: If transactional + consistency is propagated during replication, then multiple LDAP + changes submitted to a single server SHOULD BE treated as a + single 'atomic unit of work'. + + + 6.13 An LDAP Replication Standard SHOULD NOT limit the transaction + rate of a replication session. + + + 6.14 Entry change information MUST be purged or discarded in a + timely manner when change information becomes outdated due to + propagated to all replica members. + + + + + 7. Schema + + + 7.1 Replica knowledge MUST be provided as DSE attributes. + + 7.2 The Replication Protocol documents MUST define standard schema + for representing replication agreements, and MUST define the + semantics associated with modifying the attributes of + replication agreements. The documents MUST also define a + standard method for determining the location of these + agreements accessible utilizing LDAP. + + + 7.3 The Replication Protocol documents MUST define standard schema + for publishing state information about a given replica, and + MUST define a standard method for determining the location of + this information. + + + 7.4 A location independent management point MUST be defined to + provide authorized administrators with well known access to the + replication policies, regardless of network location. + + + 7.5 Replication agreements of all servers containing replicated + information MUST be accessible via LDAP. + + + 7.6 All objects MUST be uniquely identifiable throughout the object + lifetime . + + + + + 8. Administration and Management Considerations + + + + 8.1 Replication policies MUST allow replication of changed + information to be administratively postponed to a more + + + + Weiser & Stokes 21 April 2000 [Page 13] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + convenient period. + + + 8.2 Allowance for non-scheduled replication of a replica MUST be + provided upon request such that the replica server has been + down or unconnected for a period of time. + + + 8.3 Each copy of a replica MUST maintain audit history information + of which servers it has replicated with and which servers have + replicated with it. + + 8.4 A replica MUST store conflicted versions of the replicated + object to allow optional human review and intervention. + + + 8.5 Access to replication predetermined agreements, topologies, and + policies attributes MUST be provided through LDAP access. + + + 8.6 The capability to check the differences between two replicas + for the same information SHOULD be provided for. This should + entail a client invoking an operation at some server, which + causes that server to extract the contents from some other + server it has a replication agreement with and report the + differences back to the client as the result. + + + 8.7 Authenticated access SHOULD be provided so that Administrative + LDAP clients may query a server for the current state and + replication history for each replica that the server maintains + replication agreements with. + + + 8.8 The ability to view replication conflicts, and override the + resolution derived by the replication policy MUST be provided. + + + 8.9 The deletion of sensitive data MUST be handled in an orderly + manner so that at no time will that data be available without + proper access control. That is, access control information + (ACI) associated with sensitive data must be deleted after or + simultaneously with the delete of the sensitive data. Likewise, + when adding sensitive data, ACI MUST be added first or + simultaneously with the addition of that data. + + + + + 9. Acknowledgement + + + This document is based on input from IETF members interested in LDUP + Replication. + + + + + + + + + Weiser & Stokes 21 April 2000 [Page 14] + + + INTERNET-DRAFT LDAP Replication Requirements 21 October 1999 + + + + + + 10. References + + + + [RFC2251] M. Wahl, T. Howes, S. Kille "Lightweight Directory Access + Protocal", RFC 2251. + + + [RFC2119] S.Bradner, " Key words for use in RFCs to indicate + Requirement Levels", RFC 2119. + + + [LDIF] Gordon Good, "The LDAP Data Interchange Format (LDIF)", + Internet draft, draft-ietf-asid-ldif-00.txt, November 1996. + + + [Changelog] Gordon Good, "Definitions of an Object Class to Hold + LDAP Change records", Internet Draft, draft-ietf-asid-changelog- + 00.txt, November 1996. + + + [X.501] ITU-T Recommendation X.501 (1993), | ISO/IEC 9594-2: 1993, + Information Technology - Open Systems Interconnection - The + Directory: Models + + [XEROX] Hauser, C. "Managing update conflicts in Bayou, a weakly + connected replicated storage system". Palo Alto, CA: Xerox PARC, + Computer Science Laboratory; 1995 August; CSL-95-4. [CSL-95-04] + + + + 11. Author's Address + + + Russel F. Weiser + Digital Signature Trust Co. + One South Main Street + Salt Lake City, Utah 84111 + USA + + + E-mail: rweiser@digsigtrust.com + Telephone: +1-801-983-4415 + Fax +1-801-983-4408 + + + + Ellen J. Stokes + IBM + 11400 Burnet Rd. + Austin, Texas 78758 + USA + + E-mail: stokes@austin.ibm.com + Telephone: +1-512-838-3725 + Fax: +1-512-838-0156 + + + + + + Weiser & Stokes 21 April 2000 [Page 15] diff --git a/doc/drafts/draft-ietf-ldup-subentry-xx.txt b/doc/drafts/draft-ietf-ldup-subentry-xx.txt index c02b3e7e0d..f715b9464c 100644 --- a/doc/drafts/draft-ietf-ldup-subentry-xx.txt +++ b/doc/drafts/draft-ietf-ldup-subentry-xx.txt @@ -1,8 +1,8 @@ INTERNET-DRAFT -draft-ietf-ldup-subentry-00.txt +draft-ietf-ldup-subentry-01.txt Ed Reed Novell, Inc. - August 15, 1999 + August 29, 1999 LDAP Subentry Schema @@ -27,14 +27,15 @@ http://www.ietf.org/ietf/1id-abstracts.txt. The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. -This Internet-Draft expires on January 9, 1999. +This Internet-Draft expires on February 29, 1999. 2. Abstract -This document describes an object class called lDAPsubEntry which MAY +This document describes an object class called ldapSubEntry which MAY be used to indicate operations and management related entries in the -directory, called LDAP Subentries. +directory, called LDAP Subentries. This version of this document is +updated with an assigned OID for the ldapSubEntry object class. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this @@ -47,35 +48,34 @@ ones. - Reed [Page 1] - Expires January 15, 2000 + Expires February 29, 2000 -INTERNET-DRAFT 15 August 1999 +INTERNET-DRAFT 29 August 1999 LDAP Subentry Schema 3. Definition -3.1 LDAPsubEntry Class +3.1 ldapSubEntry Class -( 1.3.6.1.4.1.1466.115.121.1.?? NAME 'LDAPsubEntry' - DESC 'LDAP Subentry class, named by cn' +( 2.16.840.1.113719.2.142.6.1.1 NAME 'ldapSubEntry' + DESC 'LDAP Subentry class, version 1' SUP top STRUCTURAL MUST ( cn ) ) -The class lDAPsubEntry is intended to be used as a super class when +The class ldapSubEntry is intended to be used as a super class when defining other structural classes to be used as LDAP Subentries. The -presence of lDAPsubEntry in the list of super-classes of an entry in +presence of ldapSubEntry in the list of super-classes of an entry in the directory makes that entry an LDAP Subentry. Object classes -derived from lDAPsubEntry are themselves considered lDAPsubEntry +derived from ldapSubEntry are themselves considered ldapSubEntry classes, for the purpose of this discussion. LDAP Subentries MAY be named by their commonName attribute [LDAPv3]. Other naming attributes are also permitted. -LDAP Subentries MAY be containers, unlike their [X.500] counterparts. +LDAP Subentries MAY be containers, unlike their [X.501] counterparts. LDAP Subentries MAY be contained by, and will usually be located in the directory information tree immediately subordinate to, @@ -90,27 +90,39 @@ same way that "operational attributes" are not regularly provided in search results and read operations when only user attributes are requested). -NOTE: No special treatment of LDAP Subentries by applications is -required, but it might be worth considering creating an LDAPv3 control -to indicate when LDAP Subentries are desired to be returned (subject -to access controls and search filters, of course) for LDAP search -operations. +LDAP servers SHOULD implement the following special handling of +ldapSubEntry entries: +a) search operations which include a matching criteria +"objectclass=ldapSubEntry" MUST include entries derived from the +ldapSubEntry class in the scope of their operations; +b) search operations which do not include a matching criteria +"objectclass=ldapSubEntry" MUST IGNORE entries derived from the +ldapSubEntry class, and exclude them from the scope of their +operations. -4. Security Considerations -LDAP Subentries will frequently be used to hold data which reflects -either the actual or intended behavior of the directory service. As -such, permission to read such entries MAY need to be restricted to Reed [Page 2] - Expires January 15, 2000 + Expires February 29, 2000 -INTERNET-DRAFT 15 August 1999 +INTERNET-DRAFT 29 August 1999 LDAP Subentry Schema +The combination of SHOULD and MUST in the special handling +instructions, above, are meant to convey this: Servers SHOULD support +this special handling, and if they do they MUST do it as described, +and not some other way. + + + +4. Security Considerations + +LDAP Subentries will frequently be used to hold data which reflects +either the actual or intended behavior of the directory service. As +such, permission to read such entries MAY need to be restricted to authorized users. More importantly, IF a directory service treats the information in an LDAP Subentry as the authoritative source of policy to be used to control the behavior of the directory, then permission @@ -124,10 +136,10 @@ to authorized administrators. [LDUPINFO] _ E. Reed, "LDUP Replication Information Model", draft- ietf-ldup-infomod-01.txt -[LDAPv3] Kille, S., Wahl, M., and T. Howes, "Lightweight Directory +[LDAPv3] S. Kille, M. Wahl, and T. Howes, "Lightweight Directory Access Protocol (v3)", RFC 2251, December 1997 -[X.500] ITU-T Rec. X.501, "The Directory: Models", 1993 +[X.501] ITU-T Rec. X.501, "The Directory: Models", 1993 @@ -148,6 +160,14 @@ Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. +Reed [Page 3] + Expires February 29, 2000 + + +INTERNET-DRAFT 29 August 1999 + LDAP Subentry Schema + + The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. @@ -159,14 +179,6 @@ WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE." - -Reed [Page 3] - Expires January 15, 2000 - - -INTERNET-DRAFT 15 August 1999 - LDAP Subentry Schema - 7. Acknowledgements The use of subEntry object class to store Replica and Replication @@ -203,6 +215,14 @@ Director. USA E-mail: Ed_Reed@Novell.com + +Reed [Page 4] + Expires February 29, 2000 + + +INTERNET-DRAFT 29 August 1999 + LDAP Subentry Schema + LDUP Mailing List: ietf-ldup@imc.org @@ -216,5 +236,41 @@ Director. -Reed [Page 4] - Expires January 15, 2000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Reed [Page 5] + Expires February 29, 2000 diff --git a/doc/drafts/draft-ietf-ldup-urp-xx.txt b/doc/drafts/draft-ietf-ldup-urp-xx.txt new file mode 100644 index 0000000000..91f24cfadb --- /dev/null +++ b/doc/drafts/draft-ietf-ldup-urp-xx.txt @@ -0,0 +1,1554 @@ +INTERNET-DRAFT S. Legg +draft-ietf-ldup-urp-02.txt Telstra + A. Payne + PricewaterhouseCoopers + October 22, 1999 + + + LDUP Update Reconciliation Procedures + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + Status of this Memo + + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress". + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + This draft is published by the IETF LDUP Working Group. Distribution + of this document is unlimited. Comments should be sent to the LDUP + Replication mailing list or to the authors. + + This Internet-Draft expires on 22 April 2000. + + 1. Abstract + + This document describes the procedures used by directory servers to + reconcile updates performed by autonomously operating directory + servers in a distributed, replicated directory service. + + + + + + + +Legg & Payne Expires 22 April 2000 [Page 1] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + 2. Table of Contents + + 1. Abstract 1 + 2. Table of Contents 2 + 3. Introduction 2 + 4. Model Extensions 3 + 4.1 Unique Identifier 3 + 4.2 Timestamps & Existence 3 + 4.3 Replication Primitives 4 + 4.4 Lost & Found 5 + 5. Replication Procedures 6 + 5.1 Processing LDAP, DAP or DSP Operations on the DIT 6 + 5.1.1 Add Entry 7 + 5.1.2 Remove Entry 7 + 5.1.3 Modify Entry 7 + 5.1.4 Modify DN 9 + 5.2 Generating Replication Primitives 9 + 5.3 Processing Replication Primitives on the DIT 11 + 5.3.1 Saving Deletion Records 12 + 5.3.2 Glue Entries 13 + 5.3.3 Generating Change Sequence Numbers 13 + 5.3.4 Comparison of Attribute Values 14 + 5.3.5 Entry Naming 14 + 5.3.6 Processing Add Attribute Value Primitive 17 + 5.3.7 Processing Remove Attribute Value Primitive 17 + 5.3.8 Processing Remove Attribute Primitive 19 + 5.3.9 Processing Add Entry Primitive 19 + 5.3.10 Processing Remove Entry Primitive 20 + 5.3.11 Processing Move Entry Primitive 21 + 5.3.12 Processing Rename Entry Primitive 22 + 6. Security Considerations 23 + 7. Acknowledgements 23 + 8. References 23 + 9. Intellectual Property Notice 23 + 10. Copyright Notice 24 + 11. Authors' Address 25 + 12. Appendix A - Changes From Previous Drafts 25 + 12.1 Changes in Draft 01 25 + 12.2 Changes in Draft 02 26 + 13. Appendix B - Open Issues 26 + + + 3. Introduction + + Each DAP, LDAP or DSP operation successfully performed by a DSA is + subsequently reported to other DSAs with which it has a replication + agreement as a set of one or more simple timestamped replication + primitives. These primitives reflect the intended final state of an + + + +Legg & Payne Expires 22 April 2000 [Page 2] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + update operation rather than the specific changes required to achieve + that state. + + A DSA will receive replication primitives from its various agreement + partners according to the agreement schedules. Those primitives must + be reconciled with the current DSA contents. In broad outline, + received replication primitives are compared to the timestamp + information associated with the directory data item being operated + on. If the primitive has a more recent timestamp a change in the + directory contents is made (which may involve only the revision of + the timestamp). If the DSA has other replication agreements then the + change will be reflected in primitives sent during replication + sessions for those other agreements. If the primitive has an older + timestamp it is no longer relevant and is simply ignored. + + The update reconciliation procedures are designed to produce a + consistent outcome at all participating DSAs regardless of the order + in which the primitives are received. The primitives can also be + safely replayed in the event that an exchange of replication + information with another DSA is interrupted. This greatly simplifies + the recovery mechanisms required in the replication protocol. + + 4. Model Extensions + + This section describes the extensions to the data model required to + effect multiple master replication. + + 4.1 Unique Identifier + + A Unique Identifier is associated with each entry in the global DIT. + This Unique Identifier must be globally unique for all time in the + Directory. This can be achieved by defining a unique DSA prefix for + each DSA and then ensuring that the suffix of the Unique Identifier + is locally unique. + + Some pre-allocated global Unique Identifier values will be used to + indicate the X.500 global root entry, and the Lost & Found entry (see + Section 4.4). + + 4.2 Timestamps & Existence + + The timestamp for a replication primitive or directory data item is + in the form of a Change Sequence Number (CSN). The components of the + CSN are, from most significant to least significant, a time in + seconds, a change count, a Replica Identifier and a modification + number. Notionally a CSN is associated with an entry's Relative + Distinguished Name (the Name CSN), the reference to its superior + entry (the Parent CSN) and each of its attribute values (including + + + +Legg & Payne Expires 22 April 2000 [Page 3] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + the distinguished values), to record the time of the most recent + action on that part of the entry. + + The entry itself has a CSN (the Entry CSN) asserting the most recent + time at which the entry was added. An entry is permitted to be + removed and then re-added at one or more DSAs. In this context re- + adding an entry means reusing the Unique Identifier of a removed + entry and does not refer to the case of reusing the RDN of a removed + entry. The reuse of a Unique Identifier can arise by the explicit + action of a directory administrator to restore an entry that was + mistakenly removed. The mechanism by which an administrator adds an + entry with a reused Unique Identifier is outside the scope of the + X.500 and LDAP standards since the Unique Identifier of an entry is + not a user modifiable attribute. Note that from the perspective of a + consumer DSA of a partial area of replication an entry may appear to + be removed and added several times because modifications to the entry + change whether the entry satisfies the replication agreement + specification for the area of replication. + + Additionally, a deletion record is kept for each of the recently + deleted entries, attributes, or attribute values. The deletion record + contains a CSN and asserts that the associated directory object no + longer existed at the particular time. + + 4.3 Replication Primitives + + Each update operation performed on an entry in a part of the DIT + subject to one or more replication agreements must be subsequently + reported as replication primitives to the replication partner DSAs of + those agreements. The collection of primitives sent by a DSA to a + replication partner may reflect both the results of locally processed + user update requests and also of replicated updates received from + other DSAs. A single update operation will decompose in one or more + primitives. + + Common to all update primitives is an entry identifier argument, uid, + containing the Unique Identifier of the target entry of the change, + and a CSN argument, csn, to indicate the time of the change. In the + case of adding a new entry, the Unique Identifier for the entry is + allocated by the DSA in the course of processing the operation. + Additional arguments are present depending on the type of replication + primitive. + + The p-add-entry(uid, csn, superior, rdn) primitive is used to add a + new entry with minimal contents. The superior argument contains the + Unique Identifier of the immediate superior entry of the added entry. + The rdn argument contains the Relative Distinguished Name of the + added entry. + + + +Legg & Payne Expires 22 April 2000 [Page 4] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + The p-move-entry(uid, csn, superior) primitive is used to change the + immediate superior of an entry. The superior argument contains the + Unique Identifier of the new superior entry. + + The p-rename-entry(uid, csn, rdn) primitive is used to change the + Relative Distinguished Name of an entry. The rdn argument contains + the new RDN for the entry. + + The p-remove-entry(uid, csn) primitive is used to remove an entry. + + The p-add-attribute-value(uid, csn, type, value) primitive is used to + add a single attribute value to an entry. The type argument contains + the attribute type of the value and the value argument contains the + attribute value. + + The p-remove-attribute-value(uid, csn, type, value) primitive is used + to remove a single attribute value from an entry. The type argument + contains the attribute type of the value and the value argument + contains the attribute value. + + The p-remove-attribute(uid, csn, type) primitive is used to remove + all values of an attribute from an entry. The type argument contains + the attribute type to be removed. + + These primitives reflect the intended final state of an update + operation rather than the specific changes required to achieve that + state. + + 4.4 Lost & Found + + Each connected set of mastering DSAs have a Lost & Found entry + nominated. As a result of conflicting updates at two or more master + DSAs, an entry may be left with a reference to a non-existent + superior entry. Such an entry is called an orphaned entry. When this + situation arises, the DSA creates a glue entry for the missing + superior entry. This glue entry is made a subordinate of the Lost & + Found entry and the orphaned entry becomes a subordinate of the glue + superior entry (see Section 5.3.2). Entries that exist in the Lost & + Found subtree may still be modified by actions of the replication + protocol since entries are identified by Unique Identifiers in the + protocol, independent of their positioning in the global DIT. + + Entries will also be explicitly moved to become immediate + subordinates of the Lost & Found entry to prevent the formation of a + loop in the superior-subordinate relationships in the DIT. This + situation can only arise through conflicting move entry operations at + two or more master DSAs. + + + + +Legg & Payne Expires 22 April 2000 [Page 5] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + Entries that exist under the Lost & Found entry may be returned to a + suitable position in the DIT by an administrator or user with + appropriate access rights. + + 5. Replication Procedures + + The procedures defined in this section ensure the consistent and + correct application of the results of DAP, LDAP or DSP operations + across all multi-master replication DSAs. + + 5.1 Processing LDAP, DAP or DSP Operations on the DIT + + A successful DAP, LDAP or DSP operation applied to a part of the DIT + subject to a replication agreement will create or replace one or more + CSNs on an entry or its contents, and create zero, one or more + deletion records referencing the entry or its contents. The CSNs and + deletion records generated from an operation are atomic with that + operation. That is, either the operation succeeds, the CSNS are + revised and the deletion records are stored, or the operation fails, + no CSNs are revised and no deletion records are stored. In all + cases, all current error conditions (i.e. reasons for rejecting an + LDAP, DAP or DSP update operation) remain. + + At some later time, possibly immediately following the update or + concurrently with it, the CSNs on entry contents and deletion records + are used to generate the replication primitives that will report the + update to other DSAs via a replication session. + + All the CSNs generated from a single update operation must use the + same time, change count and Replica Identifier. The modification + number is permitted to vary but must be assigned such that when the + CSNs resulting from the operation, including those in the deletion + records, are compared to the CSNs resulting from any other operation + they are all strictly greater than or all strictly less than those + other CSNs (i.e. in a global CSN ordering of the primitives + resulting from all operations the primitives of each operation must + be contiguous in that ordering). In order for the update to be + consistently applied when replicated to other DSAs the CSNs generated + during that update must generally be greater than any pre-existing + CSNs on the updated entry's contents. It is expected that DSAs will + normally use the current time according to their system clocks in + generating the CSNs for an operation. However in an environment where + DSA clocks are not necessarily synchronized the current time may be + older than existing CSNs on entry contents. The constraints the new + CSNs must satisfy with respect to pre-existing CSNs on entry data are + covered in the sections on each type of update operation. The current + LDUP architecture draft [LDUP Model] requires client update + operations to be rejected if the current time does not satisfy the + + + +Legg & Payne Expires 22 April 2000 [Page 6] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + constraints on the generation of the CSNs. As written, URP allows a + DSA to generate CSNs in advance of its current time to satisfy the + constraints and proceed with the update. + + The LDUP Update Vector mechanism imposes the additional constraint + that the CSN generated for an update operation must also be greater + than the highest CSN generated by the DSA that has already been seen + by any other DSA. An implementation that generates successively + greater CSNs for each operation will satisfy this constraint. + + The following sections describe the additional actions to support + replication carried out in processing each particular type of update + operation. + + 5.1.1 Add Entry + + The LDAP Add operation or DAP addEntry operation is used to add a + leaf entry to the DIT. A successful request will generate a CSN for + the entry. The CSN on the entry's RDN, the CSN on the entry's + superior reference, and the CSN on each distinguished and non- + distinguished value added to the entry by the add entry operation are + set to this same value. The affected values include any operational + attributes automatically generated by the DSA. + + The Unique Identifier generated for an entry created by a user + request is required to be globally unique for all time, so there + cannot be a pre-existing entry deletion record for the same Unique + Identifier. However it is recognized that, in practice, Directory + administrators may need to restore a deleted entry using its original + Unique Identifier (the mechanism used to achieve this is undefined + and outside the scope of this specification). In this case the CSN + for the entry must be generated such that it is greater than or equal + to the CSN of any existing entry, attribute or value deletion records + and greater than any of the CSNs contained in an existing glue entry, + for the same Unique Identifier. + + 5.1.2 Remove Entry + + The LDAP Delete operation or DAP removeEntry operation is used to + remove a leaf entry from the DIT. If the request succeeds then an + entry deletion record is stored containing the Unique Identifier of + the removed entry. The CSN for the entry deletion record must be + generated such that it is greater than the entry CSN of the removed + entry. + + 5.1.3 Modify Entry + + The LDAP Modify operation (ModifyRequest) or DAP modifyEntry + + + +Legg & Payne Expires 22 April 2000 [Page 7] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + operation is used to perform a series of one or more modifications to + an entry. If the request succeeds then zero, one or more new values + with CSNs are added to the entry contents, and zero, one or more + value or attribute deletion records are stored. + + The modifications described by the modification argument of the LDAP + ModifyRequest have the following additional effects: + + a) The add alternative associates a CSN with each of the added + attribute values. + + b) The delete alternative with no listed values generates an + attribute deletion record for the removed attribute type. + + c) The delete alternative with listed values generates a value + deletion record for each of the removed values. + + d) The replace alternative first generates an attribute deletion + record for the removed attribute type. A CSN is then associated + with each of the added values. + + The modifications described by the changes argument of the X.500 + modifyEntry operation have the following additional effects: + + a) The addAttribute and addValues alternatives associate a CSN + with each of the added attribute values. These two alternatives + are equivalent from the point of view of URP since there is no CSN + associated specifically with the attribute type. + + b) The removeAttribute alternative generates an attribute deletion + record for the removed attribute type. + + c) The removeValues alternative generates a value deletion record + for each of the removed values. + + d) The alterValues alternative first generates a value deletion + record for each of the old values. Secondly, a CSN is associated + with each of the new values. + + e) The resetValues alternative generates a value deletion record + for each value actually removed. + + The CSNs generated by a modify operation must be greater than the CSN + of any pre-existing attribute value that is removed, greater than or + equal to the CSN of any pre-existing attribute deletion record or + value deletion record applying to an added attribute value, and + greater than or equal to the CSN of the entry. + + + + +Legg & Payne Expires 22 April 2000 [Page 8] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + A further constraint applies to the modification number component of + the CSNs generated by a single modify operation. The CSN generated + for an added attribute value must be greater than or equal to the CSN + on any applicable value deletion record or attribute deletion record + already created by this same operation. This constraint is satisfied + if the same modification number is used in all the CSNs generated by + a single modify operation, or if the CSNs generated as the sequence + of modifications in the operation are applied in order use + monotonically increasing modification numbers. The modification + numbers need not be consecutive in this case. + + Whenever a new value is added to the entry contents any value + deletion record for the same entry, attribute type and attribute + value may be discarded. + + 5.1.4 Modify DN + + The LDAP Modify DN operation and DAP modifyDN operation are used to + change the Relative Distinguished Name of an entry and/or to move an + entry to a new superior in the DIT. If the entry is moved to a new + superior in the DIT then the CSN on the entry's superior reference is + replaced. If the entry's RDN is changed then the CSN on the entry's + RDN is replaced. A value deletion record is stored for each of the + formally distinguished attribute values removed from the entry as a + consequence of the deleteOldRDN (modifyDN) flag or deleteoldrdn + (ModifyDNRequest) flag being set. + + If the CSN on the entry's superior reference is revised then the new + value must be greater than the previous value. If the CSN on the + entry's RDN is revised then the new value must be greater than the + previous value of the CSN on the RDN. The CSNs for any value + deletion records must be greater than the CSNs on the removed + attribute values. + + 5.2 Generating Replication Primitives + + Each time a replication session is invoked, the supplier DSA must + generate and send replication primitives for updates known to the + supplier but not yet known to the consumer DSA. The supplier uses the + Update Vector of the consumer to determine what to send. + Conceptually, the supplier scans all the glue and non-glue entries + and deletion records covered by the replication agreement with the + consumer and generates primitives where the CSNs held by the supplier + are greater than the CSN for the corresponding identified replica in + the consumer's Update Vector. + + A p-add-entry primitive is generated for each entry whose entry CSN + is greater than the Update Vector CSN for the same replica. The + + + +Legg & Payne Expires 22 April 2000 [Page 9] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + superior argument of the p-add-entry primitive contains the Unique + Identifier of the immediate superior entry of the added entry. The + rdn argument of the p-add-entry primitive contains the Relative + Distinguished Name of the created entry except that the Unique + Identifier, if distinguished, is always omitted from the RDN. The + superior and rdn arguments are provided even if the CSN on the + superior reference or the RDN are greater than the CSN on the entry. + + A p-add-attribute-value primitive is generated for each distinguished + value that has a CSN greater than the Update Vector CSN for the same + replica and greater than the CSN on the RDN of its entry, and for + each non-distinguished value that has a CSN greater than the Update + Vector CSN for the same replica. The p-add-attribute-value primitive + uses the CSN of the corresponding value. There are no separate + primitives generated for the distinguished values that have the same + CSN as the CSN on their entry's RDN. + + If the CSN on an entry's RDN is greater than the Update Vector CSN + for the same replica and greater than the CSN on the entry then a p- + rename-entry primitive is generated. The CSN for this primitive is + the CSN on the entry's RDN and the rdn argument contains the Relative + Distinguished Name of the entry. + + If the CSN on the entry's superior reference is greater than the + Update Vector CSN for the same replica and greater than the CSN on + the entry then a p-move-entry primitive is generated. The CSN for + this primitive is the CSN on the entry's superior reference and the + superior argument of the contains the Unique Identifier of the + immediate superior entry. + + A p-remove-attribute-value primitive is generated for each value + deletion record having a CSN greater than the Update Vector CSN for + the same replica. The primitive uses exactly the same arguments as + the value deletion record. + + A p-remove-attribute primitive is generated for each attribute + deletion record having a CSN greater than the Update Vector CSN for + the same replica. The primitive uses exactly the same arguments as + the attribute deletion record. + + A p-remove-entry primitive is generated for each entry deletion + record having a CSN greater than the Update Vector CSN for the same + replica. The primitive uses exactly the same arguments as the entry + deletion record. + + Rather than scanning the DIT, an implementation may choose to + generate replication primitives as the user update requests are being + processed and put these primitives into a replication log in + + + +Legg & Payne Expires 22 April 2000 [Page 10] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + preparation for sending during the next replication session. Any + replication primitives generated from an operation in this way MUST + be atomic with that operation. That is, either the operation + succeeds, and primitives are added to the replication log, or the + operation fails, and no primitives are added to the log. The + replication log may be filtered prior to sending to eliminate any + primitives that are superseded by later primitives in the log, and + any primitives having CSNs less than or equal to the relevant CSNs + contained in a consumer DSA's Update Vector. + + In a log based implementation, the p-add-attribute-value primitive + supersedes a p-remove-attribute-value primitive for the same entry, + attribute type, attribute value and equal or older CSN. It supersedes + another p-add-attribute-value primitive for the same entry, attribute + type, attribute value and older CSN. + + The p-remove-attribute-value primitive supersedes a p-add-attribute- + value primitive for the same entry, attribute type, attribute value + and older CSN. It supersedes another p-remove-attribute-value + primitive for the same entry, attribute type, attribute value and + equal or older CSN. + + The p-remove-attribute primitive supersedes a p-add-attribute-value + primitive for the same entry, attribute type and older CSN. It + supersedes a p-remove-attribute-value or another p-remove-attribute + primitive for the same entry, attribute type and equal or older CSN. + + The p-remove-entry primitive supersedes a p-add-attribute-value, p- + add-entry, p-move-entry or p-rename-entry primitive for the same + entry and older CSN. It supersedes a p-remove-attribute-value or p- + remove-attribute or another p-remove-entry primitive for the same + entry and equal or older CSN. + + The p-move-entry primitive supersedes another p-move-entry primitive + for the same entry and older CSN. + + 5.3 Processing Replication Primitives on the DIT + + Each replication primitive received from another DSA during a + replication session is processed against the DIT. + + This section defines some commonly used sub-procedures and the + algorithms for processing each of the primitives. Components of + primitives, entries, attributes and values are referenced with the . + operator. In particular the notation X.csn refers to the CSN of the + directory object X. The operators, < and > when applied to CSNs, use + the convention of CSNs becoming greater with the progression of time, + so older CSNs are less than younger CSNs. In the case where the CSN + + + +Legg & Payne Expires 22 April 2000 [Page 11] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + for object X has been discarded through the purging mechanism, X.csn + is assumed to have the least possible CSN value. In some of the + procedures a CSN will be explicitly purged. An implementation may + instead keep the CSN but set it to some value that is old enough for + it to be eligible for purging (e.g. the least possible CSN value) + without affecting the correctness of the procedures. + + For an entry, E, the notation E.rdn refers to the entry's Relative + Distinguished Name, E.dn refers to the entry's Distinguished Name, + and E.superior refers to the Unique Identifier of the entry's + superior in the DIT. + + + 5.3.1 Saving Deletion Records + + It is necessary for a DSA to remember that some entry, attribute or + attribute value has been deleted, for a period after the processing + of the update operation or primitive causing the deletion. These + records are called deletion records in the sections that follow and + are of three kinds: entry deletion records, attribute deletion + records and value deletion records. + + Value deletion records result from, and have the same parameters as, + the p-remove-attribute-value primitive. The StoreValueDeletion + procedure creates a value deletion record from the actual arguments + and stores it for later access by the various primitive processing + procedures. When an attribute value is added to an entry, a value + deletion record for the same entry, attribute type and value, and + with an older CSN, may be discarded. + + Attribute deletion records result from, and have the same parameters + as, the p-remove-attribute primitive. The StoreAttributeDeletion + procedure creates an attribute deletion record from the actual + arguments and stores it for later access. When an attribute deletion + record is stored any value deletion records for the same entry and + attribute type, and with equal or older CSNs, may be discarded. + + Entry deletion records result from, and have the same parameters as, + the p-remove-entry primitive. The StoreEntryDeletion procedure + creates an entry deletion record from the actual arguments and stores + it for later access. When an entry deletion record is stored any + value deletion records and attribute deletion records for the same + entry, and with equal or older CSNs, may be discarded. + + Since the deletion records have the same components as their + associated remove primitives an implementation may choose to use the + same internal structures for both. + + + + +Legg & Payne Expires 22 April 2000 [Page 12] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + 5.3.2 Glue Entries + + Entries are permitted to be re-added and this can lead to situations + where applicable primitives are received in the period after an entry + is removed but before the arrival of the notification of it being + re-added. In these cases a glue entry is created for the Unique + Identifier to preserve relevant updates in the event that a p-add- + entry primitive with an older CSN is later received for the same + entry. A glue entry is upgraded to a normal entry by a subsequent p- + add-entry primitive. + + A glue entry with no subordinate entries and containing only CSNs (on + itself or its component parts) that are eligible to be purged + (according to the Purge Vector in LDUP, or the Oldest Time in DMRP) + may be removed. A glue entry is discarded if its contents are + completely superseded by another p-remove-entry primitive. + + The CreateGlueEntry function is called when required to create a glue + entry as a subordinate of Lost & Found. CreateGlueEntry takes a + single parameter which is the Unique Identifier for the glue entry. + The Unique Identifier also becomes the RDN for the glue entry. No + CSNs are associated with the entry, the entry's superior reference, + or the entry's name (or equivalently they are set to the least + possible CSN value). + + 5.3.3 Generating Change Sequence Numbers + + There are circumstances where conflicts arise in the processing of a + replication primitive. It is necessary in these cases for the DSA + processing the primitives to make corrective changes and emit + additional primitives to ensure that all other DSAs reach the same + consistent state. The GenerateNextCSN function is used to obtain a + CSN for the corrective change. An implementation that generates + replication primitives as the user update requests are being + processed and puts them into a replication log must take the + additional step of creating a primitive to convey the corrective + change to other DSAs. Implementations that generate primitives by + scanning entries will pick up the corrective change automatically. + + As is the case for CSNs generated from DAP, DSP or LDAP operations, a + CSN is typically generated from the current clock time of the DSA. + The conditions imposed for the correct operation of the LDUP Update + Vector must also be satisfied. + + GenerateNextCSN takes a single CSN parameter. In addition to all + other conditions the CSN generated by the function must be greater + than this parameter. Since the CSN parameter passed to + GenerateNextCSN is always an actual CSN from some directory object + + + +Legg & Payne Expires 22 April 2000 [Page 13] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + stored in the local DSA, an implementation may choose to allocate + CSNs from an incrementing internal CSN register that is reset after + each replication session to a value greater than the largest CSN seen + so far, and thereby be safely able to disregard the parameter to + GenerateNextCSN. + + 5.3.4 Comparison of Attribute Values + + Values in primitives, in deletion records or in entries are compared + using the equality matching rule for the associated attribute type + where that type is permitted to be multi-valued. This means that two + values that are considered equal may nonetheless have minor + differences. For example, two commonName values may be equal, but use + different letter case and have different numbers of leading or + trailing spaces. Whenever a CSN for some value is refreshed the value + is also refreshed using the exact value from the primitive so that + all DSAs use exactly the same representation for the value. + + Compared values for a single-valued attribute type are all considered + to be equal even though they may be significantly different according + to that attribute type's equality matching rule. In effect the + equality operator, '=', in the following procedures is + unconditionally true when used to compare values of a single-valued + attribute type. Whenever a CSN for the value of a single-valued + attribute is refreshed the value is also refreshed using the value + from the primitive. One significant consequence is that an entry + whose RDN contains a value of a single-valued attribute type is + effectively renamed by a p-add-attribute-value primitive with a more + recent value for the attribute type. + + A value in an entry that is replaced by the exact representation from + a primitive retains its distinguished or non-distinguished status. + This includes replaced values of single-valued attribute types. + + 5.3.5 Entry Naming + + Independent changes at two or more DSAs can lead to the situation of + two distinct entries having the same name. The procedure, + CheckUniqueness(E, S, R), takes an entry and determines whether it is + uniquely named. If not, it disambiguates the names of the entries by + adding the Unique Identifier of each of the conflicting entries to + their own RDN. + + The procedure CheckUniqueness is called in each circumstance where + the Relative Distinguished Name of an entry might conflict with + another entry, either because the entry has been renamed or because + it has been moved to a new superior. An entry can be renamed + directly by a p-rename-entry primitive, or as a side-effect of other + + + +Legg & Payne Expires 22 April 2000 [Page 14] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + primitives causing changes to distinguished values. While each move + or rename of an entry potentially causes a conflict with some other + entry already having the new Distinguished Name, it also potentially + removes a previous conflict on the old Distinguished Name. The + enable the CheckUniqueness function to remove the Unique Identifier + from an entry's RDN when it is no longer needed the old name for an + entry is passed through the second and third parameters. The + parameter, S, is the Unique Identifier of the old superior entry of + E, and the parameter, R, is the old RDN of E. CheckUniqueness needs + to ignore distinguished UniqueIdentifiers when comparing entry RDNs. + The function BaseRDN(rdn) returns its argument minus any + distinguished UniqueIdentifiers to support these comparisons. + + CheckUniqueness(E, S, R) + { + make E.uid non-distinguished + IF there exists exactly one subordinate entry, C, of S + where BaseRDN(C.rdn) = BaseRDN(R) + make C.uid non-distinguished + IF E.rdn is empty + make C.uid distinguished + ELSE IF there exists a subordinate entry, C, of E.superior + where E <> C AND BaseRDN(C.rdn) = BaseRDN(E.rdn) + { + make C.uid distinguished + make E.uid distinguished + } + } + + Because updates are performed in isolation at multiple DSAs in a + multimaster configuration it is possible to encounter a situation + where there is a request to delete a distinguished value in an entry. + The recommended practice in these circumstances is to remove the + distinguished value and call CheckUniqueness to correct any resulting + name conflicts. An implementation may instead reassert the existence + of the distinguished value with a more recent CSN to avoid altering + the entry's RDN. This option is only available to updatable replicas. + Read-only replicas MUST remove the distinguished value. The function + ProtectDistinguished() returns true for an updatable part of the DIT + in an DSA that implements this option, and false otherwise. DSAs + exercising this option must generate p-add-attribute-value primitive + so that other DSAs are guaranteed to also reassert the distinguished + value. DSAs that implement the option will correctly interwork with + servers that do not. + + The primitives p-add-entry and p-rename-entry contain common elements + that are applied to the Relative Distinguished Name of an entry in + the same way. This common processing is described in the RenameEntry + + + +Legg & Payne Expires 22 April 2000 [Page 15] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + procedure. The parameters to this procedure are the entry, E, and the + p-add-entry or p-rename-entry primitive specifying the new RDN. The + procedure assumes that the entry does not currently contain any + distinguished values. It is the responsibility of the calling + procedure to first reset any pre-existing distinguished values to + non-distinguished. The procedure then resets the CSNs and sets the + distinguished flags for existing values and adds distinguished values + if necessary. The CSN for the entry's RDN, as distinct from the CSNs + on each of the distinguished values making up the RDN, is also set. + + RenameEntry(E, P) + { + FOREACH AttributeTypeAndValue, N, in P.rdn + IF there exists an attribute value, V, in E of type N.type + where V = N.value + { + IF P.csn > V.csn + { + replace V with N.value if they are not identical + V.csn := P.csn + } + make V distinguished + } + ELSE IF ProtectDistinguished() + { + V := N.value + add V to E as a distinguished value + V.csn := P.csn + FOREACH attribute deletion record (uid, type, csn) + where (uid = P.uid AND type = N.type) + IF csn > V.csn + V.csn := csn + FOREACH value deletion record (uid, type, value, csn) + where (uid = P.uid AND type = N.type AND value = N.value) + IF csn > V.csn + V.csn := csn + V.csn := GenerateNextCSN(V.csn) + } + ELSE IF no attribute deletion record (uid, type, csn) exists + where (uid = P.uid AND type = N.type AND csn > P.csn) + AND no value deletion record (uid, type, value, csn) exists + where (uid = P.uid AND type = N.type AND + value = N.value AND csn > P.csn) + { + V := N.value + add V to E as a distinguished value + V.csn := P.csn + } + + + +Legg & Payne Expires 22 April 2000 [Page 16] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + E.rdn.csn := P.csn + } + + + 5.3.6 Processing Add Attribute Value Primitive + + This section describes the algorithm for processing the p-add- + attribute-value (P.uid, P.type, P.value, P.csn) primitive, which is + responsible for adding a single attribute value. + + IF no value deletion record (uid, type, value, csn) exists where + (uid = P.uid AND type = P.type + AND value = P.value AND csn > P.csn) + AND no attribute deletion record (uid, type, csn) exists where + (uid = P.uid and type = P.type AND csn > P.csn) + AND no entry deletion record (uid, csn) exists where + (uid = P.uid AND csn > P.csn) + { + IF entry, E, with uid = P.uid does not exist + E := CreateGlueEntry(P.uid) + IF P.csn >= E.csn + IF attribute value V, of type P.type + where V = P.value exists in E + { + IF P.csn > V.csn + { + V.csn := P.csn + R := E.rdn + replace V with P.value if they are not identical + IF V is distinguished + AND P.type is a single-valued attribute type + CheckUniqueness(E, E.superior, R) + } + } + ELSE + { + V := P.value + Add V to E as a non-distinguished attribute value + V.csn := P.csn + } + } + + + 5.3.7 Processing Remove Attribute Value Primitive + + This section describes the algorithm for processing the p-remove- + attribute-value (P.uid, P. type, P.value, P.csn) primitive, which is + responsible for removing a single attribute value. A value that is + + + +Legg & Payne Expires 22 April 2000 [Page 17] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + distinguished is tagged as distinguished-not-present rather than + being immediately removed. Such a value will be physically removed + when it becomes non-distinguished. + + IF no value deletion record (uid, type, value, csn) exists + where (uid = P.uid AND type = P.type AND + value = P.value AND csn >= P.csn) + AND + no attribute deletion record (uid, type, csn) exists + where (uid = P.uid AND type = P.type AND csn >= P.csn) + AND + no entry deletion record (uid, csn) exists + where (uid = P.uid AND csn >= P.csn) + IF entry, E, with uid = P.uid exists + { + IF P.csn > E.csn + IF attribute value, V, of P.type + where V = P.value, exists in E + { + IF P.csn > V.csn + IF V is distinguished + IF ProtectDistinguished() + V.csn := GenerateNextCSN(P.csn) + ELSE + { + R := E.rdn + remove value V + CheckUniqueness(E, E.superior, R) + StoreValueDeletion (P.uid, P.type, P.value, P.csn) + } + ELSE + { + remove value V + StoreValueDeletion (P.uid, P.type, P.value, P.csn) + } + } + ELSE + StoreValueDeletion (P.uid, P.type, P.value, P.csn) + } + ELSE + StoreValueDeletion (P.uid, P.type, P.value, P.csn) + + The presence of a younger deletion record for the entry, attribute or + value provides a convenient test for whether the p-remove-attribute- + value primitive needs to be processed at all. If the value exists to + be removed then there cannot be a deletion record affecting it that + has a younger CSN. If there is a younger deletion record than the + primitive then there cannot be an older value to remove. + + + +Legg & Payne Expires 22 April 2000 [Page 18] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + 5.3.8 Processing Remove Attribute Primitive + + This section describes the algorithm for processing the p-remove- + attribute (P.uid, P.type, P.csn) primitive, which is responsible for + removing all attribute values of P.type. Values that are + distinguished are tagged as distinguished-not-present rather than + being immediately removed. Such values will be physically removed + when they become non-distinguished. + + IF no attribute deletion record (uid, type, csn) exists + where (uid = P.uid AND type = P.type AND csn >= P.csn) + AND no entry deletion record (uid, csn) exists where + (uid = P.uid AND csn >= P.csn) + IF entry, E, with uid = P.uid exists + { + IF P.csn > E.csn + { + FOREACH attribute value, V, of type P.type in E (if any) + IF P.csn > V.csn + IF V is distinguished + IF ProtectDistinguished() + V.csn := GenerateNextCSN(P.csn) + ELSE + { + R := E.rdn + remove value V + CheckUniqueness(E, E.superior, R) + } + ELSE + remove value V + StoreAttributeDeletion (P.uid, P.type, P.csn) + } + } + ELSE + StoreAttributeDeletion (P.uid, P.type, P.csn) + + + 5.3.9 Processing Add Entry Primitive + + This section describes the algorithm for processing the p-add-entry + (P.uid, P.superior, P.rdn, P.csn) primitive, which is responsible for + adding an entry. The CSN on an entry records the time of the latest + p-add-entry primitive for the Unique Identifier. In normal + circumstances there will only ever be one p-add-entry primitive + associated with an entry. The entry CSN may be discarded when it + becomes eligible to be purged according to the Purge Vector. + + IF no entry deletion record (uid, csn) exists where + + + +Legg & Payne Expires 22 April 2000 [Page 19] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + (uid = P.uid AND csn > P.csn) + IF entry, E, with uid = P.uid exists + { + IF P.csn > E.csn + { + E.csn := P.csn + FOREACH attribute value, V, in E + IF V.csn < P.csn + remove value V + process P according to + p-rename-entry(P.uid, P.rdn, P.csn) + process P according to + p-move-entry(P.uid, P.superior, P.csn) + } + } + ELSE + { + create entry E + E.csn := P.csn + E.uid := P.uid + E.uid.csn := P.csn + IF an entry with uid = P.superior does not exist + CreateGlueEntry(P.superior) + E.superior = P.superior + E.superior.csn := P.csn + RenameEntry(E, P) + CheckUniqueness(E, E.superior, E.rdn) + } + + + 5.3.10 Processing Remove Entry Primitive + + This section describes the algorithm for processing the p-remove- + entry (P.uid, P.csn) primitive, which is responsible for removing an + entry. If the target entry has attribute values with CSNs greater + than the primitive's CSN, a superior reference with a greater CSN, or + if it has any subordinate entries, it becomes a glue entry instead of + being removed. Unless it has a CSN for its superior reference that + is greater than the CSN of the p-remove-entry it is also moved to + Lost & Found. + + IF no entry deletion record (uid, csn) exists + where (uid = P.uid AND csn >= P.csn) + IF entry, E, with uid = P.uid exists + { + IF P.csn > E.csn + { + IF E.superior.csn >= P.csn + + + +Legg & Payne Expires 22 April 2000 [Page 20] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + OR any value, V, with csn >= P.csn exists + OR E has subordinates + { + R := E.rdn + S := E.superior + make E a glue entry + purge E.csn + IF E.superior.csn < P.csn + { + E.superior := LOST_AND_FOUND + purge E.superior.csn + } + IF E.rdn.csn < P.csn + purge E.rdn.csn + FOREACH attribute value, V, in E + IF V.csn < P.csn + remove value V + CheckUniqueness(E, S, R) + } + ELSE + remove entry E + StoreEntryDeletion (P.uid, P.csn) + } + } + ELSE + StoreEntryDeletion (P.uid, P.csn) + + + 5.3.11 Processing Move Entry Primitive + + This section describes the algorithm for processing the p-move-entry + (P.uid, P.superior, P.csn) primitive, which is responsible for + moving an entry. If the new superior specified by the primitive does + not exist or is a direct or indirect subordinate of the entry being + moved then the entry is moved to Lost & Found instead. + + IF no entry deletion record (uid, csn) exists + where (uid = P.uid AND csn > P.csn) + { + IF entry, E, with uid = P.uid does not exist + E := CreateGlueEntry(P.uid) + IF P.csn > E.superior.csn + { + R := E.rdn + O := E.superior + IF entry, S, with uid = P.superior does not exist + S := CreateGlueEntry(P.superior) + IF S is not in the subtree of E + + + +Legg & Payne Expires 22 April 2000 [Page 21] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + { + E.superior := P.superior + E.superior.csn = P.csn + } + ELSE + { + E.superior := LOST_AND_FOUND; + E.superior.csn := GenerateNextCSN(P.csn) + } + CheckUniqueness(E, O, R) + } + } + + + 5.3.12 Processing Rename Entry Primitive + + This section describes the algorithm for processing the p-rename- + entry (P.uid, P.rdn, P.csn) primitive, which changes the Relative + Distinguished Name of an entry. A p-rename-entry primitive that is + older than current name of an entry is not simply ignored since it + may contain attribute values that would have been added to the entry + had the primitives arrived in CSN order. These extra values would + now be non-distinguished. + + IF no entry deletion record (uid, csn) exists + where (uid = P.uid AND csn >= P.csn) + { + IF entry, E, with uid = P.uid does not exist + E := CreateGlueEntry(P.uid) + IF P.csn > E.rdn.csn + { + R := E.rdn + FOREACH distinguished attribute value, V, in entry E + make V non-distinguished + RenameEntry(E, P) + CheckUniqueness(E, E.superior, R) + } + ELSE + FOREACH AttributeTypeAndValue, N, in P.rdn + { + IF there exists an attribute value, V, in E of type + N.type AND V = N.value + { + IF P.csn > V.csn + { + replace V with N.value if they are not identical + V.csn := P.csn + } + + + +Legg & Payne Expires 22 April 2000 [Page 22] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + } + ELSE + { + IF no value deletion record (uid, type, value, csn) + exists where (uid = P.uid AND type = N.type AND + value = N.value AND csn > P.csn) + AND + no attribute deletion record (uid, type, csn) + exists where (uid = P.uid AND type = N.type AND + csn > P.csn) + { + V := N.value + Add V to E + V.csn := P.csn + } + } + } + } + + + 6. Security Considerations + + [To be supplied] + + + 7. Acknowledgements + + The authors would like to thank Suellen Faulks, Tony Robertson and + Mark Ennis from Telstra Research Laboratories who contributed to the + design and verification of the procedures described in this document. + + The authors would also like to thank the members of the LDUP + architecture group for their input into the refinement of the design. + + + 8. References + + [LDUP Model] - E. Reed, "LDUP Replication Architecture", Internet + Draft, draft-merrells-ldup-model-01.txt, November 1998. + + [BCP-11] - R. Hovey, S. Bradner, "The Organizations Involved in the + IETF Standards Process", BCP 11, RFC 2028, October 1996. + + + 9. Intellectual Property Notice + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + + + +Legg & Payne Expires 22 April 2000 [Page 23] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. [BCP-11] + Copies of claims of rights made available for publication and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementors or users of this + specification can be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + + + 10. Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + +Legg & Payne Expires 22 April 2000 [Page 24] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + 11. Authors' Address + + Steven Legg + Telstra Research Laboratories + 770 Blackburn Road + Clayton, Victoria 3168 + AUSTRALIA + + Phone: +61 3 9253 6771 + Fax: +61 3 9253 6485 + EMail: s.legg@trl.telstra.com.au + + Alison Payne + PricewaterhouseCoopers + St Jakobs Strasse 25 + CH-4002 Basel + SWITZERLAND + + Phone: +41-79-458 4177 + EMail: alison.b.payne@ch.pwcglobal.com + + 12. Appendix A - Changes From Previous Drafts + + 12.1 Changes in Draft 01 + + Some of the terminology has been changed to better align with the + terminology used in the LDUP architecture draft. + + Descriptions on the usage of CSNs have been revised to account for + the extra modification number component. + + The semantics of re-added entries has been simplified so that only + changes after the latest re-add are preserved instead of all those + after the earliest re-add. This eliminates the need for Addition CSNs + in the entry. It is anticipated that new replication primitives will + be introduced to manage entries that come and go from partial + replicas instead of using p-add-entry and p-remove-entry. + + Orphaned entries are no longer moved directly to Lost & Found. + Instead a glue entry is created in Lost & Found for the missing + superior and the orphaned entry becomes a subordinate of that. This + change eliminates the need for explicit propagated primitives for + moving orphaned entries to Lost & Found. + + Glue entries have also been used as the mechanism for saving + primitives. There are no longer any references to saved primitives + though the functionality is still present. + + + + +Legg & Payne Expires 22 April 2000 [Page 25] + + + + + +INTERNET-DRAFT LDUP Update Reconciliation Procedures October 22, 1999 + + + The procedures for processing received replication primitives have + been rearranged to follow a more consistent pattern where the + presence of deletion records is tested first. + + 12.2 Changes in Draft 02 + + Multimaster replication has been dropped as a work item for the next + edition of X.500 so references to the proposed X.500 multimaster + replication protocol have been removed. + + The treatment of distinguished values has been simplified. Previously + an attempt to remove a distinguished value caused the value to be + tagged distinguished-not-present. Now the distinguished value is + removed, and if necessary, the Unique Identifier is made + distinguished to avoid an empty RDN. Optionally, the value to be + removed can be reasserted by emitting an explicit p-add-attribute- + value primitive. + + The current draft is more implementation neutral. A replication log + no longer figures prominently in the specification. The previous + descriptions had the user updates generating replication primitives, + which in turn were used to determine the CSNs and deletion records. + The new descriptions have user updates generating CSNs and deletion + records and the primitives are subsequently generated from them. + + 13. Appendix B - Open Issues + + The precise location of the Lost & Found entry has not yet been + decided. + + Extensions to the algorithms to properly deal with partial replicas + are still to be decided. + + The draft needs some editing to use MAY, MUST, etc, in the proper + way. + + + + + + + + + + + + + + + + +Legg & Payne Expires 22 April 2000 [Page 26] + + diff --git a/doc/drafts/draft-lachman-laser-ldap-mail-routing-xx.txt b/doc/drafts/draft-lachman-laser-ldap-mail-routing-xx.txt new file mode 100644 index 0000000000..6fc6594ea8 --- /dev/null +++ b/doc/drafts/draft-lachman-laser-ldap-mail-routing-xx.txt @@ -0,0 +1,615 @@ +INTERNET-DRAFT H. Lachman +Intended Category: Standards Track Netscape Communications Corp. +Filename: draft-lachman-laser-ldap-mail-routing-01.txt G. Shapiro + Sendmail, Inc. +Expires: April 2000 October 1999 + + LDAP Schema for Intranet Mail Routing + +Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + This draft is being discussed on the Laser mailing list at + . Subscription requests can be sent to + (send an email message with the + word "subscribe" in the body). More information on the mailing list + along with an archive of back messages is available at + . + + [[Section X will be removed before the document is submitted to the + IESG.]] + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + This document defines an LDAP [1] object class called + 'inetLocalMailRecipient' and associated attributes that provide a way + to designate an LDAP entry as one that represents a local (intra- + organizational) email recipient, to specify the recipient's email + address(es), and to provide routing information pertinent to the + recipient. This is intended to support SMTP [2] message transfer + agents in routing RFC 822-based email [3] within a private enterprise + only, and is not to be used in the process of routing email across + the public Internet. + +Lachman, et. al. [Page 1] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + +1. Conventions Used in this Document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" and "OPTIONAL" in this + document are to be interpreted as described in [10]. + +2. Background and Motivation + + LDAP-based directory services are currently being used in many + organizations as a repository of information about users and other + network entities (such as groups of users, network resources, etc.). + In cases where LDAP entries are used to represent entities that are + email recipients (e.g., a mail user or a mailing list), the LDAP + entries provide a convenient place to store per-recipient data, such + as a recipient's email address. + + In many organizations, an email recipient may have an email address + (e.g., "joe@example.com") that does not specify the host that + receives mail for that recipient (e.g., "host42.example.com"). A + message transfer agent (MTA) responsible for routing mail within the + organization needs some way to determine the appropriate target host + for such a recipient. A common solution is the sendmail "aliases" + database which may contain a record that provides the necessary per- + recipient routing information (e.g., "joe: joe@host42"). A drawback + of this solution is that if the organization hosts more than one DNS + domain (e.g., "example.com" and "example.org", with "joe" in each + domain being different recipients), a more explicit mapping is + desirable. The schema defined in this document provides a way to + represent such mappings in LDAP and X.500 [4] directory services. + + An LDAP entry that represents an email recipient could conceivably + contain a variety of attributes related to email, such as disk quota + and delivery preferences. We consider here only attributes that + specify address information and routing information; these attributes + may be useful to multiple MTAs within the organization since one or + more MTAs may be responsible for intra-organizational routing. The + various MTAs in an organization may have been developed by different + implementors, so a common schema is desirable for such attributes. + +3. Overview + + The 'inetLocalMailRecipient' object class and associated attributes + identify an LDAP entry as representing an SMTP mail recipient (in the + sense "recipient" is used in [2]). A recipient may be a mail user, a + mailing list, an auto-responder of some kind (e.g., a mailing list + subscription program), a network device such as a printer or fax + machine, or other recipient type. Address attributes and routing + attributes are provided to aid SMTP MTAs in routing mail within an + organization to the appropriate target MTA for each recipient. + +Lachman, et. al. [Page 2] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + Once on the target MTA, a message is handled as per the recipient + type and options (which may be specified using other auxiliary object + classes and is outside the scope of this document). For example, the + message may be delivered to a user mailbox, or to a program or + network device, and/or forwarded to another recipient. Or, the + target MTA may be a gateway to a non-SMTP mail routing and delivery + system including non-SMTP MTAs. Note that, in this discussion, + "target MTA" refers to the final SMTP destination of messages for the + recipient in question, as we are considering routing of mail only + among the SMTP MTAs within an organization. + + The target MTA checks to see if the destination domain of the + recipient address is one that it is responsible for LDAP-based + routing. If so, checks for matching e-mail addresses in LDAP by + looking up the envelope recipient address in LDAP using the object + class described in section 4.1 and the attribute discussed in section + 4.2. If it gets back an unambiguous match, it interprets the routing + attributes as described in section 4.3. + + Routing of mail between different organizations across the public + Internet is outside the scope of this document, as the mechanism for + this is already standardized [5,6]. An 'inetLocalMailRecipient' + entry represents a mail recipient that is local to the organization + in question, not recipients in other organizations. This means that + the domain names that appear within the 'mailLocalAddress' and + 'mailHost' attribute values in an 'inetLocalMailRecipient' entry must + be DNS domain names that are within the administrative authority of + the organization in question (i.e., the organization within which + MTAs are accessing such entries and using these attributes for mail + routing). + + LDAP entries that are not 'inetLocalMailRecipient' entries should be + ignored by MTAs for the purpose of routing. An example is a + conference room whose LDAP entry contains contact information (e.g., + email address and telephone number) for the person who books + reservations for the room; the conference room is not a mail + recipient, and can safely be ignored by MTAs doing route + determination based on recipient address. + +4. Object Class and Attribute Definitions + + The 'inetLocalMailRecipient' object class and associated attributes + are defined (using syntaxes given in [7]) as follows. + +Lachman, et. al. [Page 3] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + 4.1 The inetLocalMailRecipient Object Class + + ( 2.16.840.1.113730.3.2.[[TBD]] + NAME 'inetLocalMailRecipient' + SUP top + AUXILIARY + MAY ( mailLocalAddress $ + mailHost $ mailRoutingAddress + ) + ) + + The 'inetLocalMailRecipient' object class signifies that the entry + represents an entity within the organization that can receive SMTP + mail, such as a mail user or a mailing list. In any case of an entry + containing the 'inetLocalMailRecipient' object class, attributes + defined in this document MUST be interpreted as specified in this + document. + + 4.2 Address Attribute + + ( 2.16.840.1.113730.3.1.13 + NAME 'mailLocalAddress' + DESC 'RFC 822 email address of this recipient' + EQUALITY caseIgnoreIA5Match + SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}' + ) + + The 'mailLocalAddress' attribute is used to specify email addresses, + for the recipient; for example, "nickname@example.com". The address + conforms to the syntax of an 'addr-spec' as defined in [3]. + + The 'mailLocalAddress' attribute MUST contain all addresses that + represent each recipient of the target MTA. Commonly, the value of + the 'mail' attribute should also be among the addresses listed in + the 'mailLocalAddress' attribute if it is expected to be used for + LDAP mail routing. + + When determining the disposition of a given message, MTAs using LDAP + (directly or indirectly) to route mail MUST search for an entry + with object class 'inetLocalMailRecipient' and a 'mailLocalAddress' + attribute matching the message's recipient address. If exactly one + matching entry is found, MTAs MUST regard the message as being + addressed to the entity that is represented by the directory entry. + + If multiple entries are found, but all share an identical match for + both mailRoutingAddress and mailHost (e.g., their presence or absence + is the same as well as their values if present), the MTA MAY treat + this as a single match. Duplicate entries that return different + routing attributes or contradict each other are errors, however, and + should be handled by the MTA in some locally-appropriate way, such as + returning a DSN [11] to the sender. + +Lachman, et. al. [Page 4] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + If there is no match found by the above, MTAs SHOULD have the + capability of searching for the recipient domain against the + 'mailLocalAddress' attribute using the "wildcard domain" address + "@" , e.g., "@example.org". In other words, if + mail arrives for "someone@example.org", and there is no recipient + with that address specified as 'mailLocalAddress', then the recipient + with the wildcard domain address should receive the mail. + + MTAs MAY do other searches but only after the above are done. + + In short, the address attribute 'mailLocalAddress' may be used by an + LDAP entry to answer the question "what is/are this account's email + address(es)?" + + 4.3 Routing Attributes + + ( 2.16.840.1.113730.3.1.18 + NAME 'mailHost' + DESC 'fully-qualified hostname of the MTA that is the final + SMTP destination of messages to this recipient' + EQUALITY caseIgnoreIA5Match + SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}' + SINGLE-VALUE + ) + + The 'mailHost' attribute indicates which SMTP MTA considers the + recipient's mail to be locally handleable. This information can be + used for routing, in that an intermediary MTA may take it to be the + destination for messages addressed to this recipient. Normal mail + routing requirements (i.e., use of MX records) apply to the specified + hostname unless overridden by local conventions. In other words, the + mail should be sent to the specified host without changing the + recipient address. The hostname is specified as a fully-qualified + DNS hostname with no trailing dot (e.g., "host42.example.com"). + + If the 'inetLocalMailRecipient' object class is present, the + 'mailHost' attribute for each entry MAY contain a value. If it does, + that value MUST be the fully qualified name of the server containing + the host MTA for this person. If 'mailHost' is present then it MUST + be taken as the host for this user, and all mail to this user MUST be + routed to this machine. + + ( 2.16.840.1.113730.3.1.47 + NAME 'mailRoutingAddress' + DESC 'RFC 822 address to use when routing messages to + the SMTP MTA of this recipient' + EQUALITY caseIgnoreIA5Match + SYNTAX '1.3.6.1.4.1.1466.115.121.1.26{256}' + SINGLE-VALUE + ) + +Lachman, et. al. [Page 5] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + The 'mailRoutingAddress' attribute indicates a routing address for + the recipient. The address MUST conform to the syntax of an + 'addr-spec' in [3]. An intermediary MTA MUST use this information to + route the message to the MTA that handles mail for this recipient, + e.g., the envelope address MUST be rewritten to this value. This is + useful in cases where, for a given recipient, the target MTA prefers + a particular address to appear as the recipient address in the SMTP + envelope. 'mailRoutingAddress' MAY be used as an alternative to + 'mailHost', and is intended to have the same effect as 'mailHost' + except that 'mailRoutingAddress' is an address for rewriting the + envelope. With 'mailHost', the envelope address either is not + rewritten, or is rewritten according to implementation-specific rules + and/or configuration. + + If both 'mailHost' and 'mailRoutingAddress' are present, MTAs MAY + interpret it to mean that messages are to be routed to the host + indicated by 'mailHost', while rewriting the envelope as per + 'mailRoutingAddress'. In theory, there could be peculiar cases where + this is necessary, but this is not normally expected. + + Absence of both 'mailHost' and 'mailRoutingAddress' MAY be considered an + error, unless "location-independent" recipient types are supported by + the various MTAs within the organization. This would allow any MTA in + the organization to handle the processing of mail for, say, a mailing + list. This presumes that the various MTAs all recognize the recipient + type in question, suggesting a need to standardize recipient types that + could be "location-independent". + + In short, routing attributes may be used by an LDAP entry to answer + the question "how should MTAs route mail to this account?" + (analogous to using the sendmail "aliases" database for per-user + routing within an organization). This is in contrast with + "forwarding"; forwarding and delivery options may be specified in an + LDAP entry to answer the question "what happens to mail once it + arrives at this account?", which may include forwarding to some other + account within or outside the organization (analogous to using the + sendmail ".forward" file). Such options are outside the scope of the + 'inetLocalMailRecipient' schema definition. + + The following possibilities exist as a result of an LDAP lookup on an + address: + + mailHost is mailRoutingAddress is Results in + ----------- --------------------- ---------- + set to a set mail routed to + "local" host mailRoutingAddress + + set to a not set delivered to + "local" host original address + +Lachman, et. al. [Page 6] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + set to a set MAY relay to mailHost + remote host using mailRoutingAddress + + set to a not set original address + remote host relayed to mailHost + + not set set mail routed to + mailRoutingAddress + + not set not set error or + "location-independent" + + The term "local" host above means the host specified is one that the + local (target) MTA considers to be a local delivery. The local MTA + MAY rewrite the original address when mailRoutingAddress is not set + if local conventions warrant the change. + +5. Examples + + The following examples illustrate possible uses of the + 'inetLocalMailRecipient' object class. + + Here is an example of an LDAP entry representing a mail user: + + dn: uid=joe,o=Example Corp,c=US + objectClass: top + objectClass: person + objectClass: organizationalPerson + objectClass: inetOrgPerson + objectClass: inetLocalMailRecipient + objectClass: nsMessagingServerUser + cn: Joe User + sn: User + uid: joe + userPassword: {crypt}y2KxtbzMYnApU + mail: joe@example.com + mailLocalAddress: joe@example.com + mailLocalAddress: joe@another.example.com + mailHost: nsmail1.example.com + mailDeliveryOption: mailbox + mailQuota: 1000000 + mailForwardingAddress: mary@example.com + + Joe User is a user of a hypothetical mail system called NS Messaging. + Let's say mail arrives on an MTA called "mx.example.com", addressed + to "joe@example.com". That MTA searches the directory for a mail + recipient with that address, using an LDAP search filter [8] such as: + + (&(objectClass=inetLocalMailRecipient) + (mailLocalAddress=joe@example.com)) + +Lachman, et. al. [Page 7] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + It finds Joe's LDAP entry, and routes the message to the target MTA + "nsmail1.example.com", while not rewriting the SMTP envelope + recipient address. Then, "nsmail1.example.com" receives the message, + searches for and finds the recipient in the directory, ascertains + that it is the recipient's target MTA, and handles the message as per + other attributes in the recipient's entry and/or the MTA + configuration (in this case, the message is delivered to a mailbox, + and forwarded to another recipient). + + Note that this document does not specify the rules an MTA is to use + to ascertain whether or not it is the target MTA for a given + recipient (it could check the recipient's 'mailHost' value against + its own hostname, or check the recipient's 'mailRoutingAddress', or + check the MTA configuration, or some combination of these). + + Here is another example of an LDAP entry representing a mail user: + + dn: uid=john,o=Example Corp,c=US + objectClass: top + objectClass: person + objectClass: organizationalPerson + objectClass: inetOrgPerson + objectClass: inetLocalMailRecipient + objectClass: xyzMailUser + cn: John Doe + sn: Doe + uid: john + userPassword: {crypt}y2KxtbzMYnApU + mail: john@example.com + mailLocalAddress: john@example.com + mailRoutingAddress: John_Doe@xyz-gw.example.com + xyzPostOfficeName: PO_1 + xyzClusterNumber: 3 + xyzMessageStoreId: 9 + + John Doe is a user of a hypothetical mail system called XYZ Mail. + Let's say mail arrives on an MTA called "mx.example.com", addressed + to "john@example.com". That MTA searches the directory for a mail + recipient with that address, and routes the message to "xyz- + gw.example.com", rewriting the SMTP envelope recipient address to + "John_Doe@xyz-gw.example.com", as per the 'mailRoutingAddress'. On + "xyz-gw.example.com", the message is gatewayed into the XYZ Mail + system and then dealt with as per other attributes. + +Lachman, et. al. [Page 8] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + + Here is an example of an LDAP entry representing a mailing list: + + dn: cn=Scuba Group,o=Example Corp,c=US + objectClass: top + objectClass: groupOfUniqueNames + objectClass: inetLocalMailRecipient + objectClass: mailGroup + cn: Scuba Group + mail: scuba@example.com + mailLocalAddress: scuba@example.com + mailHost: host42.example.com + mgrpRFC822MailMember: joe@example.com + mgrpRFC822MailMember: john@example.com + + The Scuba Group is a mail group (mailing list) that includes two + members. A message addressed to "scuba@example.com" is routed to + "host42.example.com" where it is then resent to the mailing list + members. The 'mailGroup' object class is specified elsewhere [9]. + + Here is an example of an LDAP entry representing a forwarding alias: + + dn: cn=Jane Roe Forwarding Alias,o=Example,c=US + objectClass: top + objectClass: inetLocalMailRecipient + objectClass: mailForwardingAlias + mail: janeroe@example.org + mailLocalAddress: janeroe@example.org + mailHost: mail.example.org + mailForwardingAddress: janeroe@elsewhere.example.com + cn: Jane Roe Forwarding Alias + + This entry uses a hypothetical object class 'mailForwardingAlias' + that is not specified here, but is used as an example of how an LDAP + entry might represent such a recipient type. A message addressed to + "janeroe@example.org" is routed to "mail.example.org" where it is + then forwarded. In this case, Jane Roe may be a former member of the + Example Organization, and they are forwarding her mail to her new + address elsewhere. + +6. Security Considerations + + As in all cases where account information is stored in an LDAP-based + directory service, network administrators must be careful to ensure + that their directory service controls users' access to the entries + and attributes stored therein, according to site policy. In + particular, mail routing information should not be accessible from + outside the organization, since it is intended for use only by MTAs + within the organization. + +Lachman, et. al. [Page 9] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + +7. Acknowledgments + + The 'inetLocalMailRecipient' object class is based on an earlier + design done by the Netscape Messaging and Directory Server teams, + which was implemented and deployed to customers as part of Netscape + Messaging Server. Various team members contributed to the design, + including Bill Fitler, Bruce Steinback, Prabhat Keni, Mike Macgirvin, + John Myers, John Kristian, Tim Howes, Mark Smith, and Leif Hedstrom. + Thanks also to Jeff Hodges of Stanford for contributing to the early + design discussions, and to the other participants in the IETF LASER + BOF, including, from Sun Microsystems, John Beck, Anil Srivastava, + and Darryl Huff. + +8. References + + [1] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access + Protocol (v3)", RFC 2251, December 1997. + + [2] J. Postel, "Simple Mail Transfer Protocol", STD 10, RFC 821, + August 1982. + + [3] D. Crocker, "Standard for the Format of ARPA Internet Text + Messages", STD 11, RFC 822, August 1982. + + [4] "Information Processing Systems - Open Systems Interconnection - + The Directory: Overview of Concepts, Models and Service", ISO/IEC JTC + 1/SC21, International Standard 9594-1, 1988. + + [5] C. Partridge, "Mail routing and the domain system", STD 14, RFC + 974, January 1986. + + [6] R. Braden, "Requirements for Internet hosts - application and + support", STD 3, RFC 1123, October 1989. + + [7] M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight X.500 + Directory Access Protocol (v3): Attribute Syntax Definitions", RFC + 2252, December 1997. + + [8] T. Howes, "The String Representation of LDAP Search Filters", + RFC 2254, December 1997. + + [9] B. Steinback, "Using LDAP for SMTP Mailing Lists and Aliases", + Internet-Draft (work in progress). + + [10] S. Bradner, "Key words for use in RFCs to Indicate Requirement + Levels", BCP 14, RFC 2119, March 1997. + + [11] K. Moore, "SMTP Service Extension for Delivery Status + Notifications", RCP 1891, January 1996. + +Lachman, et. al. [Page 10] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + +9. Authors' Addresses + + Hans Lachman + Netscape Communications Corp. + 501 East Middlefield Road + Mountain View, CA 94043 + Phone: (650) 254-1900 + EMail: lachman@netscape.com + + Gregory Neil Shapiro + Sendmail, Inc. + 6603 Shellmound Street + Emeryville, CA 94608-1042 + Phone: +1 510-594-5522 + Fax: +1 510-594-5411 + EMail: gshapiro@sendmail.org + +X. Change Summary + +X.1.1 Substantive changes between + draft-lachman-laser-ldap-mail-routing-00.txt and + draft-lachman-laser-ldap-mail-routing-01.txt + + (i) Added Gregory Neil Shapiro as another author. + (ii) Changed Draft heaer. + (iii) Added "Conventions Used in this Document" section. + (iv) Replaced RFC mentions with reference numbers. + (v) Add new MUST/SHOULD/MAY sections to bring more in line with + RFC documents. + (vi) Clarify job of MTA in Overview by adding third paragraph. + (vii) mailRoutingAddress can be outside of administrative control. + (viii) Eliminated use of 'mail' attribute for mail routing. + (ix) Changed name of 'mailAlternateAddress' to 'mailLocalAddress'. + (x) Remove "routable" from 'mailLocalAddress' description. + (xi) Clarify which addresses MUST be in 'mailLocalAddress'. + (xii) Allow for multiple responses if they all have the same + routing attribute values. + (xiii) Clarify use of MX records on routing attributes. + (xiv) Add a table to clarify use of 'mailHost' and + 'mailRoutingAddress'. + (xv) Remove document weakening statements from section 5. + (xvi) Only use reserved domains (example.com, example.org) in + examples. + (xvii) Clean up references + (xviii) Added section X to list the changes between draft versions. + +Lachman, et. al. [Page 11] + +INTERNET-DRAFT LDAP Schema for Intranet Mail Routing October 1999 + +10. Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished + to others, and derivative works that comment on or otherwise + explain it or assist in its implementation may be prepared, copied, + published and distributed, in whole or in part, without + restriction of any kind, provided that the above copyright notice + and this paragraph are included on all such copies and derivative + works. However, this document itself may not be modified in any + way, such as by removing the copyright notice or references to the + Internet Society or other Internet organizations, except as needed + for the purpose of developing Internet standards in which case the + procedures for copyrights defined in the Internet Standards + process must be followed, or as required to translate it into + languages other than English. + + The limited permissions granted above are perpetual and will not + be revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on + an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Lachman, et. al. [Page 12] diff --git a/doc/drafts/draft-leach-uuids-guids-01.txt b/doc/drafts/draft-leach-uuids-guids-01.txt new file mode 100644 index 0000000000..d611d06fb0 --- /dev/null +++ b/doc/drafts/draft-leach-uuids-guids-01.txt @@ -0,0 +1,1708 @@ + + + + + + +Network Working Group Paul J. Leach, Microsoft +INTERNET-DRAFT Rich Salz, Certco + +Category: Standards Track +Expires August 4, 1998 February 4, 1998 + + + + UUIDs and GUIDs + +STATUS OF THIS MEMO + + This document is an Internet-Draft. Internet-Drafts are working + documents of the Internet Engineering Task Force (IETF), its areas, + and its working groups. Note that other groups may also distribute + working documents as Internet-Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress". + + To learn the current status of any Internet-Draft, please check the + "1id-abstracts.txt" listing contained in the Internet-Drafts Shadow + Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe), + munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or + ftp.isi.edu (US West Coast). + + Distribution of this document is unlimited. Please send comments to + the authors or the CIFS mailing list at . + Discussions of the mailing list are archived at + "-" "-" + "-" + + "-" + time_low = 4* + time_mid = 2* + time_high_and_version = 2* + clock_seq_and_reserved = + clock_seq_low = + node = 6* + hexDigit = + "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + | "a" | "b" | "c" | "d" | "e" | "f" + | "A" | "B" | "C" | "D" | "E" | "F" + + The following is an example of the string representation of a UUID: + + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + +3.6 Comparing UUIDs for equality + + Consider each field of the UUID to be an unsigned integer as shown in + the table in section 3.1. Then, to compare a pair of UUIDs, + arithmetically compare the corresponding fields from each UUID in + order of significance and according to their data type. Two UUIDs are + equal if and only if all the corresponding fields are equal. + + + Leach, Salz expires Aug 1998 [Page 12] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + Note: as a practical matter, on many systems comparison of two UUIDs + for equality can be performed simply by comparing the 128 bits of + their in-memory representation considered as a 128 bit unsigned + integer. Here, it is presumed that by the time the in-memory + representation is obtained the appropriate byte-order + canonicalizations have been carried out. + + +3.7 Comparing UUIDs for relative order + + Two UUIDs allocated according to the same variant can also be ordered + lexicographically. For the UUID variant herein defined, the first of + two UUIDs follows the second if the most significant field in which + the UUIDs differ is greater for the first UUID. The first of a pair + of UUIDs precedes the second if the most significant field in which + the UUIDs differ is greater for the second UUID. + + +3.8 Byte order of UUIDs + + UUIDs may be transmitted in many different forms, some of which may + be dependent on the presentation or application protocol where the + UUID may be used. In such cases, the order, sizes and byte orders of + the UUIDs fields on the wire will depend on the relevant presentation + or application protocol. However, it is strongly RECOMMENDED that + the order of the fields conform with ordering set out in section 3.1 + above. Furthermore, the payload size of each field in the application + or presentation protocol MUST be large enough that no information + lost in the process of encoding them for transmission. + + In the absence of explicit application or presentation protocol + specification to the contrary, a UUID is encoded as a 128-bit object, + as follows: the fields are encoded as 16 octets, with the sizes and + order of the fields defined in section 3.1, and with each field + encoded with the Most Significant Byte first (also known as network + byte order). + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_low | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_mid | time_hi_and_version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |clk_seq_hi_res | clk_seq_low | node (0-1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | node (2-5) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + + + + + + Leach, Salz expires Aug 1998 [Page 13] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + +4. Node IDs when no IEEE 802 network card is available + + If a system wants to generate UUIDs but has no IEE 802 compliant + network card or other source of IEEE 802 addresses, then this section + describes how to generate one. + + The ideal solution is to obtain a 47 bit cryptographic quality random + number, and use it as the low 47 bits of the node ID, with the most + significant bit of the first octet of the node ID set to 1. This bit + is the unicast/multicast bit, which will never be set in IEEE 802 + addresses obtained from network cards; hence, there can never be a + conflict between UUIDs generated by machines with and without network + cards. + + If a system does not have a primitive to generate cryptographic + quality random numbers, then in most systems there are usually a + fairly large number of sources of randomness available from which one + can be generated. Such sources are system specific, but often + include: + + - the percent of memory in use + - the size of main memory in bytes + - the amount of free main memory in bytes + - the size of the paging or swap file in bytes + - free bytes of paging or swap file + - the total size of user virtual address space in bytes + - the total available user address space bytes + - the size of boot disk drive in bytes + - the free disk space on boot drive in bytes + - the current time + - the amount of time since the system booted + - the individual sizes of files in various system directories + - the creation, last read, and modification times of files in various + system directories + - the utilization factors of various system resources (heap, etc.) + - current mouse cursor position + - current caret position + - current number of running processes, threads + - handles or IDs of the desktop window and the active window + - the value of stack pointer of the caller + - the process and thread ID of caller + - various processor architecture specific performance counters + (instructions executed, cache misses, TLB misses) + + (Note that it precisely the above kinds of sources of randomness that + are used to seed cryptographic quality random number generators on + systems without special hardware for their construction.) + + In addition, items such as the computer's name and the name of the + operating system, while not strictly speaking random, will help + differentiate the results from those obtained by other systems. + + The exact algorithm to generate a node ID using these data is system + specific, because both the data available and the functions to obtain + + Leach, Salz expires Aug 1998 [Page 14] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + them are often very system specific. However, assuming that one can + concatenate all the values from the randomness sources into a buffer, + and that a cryptographic hash function such as MD5 [3] is available, + then any 6 bytes of the MD5 hash of the buffer, with the multicast + bit (the high bit of the first byte) set will be an appropriately + random node ID. + + Other hash functions, such as SHA-1 [4], can also be used. The only + requirement is that the result be suitably random _ in the sense that + the outputs from a set uniformly distributed inputs are themselves + uniformly distributed, and that a single bit change in the input can + be expected to cause half of the output bits to change. + + +5. Obtaining IEEE 802 addresses + + At the time of writing, the following URL + + http://standards.ieee.org/db/oui/forms/ + + contains information on how to obtain an IEEE 802 address block. At + the time of writing, the cost is $1250 US. + + +6. Security Considerations + + It should not be assumed that UUIDs are hard to guess; they should + not be used as capabilities. + + +7. Acknowledgements + + This document draws heavily on the OSF DCE specification for UUIDs. + Ted Ts'o provided helpful comments, especially on the byte ordering + section which we mostly plagiarized from a proposed wording he + supplied (all errors in that section are our responsibility, + however). + + +8. References + + [1] Lisa Zahn, et. al., Network Computing Architecture, Prentice + Hall, Englewood Cliffs, NJ, 1990 + + [2] DCE: Remote Procedure Call, Open Group CAE Specification C309 + ISBN 1-85912-041-5 28cm. 674p. pbk. 1,655g. 8/94 + + [3] R. Rivest, RFC 1321, "The MD5 Message-Digest Algorithm", + 04/16/1992. + + [4] NIST FIPS PUB 180-1, "Secure Hash Standard," National Institute + of Standards and Technology, U.S. Department of Commerce, DRAFT, May + 31, 1994. + + + Leach, Salz expires Aug 1998 [Page 15] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + +9. Authors' addresses + + Paul J. Leach + Microsoft + 1 Microsoft Way + Redmond, WA, 98052, U.S.A. + paulle@microsoft.com + Tel. 425 882 8080 + Fax. 425 936 7329 + + Rich Salz + 100 Cambridge Park Drive + Cambridge MA 02140 + salzr@certco.com + Tel. 617 499 4075 + Fax. 617 576 0019 + + +10. Notice + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. Copies of + claims of rights made available for publication and any assurances of + licenses to be made available, or the result of an attempt made to + obtain a general license or permission for the use of such + proprietary rights by implementors or users of this specification can + be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + + +11. Full Copyright Statement + + Copyright (C) The Internet Society 1997. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + + Leach, Salz expires Aug 1998 [Page 16] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + Appendix A _ UUID Sample Implementation + + This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h, + sysdep.c and utest.c. The uuid.* files are the system independent + implementation of the UUID generation algorithms described above, + with all the optimizations described above except efficient state + sharing across processes included. The code has been tested on Linux + (Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. The + code assumes 64 bit integer support, which makes it a lot clearer. + + All the following source files should be considered to have the + following copyright notice included: + + copyrt.h + + /* + ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. + ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & + ** Digital Equipment Corporation, Maynard, Mass. + ** Copyright (c) 1998 Microsoft. + ** To anyone who acknowledges that this file is provided "AS IS" + ** without any express or implied warranty: permission to use, copy, + ** modify, and distribute this file for any purpose is hereby + ** granted without fee, provided that the above copyright notices and + ** this notice appears in all source code copies, and that none of + ** the names of Open Software Foundation, Inc., Hewlett-Packard + ** Company, or Digital Equipment Corporation be used in advertising + ** or publicity pertaining to distribution of the software without + ** specific, written prior permission. Neither Open Software + ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital + Equipment + ** Corporation makes any representations about the suitability of + ** this software for any purpose. + */ + + + uuid.h + + + Leach, Salz expires Aug 1998 [Page 17] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + #include "copyrt.h" + #undef uuid_t + typedef struct _uuid_t { + unsigned32 time_low; + unsigned16 time_mid; + unsigned16 time_hi_and_version; + unsigned8 clock_seq_hi_and_reserved; + unsigned8 clock_seq_low; + byte node[6]; + } uuid_t; + + /* uuid_create -- generate a UUID */ + int uuid_create(uuid_t * uuid); + + /* uuid_create_from_name -- create a UUID using a "name" + from a "name space" */ + void uuid_create_from_name( + uuid_t * uuid, /* resulting UUID */ + uuid_t nsid, /* UUID to serve as context, so identical + names from different name spaces generate + different UUIDs */ + void * name, /* the name from which to generate a UUID */ + int namelen /* the length of the name */ + ); + + /* uuid_compare -- Compare two UUID's "lexically" and return + -1 u1 is lexically before u2 + 0 u1 is equal to u2 + 1 u1 is lexically after u2 + Note: lexical ordering is not temporal ordering! + */ + int uuid_compare(uuid_t *u1, uuid_t *u2); + + uuid.c + + #include "copyrt.h" + #include + #include + #include + #include + #include "sysdep.h" + #include "uuid.h" + + /* various forward declarations */ + static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, + uuid_node_t * node); + static void write_state(unsigned16 clockseq, uuid_time_t timestamp, + uuid_node_t node); + static void format_uuid_v1(uuid_t * uuid, unsigned16 clockseq, + uuid_time_t timestamp, uuid_node_t node); + static void format_uuid_v3(uuid_t * uuid, unsigned char hash[16]); + static void get_current_time(uuid_time_t * timestamp); + static unsigned16 true_random(void); + + + Leach, Salz expires Aug 1998 [Page 18] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + /* uuid_create -- generator a UUID */ + int uuid_create(uuid_t * uuid) { + uuid_time_t timestamp, last_time; + unsigned16 clockseq; + uuid_node_t node; + uuid_node_t last_node; + int f; + + /* acquire system wide lock so we're alone */ + LOCK; + + /* get current time */ + get_current_time(×tamp); + + /* get node ID */ + get_ieee_node_identifier(&node); + + /* get saved state from NV storage */ + f = read_state(&clockseq, &last_time, &last_node); + + /* if no NV state, or if clock went backwards, or node ID changed + (e.g., net card swap) change clockseq */ + if (!f || memcmp(&node, &last_node, sizeof(uuid_node_t))) + clockseq = true_random(); + else if (timestamp < last_time) + clockseq++; + + /* stuff fields into the UUID */ + format_uuid_v1(uuid, clockseq, timestamp, node); + + /* save the state for next time */ + write_state(clockseq, timestamp, node); + + UNLOCK; + return(1); + }; + + /* format_uuid_v1 -- make a UUID from the timestamp, clockseq, + and node ID */ + void format_uuid_v1(uuid_t * uuid, unsigned16 clock_seq, uuid_time_t + timestamp, uuid_node_t node) { + /* Construct a version 1 uuid with the information we've gathered + * plus a few constants. */ + uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF); + uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF); + uuid->time_hi_and_version = (unsigned short)((timestamp >> 48) & + 0x0FFF); + uuid->time_hi_and_version |= (1 << 12); + uuid->clock_seq_low = clock_seq & 0xFF; + uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; + uuid->clock_seq_hi_and_reserved |= 0x80; + memcpy(&uuid->node, &node, sizeof uuid->node); + }; + + + Leach, Salz expires Aug 1998 [Page 19] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + /* data type for UUID generator persistent state */ + typedef struct { + uuid_time_t ts; /* saved timestamp */ + uuid_node_t node; /* saved node ID */ + unsigned16 cs; /* saved clock sequence */ + } uuid_state; + + static uuid_state st; + + /* read_state -- read UUID generator state from non-volatile store */ + int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, + uuid_node_t *node) { + FILE * fd; + static int inited = 0; + + /* only need to read state once per boot */ + if (!inited) { + fd = fopen("state", "rb"); + if (!fd) + return (0); + fread(&st, sizeof(uuid_state), 1, fd); + fclose(fd); + inited = 1; + }; + *clockseq = st.cs; + *timestamp = st.ts; + *node = st.node; + return(1); + }; + + /* write_state -- save UUID generator state back to non-volatile + storage */ + void write_state(unsigned16 clockseq, uuid_time_t timestamp, + uuid_node_t node) { + FILE * fd; + static int inited = 0; + static uuid_time_t next_save; + + if (!inited) { + next_save = timestamp; + inited = 1; + }; + /* always save state to volatile shared state */ + st.cs = clockseq; + st.ts = timestamp; + st.node = node; + if (timestamp >= next_save) { + fd = fopen("state", "wb"); + fwrite(&st, sizeof(uuid_state), 1, fd); + fclose(fd); + /* schedule next save for 10 seconds from now */ + next_save = timestamp + (10 * 10 * 1000 * 1000); + }; + }; + + Leach, Salz expires Aug 1998 [Page 20] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + + /* get-current_time -- get time as 60 bit 100ns ticks since whenever. + Compensate for the fact that real clock resolution is + less than 100ns. */ + void get_current_time(uuid_time_t * timestamp) { + uuid_time_t time_now; + static uuid_time_t time_last; + static unsigned16 uuids_this_tick; + static int inited = 0; + + if (!inited) { + get_system_time(&time_now); + uuids_this_tick = UUIDS_PER_TICK; + inited = 1; + }; + + while (1) { + get_system_time(&time_now); + + /* if clock reading changed since last UUID generated... */ + if (time_last != time_now) { + /* reset count of uuids gen'd with this clock reading */ + uuids_this_tick = 0; + break; + }; + if (uuids_this_tick < UUIDS_PER_TICK) { + uuids_this_tick++; + break; + }; + /* going too fast for our clock; spin */ + }; + /* add the count of uuids to low order bits of the clock reading */ + *timestamp = time_now + uuids_this_tick; + }; + + /* true_random -- generate a crypto-quality random number. + This sample doesn't do that. */ + static unsigned16 + true_random(void) + { + static int inited = 0; + uuid_time_t time_now; + + if (!inited) { + get_system_time(&time_now); + time_now = time_now/UUIDS_PER_TICK; + srand((unsigned int)(((time_now >> 32) ^ time_now)&0xffffffff)); + inited = 1; + }; + + return (rand()); + } + + + + Leach, Salz expires Aug 1998 [Page 21] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + /* uuid_create_from_name -- create a UUID using a "name" from a "name + space" */ + void uuid_create_from_name( + uuid_t * uuid, /* resulting UUID */ + uuid_t nsid, /* UUID to serve as context, so identical + names from different name spaces generate + different UUIDs */ + void * name, /* the name from which to generate a UUID */ + int namelen /* the length of the name */ + ) { + MD5_CTX c; + unsigned char hash[16]; + uuid_t net_nsid; /* context UUID in network byte order */ + + /* put name space ID in network byte order so it hashes the same + no matter what endian machine we're on */ + net_nsid = nsid; + htonl(net_nsid.time_low); + htons(net_nsid.time_mid); + htons(net_nsid.time_hi_and_version); + + MD5Init(&c); + MD5Update(&c, &net_nsid, sizeof(uuid_t)); + MD5Update(&c, name, namelen); + MD5Final(hash, &c); + + /* the hash is in network byte order at this point */ + format_uuid_v3(uuid, hash); + }; + + /* format_uuid_v3 -- make a UUID from a (pseudo)random 128 bit number + */ + void format_uuid_v3(uuid_t * uuid, unsigned char hash[16]) { + /* Construct a version 3 uuid with the (pseudo-)random number + * plus a few constants. */ + + memcpy(uuid, hash, sizeof(uuid_t)); + + /* convert UUID to local byte order */ + ntohl(uuid->time_low); + ntohs(uuid->time_mid); + ntohs(uuid->time_hi_and_version); + + /* put in the variant and version bits */ + uuid->time_hi_and_version &= 0x0FFF; + uuid->time_hi_and_version |= (3 << 12); + uuid->clock_seq_hi_and_reserved &= 0x3F; + uuid->clock_seq_hi_and_reserved |= 0x80; + }; + + /* uuid_compare -- Compare two UUID's "lexically" and return + -1 u1 is lexically before u2 + 0 u1 is equal to u2 + 1 u1 is lexically after u2 + + Leach, Salz expires Aug 1998 [Page 22] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + Note: lexical ordering is not temporal ordering! + */ + int uuid_compare(uuid_t *u1, uuid_t *u2) + { + int i; + + #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; + CHECK(u1->time_low, u2->time_low); + CHECK(u1->time_mid, u2->time_mid); + CHECK(u1->time_hi_and_version, u2->time_hi_and_version); + CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved); + CHECK(u1->clock_seq_low, u2->clock_seq_low) + for (i = 0; i < 6; i++) { + if (u1->node[i] < u2->node[i]) + return -1; + if (u1->node[i] > u2->node[i]) + return 1; + } + return 0; + }; + + sysdep.h + + #include "copyrt.h" + /* remove the following define if you aren't running WIN32 */ + #define WININC 0 + + #ifdef WININC + #include + #else + #include + #include + #include + #endif + + /* change to point to where MD5 .h's live */ + /* get MD5 sample implementation from RFC 1321 */ + #include "global.h" + #include "md5.h" + + /* set the following to the number of 100ns ticks of the actual + resolution of + your system's clock */ + #define UUIDS_PER_TICK 1024 + + /* Set the following to a call to acquire a system wide global lock + */ + #define LOCK + #define UNLOCK + + typedef unsigned long unsigned32; + typedef unsigned short unsigned16; + typedef unsigned char unsigned8; + typedef unsigned char byte; + + Leach, Salz expires Aug 1998 [Page 23] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + + /* Set this to what your compiler uses for 64 bit data type */ + #ifdef WININC + #define unsigned64_t unsigned __int64 + #define I64(C) C + #else + #define unsigned64_t unsigned long long + #define I64(C) C##LL + #endif + + + typedef unsigned64_t uuid_time_t; + typedef struct { + char nodeID[6]; + } uuid_node_t; + + void get_ieee_node_identifier(uuid_node_t *node); + void get_system_time(uuid_time_t *uuid_time); + void get_random_info(char seed[16]); + + + sysdep.c + + #include "copyrt.h" + #include + #include "sysdep.h" + + /* system dependent call to get IEEE node ID. + This sample implementation generates a random node ID + */ + void get_ieee_node_identifier(uuid_node_t *node) { + char seed[16]; + FILE * fd; + static inited = 0; + static uuid_node_t saved_node; + + if (!inited) { + fd = fopen("nodeid", "rb"); + if (fd) { + fread(&saved_node, sizeof(uuid_node_t), 1, fd); + fclose(fd); + } + else { + get_random_info(seed); + seed[0] |= 0x80; + memcpy(&saved_node, seed, sizeof(uuid_node_t)); + fd = fopen("nodeid", "wb"); + if (fd) { + fwrite(&saved_node, sizeof(uuid_node_t), 1, fd); + fclose(fd); + }; + }; + inited = 1; + }; + + Leach, Salz expires Aug 1998 [Page 24] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + *node = saved_node; + }; + + /* system dependent call to get the current system time. + Returned as 100ns ticks since Oct 15, 1582, but resolution may be + less than 100ns. + */ + #ifdef _WINDOWS_ + + void get_system_time(uuid_time_t *uuid_time) { + ULARGE_INTEGER time; + + GetSystemTimeAsFileTime((FILETIME *)&time); + + /* NT keeps time in FILETIME format which is 100ns ticks since + Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. + The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) + + 18 years and 5 leap days. + */ + + time.QuadPart += + (unsigned __int64) (1000*1000*10) // seconds + * (unsigned __int64) (60 * 60 * 24) // days + * (unsigned __int64) (17+30+31+365*18+5); // # of days + + *uuid_time = time.QuadPart; + + }; + + void get_random_info(char seed[16]) { + MD5_CTX c; + typedef struct { + MEMORYSTATUS m; + SYSTEM_INFO s; + FILETIME t; + LARGE_INTEGER pc; + DWORD tc; + DWORD l; + char hostname[MAX_COMPUTERNAME_LENGTH + 1]; + } randomness; + randomness r; + + MD5Init(&c); + /* memory usage stats */ + GlobalMemoryStatus(&r.m); + /* random system stats */ + GetSystemInfo(&r.s); + /* 100ns resolution (nominally) time of day */ + GetSystemTimeAsFileTime(&r.t); + /* high resolution performance counter */ + QueryPerformanceCounter(&r.pc); + /* milliseconds since last boot */ + r.tc = GetTickCount(); + r.l = MAX_COMPUTERNAME_LENGTH + 1; + + Leach, Salz expires Aug 1998 [Page 25] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + GetComputerName(r.hostname, &r.l ); + MD5Update(&c, &r, sizeof(randomness)); + MD5Final(seed, &c); + }; + #else + + void get_system_time(uuid_time_t *uuid_time) + { + struct timeval tp; + + gettimeofday(&tp, (struct timezone *)0); + + /* Offset between UUID formatted times and Unix formatted times. + UUID UTC base time is October 15, 1582. + Unix base time is January 1, 1970. + */ + *uuid_time = (tp.tv_sec * 10000000) + (tp.tv_usec * 10) + + I64(0x01B21DD213814000); + }; + + void get_random_info(char seed[16]) { + MD5_CTX c; + typedef struct { + struct sysinfo s; + struct timeval t; + char hostname[257]; + } randomness; + randomness r; + + MD5Init(&c); + sysinfo(&r.s); + gettimeofday(&r.t, (struct timezone *)0); + gethostname(r.hostname, 256); + MD5Update(&c, &r, sizeof(randomness)); + MD5Final(seed, &c); + }; + + #endif + + utest.c + + #include "copyrt.h" + #include "sysdep.h" + #include + #include "uuid.h" + + uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b810, + 0x9dad, + 0x11d1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + }; + + + + Leach, Salz expires Aug 1998 [Page 26] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + /* puid -- print a UUID */ + void puid(uuid_t u); + + /* Simple driver for UUID generator */ + void main(int argc, char **argv) { + uuid_t u; + int f; + + uuid_create(&u); + printf("uuid_create() -> "); puid(u); + + f = uuid_compare(&u, &u); + printf("uuid_compare(u,u): %d\n", f); /* should be 0 */ + f = uuid_compare(&u, &NameSpace_DNS); + printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */ + f = uuid_compare(&NameSpace_DNS, &u); + printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */ + + uuid_create_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); + printf("uuid_create_from_name() -> "); puid(u); + }; + + void puid(uuid_t u) { + int i; + + printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u.time_low, u.time_mid, + u.time_hi_and_version, u.clock_seq_hi_and_reserved, + u.clock_seq_low); + for (i = 0; i < 6; i++) + printf("%2.2x", u.node[i]); + printf("\n"); + }; + +Appendix B _ Sample output of utest + + uuid_create() -> 7d444840-9dc0-11d1-b245-5ffdce74fad2 + uuid_compare(u,u): 0 + uuid_compare(u, NameSpace_DNS): 1 + uuid_compare(NameSpace_DNS, u): -1 + uuid_create_from_name() -> e902893a-9d22-3c7e-a7b8-d6e313b71d9f + +Appendix C _ Some name space IDs + + This appendix lists the name space IDs for some potentially + interesting name spaces, as initialized C structures and in the + string representation defined in section 3.5 + + uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b810, + 0x9dad, + 0x11d1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + }; + + + Leach, Salz expires Aug 1998 [Page 27] + + + Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98 + + + uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b811, + 0x9dad, + 0x11d1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + }; + + uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b812, + 0x9dad, + 0x11d1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + }; + + uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b814, + 0x9dad, + 0x11d1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/drafts/draft-rharrison-ldap-extpartresp-xx.txt b/doc/drafts/draft-rharrison-ldap-extpartresp-xx.txt new file mode 100644 index 0000000000..c3b747eeb1 --- /dev/null +++ b/doc/drafts/draft-rharrison-ldap-extpartresp-xx.txt @@ -0,0 +1,176 @@ +Individual Submission to LDAPExt Working Group R. Harrison +Internet Draft Novell, Inc. +Document: draft-rharrison-ldap-extpartresp-00.txt October, 1999 +Category: Proposed Standard + + + Extended Partial Response + Protocol Enhancement to LDAP v3 + + +Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026 [1]. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. Internet-Drafts are draft documents valid for a maximum of + six months and may be updated, replaced, or obsoleted by other + documents at any time. It is inappropriate to use Internet- Drafts + as reference material or to cite them other than as "work in + progress." + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + +1. Abstract + + This document describes the ExtendedPartialResponse, an element of + LDAP v3 protocol which allows multiple responses to LDAP v3 extended + requests. Extended partial responses are backward compatible with + the existing LDAP v3 Extended Operation defined in [LDAPv3]. + +2. Conventions used in this document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in + this document are to be interpreted as described in [RFC2119]. + + +3. Motivation for the Extended Partial Response + + The Extended Operation ([LDAPv3] Section 4.12) was defined in LDAP + v3 to allow additional operations to be defined as part of the + protocol without requiring a new revision of the protocol. + + The LDAP v3 Extended Operation allows for a single extended response + to each extended request, but this paradigm may not be efficient + enough for some directory operations. For instance, the LDAP search + operation is a directory operation that is much more efficient when + multiple partial responses are used to service a single request. The + +Harrison Individual Submission û Expires April 14, 2000 1 + + LDAP v3 Extended Partial Response October, 1999 + + + extended partial response generalizes the current extended operation + definition to give LDAP server implementers the ability to make use + of a single-request-multiple-response paradigm for extended LDAP + operations that would benefit from it. + +4. Element of Protocol + + The ExtendedPartialResponse is defined as + + ExtendedPartialResponse ::= [APPLICATION 25] SEQUENCE { + responseName [0] LDAPOID, + response [1] OCTET STRING OPTIONAL } + + An LDAP server responds to an LDAP v3 ExtendedRequest with zero or + more ExtendedPartialResponses followed by one ExtendedResponse. This + ensures backward compatibility with existing LDAP extensions which + do not make use of the ExtendedPartialResponse. As with all LDAP + extensions, LDAP extensions that make use of the + ExtendedPartialResponse have predefined syntax and semantics that + are defined in RFCs or are private to a particular implementation. + +5. Security Considerations + + This draft describes an enhancement to the LDAP v3 protocol + [LDAPv3]. All security considerations of [LDAPv3] apply to this + draft, however it does not introduce any new security considerations + to the LDAP v3 protocol. + +6. References + + [LDAPv3] + Wahl, M., Howes, T., and S. Kille, "Lightweight Directory + Access Protocol (v3)", RFC 2251, December 1997. + + [ReqsKeywords] + Scott Bradner. "Key Words for use in RFCs to Indicate + Requirement Levels". RFC 2119. + + +7. Acknowledgments + + The author would like to acknowledge the readers of the LDAP + Extensions working group mail list who responded to the suggestion + that a multiple-response paradigm might be useful for LDAP extended + requests. Special thanks go to two individuals: David Wilbur who + first introduced the idea on the working group list, and Thomas + Salter, who succinctly summarized the discussion and suggested the + name ExtendedPartialResponse in his summary. + +8. Author's Addresses + + Roger Harrison + Novell, Inc. + +Harrison Individual Submission û Expires April 14, 2000 2 + + LDAP v3 Extended Partial Response October, 1999 + + + 122 E. 1700 S. + Provo, UT 84606 + +1 801 861 2642 + roger_harrison@novell.com + +Full Copyright Statement + + "Copyright (C) The Internet Society (date). All Rights Reserved. + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implmentation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph + are included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Harrison Individual Submission û Expires April 14, 2000 3 + diff --git a/doc/drafts/draft-smith-ldap-c-api-ext-vlv-xx.txt b/doc/drafts/draft-smith-ldap-c-api-ext-vlv-xx.txt new file mode 100644 index 0000000000..6b4f28b6b5 --- /dev/null +++ b/doc/drafts/draft-smith-ldap-c-api-ext-vlv-xx.txt @@ -0,0 +1,468 @@ +Network Working Group M. Smith +INTERNET-DRAFT Netscape Communications Corp. +Intended Category: Standards Track +Expires: 18 April 2000 + + 18 October 1999 + + LDAP C API Virtual List View Extension + + +1. Status of this Memo + +This document is an Internet-Draft and is in full conformance with all +provisions of Section 10 of RFC2026. Internet-Drafts are working docu- +ments of the Internet Engineering Task Force (IETF), its areas, and its +working groups. Note that other groups may also distribute working +documents as Internet-Drafts. + +Internet-Drafts are draft documents valid for a maximum of six months +and may be updated, replaced, or obsoleted by other documents at any +time. It is inappropriate to use Internet-Drafts as reference material +or to cite them other than as "work in progress." + +The list of current Internet-Drafts can be accessed at +http://www.ietf.org/ietf/1id-abstracts.txt. + +The list of Internet-Draft Shadow Directories can be accessed at +http://www.ietf.org/shadow.html. + +This draft document will be submitted to the RFC Editor as a Standards +Track document. Distribution of this memo is unlimited. Technical dis- +cussion of this document will take place on the IETF LDAP Extension +Working Group mailing list . Please send +editorial comments directly to the author . + +Copyright (C) The Internet Society (1998-1999). All Rights Reserved. + +Please see the Copyright section near the end of this document for more +information. + +Expires: 18 April 2000 [Page 1] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +2. Introduction + +This document defines a virtual list view extension for the LDAP C API +to support the LDAP protocol extensions for scrolling view browsing of +search results. More specifically, this document defines functions to +create virtual list view request controls and to parse virtual list view +response controls. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are +to be interpreted as described in RFC 2119 [KEYWORDS]. + +3. Table of Contents + +1. Status of this Memo............................................1 +2. Introduction...................................................2 +3. Table of Contents..............................................2 +4. Background and Intended Usage..................................2 +5. Advertising the Virtual List View C LDAP API Extension.........3 +6. Creating a Virtual List View Request Control...................3 +7. Parsing a Virtual List View Response Control...................6 +8. Example Code...................................................8 +9. Security Considerations........................................8 +10. Copyright......................................................8 +11. Bibliography...................................................9 +12. Author's Address...............................................9 +13. Appendix A - Summary of Additions to the C LDAP API............9 + +4. Background and Intended Usage + +The LDAP C API [CAPI] defines a C language application programming +interface (API) to the Lightweight Directory Access Protocol [LDAP]. +This document defines an extension to that API to support an optional +LDAP protocol extension for scrolling view browsing of search results, +also known as Virtual List View [VLV]. + +The scrolling view browsing LDAP extension itself is designed to allow a +"virtual list box" feature to be supported efficiently by LDAP servers +and clients. The protocol extension consists of two LDAP controls: a +Virtual List View (VLV) Request control which is sent by a client to a +server along with an LDAP search request and a Virtual List View +Response control which is returned by the server to send back status +information about the VLV request. + +LDAP clients that wish to use the "virtual list box" feature SHOULD +first check the supportedControls attribute in a server's rootDSE to + +Expires: 18 April 2000 [Page 2] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +determine if a value identical to the Virtual List View Request +control's OID is present. If the OID is present and the client chooses +to use the VLV feature, it MUST construct a Virtual List View Request +control and a Server Side Sorting Control [SSS] and send both controls +to the server within an LDAP searchRequest message. Both controls +SHOULD be marked critical. Client applications MAY use the +ldap_create_vlv_control() function described in this document to create +a Virtual List View Request control. + +At the end of the search request processing, the server SHOULD return a +Virtual List View Response control in the LDAP searchResultDone message. +A Virtual List View Response control MAY be parsed to extract its con- +tents by using the ldap_parse_vlv_control() function described in this +document. + +5. Advertising the Virtual List View C LDAP API Extension + +To conform with the requirements defined in the C LDAP API specification +[CAPI], implementations that support this extension SHOULD advertise the +existence of this extension as follows: + + Define the macro LDAP_API_FEATURE_VIRTUAL_LIST_VIEW as a value that + corresponds to the "level" or revision of this specification. When + this document is published as an RFC, the value to use for + LDAP_API_FEATURE_VIRTUAL_LIST_VIEW is the RFC number itself. While + this document is an Internet Draft, the value to use is 1000 plus the + revision number of this draft, i.e., 1000 for the -00 revision of + this draft, 1001 for the -01 version, and so on. + + Return the text string VIRTUAL_LIST_VIEW in the ldapai_extensions + array of the LDAPAPIInfo structure following a successful call to + ldap_get_option() with an option parameter value of + LDAP_OPT_API_INFO. + + Return information about the extension when the ldapaif_name field in + the LDAPAPIFeatureInfo structure is set to the text string + VIRTUAL_LIST_VIEW and a call to ldap_get_option() with an option + parameter value of LDAP_OPT_API_FEATURE_INFO is made. + +6. Creating a Virtual List View Request Control + +The LDAPVLVInfo structure describes a Virtual List View Request control +and is passed to the ldap_create_vlv_control() function to create a Vir- +tualListViewRequest control. The resulting control SHOULD be passed to + +Expires: 18 April 2000 [Page 3] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +the ldap_search_ext() or ldap_search_ext_s() functions described in +[CAPI] to send them to the server. The ldap_create_sort_control() func- +tion described in [SSSAPI] MAY be used to create a Sort control that is +be passed to the server along with the VirtualListViewRequest control. + +The LDAPVLVInfo structure MAY also be used by applications to manage the +state information associated with a series of virtual list view +client/server interactions. + + /* LDAPVLVInfo structure: */ + typedef struct ldapvlvinfo { + int ldvlv_version; /* version of this struct (1) */ + unsigned long ldvlv_before_count; + unsigned long ldvlv_after_count; + unsigned long ldvlv_offset; /* used if ldvlv_attrvalue is NULL +*/ + unsigned long ldvlv_count; /* used if ldvlv_attrvalue is NULL +* + struct berval *ldvlv_attrvalue; + struct berval *ldvlv_context; + void *ldvlv_extradata; /* for use by application */ + } LDAPVLVInfo; + + /* value for the ldvlv_version field of the LDAPVLVInfo structure: */ + #define LDAP_VLVINFO_VERSION 1 + + /* function used to create a VirtualListViewRequest control: */ + int ldap_create_vlv_control( + LDAP *ld, + LDAPVLVInfo *vlvinfop, + LDAPControl **ctrlp + ); + + /* OID of the VirtualListViewRequest control: */ + #define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" + +The parameters to the ldap_create_vlv_control() function are: + +ld An LDAP session handle, as obtained from a call to + ldap_init(). + +vlvinfop The address of an LDAPVLVInfo structure whose con- + tents are used to construct the value of the control + that is created. + +ctrlp A result parameter that will be assigned the address + of an LDAPControl structure that contains the Virtu- + alListViewRequest control created by this function. + The memory occupied by the LDAPControl structure + SHOULD be freed when it is no longer in use by + +Expires: 18 April 2000 [Page 4] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + + calling ldap_control_free(). + +The ldap_create_vlv_control() function returns a C LDAP API error code +to indicate success or failure (LDAP_SUCCESS if all goes well). + +The members of the LDAPVLVInfo structure are: + +ldvlv_version A number that identifies the version of the + LDAPVLVInfo structure. This SHOULD always be set to + the value LDAP_VLVINFO_VERSION (1). + +ldvlv_before_count A count of the number of entries before the target + entry the client wants the server to send back. + This field corresponds to the beforeCount element of + the BER-encoded VirtualListViewRequest control value + itself. + +ldvlv_after_count A count of the number of entries after the target + entry the client wants the server to send back. + This field corresponds to the afterCount element of + the BER-encoded VirtualListViewRequest control value + itself. + +ldvlv_offset This field is only used if ldvlv_attrvalue is NULL, + i.e, if the byoffset choice within the VirtualList- + ViewRequest control is to be used. ldvlv_offset is + used along with the ldvlv_count value by the server + to determine the target entry. This field + corresponds to the offset element within the BER- + encoded VirtualListViewRequest control value itself. + +ldvlv_count This field is only used if ldvlv_attrvalue is NULL, + i.e., if the byIndex choice within the VirtualList- + ViewRequest control is to be used. ldvlv_count is + used along with the ldvlv_offset value by the server + to determine the target entry. This field + corresponds to the contentCount element within the + BER-encoded VirtualListViewRequest control value + itself. + +ldvlv_attrvalue If this is not NULL, it indicates that the + greaterThanOrEqual choice within the VirtualList- + ViewRequest is to be used. ldvlv_attrvalue + corresponds to the assertionValue element of the + BER-encoded VirtualListViewRequest control value + itself. This value is compared by the server with + the values of the attribute specified by the primary + sort key to determine the target entry. + +Expires: 18 April 2000 [Page 5] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +ldvlv_context If this is not NULL, it is included as the context + identifier in the VirtualListViewRequest control; + ldvlv_context corresponds to the contextID element + within the BER-encoded VirtualListViewRequest con- + trol value itself. If ldvlv_context is NULL, no + context identifier is included in the VirtualList- + ViewRequest control. + +ldvlv_extradata This field is reserved for application-specific use + and is not used by the ldap_create_vlv_control() + function; it has no effect on the control that is + created. + +7. Parsing a Virtual List View Response Control + +When an application receives the result from a VLV search, it SHOULD use +the ldap_parse_vlv_control() function to look for and parse the Virtual +List View Response control returned by the server. + + /* function used to look for and parse a VirtualListViewResponse +control: */ + int ldap_parse_vlv_control( + LDAP *ld, + LDAPControl **ctrls, + unsigned long *target_posp, + unsigned long *list_countp, + struct berval **contextp, + int *errcodep + ); + + /* OID of the VirtualListViewResponse control: */ + #define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" + + /* new error codes: */ + #define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 */ + #define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 */ + +The parameters to the ldap_parse_vlv_control() function are: + +ld An LDAP session handle. + +ctrls The address of a NULL-terminated array of LDAPCon- + trol structures, typically obtained by a call to + ldap_parse_result(). + +target_posp This result parameter is filled in with the list + index of the target entry. If this parameter is + NULL, the target position is not returned. The + +Expires: 18 April 2000 [Page 6] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + + value for this result parameter is pulled from the + targetPosition element of the BER-encoded Virtual- + ListViewResponse control value itself. + +list_countp This result parameter is filled in with the server's + estimate of the size of the list. If this parameter + is NULL, the size is not returned. The value for + this result parameter is pulled from the con- + tentCount element of the BER-encoded VirtualList- + ViewResponse control value itself. + +contextp This result parameter is filled in with the address + of a struct berval that contains the server- + generated context identifier if one was returned by + the server. If the server did not return a context + identifier, this parameter will be set to NULL. The + struct berval returned SHOULD be disposed of by cal- + ling ber_bvfree() when it is no longer needed. If + NULL is passed for contextp, the context identifier + is not returned. + +errcodep This result parameter is filled in with the VLV + result code. If this parameter is NULL, the result + code is not returned. The value for this result + parameter is pulled from the virtualListViewResult + element of the BER-encoded VirtualListViewResponse + control value itself. As specified in the VLV pro- + tocol extension [VLV], it will have one of the fol- + lowing values: + + LDAP_SUCCESS (0); defined in [CAPI] + LDAP_OPERATIONS_ERROR (1); defined in [CAPI] + LDAP_UNWILLING_TO_PERFORM (53); defined in [CAPI] + LDAP_INSUFFICIENT_ACCESS (50); defined in [CAPI] + LDAP_BUSY (51); defined in [CAPI] + LDAP_TIMELIMIT_EXCEEDED (3); defined in [CAPI] + LDAP_ADMINLIMIT_EXCEEDED (11); defined in [CAPI] + LDAP_SORT_CONTROL_MISSING (60); defined above + LDAP_INDEX_RANGE_ERROR (61); defined above + LDAP_OTHER (80); defined in [CAPI] + +The ldap_parse_vlv_control() function returns an LDAP error code that +indicates whether a VLV Result control was found and whether the parsing +was successful. LDAP_SUCCESS is returned if all goes well, +LDAP_CONTROL_NOT_FOUND is returned if the ctrls array does not include a +VirtualListViewResponse control, and another LDAP error code that is +defined in [CAPI] is returned if a parsing error or other problem +occurs. + +Expires: 18 April 2000 [Page 7] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +8. Example Code + +To be provided. + +9. Security Considerations + +Most servers will be configured to restrict access to the Virtual List +View feature since poorly-behaved or malicious clients may cause many +resources to be consumed on the server, or allow users to retrieve too +many entries, or allow users to get an accurate count of the number of +entries present in a portion of the DIT. Clients should take care to +not abuse the VLV feature and should be prepared for servers to refuse +to service a particular VLV request due to access control or other +site-defined policies. + +Please see the protocol extension document [VLV] for a discussion of +related security considerations. + +10. Copyright + +Copyright (C) The Internet Society (1998-1999). All Rights Reserved. + +This document and translations of it may be copied and furnished to oth- +ers, and derivative works that comment on or otherwise explain it or +assist in its implementation may be prepared, copied, published and dis- +tributed, in whole or in part, without restriction of any kind, provided +that the above copyright notice and this paragraph are included on all +such copies and derivative works. However, this document itself may not +be modified in any way, such as by removing the copyright notice or +references to the Internet Society or other Internet organizations, +except as needed for the purpose of developing Internet standards in +which case the procedures for copyrights defined in the Internet Stan- +dards process must be followed, or as required to translate it into +languages other than English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an "AS +IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK +FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT +INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FIT- +NESS FOR A PARTICULAR PURPOSE. + +Expires: 18 April 2000 [Page 8] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +11. Bibliography + +[CAPI] M. Smith, T. Howes, A. Herron, M. Wahl, A. Anantha, "The C + LDAP Application Program Interface", INTERNET-DRAFT, + , 8 October 1999. + +[KEYWORDS] S. Bradner, "Key words for use in RFCs to Indicate Require- + ment Levels", RFC 2119, March 1997. + +[LDAP] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access + Protocol (v3)", RFC 2251, December 1997. + +[SSS] A. Herron, T. Howes, M. Wahl, A. Anantha, "LDAP Control + Extension for Server Side Sorting of Search Results", + INTERNET-DRAFT, April 1999. + +[SSSAPI] C. Weider, A. Herron, T. Howes, M. Smith, M. Wahl, "LDAP API + Extensions for Sort and Simple Paged Results", INTERNET- + DRAFT, , July 1997. + +[VLV] D. Boreham, J. Sermersheim, A. Anantha, M. Armijo, "LDAP + Extensions for Scrolling View Browsing of Search Results", + INTERNET-DRAFT , 11 + June 1999. + +12. Author's Address + + Mark Smith + Netscape Communications Corp. + 501 E. Middlefield Rd., Mailstop MV068 + Mountain View, CA 94043 + USA + +1 650 937-3477 + mcs@netscape.com + +13. Appendix A - Summary of Additions to the C LDAP API + +This extension introduces the following macros: + + LDAP_API_FEATURE_VIRTUAL_LIST_VIEW + LDAP_VLVINFO_VERSION + LDAP_CONTROL_VLVREQUEST + LDAP_CONTROL_VLVRESPONSE + LDAP_SORT_CONTROL_MISSING + LDAP_INDEX_RANGE_ERROR + +Expires: 18 April 2000 [Page 9] + +INTERNET-DRAFT LDAP C API Virtual List View Extension 18 October 1999 + +This extension introduces the following structures and typedefs: + + ldapvlvinfo + LDAPVLVInfo + +This extension introduces the following functions: + + ldap_create_vlv_control() + ldap_parse_vlv_control() + +Expires: 18 April 2000 [Page 10] diff --git a/doc/man/Makefile.in b/doc/man/Makefile.in new file mode 100644 index 0000000000..ace0d25e9a --- /dev/null +++ b/doc/man/Makefile.in @@ -0,0 +1,6 @@ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, See COPYRIGHT file +## +## man Makefile.in for OpenLDAP + +SUBDIRS= man1 man3 man5 man8 diff --git a/doc/man/man1/Makefile.in b/doc/man/man1/Makefile.in new file mode 100644 index 0000000000..a23d711de1 --- /dev/null +++ b/doc/man/man1/Makefile.in @@ -0,0 +1,6 @@ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, See COPYRIGHT file +## +## man1 Makefile.in for OpenLDAP + +MANSECT=1 diff --git a/doc/man/man1/ldapdelete.1 b/doc/man/man1/ldapdelete.1 index 0fd09f4a98..22eb9a2f9d 100644 --- a/doc/man/man1/ldapdelete.1 +++ b/doc/man/man1/ldapdelete.1 @@ -1,4 +1,7 @@ -.TH LDAPDELETE 1 "17 August 1999" "OpenLDAP LDVERSION" +.TH LDAPDELETE 1 "20 April 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapdelete \- LDAP delete entry tool .SH SYNOPSIS @@ -32,6 +35,18 @@ ldapdelete \- LDAP delete entry tool [\c .BI \-p \ ldapport\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .IR dn ]... .SH DESCRIPTION .I ldapdelete @@ -108,6 +123,54 @@ Specify an alternate TCP port where the ldap server is listening. .TP .BI \-P \ 2\fR\||\|\fI3 Specify the LDAP protocol version to use. +.TP +.BI \-r +Do a recursive delete. If the DN specified isn't a leaf, its +children, and all their children are deleted down the tree. No +verification is done, so if you add this switch, ldapdelete will +happily delete large portions of your tree. Use with care. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH EXAMPLE The following command: .LP diff --git a/doc/man/man1/ldapmodify.1 b/doc/man/man1/ldapmodify.1 index 3da8bcd944..25eec8031e 100644 --- a/doc/man/man1/ldapmodify.1 +++ b/doc/man/man1/ldapmodify.1 @@ -1,4 +1,7 @@ -.TH LDAPMODIFY 1 "17 August 1999" "OpenLDAP LDVERSION" +.TH LDAPMODIFY 1 "20 April 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools .SH SYNOPSIS @@ -18,6 +21,8 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BR \-k ] [\c +.BR \-K ] +[\c .BR \-M[M] ] [\c .BI \-d \ debuglevel\fR] @@ -34,6 +39,18 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BI \-P \ 2\fR\||\|\fI3\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] .LP .B ldapadd @@ -52,16 +69,34 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BR \-K ] [\c +.BR \-M[M] ] +[\c .BI \-d \ debuglevel\fR] [\c .BI \-D \ binddn\fR] [\c +.BR \-W ] +[\c .BI \-w \ passwd\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c +.BI \-P \ 2\fR\||\|\fI3\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] .SH DESCRIPTION .B ldapmodify @@ -159,6 +194,48 @@ Specify an alternate TCP port where the ldap server is listening. .TP .BI \-P \ 2\fR\||\|\fI3 Specify the LDAP protocol version to use. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH INPUT FORMAT The contents of \fIfile\fP (or standard input if no \-f flag is given on the command line) should conform to the format defined in diff --git a/doc/man/man1/ldapmodrdn.1 b/doc/man/man1/ldapmodrdn.1 index a177cf9425..790731e0d4 100644 --- a/doc/man/man1/ldapmodrdn.1 +++ b/doc/man/man1/ldapmodrdn.1 @@ -1,4 +1,7 @@ -.TH LDAPMODRDN 1 "17 August 1999" "OpenLDAP LDVERSION" +.TH LDAPMODRDN 1 "20 April 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapmodrdn \- LDAP rename entry tool .SH SYNOPSIS @@ -32,6 +35,18 @@ ldapmodrdn \- LDAP rename entry tool [\c .BI \-P \ 2\fR\||\|\fI3\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] [\c .I dn rdn\fR] @@ -110,6 +125,48 @@ Specify an alternate TCP port where the ldap server is listening. .TP .BI \-P \ 2\fR\||\|\fI3 Specify the LDAP protocol version to use. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH INPUT FORMAT If the command-line arguments \fIdn\fP and \fIrdn\fP are given, \fIrdn\fP will replace the RDN of the entry specified by the DN, \fIdn\fP. diff --git a/doc/man/man1/ldappasswd.1 b/doc/man/man1/ldappasswd.1 new file mode 100644 index 0000000000..d2b1391b90 --- /dev/null +++ b/doc/man/man1/ldappasswd.1 @@ -0,0 +1,151 @@ +.TH LDAPPASSWD 1 "20 April 2000" "LDAPPasswd" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.SH NAME +ldappasswd \- change the password of an LDAP entry +.SH SYNOPSIS +.B ldappasswd +[\c +.BR \-A ] +[\c +.BI \-a \ oldPasswd\fR] +.BI \-D \ binddn\fR +[\c +.BI \-d \ debuglevel\fR] +[\c +.BI \-h \ ldaphost\fR] +[\c +.BR \-n ] +[\c +.BI \-p \ ldapport\fR] +[\c +.BR \-S ] +[\c +.BI \-s \ newPasswd\fR] +[\c +.BR \-v ] +[\c +.BR \-W ] +[\c +.BI \-w \ passwd\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +.SH DESCRIPTION +.B ldappasswd +is a tool to set the password of an LDAP user. +It is neither designed nor intended to be a replacement for +.BR passwd (1) +and should not be installed as such. +.LP +.B ldappasswd +sets the password of associated with the user. If the new +password is not specified on the command line or the user +doesn't enable prompting, the server will be asked to generate +a password for the user. +.SH OPTIONS +.TP +.BI \-A +Prompt for old password. +This is used instead of specifying the password on the command line. +.TP +.BI \-a \ oldPasswd +Set the old password to \fIoldPasswd\fP. +.TP +.BI \-D \ binddn +Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should +be a string-represented DN as defined in RFC 2253. +This flag is not optional. The user DN will be used if the +bind DN is not provided. +.TP +.BI \-d \ debuglevel +Set the LDAP debugging level to \fIdebuglevel\fP. +.B ldappasswd +must be compiled with LDAP_DEBUG defined for this option to have any effect. +.TP +.BI \-h \ ldaphost +Specify an alternate host on which the ldap server is running. +.TP +.B \-n +Do not set password. (Can be useful when used in conjunction with +.BR \-v \ or +.BR \-d ) +.TP +.BI \-S +Prompt for new password. +This is used instead of specifying the password on the command line. +.TP +.BI \-s \ newPasswd +Set the new password to \fInewPasswd\fP. +.TP +.BI \-p \ ldapport +Specify an alternate port on which the ldap server is running. +.TP +.B \-v +Increase the verbosity of output. Can be specified multiple times. +.TP +.BI \-W +Prompt for bind password. +This is used instead of specifying the password on the command line. +.TP +.BI \-w \ passwd +Use \fIpasswd\fP as the password to bind with. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. +.SH SEE ALSO +.BR ldap_bind (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man1/ldapsearch.1 b/doc/man/man1/ldapsearch.1 index 7a53977f76..91be9d6d44 100644 --- a/doc/man/man1/ldapsearch.1 +++ b/doc/man/man1/ldapsearch.1 @@ -1,4 +1,7 @@ -.TH LDAPSEARCH 1 "17 August 1999" "OpenLDAP LDVERSION" +.TH LDAPSEARCH 1 "20 April 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapsearch \- LDAP search tool .SH SYNOPSIS @@ -53,6 +56,18 @@ ldapsearch \- LDAP search tool .BI \-l \ timelimit\fR] [\c .BI \-z \ sizelimit\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] .I filter [\c .IR attrs... ] @@ -222,6 +237,48 @@ of limit. A server may impose a maximal sizelimit which only the root user may override. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH OUTPUT FORMAT If one or more entries are found, each entry is written to standard output in the form: diff --git a/doc/man/man1/ud.1 b/doc/man/man1/ud.1 index 43284a7f74..373c7a4724 100644 --- a/doc/man/man1/ud.1 +++ b/doc/man/man1/ud.1 @@ -1,16 +1,21 @@ -.TH UD 1 "18 March 1993" "U-M LDAP LDVERSION" +.TH UD 1 "12 September 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .UC 6 .SH NAME -ud \- interactive X.500 Directory Server query program +ud \- interactive LDAP Directory Server query program .SH SYNOPSIS .B ud -[-Dv] [-s +[\c +.BR -Dv ] +.RB [ -s .IR server ] -[-d +.RB [ -d .IR debug-mask ] -[-l +.RB [ -l .IR ldap-debug-mask ] -[-f +.RB [ -f .IR file ] .SH DESCRIPTION .IR ud @@ -18,7 +23,7 @@ is used to interogate a directory server via the Lightweight Directory Access Protocol (LDAP). .SH OPTIONS .TP 1i -.B \-s +.BI \-s \ server Used to specify the name of an LDAP server to which .B ud should connect. If this @@ -34,7 +39,7 @@ the name can be resolved (presumably through the use of a CNAME or A record in the DNS and the appropriate search path specified in the resolver config file). .TP 1i -.B \-d +.BI \-d \ debug-mask Sets the .B ud debug mask to the value specified. @@ -42,10 +47,10 @@ Values for the mask can be dumped by using the .IR \-D flag. .TP 1i -.B \-f +.BI \-f \ file Sets the configuration file to the name specified. .TP 1i -.B \-l +.BI \-l \ ldap-debug-mask Sets the LDAP debug mask to the value specified. .TP 1i .B \-v @@ -59,6 +64,7 @@ Prints out a list of valid ud debug masks. ETCDIR/ud.conf The ud configuration file. .SH "SEE ALSO" .BR ud.conf (5), +.BR ldap.conf (5), .BR ldap (3) .SH DIAGNOSTICS .B ud @@ -71,3 +77,8 @@ uses the ldap_perror() routine to print an informative diagnostic. Too numerous to mention. .SH AUTHOR Bryan Beecher, University of Michigan +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/Makefile.in b/doc/man/man3/Makefile.in new file mode 100644 index 0000000000..b1ec689731 --- /dev/null +++ b/doc/man/man3/Makefile.in @@ -0,0 +1,6 @@ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, See COPYRIGHT file +## +## man3 Makefile.in for OpenLDAP + +MANSECT=3 diff --git a/doc/man/man3/cldap_close.3 b/doc/man/man3/cldap_close.3 index 7896ba0923..9e1e9d07e3 100644 --- a/doc/man/man3/cldap_close.3 +++ b/doc/man/man3/cldap_close.3 @@ -1,10 +1,12 @@ -.TH CLDAP_CLOSE 3 "18 November 1994" "U-M LDAP LDVERSION" +.TH CLDAP_CLOSE 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME cldap_close \- Dispose of Connectionless LDAP Pointer .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -28,3 +30,8 @@ returned by a previous call to .BR cldap_open (3), .BR cldap_search_s (3), .BR cldap_setretryinfo (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/cldap_open.3 b/doc/man/man3/cldap_open.3 index 738bda2324..735800110a 100644 --- a/doc/man/man3/cldap_open.3 +++ b/doc/man/man3/cldap_open.3 @@ -1,10 +1,12 @@ -.TH CLDAP_OPEN 3 "18 November 1994" "U-M LDAP LDVERSION" +.TH CLDAP_OPEN 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME cldap_open \- Prepare for Connectionless LDAP Communication .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -51,3 +53,8 @@ will return NULL and errno will be set appropriately. .BR cldap_setretryinfo (3), .BR cldap_close (3), .BR udp (4p) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/cldap_search_s.3 b/doc/man/man3/cldap_search_s.3 index 1c4da546f9..826144f26e 100644 --- a/doc/man/man3/cldap_search_s.3 +++ b/doc/man/man3/cldap_search_s.3 @@ -1,10 +1,12 @@ -.TH CLDAP_SEARCH_S 3 "18 November 1994" "U-M LDAP LDVERSION" +.TH CLDAP_SEARCH_S 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME cldap_search_s \- Connectionless LDAP Search .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -103,3 +105,8 @@ for more information. .BR cldap_setretryinfo (3), .BR cldap_close (3), .BR udp (4p) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/cldap_setretryinfo.3 b/doc/man/man3/cldap_setretryinfo.3 index 55ef67159d..37f6d3932c 100644 --- a/doc/man/man3/cldap_setretryinfo.3 +++ b/doc/man/man3/cldap_setretryinfo.3 @@ -1,10 +1,12 @@ -.TH CLDAP_SETRETRYINFO 3 "18 November 1994" "U-M LDAP LDVERSION" +.TH CLDAP_SETRETRYINFO 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME cldap_setretryinfo \- Set Connectionless LDAP Request Retransmission Parameters .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -40,3 +42,8 @@ algorithm used. .BR cldap_open (3), .BR cldap_search_s (3), .BR cldap_close (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/lber-decode.3 b/doc/man/man3/lber-decode.3 index e05fb33c4b..70b260f2a3 100644 --- a/doc/man/man3/lber-decode.3 +++ b/doc/man/man3/lber-decode.3 @@ -1,6 +1,9 @@ -.TH LBER-DECODE 3 "18 November 1994" +.TH LBER_DECODE 3 "12 May 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME -ber_get_next, ber_skiptag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_stringb, ber_get_stringa, ber_get_null, ber_get_boolean, ber_get_bitstring, ber_first_element, ber_next_element \- LBER simplified Basic Encoding Rules library routines for decoding +ber_get_next, ber_skip_tag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_enum, ber_get_stringb, ber_get_stringa, ber_get_null, ber_get_boolean, ber_get_bitstring, ber_first_element, ber_next_element \- LBER simplified Basic Encoding Rules library routines for decoding .SH SYNOPSIS .nf .ft B @@ -10,154 +13,117 @@ ber_get_next, ber_skiptag, ber_peek_tag, ber_scanf, ber_get_int, ber_get_stringb .LP .nf .ft B -typedef struct berelement { - char *ber_buf; - char *ber_ptr; - char *ber_end; - struct seqorset *ber_sos; - int ber_tag; - int ber_usertag; -} BerElement; +ber_tag_t ber_get_next( + Sockbuf *sb, + ber_len_t \(**len, + BerElement \(**ber); .ft .fi .LP .nf .ft B -typedef struct sockbuf { - int sb_sd; - BerElement sb_ber; -} Sockbuf; +ber_tag_t ber_skip_tag( + BerElement \(**ber, + ber_len_t long \(**len); .ft .fi .LP .nf .ft B -typedef struct berval { - unsigned long bv_len; - char *bv_val; -}; +ber_tag_t ber_peek_tag( + BerElement \(**ber, + ber_len_t \(**len); .ft .fi .LP .nf .ft B -ber_get_next(sb, len, ber) -Sockbuf *sb; -unsigned long \(**len; -BerElement \(**ber; +ber_tag_t ber_scanf( + BerElement \(**ber, + const char \(**fmt, ...); .ft .fi .LP .nf .ft B -ber_skip_tag(ber, len) -BerElement \(**ber; -unsigned long \(**len; +ber_tag_t ber_get_int( + BerElement \(**ber, + ber_int_t \(**num); .ft .fi .LP .nf .ft B -ber_peek_tag(ber, len) -BerElement \(**ber; -unsigned long \(**len; +ber_tag_t ber_get_enum( + BerElement \(**ber, + ber_int_t \(**num); .ft .fi .LP .nf .ft B -ber_get_int(ber, num) -BerElement \(**ber; -long \(**num; +ber_tag_t ber_get_stringb( + BerElement \(**ber, + char \(**buf, + ber_len_t \(**len); .ft .fi .LP .nf .ft B -ber_get_stringb(ber, buf, len) -BerElement \(**ber; -char \(**buf; -unsigned long \(**len; +ber_tag_t ber_get_stringa( + BerElement \(**ber, + char \(***buf); .ft .fi .LP .nf .ft B -ber_get_stringa(ber, buf) -BerElement \(**ber; -char \(***buf; +ber_tag_t ber_get_stringal( + BerElement \(**ber, + struct berval \(***bv); .ft .fi .LP .nf .ft B -ber_get_stringal(ber, bv) -BerElement \(**ber; -struct berval \(***bv; +ber_tag_t ber_get_null( + BerElement \(**ber ); .ft .fi .LP .nf .ft B -ber_get_null(ber) -BerElement \(**ber; +ber_tag_t ber_get_boolean( + BerElement \(**ber, + ber_int_t \(**bool); .ft .fi .LP .nf .ft B -ber_get_boolean(ber, bool) -BerElement \(**ber; -int \(**bool; +ber_tag_t ber_get_bitstringa( + BerElement \(**ber, + char \(***buf, + ber_len_t \(**blen); .ft .fi .LP .nf .ft B -ber_get_bitstringa(ber, buf, blen) -BerElement \(**ber; -char \(***buf; -unsigned long \(**blen; +ber_tag_t ber_first_element( + BerElement \(**ber, + ber_len_t \(**len, + char \(***cookie); .ft .fi .LP .nf .ft B -ber_first_element(ber, len, cookie) -BerElement \(**ber; -unsigned long \(**len; -char \(***cookie; -.ft -.fi -.LP -.nf -.ft B -ber_next_element(ber, len, cookie) -BerElement \(**ber; -unsigned long \(**len; -char \(**cookie; -.ft -.fi -.LP -.nf -.ft B -ber_scanf(ber, fmt [, arg...] ) -BerElement \(**ber; -char \(**fmt; -.ft -.fi -.LP -.nf -.ft B -ber_bvfree(bv) -struct berval \(**bv; -.ft -.fi -.LP -.nf -.ft B -ber_bvecfree(bvec) -struct berval \(***bvec; +ber_tag_t ber_next_element( + BerElement \(**ber, + ber_len_t \(**len, + const char \(**cookie); .SH DESCRIPTION .LP These routines provide a subroutine interface to a simplified @@ -172,6 +138,7 @@ in the descriptions below, it refers to the tag, class, and primitive or constructed bit in the first octet of the encoding. This man page describes the decoding routines in the lber library. See lber-encode(3) for details on the corresponding encoding routines. +Consult lber-types(3) for information about types, allocators, and deallocators. .LP Normally, the only routines that need be called by an application are ber_get_next() to get the next BER element and ber_scanf() @@ -207,27 +174,38 @@ characters. Octet string. A char ** should be supplied. Memory is allocated, filled with the contents of the octet string, null-terminated, and returned in the parameter. +The caller should free the returned ber_val using ber_memfree(). .TP .SM s Octet string. A char * buffer should be supplied, followed by a pointer -to an integer initialized to the size of the buffer. Upon return, the +to a ber_len_t initialized to the size of the buffer. Upon return, the null-terminated octet string is put into the buffer, and the integer is set to the actual size of the octet string. .TP .SM O Octet string. A struct ber_val ** should be supplied, which upon return -points to a malloced struct berval containing the octet string and its -length. ber_bvfree() can be called to free the malloced memory. +points to a dynamically allocated struct berval containing the octet string +and its length. +The caller should free the returned structure using ber_bvfree(). +.TP +.SM o +Octet string. A struct ber_val * should be supplied, which upon return +points containing the dynamically allocated octet string and its length. +The caller should free the returned octet string using ber_memfree(). .TP .SM b -Boolean. A pointer to an integer should be supplied. +Boolean. A pointer to a ber_int_t should be supplied. +.TP +.SM e +Enumeration. A pointer to a ber_int_t should be supplied. .TP .SM i -Integer. A pointer to an integer should be supplied. +Integer. A pointer to a ber_int_t should be supplied. .TP .SM B -Bitstring. A char ** should be supplied which will point to the malloced -bits, followed by an unsigned long *, which will point to the length +Bitstring. A char ** should be supplied which will point to the +dynamically allocated +bits, followed by an ber_len_t *, which will point to the length (in bits) of the bitstring returned. .TP .SM n @@ -236,16 +214,28 @@ it is recognized. .TP .SM v Sequence of octet strings. A char *** should be supplied, which upon -return points to a malloced null-terminated array of char *'s +return points to a dynamically allocated null-terminated array of char *'s containing the octet strings. NULL is returned if the sequence is empty. +The caller should free the returned array and octet strings using +ber_memvfree(). .TP .SM V Sequence of octet strings with lengths. A struct berval *** should be supplied, which upon -return points to a malloced null-terminated array of struct berval *'s +return points to a dynamically allocated null-terminated array of +struct berval *'s containing the octet strings and their lengths. -NULL is returned if the sequence is empty. ber_bvecfree() can be called -to free the malloced memory. +NULL is returned if the sequence is empty. +The caller should free the returned structures using ber_bvecfree(). +.TP +.SM l +Length of the next element. A pointer to a ber_len_t should be supplied. +.TP +.SM t +Tag of the next element. A pointer to a ber_tag_t should be supplied. +.TP +.SM T +Skip element and return its tag. A pointer to a ber_tag_t should be supplied. .TP .SM x Skip element. The next element is skipped. @@ -267,7 +257,7 @@ End set. No parameter is required and no action is taken. .LP The ber_get_int() routine tries to interpret the next element as an integer, returning the result in \fInum\fP. The tag of whatever it finds is returned -on success, -1 on failure. +on success, LBER_ERROR (\-1) on failure. .LP The ber_get_stringb() routine is used to read an octet string into a preallocated buffer. The \fIlen\fP parameter should be initialized to @@ -275,23 +265,28 @@ the size of the buffer, and will contain the length of the octet string read upon return. The buffer should be big enough to take the octet string value plus a terminating NULL byte. .LP -The ber_get_stringa() routine is used to malloc space into which an octet -string is read. +The ber_get_stringa() routine is used to dynamically allocate space into +which an octet string is read. +The caller should free the returned string using ber_memfree(). .LP -The ber_get_stringal() routine is used to malloc space into which an octet -string and its length are read. It takes a struct berval **, and returns -the result in this parameter. +The ber_get_stringal() routine is used to dynamically allocate space +into which an octet string and its length are read. It takes a +struct berval **, and returns the result in this parameter. +The caller should free the returned structure using ber_bvfree(). .LP The ber_get_null() routine is used to read a NULL element. It returns the tag of the element it skips over. .LP -The ber_get_boolean() routine is used to read a boolean value. It is called -the same way that ber_get_int() is called. +The ber_get_boolean() routine is used to read a boolean value. +It is called the same way that ber_get_int() is called. +.LP +The ber_get_enum() routine is used to read a enumeration value. +It is called the same way that ber_get_int() is called. .LP The ber_get_bitstringa() routine is used to read a bitstring value. It -takes a char ** which will hold the malloced bits, followed by an -unsigned long *, which will point to the length (in bits) of the -bitstring returned. +takes a char ** which will hold the dynamically allocated bits, followed by an +ber_len_t *, which will point to the length (in bits) of the bitstring returned. +The caller should free the returned string using ber_memfree(). .LP The ber_first_element() routine is used to return the tag and length of the first element in a set or sequence. It also returns in \fIcookie\fP @@ -325,30 +320,42 @@ the following ASN.1 object: The element can be decoded using ber_scanf() as follows. .LP .nf - int scope, ali, size, time, attrsonly; + ber_int_t scope, deref, size, time, attrsonly; char *dn, **attrs; + ber_tag_t tag; - if ( ber_scanf( ber, "{aiiiib{v}}", &dn, &scope, &ali, - &size, &time, &attrsonly, &attrs ) == -1 ) + tag = ber_scanf( ber, "{aeeiib{v}}", + &dn, &scope, &deref, + &size, &time, &attrsonly, &attrs ); + + if( tag == LBER_ERROR ) { /* error */ - else + } else { /* success */ + } + + ber_memfree( dn ); + ber_memvfree( attrs ); .fi .SH ERRORS -If an error occurs during decoding, generally these routines return -1. +If an error occurs during decoding, generally these routines return +LBER_ERROR (\-1). .LP .SH NOTES .LP The return values for all of these functions are declared in the - header file. Some routines may malloc memory. + header file. +Some routines may dynamically allocate memory +which must be freed by the caller using supplied deallocation routines. .SH SEE ALSO .BR lber-encode (3) +.BR lber-types (3) .BR ldap-parse (3) .BR ldap-sync (3) .BR ldap-async (3) .LP -Yeong, W., Howes, T., and Hardcastle-Kille, S., "Lightweight Directory Access -Protocol", OSI-DS-26, April 1992. +Yeong, W., Howes, T., and Hardcastle-Kille, S., +"Lightweight Directory Access Protocol", OSI-DS-26, April 1992. .LP Information Processing - Open Systems Interconnection - Model and Notation - Service Definition - Specification of Basic Encoding Rules for Abstract @@ -356,3 +363,8 @@ Syntax Notation One, International Organization for Standardization, International Standard 8825. .SH AUTHOR Tim Howes, University of Michigan +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/lber-decode.3.links b/doc/man/man3/lber-decode.3.links new file mode 100644 index 0000000000..3ec93287f9 --- /dev/null +++ b/doc/man/man3/lber-decode.3.links @@ -0,0 +1,13 @@ +ber_get_next.3 +ber_skip_tag.3 +ber_peek_tag.3 +ber_scanf.3 +ber_get_int.3 +ber_get_stringa.3 +ber_get_stringb.3 +ber_get_null.3 +ber_get_enum.3 +ber_get_boolean.3 +ber_get_bitstring.3 +ber_first_element.3 +ber_next_element.3 diff --git a/doc/man/man3/lber-encode.3 b/doc/man/man3/lber-encode.3 index 01304810b7..9d5fbb980d 100644 --- a/doc/man/man3/lber-encode.3 +++ b/doc/man/man3/lber-encode.3 @@ -1,6 +1,9 @@ -.TH LBER-ENCODE 3 "15 June 1992" +.TH LBER_ENCODE 3 "12 May 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME -ber_alloc, ber_flush, ber_printf, ber_put_int, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding +ber_alloc_t, ber_flush, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding .SH SYNOPSIS .nf .ft B @@ -10,131 +13,118 @@ ber_alloc, ber_flush, ber_printf, ber_put_int, ber_put_ostring, ber_put_string, .LP .nf .ft B -typedef struct berelement { - char *ber_buf; - char *ber_ptr; - char *ber_end; - struct seqorset *ber_sos; - int ber_tag; - int ber_usertag; -} BerElement; +BerElement *ber_alloc_t( int options ); .ft .fi .LP .nf .ft B -typedef struct sockbuf { - int sb_sd; - BerElement sb_ber; -} Sockbuf; +int ber_flush( + Sockbuf *sb, + BerElement *ber, + int freeit); .ft .fi .LP .nf .ft B -BerElement *ber_alloc() +int ber_printf( + BerElement *ber, + const char \(**fmt, ...); .ft .fi .LP .nf .ft B -ber_flush(sb, ber, freeit) -Sockbuf *sb; -BerElement *ber; -int freeit; +int ber_put_int( + BerElement *ber, + ber_int_t num, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_printf(ber, fmt [, arg... ] ) -BerElement *ber; -char \(**fmt; +int ber_put_enum( + BerElement *ber, + ber_int_t num, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_put_int(ber, num, tag) -BerElement *ber; -long num; -char tag; +int ber_put_ostring( + BerElement *ber, + const char \(**str, + ber_len_t long len, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_put_ostring(ber, str, len, tag) -BerElement *ber; -char \(**str; -unsigned long len; -char tag; +int ber_put_string( + BerElement *ber, + const char \(**str, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_put_string(ber, str, tag) -BerElement *ber; -char \(**str; -char tag; +int ber_put_null( + BerElement *ber; + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_put_null(ber, tag) -BerElement *ber; -char tag; +int ber_put_boolean( + BerElement *ber; + ber_int_t bool; + ber_tag_t tag; .ft .fi .LP .nf .ft B -ber_put_boolean(ber, bool, tag) -BerElement *ber; -int bool; -char tag; +int ber_put_bitstring( + BerElement *ber, + const char *str, + ber_len_t blen, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_put_bitstring(ber, str, blen, tag) -BerElement *ber; -char *str; -int blen; -char tag; +int ber_start_seq( + BerElement *ber, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_start_seq(ber, tag) -BerElement *ber; -char tag; +int ber_start_set( + BerElement *ber, + ber_tag_t tag); .ft .fi .LP .nf .ft B -ber_start_set(ber, tag) -BerElement *ber; -char tag; +int ber_put_seq( + BerElement *ber); .ft .fi .LP .nf .ft B -ber_put_seq(ber) -BerElement *ber; -.ft -.fi -.LP -.nf -.ft B -ber_put_set(ber) -BerElement *ber; +int ber_put_set( + BerElement *ber); .SH DESCRIPTION .LP These routines provide a subroutine interface to a simplified @@ -149,16 +139,18 @@ in the descriptions below, it refers to the tag, class, and primitive or constructed bit in the first octet of the encoding. This man page describes the encoding routines in the lber library. See lber-decode(3) for details on the corresponding decoding routines. +Consult lber-types(3) for information about types, allocators, and deallocators. .LP Normally, the only routines that need be called by an application -are ber_alloc() to allocate a BER element for encoding, ber_printf() +are ber_alloc_t() to allocate a BER element for encoding, ber_printf() to do the actual encoding, and ber_flush() to actually write the element. The other routines are provided for those applications that need more control than ber_printf() provides. In general, these routines return the length of the element encoded, or -1 if an error occurred. .LP -The ber_alloc() routine is used to allocate a new BER element. The +The ber_alloc_t() routine is used to allocate a new BER element. It +should be called with an argument of LBER_USE_DER. The ber_flush() routine is used to actually write the element to a socket (or file) descriptor, once it has been fully encoded (using ber_printf() and friends). The \fIsb\fP structure contains the descriptor and a @@ -177,11 +169,15 @@ The format string can contain the following characters: .LP .TP 3 .SM b -Boolean. An integer parameter should be supplied. A boolean element +Boolean. An ber_int_t parameter should be supplied. A boolean element is output. .TP +.SM e +Enumeration. An ber_int_t parameter should be supplied. An +enumeration element is output. +.TP .SM i -Integer. An integer parameter should be supplied. An integer element +Integer. An ber_int_t parameter should be supplied. An integer element is output. .TP .SM B @@ -196,19 +192,28 @@ Null. No parameter is required. A null element is output. Octet string. A char * is supplied, followed by the length of the string pointed to. An octet string element is output. .TP +.SM O +Octet string. A struct berval * is supplied. +An octet string element is output. +.TP .SM s Octet string. A null-terminated string is supplied. An octet string element is output, not including the trailing NULL octet. .TP .SM t -Tag. An int specifying the tag to give the next element is provided. -This works across calls. +Tag. A ber_tag_t specifying the tag to give the next element +is provided. This works across calls. .TP .SM v Several octet strings. A null-terminated array of char *'s is supplied. Note that a construct like '{v}' is required to get an actual SEQUENCE OF octet strings. .TP +.SM V +Several octet strings. A null-terminated array of struct berval *'s +is supplied. Note that a construct like '{V}' is required to get +an actual SEQUENCE OF octet strings. +.TP .SM { Begin sequence. No parameter is required. .TP @@ -225,6 +230,9 @@ End set. No parameter is required. The ber_put_int() routine writes the integer element \fInum\fP to the BER element \fIber\fP. .LP +The ber_put_enum() routine writes the enumberation element +\fInum\fP to the BER element \fIber\fP. +.LP The ber_put_boolean() routine writes the boolean value given by \fIbool\fP to the BER element. .LP @@ -278,18 +286,27 @@ the following ASN.1 object: can be achieved like so: .LP .nf - int scope, ali, size, time, attrsonly; + int rc; + ber_int_t scope, ali, size, time, attrsonly; char *dn, **attrs; + BerElement *ber; /* ... fill in values ... */ - if ( (ber = ber_alloc()) == NULLBER ) + + ber = ber_alloc_t( LBER_USE_DER ); + + if ( ber == NULL ) { /* error */ + } - if ( ber_printf( ber, "{siiiib{v}}", dn, scope, ali, - size, time, attrsonly, attrs ) == -1 ) + rc = ber_printf( ber, "{siiiib{v}}", dn, scope, ali, + size, time, attrsonly, attrs ); + + if( rc == -1 ) { /* error */ - else + } else { /* success */ + } .fi .SH ERRORS If an error occurs during encoding, generally these routines return -1. @@ -299,13 +316,14 @@ If an error occurs during encoding, generally these routines return -1. The return values for all of these functions are declared in the header file. .SH SEE ALSO +.BR lber-decode (3) +.BR lber-types (3) .BR ldap-async (3) .BR ldap-sync (3) .BR ldap-parse (3) -.BR lber-decode (3) .LP -Yeong, W., Howes, T., and Hardcastle-Kille, S., "Lightweight Directory Access -Protocol", OSI-DS-26, April 1992. +Yeong, W., Howes, T., and Hardcastle-Kille, S., +"Lightweight Directory Access Protocol", OSI-DS-26, April 1992. .LP Information Processing - Open Systems Interconnection - Model and Notation - Service Definition - Specification of Basic Encoding Rules for Abstract @@ -313,3 +331,8 @@ Syntax Notation One, International Organization for Standardization, International Standard 8825. .SH AUTHOR Tim Howes, University of Michigan +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/lber-encode.3.links b/doc/man/man3/lber-encode.3.links new file mode 100644 index 0000000000..54cd0e9669 --- /dev/null +++ b/doc/man/man3/lber-encode.3.links @@ -0,0 +1,11 @@ +ber_alloc_t.3 +ber_flush.3 +ber_printf.3 +ber_put_int.3 +ber_put_ostring.3 +ber_put_string.3 +ber_put_null.3 +ber_put_enum.3 +ber_start_set.3 +ber_put_seq.3 +ber_put_set.3 diff --git a/doc/man/man3/ldap.3 b/doc/man/man3/ldap.3 index 8f2c20e9e0..ca7ee33627 100644 --- a/doc/man/man3/ldap.3 +++ b/doc/man/man3/ldap.3 @@ -1,10 +1,12 @@ -.TH LDAP 3 "13 November 1995" "U-M LDAP LDVERSION" +.TH LDAP 3 "13 May 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap - Lightweight Directory Access Protocol package .SH SYNOPSIS .nf .ft B -#include #include .ft .fi @@ -12,10 +14,8 @@ ldap - Lightweight Directory Access Protocol package .LP The Lightweight Directory Access Protocol provides TCP/IP access to the X.500 Directory or to a stand-alone LDAP server. -The University of Michigan LDAP package includes a stand-alone server in +The OpenLDAP LDAP package includes a stand-alone server in .BR slapd (8), -an LDAP to X.500 gateway in -.BR ldapd (8), various LDAP clients, and an LDAP client library used to provide programmatic access to the LDAP protocol. This man page gives an overview of the LDAP library routines. @@ -192,10 +192,7 @@ equivalent to .BR ldap_unbind (3) .TP .SM ldap_memfree (3) -dispose of memory allocated by LDAP routines (this is only used on the -Microsoft Windows platforms; use -.BR free (3) -on all other platforms). +dispose of memory allocated by LDAP routines. .TP .SM ldap_enable_cache(3) enable LDAP client caching @@ -326,6 +323,9 @@ extract the DN from an entry .SM ldap_explode_dn(3) convert a DN into its component parts .TP +.SM ldap_explode_rdn(3) +convert a RDN into its component parts +.TP .SM ldap_explode_dns(3) convert a DNS-style DN into its component parts (experimental) .TP @@ -398,6 +398,12 @@ depreciated - use ldap_modrdn2_s(3) .SM ldap_msgfree(3) free results allocated by ldap_result(3) .TP +.SM ldap_msgtype(3) +return the message type of a message from ldap_result(3) +.TP +.SM ldap_msgid(3) +return the message id of a message from ldap_result(3) +.TP .SM ldap_search(3) asynchronously search the directory .TP @@ -494,8 +500,12 @@ set retry and timeout information using connectionless LDAP .SM cldap_close(3) terminate a connectionless LDAP session .SH SEE ALSO -.BR ldapd (8), .BR slapd (8) .SH AUTHORS Tim Howes, Mark Smith, Gordon Good, Lance Sloan, and Steve Rothwell from the University of Michigan, along with help from lots of others. +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_abandon.3 b/doc/man/man3/ldap_abandon.3 index 770513cb3d..6aff579d5f 100644 --- a/doc/man/man3/ldap_abandon.3 +++ b/doc/man/man3/ldap_abandon.3 @@ -1,10 +1,12 @@ -.TH LDAP_ABANDON 3 "1 December 1994" "U-M LDAP LDVERSION" +.TH LDAP_ABANDON 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_abandon \- Abandon an LDAP operation in progress .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -40,3 +42,8 @@ for details. .BR ldap(3), .BR ldap_result(3), .B ldap_error(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_add.3 b/doc/man/man3/ldap_add.3 index 85290ad94e..12482ab576 100644 --- a/doc/man/man3/ldap_add.3 +++ b/doc/man/man3/ldap_add.3 @@ -1,10 +1,12 @@ -.TH LDAP_ADD 3 "15 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_ADD 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_add, ldap_add_s \- Perform an LDAP add operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -58,3 +60,8 @@ directly (LDAP_SUCCESS if everything went ok, some error otherwise). .SH SEE ALSO .BR ldap(3), .B ldap_modify(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_bind.3 b/doc/man/man3/ldap_bind.3 index c172b28c3a..4eb5d82101 100644 --- a/doc/man/man3/ldap_bind.3 +++ b/doc/man/man3/ldap_bind.3 @@ -1,10 +1,12 @@ -.TH LDAP_BIND 3 "28 March 1996" "U-M LDAP LDVERSION" +.TH LDAP_BIND 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_bind, ldap_bind_s, ldap_simple_bind, ldap_simple_bind_s, ldap_kerberos_bind_s, ldap_kerberos_bind1, ldap_kerberos_bind1_s, ldap_kerberos_bind2, ldap_kerberos_bind2_s, ldap_unbind, ldap_unbind_s, ldap_set_rebind_proc \- LDAP bind routines .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -194,3 +196,8 @@ for more information. .BR ldap(3), .BR ldap_error(3), .BR ldap_open(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_cache.3 b/doc/man/man3/ldap_cache.3 index fbc8b0fcb0..db7e9f22e2 100644 --- a/doc/man/man3/ldap_cache.3 +++ b/doc/man/man3/ldap_cache.3 @@ -1,10 +1,12 @@ -.TH LDAP_CACHE 3 "14 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_CACHE 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_enable_cache, ldap_disable_cache, ldap_destroy_cache, ldap_flush_cache, ldap_uncache_entry, ldap_uncache_request, ldap_set_cache_options \- LDAP client caching routines .SH SYNOPSIS .nf .ft B -#include #include .ft .LP @@ -115,3 +117,8 @@ void and return nothing. .BR ldap_search (3), .BR ldap_compare (3), .BR cldap_search_s (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_charset.3 b/doc/man/man3/ldap_charset.3 index c926b07e6a..37c9eeab83 100644 --- a/doc/man/man3/ldap_charset.3 +++ b/doc/man/man3/ldap_charset.3 @@ -1,4 +1,7 @@ -.TH LDAP_CHARSET 3 "28 March 1996" "U-M LDAP LDVERSION" +.TH LDAP_CHARSET 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_set_string_translators, ldap_t61_to_8859, @@ -9,7 +12,6 @@ ldap_enable_translation \- LDAP character set translation routines .SH SYNOPSIS .nf .ft B -#include #include .ft .LP @@ -95,7 +97,7 @@ to be translated and \fI*lenp\fP should contain the number of bytes to translate. If \fIfree_input\fP is non-zero, the input buffer will be freed if translation is a success. If the translation is a success, LDAP_SUCCESS will be returned, \fI*bufp\fP will point to a newly -malloc'd buffer that contains the translated characters, and +dynamically allocated buffer that contains the translated characters, and \fI*lenp\fP will contain the length of the result. If translation fails, an LDAP error code will be returned. @@ -125,3 +127,8 @@ For example, you would not want to translate a binary attributes such as jpegPhoto. .SH SEE ALSO .BR ldap (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_compare.3 b/doc/man/man3/ldap_compare.3 index 3df8ca9c6b..1051c68503 100644 --- a/doc/man/man3/ldap_compare.3 +++ b/doc/man/man3/ldap_compare.3 @@ -1,10 +1,12 @@ -.TH LDAP_COMPARE 3 "15 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_COMPARE 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_compare, ldap_compare_s \- Perform an LDAP compare operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -49,3 +51,8 @@ There is no way to compare binary values, but there should be. .SH SEE ALSO .BR ldap(3), .BR ldap_error(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_delete.3 b/doc/man/man3/ldap_delete.3 index 3149890d84..cff482e13c 100644 --- a/doc/man/man3/ldap_delete.3 +++ b/doc/man/man3/ldap_delete.3 @@ -1,10 +1,12 @@ -.TH LDAP_DELETE 3 "15 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_DELETE 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_delete, ldap_delete_s \- Perform an LDAP delete operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -46,3 +48,8 @@ non-negative message id of the request if things went ok. .SH SEE ALSO .BR ldap(3), .BR ldap_error(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_disptmpl.3 b/doc/man/man3/ldap_disptmpl.3 index 03c1e656ec..b044882451 100644 --- a/doc/man/man3/ldap_disptmpl.3 +++ b/doc/man/man3/ldap_disptmpl.3 @@ -1,4 +1,7 @@ -.TH LDAP_DISPTMPL 3 "13 December 1994" "U-M LDAP LDVERSION" +.TH LDAP_DISPTMPL 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_init_templates, ldap_init_templates_buf, ldap_free_templates, ldap_first_disptmpl, ldap_next_disptmpl, ldap_oc2template, ldap_tmplattrs, ldap_first_tmplrow, ldap_next_tmplrow, ldap_first_tmplcol, ldap_next_tmplcol, \- LDAP display template routines .SH SYNOPSIS @@ -448,3 +451,8 @@ upon error. .BR ldap (3), .BR ldap_entry2text (3), .BR ldaptemplates.conf (5) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_entry2text.3 b/doc/man/man3/ldap_entry2text.3 index 54454253a1..263eb9a65b 100644 --- a/doc/man/man3/ldap_entry2text.3 +++ b/doc/man/man3/ldap_entry2text.3 @@ -1,10 +1,12 @@ -.TH LDAP_ENTRY2TEXT 3 "13 November 1994" "U-M LDAP %LDVERSION%" +.TH LDAP_ENTRY2TEXT 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_entry2text, ldap_entry2text_search, ldap_vals2text \- LDAP entry display routines .SH SYNOPSIS .nf .ft B -#include #include #include .ft @@ -324,3 +326,8 @@ ETCDIR/ldaptemplates.conf .BR ldap (3), .BR ldap_disptmpl (3), .BR ldaptemplates.conf (5) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_error.3 b/doc/man/man3/ldap_error.3 index c517b7e6e3..cc77bbb2fc 100644 --- a/doc/man/man3/ldap_error.3 +++ b/doc/man/man3/ldap_error.3 @@ -1,10 +1,12 @@ -.TH LDAP_ERROR 3 "15 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_ERROR 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_perror, ld_errno, ldap_result2error, ldap_errlist, ldap_err2string \- LDAP protocol error handling routines .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -189,7 +191,7 @@ An unknown error occurred. The LDAP library can't contact the LDAP server. .TP .SM LDAP_LOCAL_ERROR -Some local error occurred. This is usually a failed malloc. +Some local error occurred. This is usually a failed dynamic memory allocation. .TP .SM LDAP_ENCODING_ERROR An error was encountered encoding parameters to send to the LDAP server. @@ -212,8 +214,14 @@ An ldap routine was called with a bad parameter (e.g., a NULL ld pointer, etc.). .TP .SM LDAP_NO_MEMORY -An memory allocation (e.g., malloc(3)) call failed in an ldap +An memory allocation (e.g., malloc(3) or other dynamic memory +allocator) call failed in an ldap library routine. .SH SEE ALSO .BR ldap(3), .BR perror(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_first_attribute.3 b/doc/man/man3/ldap_first_attribute.3 index 452a928bf1..52716a6ca7 100644 --- a/doc/man/man3/ldap_first_attribute.3 +++ b/doc/man/man3/ldap_first_attribute.3 @@ -1,10 +1,12 @@ -.TH LDAP_FIRST_ATTRIBUTE 3 "25 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_FIRST_ATTRIBUTE 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_attribute, ldap_next_attribute \- step through LDAP entry attributes .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -43,15 +45,9 @@ allocated to keep track of its current position. This pointer should be passed to subsequent calls to .B ldap_next_attribute() and is used used -to effectively step through the entry's attributes. This pointer -is freed by -.B ldap_next_attribute() -when there are no more attributes (that -is, when -.B ldap_next_attribute() -returns NULL). Otherwise, the caller is -responsible for freeing the BerElement pointed to by \fIberptr\fP when -it is no longer needed by calling +to effectively step through the entry's attributes. The caller is +solely responsible for freeing the BerElement pointed to by \fIberptr\fP +when it is no longer needed by calling .BR ber_free (3). When calling .BR ber_free (3) @@ -69,11 +65,15 @@ for a description of possible error codes. .SH NOTES The .B ldap_first_attribute() -routine mallocs memory that may need to -be freed by the caller via -.BR ber_free (3). +routine dyanamically allocated memory that must be freed by the caller via +.BR ber_free (3). .SH SEE ALSO .BR ldap(3), .BR ldap_first_entry(3), .BR ldap_get_values(3), .BR ldap_error(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_first_entry.3 b/doc/man/man3/ldap_first_entry.3 index 368ad0ffff..1eb45be7b6 100644 --- a/doc/man/man3/ldap_first_entry.3 +++ b/doc/man/man3/ldap_first_entry.3 @@ -1,10 +1,12 @@ -.TH LDAP_FIRST_ENTRY 3 "25 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_FIRST_ENTRY 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_first_entry, ldap_next_entry, ldap_count_entries \- LDAP result entry parsing and counting routines .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -81,3 +83,8 @@ for a description of possible error codes. .BR ldap_first_attribute(3), .BR ldap_get_values(3), .BR ldap_get_dn(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_friendly.3 b/doc/man/man3/ldap_friendly.3 index 1cf254b475..a6dea4cbe0 100644 --- a/doc/man/man3/ldap_friendly.3 +++ b/doc/man/man3/ldap_friendly.3 @@ -1,29 +1,31 @@ -.TH LDAP_FRIENDLY 3 "11 October 1993" "U-M LDAP LDVERSION" +.TH LDAP_FRIENDLY 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_friendly_name, ldap_free_friendlymap \- LDAP unfriendly to friendly name mapping routine .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B -typedef struct friendly { - char *f_unfriendly; - char *f_friendly; -} FriendlyMap; +typedef struct ldap_friendly { + char *lf_unfriendly; + char *lf_friendly; +} LDAPFriendlyMap; .LP .ft B char *ldap_friendly_name(filename, name, map) .ft char *filename; char *name; -FriendlyMap **map; +LDAPFriendlyMap **map; .LP .ft B void ldap_free_friendlymap(map) .ft -FriendlyMap **map; +LDAPFriendlyMap **map; .SH DESCRIPTION This routine is used to map one set of strings to another. Typically, this is done for country names, to map from the two-letter country @@ -40,10 +42,10 @@ For example: .LP .nf .ft tt - FriendlyMap *map = NULL; + LDAPFriendlyMap *map = NULL; printf( "unfriendly %s => friendly %s\\n", name, - ldap_friendly_name( "ETCDIR/ldapfriendly", name, &map ) ); + ldap_friendly_name( "DATADIR/ldapfriendly", name, &map ) ); .ft .fi .LP @@ -63,6 +65,11 @@ NULL is returned by if there is an error opening \fIfilename\fP, or if the file has a bad format, or if the \fImap\fP parameter is NULL. .SH FILES -ETCDIR/ldapfriendly.conf +DATADIR/ldapfriendly.conf .SH SEE ALSO .BR ldap (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_get_dn.3 b/doc/man/man3/ldap_get_dn.3 index 55530fcbd4..c76f28242c 100644 --- a/doc/man/man3/ldap_get_dn.3 +++ b/doc/man/man3/ldap_get_dn.3 @@ -1,10 +1,12 @@ -.TH LDAP_GET_DN 3 "16 June 1995" "U-M LDAP LDVERSION" +.TH LDAP_GET_DN 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME -ldap_get_dn, ldap_explode_dn, ldap_dn2ufn, ldap_is_dns_dn, ldap_explode_dns \- LDAP DN handling routines +ldap_get_dn, ldap_explode_dn, ldap_explode_rdn, ldap_dn2ufn, ldap_is_dns_dn, ldap_explode_dns \- LDAP DN handling routines .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -20,6 +22,12 @@ char *dn; int notypes; .LP .ft B +char **ldap_explode_rdn(rdn, notypes) +.ft +char *rdn; +int notypes; +.LP +.ft B char *ldap_dn2ufn(dn) .ft char *dn; @@ -47,10 +55,9 @@ routine takes an \fIentry\fP as returned by or .BR ldap_next_entry (3) and returns a copy of -the entry's DN. Space for the DN will have been obtained via -.BR malloc (3), -and should be freed by the caller by a call to -.BR free (3). +the entry's DN. Space for the DN will be obtained dynamically +and should be freed by the caller using +.BR ldap_memfree (3). .LP The .B ldap_explode_dn() @@ -68,16 +75,24 @@ c=US" would return as either { "cn=Bob", "c=US", NULL } or { "Bob", The result can be freed by calling .BR ldap_value_free (3). .LP +Similarly, the +.B ldap_explode_rdn() +routine takes an RDN as returned by +.B ldap_explode_dn(dn,0) +and breaks it up into its "type=value" component parts (or just "value", +if the \fInotypes\fP parameter is set). The result can be freed by +calling +.BR ldap_value_free (3). +.LP .B ldap_dn2ufn() is used to turn a DN as returned by .B ldap_get_dn() into a more user-friendly form, stripping off type names. See RFC 1781 "Using the Directory to Achieve User Friendly Naming" for more details on the UFN format. The space for the UFN returned -is obtained by a call to -.BR malloc (3), -and the user is responsible for freeing it via a call to -.BR free (3). +is obtained dynamically and the user is responsible for freeing it +via a call to +.BR ldap_memfree (3). .LP .B ldap_is_dns_dn() returns non-zero if the dn string is an experimental @@ -101,6 +116,7 @@ field in the \fIld\fP parameter is set to indicate the error. See .BR ldap_error (3) for a description of possible error codes. .BR ldap_explode_dn() , +.BR ldap_explode_rdn() , .B ldap_explode_dns() and .B ldap_dn2ufn() @@ -108,9 +124,15 @@ will return NULL with .BR errno (3) set appropriately in case of trouble. .SH NOTES -These routines malloc memory that the caller must free. +These routines dyanamically allocate memory that the caller must free. .SH SEE ALSO .BR ldap(3), -.BR ldap_first_entry(3), .BR ldap_error(3), +.BR ldap_first_entry(3), +.BR ldap_memfree(3), .BR ldap_value_free(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_get_values.3 b/doc/man/man3/ldap_get_values.3 index ac0dcdb6b3..f87ceb8c57 100644 --- a/doc/man/man3/ldap_get_values.3 +++ b/doc/man/man3/ldap_get_values.3 @@ -1,10 +1,12 @@ -.TH LDAP_GET_VALUES 3 "25 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_GET_VALUES 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_get_values, ldap_get_values_len, ldap_count_values \- LDAP attribute value handling routines .SH SYNOPSIS .nf .ft B -#include #include typedef struct berval { @@ -91,9 +93,15 @@ indicate the error. See .BR ldap_error (3) for a description of possible error codes. .SH NOTES -These routines malloc memory that the caller must free. +These routines dynamically allocate memory which the caller must free +using the supplied routines. .SH SEE ALSO .BR ldap(3), .BR ldap_first_entry(3), .BR ldap_first_attribute(3), .BR ldap_error(3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_getfilter.3 b/doc/man/man3/ldap_getfilter.3 index 67a8df3ccd..0d02b1b89e 100644 --- a/doc/man/man3/ldap_getfilter.3 +++ b/doc/man/man3/ldap_getfilter.3 @@ -1,11 +1,13 @@ -.TH LDAP_GETFILTER 3 "28 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_GETFILTER 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_init_getfilter, ldap_init_getfilter_buf, ldap_getfilter_free, ldap_getfirstfilter, ldap_getnextfilter, ldap_build_filter \- LDAP filter generating routines .SH SYNOPSIS .nf .ft B -#include #include .ft .fi @@ -185,9 +187,16 @@ are no more appropriate filters to return. .SH NOTES .LP The return values for all of these functions are declared in the - header file. Some routines may malloc memory. + header file. +Some routines may dynamically allocate memory +which the caller must free using the supplied deallocator routines. .SH FILES ETCDIR/ldapfilter.conf .SH SEE ALSO .BR ldap (3), .BR ldapfilter.conf (5) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_modify.3 b/doc/man/man3/ldap_modify.3 index baf71a3736..4434ba202b 100644 --- a/doc/man/man3/ldap_modify.3 +++ b/doc/man/man3/ldap_modify.3 @@ -1,10 +1,12 @@ -.TH LDAP_MODIFY 3 "15 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_MODIFY 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_modify, ldap_modify_s \- Perform an LDAP modify operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -111,3 +113,8 @@ field of \fIld\fP. .BR ldap (3), .BR ldap_error (3), .BR ldap_add (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_modrdn.3 b/doc/man/man3/ldap_modrdn.3 index 1b382758f1..e566036c26 100644 --- a/doc/man/man3/ldap_modrdn.3 +++ b/doc/man/man3/ldap_modrdn.3 @@ -1,10 +1,12 @@ -.TH LDAP_MODRDN 3 "1 December 1994" "U-M LDAP LDVERSION" +.TH LDAP_MODRDN 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_modrdn, ldap_modrdn_s, ldap_modrdn2, ldap_modrdn2_s \- Perform an LDAP modify RDN operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -73,3 +75,8 @@ for more details. .SH SEE ALSO .BR ldap (3), .BR ldap_error (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_open.3 b/doc/man/man3/ldap_open.3 index 746e66509a..8c03c0dbaa 100644 --- a/doc/man/man3/ldap_open.3 +++ b/doc/man/man3/ldap_open.3 @@ -1,10 +1,12 @@ -.TH LDAP_OPEN 3 "28 March 1996" "U-M LDAP LDVERSION" +.TH LDAP_OPEN 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_init, ldap_open \- Initialize the LDAP library and open a connection to an LDAP server .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -81,8 +83,8 @@ but does not open a connection to the LDAP server. The actual connection open will occur when the first operation is attempted. At this time, .B ldap_init() -should only -be used if the LDAP library is compiled with LDAP_REFERRALS defined. +is preferred. +.B ldap_open() will be depreciated in a later release. .SH ERRORS If an error occurs, these routines will return NULL and errno should be set appropriately. @@ -111,3 +113,8 @@ in the LDAP structure. .BR ldap (3), .BR ldap_bind (3), .BR errno (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_result.3 b/doc/man/man3/ldap_result.3 index 306e8be44c..68ca6f9cb8 100644 --- a/doc/man/man3/ldap_result.3 +++ b/doc/man/man3/ldap_result.3 @@ -1,10 +1,12 @@ -.TH LDAP_RESULT 3 "26 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_RESULT 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_result \- Wait for the result of an LDAP operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -19,6 +21,16 @@ LDAPMessage **result; int ldap_msgfree(msg) .ft LDAPMessage *msg; +.LP +.ft B +int ldap_msgtype(msg) +.ft +LDAPMessage *msg; +.LP +.ft B +int ldap_msgid(msg) +.ft +LDAPMessage *msg; .SH DESCRIPTION The .B ldap_result() @@ -92,15 +104,32 @@ or and friends. It takes a pointer to the result to be freed and returns the type of the message it freed. +.LP +The +.B ldap_msgtype() +routine returns the type of a message. +.LP +The +.B ldap_msgid() +routine returns the message id of a message. .SH ERRORS .B ldap_result() returns -1 if something bad happens, and zero if the timeout specified was exceeded. +.B ldap_msgtype() +and +.B ldap_msgid() +return -1 on error. .SH NOTES -This routine mallocs memory for results that it receives. The memory -can be freed by calling +This routine dynamically allocates memory for results that it receives. +The memory can be freed by the caller using .BR ldap_msgfree . .SH SEE ALSO .BR ldap (3), .BR ldap_search (3), .BR select (2) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_schema.3 b/doc/man/man3/ldap_schema.3 new file mode 100644 index 0000000000..79c4b5cf4a --- /dev/null +++ b/doc/man/man3/ldap_schema.3 @@ -0,0 +1,328 @@ +.TH LDAP_SCHEMA 3 "4 June 2000" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.SH NAME +ldap_str2syntax, ldap_syntax2str, ldap_syntax2name, ldap_syntax_free, +ldap_str2matchingrule, ldap_matchingrule2str, ldap_matchingrule2name, +ldap_matchingrule_free, +ldap_str2attributetype, ldap_attributetype2str, +ldap_attributetype2name, ldap_attributetype_free, +ldap_str2objectclass, ldap_objectclass2str, ldap_objectclass2name, +ldap_objectclass_free, +ldap_scherr2str \- Schema definition handling routines +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +LDAP_SYNTAX * ldap_str2syntax(s, code, errp, flags) +.ft +const char * s; +int * code; +const char ** errp; +const int flags; +.LP +.ft B +char * ldap_syntax2str(syn) +.ft +const LDAP_SYNTAX * syn; +.LP +.ft B +const char * ldap_syntax2name(syn) +.ft +LDAP_SYNTAX * syn; +.LP +.ft B +ldap_syntax_free(syn) +.ft +LDAP_SYNTAX * syn; +.LP +.ft B +LDAP_MATCHING_RULE * ldap_str2matchingrule(s, code, errp, flags) +.ft +const char * s; +int * code; +const char ** errp; +const int flags; +.LP +.ft B +char * ldap_matchingrule2str(mr); +.ft +const LDAP_MATCHING_RULE * mr; +.LP +.ft B +const char * ldap_matchingrule2name(mr) +.ft +LDAP_MATCHING_RULE * mr; +.LP +.ft B +ldap_matchingrule_free(mr) +.ft +LDAP_MATCHING_RULE * mr; +.LP +.ft B +LDAP_ATTRIBUTE_TYPE * ldap_str2attributetype(s, code, errp, flags) +.ft +const char * s; +int * code; +const char ** errp; +const int flags; +.LP +.ft B +char * ldap_attributetype2str(at) +.ft +const LDAP_ATTRIBUTE_TYPE * at; +.LP +.ft B +const char * ldap_attributetype2name(at) +.ft +LDAP_ATTRIBUTE_TYPE * at; +.LP +.ft B +ldap_attributetype_free(at) +.ft +LDAP_ATTRIBUTE_TYPE * at; +.LP +.ft B +LDAP_OBJECT_CLASS * ldap_str2objectclass(s, code, errp, flags) +.ft +const char * s; +int * code; +const char ** errp; +const int flags; +.LP +.ft B +char * ldap_objectclass2str(oc) +.ft +const LDAP_OBJECT_CLASS * oc; +.LP +.ft B +const char * ldap_objectclass2name(oc) +.ft +LDAP_OBJECT_CLASS * oc; +.LP +.ft B +ldap_objectclass_free(oc) +.ft +LDAP_OBJECT_CLASS * oc; +.LP +.ft B +char * ldap_scherr2str(code) +.ft +int code; +.SH DESCRIPTION +These routines are used to parse schema definitions in the syntax +defined in RFC2252 into structs and handle these structs. These +routines handle four kinds of definitions: syntaxes, matching rules, +attribute types and objectclasses. For each definition kind, four +routines are provided. +.LP +.B ldap_str2xxx() +takes a definition in RFC2252 format in argument +.IR s +as a NUL-terminated string and returns, if possible, a pointer to a +newly allocated struct of the appropriate kind. The caller is +responsible for freeing the struct by calling +.B ldap_xxx_free() +when not needed any longer. The routine returns NULL if some problem +happened. In this case, the integer pointed at by argument +.IR code +will receive an error code (see below the description of +.B ldap_scherr2str() +for an explanation of the values) and a pointer to a NUL-terminated +string will be placed where requested by argument +.IR errp +, indicating where in argument +.IR s +the error happened, so it must not be freed by the caller. Argument +.IR flags +is a bit mask of parsing options controlling the relaxation of the +syntax recognized. The following values are defined: +.TP +.B LDAP_SCHEMA_ALLOW_NONE +strict parsing according to RFC2252. +.TP +.B LDAP_SCHEMA_ALLOW_NO_OID +permit definitions that do not contain an initial OID. +.TP +.B LDAP_SCHEMA_ALLOW_QUOTED +permit quotes around some items that should not have them. +.TP +.B LDAP_SCHEMA_ALLOW_DESCR +permit a +.B descr +instead of a numeric OID in places where the syntax expect the latter. +.TP +.B LDAP_SCHEMA_ALLOW_DESCR_PREFIX +permit that the initial numeric OID contains a prefix in +.B descr +format. +.TP +.B LDAP_SCHEMA_ALLOW_ALL +be very liberal, include all options. +.LP +The structures returned are as follows: +.sp +.RS +.nf +.ne 7 +.ta 8n 16n 32 n +typedef struct ldap_schema_extension_item { + char *lsei_name; /* Extension name */ + char **lsei_values; /* Extension values */ +} LDAP_SCHEMA_EXTENSION_ITEM; + +typedef struct ldap_syntax { + char *syn_oid; /* OID */ + char **syn_names; /* Names */ + char *syn_desc; /* Description */ + LDAP_SCHEMA_EXTENSION_ITEM **syn_extensions; /* Extension */ +} LDAP_SYNTAX; + +typedef struct ldap_matchingrule { + char *mr_oid; /* OID */ + char **mr_names; /* Names */ + char *mr_desc; /* Description */ + int mr_obsolete; /* Is obsolete? */ + char *mr_syntax_oid; /* Syntax of asserted values */ + LDAP_SCHEMA_EXTENSION_ITEM **mr_extensions; /* Extensions */ +} LDAP_MATCHING_RULE; + +typedef struct ldap_attributetype { + char *at_oid; /* OID */ + char **at_names; /* Names */ + char *at_desc; /* Description */ + int at_obsolete; /* Is obsolete? */ + char *at_sup_oid; /* OID of superior type */ + char *at_equality_oid; /* OID of equality matching rule */ + char *at_ordering_oid; /* OID of ordering matching rule */ + char *at_substr_oid; /* OID of substrings matching rule */ + char *at_syntax_oid; /* OID of syntax of values */ + int at_syntax_len; /* Suggested minimum maximum length */ + int at_single_value; /* Is single-valued? */ + int at_collective; /* Is collective? */ + int at_no_user_mod; /* Are changes forbidden through LDAP? */ + int at_usage; /* Usage, see below */ + LDAP_SCHEMA_EXTENSION_ITEM **at_extensions; /* Extensions */ +} LDAP_ATTRIBUTE_TYPE; + +typedef struct ldap_objectclass { + char *oc_oid; /* OID */ + char **oc_names; /* Names */ + char *oc_desc; /* Description */ + int oc_obsolete; /* Is obsolete? */ + char **oc_sup_oids; /* OIDs of superior classes */ + int oc_kind; /* Kind, see below */ + char **oc_at_oids_must; /* OIDs of required attribute types */ + char **oc_at_oids_may; /* OIDs of optional attribute types */ + LDAP_SCHEMA_EXTENSION_ITEM **oc_extensions; /* Extensions */ +} LDAP_OBJECT_CLASS; +.ta +.fi +.RE +.PP +Some integer fields (those described with a question mark) have a +truth value, for these fields the possible values are: +.TP +.B LDAP_SCHEMA_NO +The answer to the question is no. +.TP +.B LDAP_SCHEMA_YES +The answer to the question is yes. +.LP +For attribute types, the following usages are possible: +.TP +.B LDAP_SCHEMA_USER_APPLICATIONS +the attribute type is non-operational. +.TP +.B LDAP_SCHEMA_DIRECTORY_OPERATION +the attribute type is operational and is pertinent to the directory +itself, i.e. it has the same value on all servers that master the +entry containing this attribute type. +.TP +.B LDAP_SCHEMA_DISTRIBUTED_OPERATION +the attribute type is operational and is pertinent to replication, +shadowing or other distributed directory aspect. TBC. +.TP +.B LDAP_SCHEMA_DSA_OPERATION +the attribute type is operational and is pertinent to the directory +server itself, i.e. it may have different values for the same entry +when retrieved from different servers that master the entry. +.LP +Object classes can be of three kinds: +.TP +.B LDAP_SCHEMA_ABSTRACT +the object class is abstract, i.e. there cannot be entries of this +class alone. +.TP +.B LDAP_SCHEMA_STRUCTURAL +the object class is structural, i.e. it describes the main role of the +entry. On some servers, once the entry is created the set of +structural object classes assigned cannot be changed: none of those +present can be removed and none other can be added. +.TP +.B LDAP_SCHEMA_AUXILIARY +the object class is auxiliary, i.e. it is intended to go with other, +structural, object classes. These can be added or removed at any time +if attribute types are added or removed at the same time as needed by +the set of object classes resulting from the operation. +.LP +Routines +.B ldap_xxx2name() +return a canonical name for the definition. +.LP +Routines +.B ldap_xxx2str() +return a string representation in the format described by RFC2252 of +the struct passed in the argument. The string is a newly allocated +string that must be freed by the caller. These routines may return +NULL if no memory can be allocated for the string. +.LP +.B ldap_scherr2str() +returns a NUL-terminated string with a text description of the error +found. This is a pointer to a static area, so it must not be freed by +the caller. The argument +.IR code +comes from one of the parsing routines and can adopt the following +values: +.TP +.B LDAP_SCHERR_OUTOFMEM +Out of memory. +.TP +.B LDAP_SCHERR_UNEXPTOKEN +Unexpected token. +.TP +.B LDAP_SCHERR_NOLEFTPAREN +Missing opening parenthesis. +.TP +.B LDAP_SCHERR_NORIGHTPAREN +Missing closing parenthesis. +.TP +.B LDAP_SCHERR_NODIGIT +Expecting digit. +.TP +.B LDAP_SCHERR_BADNAME +Expecting a name. +.TP +.B LDAP_SCHERR_BADDESC +Bad description. +.TP +.B LDAP_SCHERR_BADSUP +Bad superiors. +.TP +.B LDAP_SCHERR_DUPOPT +Duplicate option. +.TP +.B LDAP_SCHERR_EMPTY +Unexpected end of data. + +.SH SEE ALSO +.BR ldap (3), +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. + diff --git a/doc/man/man3/ldap_schema.3.links b/doc/man/man3/ldap_schema.3.links new file mode 100644 index 0000000000..05e1675c2f --- /dev/null +++ b/doc/man/man3/ldap_schema.3.links @@ -0,0 +1,17 @@ +ldap_str2syntax.3 +ldap_syntax2str.3 +ldap_syntax2name.3 +ldap_syntax_free.3 +ldap_str2matchingrule.3 +ldap_matchingrule2str.3 +ldap_matchingrule2name.3 +ldap_matchingrule_free.3 +ldap_str2attributetype.3 +ldap_attributetype2str.3 +ldap_attributetype2name.3 +ldap_attributetype_free.3 +ldap_str2objectclass.3 +ldap_objectclass2str.3 +ldap_objectclass2name.3 +ldap_objectclass_free.3 +ldap_scherr2str.3 diff --git a/doc/man/man3/ldap_search.3 b/doc/man/man3/ldap_search.3 index e1a7022bcd..a008db650f 100644 --- a/doc/man/man3/ldap_search.3 +++ b/doc/man/man3/ldap_search.3 @@ -1,11 +1,13 @@ -.TH LDAP_SEARCH 3 "23 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_SEARCH 3 "25 July 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_search, ldap_search_s, ldap_search_st \- Perform an LDAP search operation .SH SYNOPSIS .nf .ft B #include /* for struct timeval definition */ -#include #include .LP .ft B @@ -87,8 +89,16 @@ filters. See for routines to help in constructing search filters automatically. .LP \fIAttrs\fP is a null-terminated array of attribute types to return -from entries that match \fIfilter\fP. If NULL is specified, all -attributes will be returned. \fIAttrsonly\fP should be set to 1 if +from entries that match \fIfilter\fP. +If NULL is specified, all attributes will be returned. +The type "*" (LDAP_ALL_USER_ATTRIBUTES) may be used to request +all user attributes to be returned. +The type "+"(LDAP_ALL_OPERATIONAL_ATTRIBUTES) may be used to request +all operational attributes to be returned. +To request no attributes, the type "1.1" (LDAP_NO_ATTRS) +should be listed by itself. +.LP +\fIAttrsonly\fP should be set to 1 if only attribute types are wanted. It should be set to 0 if both attributes types and attribute values are wanted. .SH ERRORS @@ -107,10 +117,17 @@ and list functionality are subsumed by these routines, by using a filter like "objectclass=*" and a scope of LDAP_SCOPE_BASE (to emulate read) or LDAP_SCOPE_ONELEVEL (to emulate list). .LP -These routines may malloc memory. Return values are contained +These routines may dynamically allocate memory. The caller is +responsible for freeing such memory using supplied deallocation +routines. Return values are contained in . .SH SEE ALSO .BR ldap (3), .BR ldap_result (3), .BR ldap_getfilter (3), .BR ldap_error (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_searchprefs.3 b/doc/man/man3/ldap_searchprefs.3 index 98b6e78d77..02a404c942 100644 --- a/doc/man/man3/ldap_searchprefs.3 +++ b/doc/man/man3/ldap_searchprefs.3 @@ -1,4 +1,7 @@ -.TH SEARCHPREFS 3 "13 June 1994" "U-M LDAP LDVERSION" +.TH SEARCHPREFS 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_init_searchprefs, ldap_init_searchprefs_buf, ldap_free_searchprefs, ldap_first_searchobj, ldap_next_searchobj \- LDAP search preference configuration routeines .SH SYNOPSIS @@ -156,3 +159,8 @@ OSI-DS-23, April 1992. Information Processing - Open Systems Interconnection - The Directory, International Organization for Standardization. International Standard 9594, (1988). +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_sort.3 b/doc/man/man3/ldap_sort.3 index f56122af0b..3d451e55ff 100644 --- a/doc/man/man3/ldap_sort.3 +++ b/doc/man/man3/ldap_sort.3 @@ -1,10 +1,12 @@ -.TH LDAP_SORT 3 "14 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_SORT 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_sort_entries, ldap_sort_values, ldap_sort_strcasecmp \- LDAP sorting routines .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -93,9 +95,16 @@ may produce unexpected results for multi-valued attributes. When sorting by DN, the comparison function is applied to an exploded version of the DN, without types. The return values for all of these functions are declared in the - header file. Some routines may malloc memory. + header file. Some routines may dynamically allocate memory. +Callers are responsible for freeing such memory using the supplied +deallocation routines. .SH SEE ALSO .BR ldap (3), .BR ldap_search (3), .BR ldap_result (3), .BR qsort (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_ufn.3 b/doc/man/man3/ldap_ufn.3 index 6fe1a5123d..b0c8a13d20 100644 --- a/doc/man/man3/ldap_ufn.3 +++ b/doc/man/man3/ldap_ufn.3 @@ -1,10 +1,12 @@ -.TH LDAP_UFN 3 "23 November 1994" "U-M LDAP LDVERSION" +.TH LDAP_UFN 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_ufn_search_s, ldap_ufn_search_c, ldap_ufn_search_ct, ldap_ufn_setfilter, ldap_ufn_setfilter, ldap_ufn_setprefix, ldap_ufn_timeout \- Perform an LDAP user friendly search operation .SH SYNOPSIS .nf .ft B -#include #include .LP .ft B @@ -119,7 +121,9 @@ should actually be a pointer to a struct timeval (this is so .B ldap_ufn_timeout() can be used as a cancelproc in the above routines). .SH NOTES -These routines may malloc memory. Return values are contained +These routines may dynamically allocate memory. The caller is +required to free such memory using the supplied deallocation routines. +Return values are contained in . .SH SEE ALSO .BR gettimeofday (2), @@ -128,3 +132,8 @@ in . .BR ldap_getfilter (3), .BR ldapfilter.conf (5), .BR ldap_error (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man3/ldap_url.3 b/doc/man/man3/ldap_url.3 index 7e04bcc337..8b48e4c4d5 100644 --- a/doc/man/man3/ldap_url.3 +++ b/doc/man/man3/ldap_url.3 @@ -1,4 +1,7 @@ -.TH LDAP_URL 3 "28 March 1996" "U-M LDAP LDVERSION" +.TH LDAP_URL 3 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap_is_ldap_url, ldap_url_parse, @@ -9,7 +12,6 @@ ldap_url_search_st \- LDAP Uniform Resource Locator routines .SH SYNOPSIS .nf .ft B -#include #include .ft .LP @@ -71,10 +73,10 @@ LDAP URLs look like this: where: \fIhostport\fP is a host name with an optional ":portnumber" - \fIdn\f is the base DN to be used for an LDAP search operation + \fIdn\fP is the base DN to be used for an LDAP search operation \fIattributes\fP is a comma separated list of attributes to be retrieved \fIscope\fP is one of these three strings: base one sub (default=base) - \fIfilter\f is LDAP search filter as used in a call to ldap_search(3) + \fIfilter\fP is LDAP search filter as used in a call to ldap_search(3) e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich .fi @@ -134,3 +136,8 @@ Currently available at this URL: .nf ftp://ds.internic.net/internet-drafts/draft-ietf-asid-ldap-format-03.txt .fi +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man5/Makefile.in b/doc/man/man5/Makefile.in new file mode 100644 index 0000000000..b83e294784 --- /dev/null +++ b/doc/man/man5/Makefile.in @@ -0,0 +1,6 @@ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, See COPYRIGHT file +## +## man5 Makefile.in for OpenLDAP + +MANSECT=5 diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5 index 00d9d4adc0..1e9e5266e9 100644 --- a/doc/man/man5/ldap.conf.5 +++ b/doc/man/man5/ldap.conf.5 @@ -1,9 +1,13 @@ .TH LDAP.CONF 5 "29 November 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .UC 6 .SH NAME -ldap.conf \- ldap configuration file +ldap.conf, .ldaprc \- ldap configuration file .SH SYNOPSIS ETCDIR/ldap.conf +\fP.ldaprc\fP .SH DESCRIPTION The .I ldap.conf @@ -29,13 +33,24 @@ Environmental variables may also be used to augment the file based defaults. The name of the option is the as listed but with a prefix of \fBLDAP\fP. For example, to define \fBBASE\fP via the environment, define the variable \fBLDAPBASE\fP to desired value. +.LP +Some options are user\-only. Such options are ignored if present +in the +.IR ldap.conf +(or file specified by +.BR LDAPCONF ). .SH OPTIONS The different configuration options are: .TP 1i \fBBASE \fP -Used to specify the default base dn to use when performing ldap operations. +Used to specify the default base DN to use when performing ldap operations. The base must be specified as a Distinguished Name in LDAP format. .TP 1i +\fBBINDDN \fP +Used to specify the default bind DN to use when performing ldap operations. +The bind DN must be specified as a Distinguished Name in LDAP format. +This is a user\-only option. +.TP 1i \fBHOST \fP Used to specify the name(s) of an LDAP server(s) to which .I ldap diff --git a/doc/man/man5/ldapfilter.conf.5 b/doc/man/man5/ldapfilter.conf.5 index 954bc2fd4d..97d720dae9 100644 --- a/doc/man/man5/ldapfilter.conf.5 +++ b/doc/man/man5/ldapfilter.conf.5 @@ -1,4 +1,7 @@ -.TH LDAPFILTER.CONF 5 "21 September 1994" "U-M LDAP LDVERSION" +.TH LDAPFILTER.CONF 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapfilter.conf \- configuration file for LDAP get filter routines .SH SYNOPSIS @@ -196,3 +199,8 @@ ETCDIR/ldapfilter.conf .SH SEE ALSO .BR ldap (3), .BR ldap_getfilter (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man5/ldapfriendly.5 b/doc/man/man5/ldapfriendly.5 index 088fd13560..3cf6f02edc 100644 --- a/doc/man/man5/ldapfriendly.5 +++ b/doc/man/man5/ldapfriendly.5 @@ -1,16 +1,19 @@ -.TH LDAPFRIENDLY 5 "24 November 1994" "U-M LDAP LDVERSION" +.TH LDAPFRIENDLY 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME -ldapfriendly \- configuration file for LDAP friendly routines +ldapfriendly \- data file for LDAP friendly routines .SH SYNOPSIS -ETCDIR/ldapfriendly +DATADIR/ldapfriendly .SH DESCRIPTION .LP -The file ETCDIR/ldapfriendly contains simple mapping information +The file DATADIR/ldapfriendly contains simple mapping information used by the .BR ldap_friendly_name (3) routine. Blank lines and lines that have a first character of `#' are treated as comments and -ignored. The configuration information consists of lines that contain +ignored. The information consists of lines that contain an "unfriendly" name, a tab, and a "friendly" name. .LP Other friendly mapping files can be created and used by @@ -20,7 +23,12 @@ above and include the file name in the .B ldap_friendly_name() call. .SH FILES -ETCDIR/ldapfriendly +DATADIR/ldapfriendly .SH SEE ALSO .BR ldap (3), .BR ldap_friendly_name (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man5/ldapsearchprefs.conf.5 b/doc/man/man5/ldapsearchprefs.conf.5 index 7f58505ed3..a075148c78 100644 --- a/doc/man/man5/ldapsearchprefs.conf.5 +++ b/doc/man/man5/ldapsearchprefs.conf.5 @@ -1,4 +1,7 @@ -.TH LDAPSEARCHPREFS.CONF 5 "1 December 1994" "U-M LDAP LDVERSION" +.TH LDAPSEARCHPREFS.CONF 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldapsearchprefs.conf \- configuration file for LDAP search preference routines .SH SYNOPSIS @@ -244,3 +247,8 @@ ETCDIR/ldapsearchprefs.conf .SH SEE ALSO .BR ldap (3). .BR ldap-searchprefs (3) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man5/ldaptemplates.conf.5 b/doc/man/man5/ldaptemplates.conf.5 index 6a68e721f0..e5a87b6c80 100644 --- a/doc/man/man5/ldaptemplates.conf.5 +++ b/doc/man/man5/ldaptemplates.conf.5 @@ -1,4 +1,7 @@ .TH LDAPTEMPLATES.CONF 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldaptemplates.conf \- configuration file for LDAP display template routines .SH SYNOPSIS diff --git a/doc/man/man5/ldif.5 b/doc/man/man5/ldif.5 index a0cb4774c6..1cb621a5dc 100644 --- a/doc/man/man5/ldif.5 +++ b/doc/man/man5/ldif.5 @@ -1,4 +1,7 @@ .TH LDIF 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldif \- LDAP Data Interchange Format .SH DESCRIPTION diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 44feb794fa..4016f9df55 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -1,4 +1,7 @@ .TH SLAPD.CONF 5 "5 August 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slapd.conf \- configuration file for slapd, the stand-alone LDAP daemon .SH SYNOPSIS @@ -64,26 +67,23 @@ overridden in a backend definition. Arguments that should be replaced by actual text are shown in brackets <>. .TP .B -access to [ by ]+ -Grant access (specified by ) to a set of entries and/or +access to [ by ]+ +Grant access (specified by ) to a set of entries and/or attributes (specified by ) by one or more requestors (specified -by ). Refer to "The SLAPD and SLURPD Administrator's Guide" for -information on using the -.B slapd -access-control mechanisms. +by ). +See Developer's FAQ (http://www.openldap.org/faq/) for details. .TP .B -attribute ( [NAME ] [DESC ] [OBSOLETE] \ +attributetype ( [NAME ] [DESC ] [OBSOLETE] \ [SUP ] [EQUALITY ] [ORDERING ] [SUBSTR ] \ [SYNTAX ] [SINGLE-VALUE] [COLLECTIVE] [NO-USER-MODIFICATION] \ [USAGE ] ) Specify an attribute type using the LDAPv3 syntax defined in RFC 2252. -This is the preferred format for attribute type definitions. The slapd -parser extends the RFC 2252 definition by allowing string forms as well -as numeric OIDs to be used for the attribute OID and attribute syntax OID. +The slapd parser extends the RFC 2252 definition by allowing string +forms as well as numeric OIDs to be used for the attribute OID and +attribute syntax OID. (See the -.B -objectidentifier +.B objectidentifier description.) Currently the syntax name parser is case-sensitive. The known syntax names are: .RS @@ -103,40 +103,18 @@ SubstringAssertion NISnetgrouptriple Bootparameter .RE .RE .TP -.B -attribute [] { bin | ces | cis | tel | dn } -Associate a syntax with an attribute name. This directive is deprecated -in favor of the one above. By default, an -attribute is assumed to have syntax -.BR cis . -An optional alternate name can be -given for an attribute. The possible syntaxes and their meanings are: -.RS -.RS -.PD 0 -.TP -.B bin -binary -.TP -.B ces -case exact string -.TP -.B cis -case ignore string -.TP -.B tel -telephone number string -.TP -.B dn -distinguished name -.PD -.RE -.RE +.B concurrency +Specify a desired level of concurrency. Provided to the underlying +thread system as a hint. The default is not to provdide any hint. .TP .B -defaultaccess [self]{ none | compare | search | read | write } -Specify the default access to grant requestors not matched by -any other access line. The default behavior is to grant read access. +defaultaccess { none | auth | compare | search | read | write } +Specify the default access level to grant requestors when +no access directives were provided for the database. +The default behavior is to grant 'read' access. It is +recommended that +.B access +directives be used instead. .TP .B idletimeout Specify the number of seconds to wait before forcibly closing @@ -225,18 +203,12 @@ objectclass ( [NAME ] [DESC ] [{ ABSTRACT | STRUCTURAL | AUXILIARY }] [MUST ] \ [MAY ] ) Specify an objectclass using the LDAPv3 syntax defined in RFC 2252. -This is the preferred format for object class definitions. The slapd -parser extends the RFC 2252 definition by allowing string forms as well -as numeric OIDs to be used for the object class OID. (See the +The slapd parser extends the RFC 2252 definition by allowing string +forms as well as numeric OIDs to be used for the object class OID. +(See the .B objectidentifier -description.) Object classes are "STRUCTURAL" by default. -.TP -.B -objectclass requires allows -Define the schema rules for the object class named . These are -used in conjunction with the schemacheck option. This directive is -deprecated in favor of the one above. +description.) Object classes are "STRUCTURAL" by default. .TP .B objectidentifier { | [:] } Define a string name that equates to the given OID. The string can be used @@ -347,9 +319,10 @@ or administrative limit restrictions for operations on this database. .TP .B rootpw Specify a password (or hash of the password) for the rootdn. -This option accepts all password formats known to the server -including \fB{SHA}\fP, \fB{MD5}\fP, \fB{CRYPT}\fP, and cleartext. -Cleartext passwords are not recommended. +This option accepts all RFC 2307 userPassword formats known to +the server including \fB{SSHA}\fP, \fB{SHA}\fP, \fB{SMD5}\fP, +\fB{MD5}\fP, \fB{CRYPT}\fP, and cleartext schemes. Cleartext +and \fB{CRYPT}\fP passwords are not recommended. .TP .B suffix Specify the DN suffix of queries that will be passed to this @@ -384,20 +357,25 @@ Specify the size in bytes of the in-memory cache associated with each open index file. If not supported by the underlying database method, this option is ignored without comment. The default is 100000 bytes. .TP -.B dbcachenowsync -Specify that database writes should not be immediately synchronized -with in memory changes. Enabling this option may improve performance -at the expense of data security. +.B dbnolocking +Specify that no database locking should be performed. +Enabling this option may improve performance at the expense of data security. +.B dbnosync +Specify that on-disk database contents should not be immediately +synchronized with in memory changes. Enabling this option may improve +performance at the expense of data security. .TP .B directory -Specify the directory where the LDBM files containing the database and -associated indexes live. The default is -.B /usr/tmp. +Specify the directory where the LDBM files containing this database and +associated indexes live. A separate directory must be specified for +each database. The default is +.BR LOCALSTATEDIR/openldap-ldbm . .TP .B index { | default } [ pres,eq,approx,sub,none ] Specify the indexes to maintain for the given attribute. If only -an is given, all possible indexes are maintained. +an is given, the indices specified for \fBdefault\fR +are maintained. .TP .B mode Specify the file protection mode that newly created database diff --git a/doc/man/man5/slapd.replog.5 b/doc/man/man5/slapd.replog.5 index 83d0cc69fd..3f600f27b3 100644 --- a/doc/man/man5/slapd.replog.5 +++ b/doc/man/man5/slapd.replog.5 @@ -1,4 +1,7 @@ -.TH SLAPD.REPLOG 5 "11 April 1995" "U-M LDAP LDVERSION" +.TH SLAPD.REPLOG 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slapd.replog \- slapd replication log format .SH SYNOPSIS @@ -156,3 +159,8 @@ slapd.replog.lock .BR ldif (5), .BR slapd (8), .BR slurpd (8) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man5/ud.conf.5 b/doc/man/man5/ud.conf.5 index 13575bf7ea..f9610f8335 100644 --- a/doc/man/man5/ud.conf.5 +++ b/doc/man/man5/ud.conf.5 @@ -1,9 +1,12 @@ -.TH UD.CONF 5 "18 March 1993" "U-M LDAP LDVERSION" +.TH UD.CONF 5 "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .UC 6 .SH NAME ud.conf \- ud configuration file .SH SYNOPSIS -/etc/ud.conf +ETCDIR/ud.conf .SH DESCRIPTION The .I ud @@ -17,13 +20,13 @@ configuration file. .SH OPTIONS The different configuration options are: .TP 1i -\fBserver \fP +\fBHOST \fP Used to specify the name of an LDAP server to which .I ud should connect. There may be only one entry per config file. The server's name can be specified as a domain-style name or an IP address. .TP 1i -\fBbase \fP +\fBBASE \fP Used to specify the search base to use when performing search operations. The base may be changed by those using .I ud @@ -33,7 +36,7 @@ command. There may be only one entry per config file. The base must be specified as a Distinguished Name in LDAP format. .TP 1i -\fBgroupbase \fP +\fBGROUPBASE \fP Used to specify the base used when creating groups. The base may be changed by those using .I ud @@ -43,7 +46,7 @@ command. There may be only one entry per config file. The base must be specified as a Distinguished Name in LDAP format. .TP 1i -\fBsearch \fP +\fBSEARCH \fP Used to specify a search algorithm to use when performing searches. More than one algorithm may be specified, and each is tried in turn until a suitable response is found. @@ -88,9 +91,14 @@ For example, causes this algorithm to be applied when the number of fields is exactly equal to one. If there is exactly one field, the token is looked up as a UID. .SH FILES -.I /etc/ud.conf +.I ETCDIR/ud.conf .SH "SEE ALSO" ud(1), ldap(3) .SH AUTHOR Bryan Beecher, University of Michigan +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/Makefile.in b/doc/man/man8/Makefile.in new file mode 100644 index 0000000000..795dd928a8 --- /dev/null +++ b/doc/man/man8/Makefile.in @@ -0,0 +1,6 @@ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, See COPYRIGHT file +## +## man8 Makefile.in for OpenLDAP + +MANSECT=8 diff --git a/doc/man/man8/centipede.8 b/doc/man/man8/centipede.8 index 680e9b971d..361f1aa6b4 100644 --- a/doc/man/man8/centipede.8 +++ b/doc/man/man8/centipede.8 @@ -1,8 +1,11 @@ -.TH CENTIPEDE 8C "2 December 1995" "U-M LDAP LDVERSION" +.TH CENTIPEDE 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME centipede \- LDAP centroid index generation and maintenance program .SH SYNOPSIS -.B ETCDIR/centipede +.B SBINDIR/centipede .B [\-f filter] .B [\-F] [\-R] .B [\-f filter] [\-t directory] @@ -25,7 +28,7 @@ The basic form of the command is as follows .LP .nf .ft tt - ETCDIR/centipede [options] + SBINDIR/centipede [options] -s "ldap://[host/]subtree-to-index-dn" -d "ldap://[host/]parent-of-index-entry-dn" attributes @@ -61,7 +64,7 @@ like this: .LP .nf .ft tt - ETCDIR/centipede -f '(objectclass=person)' + SBINDIR/centipede -f '(objectclass=person)' -m simple -b your-rootdn -p your-rootdnpw -s "ldap://babs.com/o=BabsCo, c=US" -d "ldap://vertigo.rs.itd.umich.edu/c=US" @@ -152,3 +155,8 @@ etc.). A future version may also allow weights to be generated. .BR slapd (8) .LP "The SLAPD and SLURPD Administrator's Guide" +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/chlog2replog.8 b/doc/man/man8/chlog2replog.8 index e99dfd81c9..d17c83cc5c 100644 --- a/doc/man/man8/chlog2replog.8 +++ b/doc/man/man8/chlog2replog.8 @@ -1,9 +1,12 @@ -.TH CHLOG2REPLOG 8C "26 April 1996" "U-M LDAP LDVERSION" +.TH CHLOG2REPLOG 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME chlog2replog \- convert an X.500 DSA-style changelog to an LDAP-style replication log .SH SYNOPSIS -.B ETCDIR/chlog2replog +.B SBINDIR/chlog2replog .B \-r hostname:port [\-r hostname:port ...] .B \-d dn\-suffix [\-o output\-file] < input\-file .LP @@ -64,7 +67,7 @@ DNs, and including a replica: entry for host "ldapserver," port .LP .nf .ft tt - ETCDIR/chlog2replog -d ", o=University of Michigan, c=US" + SBINDIR/chlog2replog -d ", o=University of Michigan, c=US" -r ldapserver:389 < changelog .ft .fi @@ -75,7 +78,7 @@ give this command: .LP .nf .ft tt - ETCDIR/chlog2replog -d ", o=University of Michigan, c=US" + SBINDIR/chlog2replog -d ", o=University of Michigan, c=US" -r ldapserver:389 -o replog < changelog .ft .fi @@ -86,7 +89,7 @@ give this command: .LP .nf .ft tt - tail +0f changelog | ETCDIR/chlog2replog + tail +0f changelog | SBINDIR/chlog2replog -d ", o=University of Michigan, c=US" -r ldapserver:389 -o replog < changelog .ft @@ -100,3 +103,8 @@ give this command: .BR slapd (8), .LP "The SLAPD and SLURPD Administrator's Guide" +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/edb2ldif.8 b/doc/man/man8/edb2ldif.8 index d2573287d6..bcfcadbe4f 100644 --- a/doc/man/man8/edb2ldif.8 +++ b/doc/man/man8/edb2ldif.8 @@ -1,4 +1,7 @@ .TH EDB2LDIF 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME edb2ldif \- QUIPU EDB file to LDIF conversion tool .SH SYNOPSIS diff --git a/doc/man/man8/go500.8 b/doc/man/man8/go500.8 index 6fbbf8f5d3..d7c2a8cb03 100644 --- a/doc/man/man8/go500.8 +++ b/doc/man/man8/go500.8 @@ -1,8 +1,11 @@ -.TH GO500 8C "27 November 1994" "U-M LDAP LDVERSION" +.TH GO500 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME go500 \- Local Gopher index search to X.500 search gateway .SH SYNOPSIS -.B ETCDIR/go500 [\-b searchbase] [\-d level] [\-l] +.B LIBEXECDIR/go500 [\-b searchbase] [\-d level] [\-l] .B [\-x hostname] [\-c rdncount] [\-f filterfile] .B [\-t templatefile] .B [\-p port] [\-I] @@ -27,7 +30,7 @@ as a stand-alone server, simply start it with no arguments .LP .nf .ft tt - ETCDIR/go500 + LIBEXECDIR/go500 .ft .fi .LP @@ -38,8 +41,8 @@ or equivalent file: .LP .nf .ft tt - if [ -f ETCDIR/go500 ]; then - ETCDIR/go500; echo ' go500' + if [ -f LIBEXECDIR/go500 ]; then + LIBEXECDIR/go500; echo ' go500' fi .ft .fi @@ -65,7 +68,7 @@ file, or the equivalent: .LP .nf .ft tt - go500 stream tcp nowait nobody ETCDIR/go500 go500 -I + go500 stream tcp nowait nobody LIBEXECDIR/go500 go500 -I .ft .fi .LP @@ -168,3 +171,8 @@ include file. .BR inetd (8), .BR gopherd (8), .BR go500gw (8) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/go500gw.8 b/doc/man/man8/go500gw.8 index 4464a88b43..066fec91af 100644 --- a/doc/man/man8/go500gw.8 +++ b/doc/man/man8/go500gw.8 @@ -1,8 +1,11 @@ -.TH GO500GW 8C "27 November 1994" "U-M LDAP LDVERSION" +.TH GO500GW 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME go500gw \- General Gopher to X.500 gateway for browsing and searching .SH SYNOPSIS -.B ETCDIR/go500gw [\-a] [\-d level] [\-f filterfile] +.B LIBEXECDIR/go500gw [\-a] [\-d level] [\-f filterfile] .B [\-t templatefile] [\-c rdncount] .B [\-h helpfile] [\-l] [\-p listenport] .B [\-P ldapport] [\-x ldaphost] [\-I] @@ -27,7 +30,7 @@ as a stand-alone server, simply start it with no arguments .LP .nf .ft tt - ETCDIR/go500gw + LIBEXECDIR/go500gw .ft .fi .LP @@ -38,8 +41,8 @@ or equivalent file: .LP .nf .ft tt - if [ -f ETCDIR/go500gw ]; then - ETCDIR/go500gw; echo ' go500gw' + if [ -f LIBEXECDIR/go500gw ]; then + LIBEXECDIR/go500gw; echo ' go500gw' fi .ft .fi @@ -64,7 +67,7 @@ file, or the equivalent: .LP .nf .ft tt - go500gw stream tcp nowait nobody ETCDIR/go500gw go500gw -I + go500gw stream tcp nowait nobody LIBEXECDIR/go500gw go500gw -I .ft .fi .LP @@ -168,3 +171,8 @@ include file. .BR inetd (8), .BR gopherd (8), .BR go500 (8) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/in.xfingerd.8 b/doc/man/man8/in.xfingerd.8 index a2cf788b18..5f65271896 100644 --- a/doc/man/man8/in.xfingerd.8 +++ b/doc/man/man8/in.xfingerd.8 @@ -1,8 +1,11 @@ -.TH IN.XFINGERD 8C "27 November 1994" "U-M LDAP LDVERSION" +.TH IN.XFINGERD 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME in.xfingerd \- Finger to LDAP/X.500 gateway daemon .SH SYNOPSIS -.B ETCDIR/in.xfingerd [\-f filterfile] [\-i] +.B LIBEXECDIR/in.xfingerd [\-f filterfile] [\-i] .B [\-l] [\-t templatefile] [\-c rdncount] [\-x hostname] .B [\-p port] .SH DESCRIPTION @@ -22,7 +25,7 @@ file, or the equivalent: .LP .nf .ft tt - finger stream tcp nowait nobody ETCDIR/in.xfingerd in.xfingerd + finger stream tcp nowait nobody LIBEXECDIR/in.xfingerd in.xfingerd .ft .fi .LP @@ -77,3 +80,8 @@ for your site. .BR ldap (3), .BR ldap_getfilter (3), .BR inetd (8), +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/ldif.8 b/doc/man/man8/ldif.8 index 3e052e16c6..be3bc42847 100644 --- a/doc/man/man8/ldif.8 +++ b/doc/man/man8/ldif.8 @@ -1,4 +1,7 @@ .TH LDIF 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldif \- convert arbitrary data to LDIF format .SH SYNOPSIS diff --git a/doc/man/man8/mail500.8 b/doc/man/man8/mail500.8 index fd9bffb105..cc40891ead 100644 --- a/doc/man/man8/mail500.8 +++ b/doc/man/man8/mail500.8 @@ -1,14 +1,17 @@ -.TH MAIL500 8C "30 November 1994" "U-M LDAP LDVERSION" +.TH MAIL500 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mail500 \- X.500 capable mailer .LP fax500 \- X.500 capable fax delivery agent .SH SYNOPSIS -.B ETCDIR/mail500 [\-d level] [\-f mailfrom] +.B LIBEXECDIR/mail500 [\-d level] [\-f mailfrom] .B [\-h hostname] [\-l ldaphost] .B [\-m address] [\-v vacationhost] .LP -.B ETCDIR/fax500 [\-d level] [\-f mailfrom] +.B LIBEXECDIR/fax500 [\-d level] [\-f mailfrom] .B [\-h hostname] [\-l ldaphost] .B [\-m address] .SH DESCRIPTION @@ -253,8 +256,8 @@ The mail500 and fax500 mailers should be defined similar to this in the sendmail.cf file: .LP .nf -Mmail500, P=ETCDIR/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u -Mfax500, P=ETCDIR/fax500, F=DFMSmnXuh, A=fax500 -f $f -h $h -m $n@$w $u +Mmail500, P=LIBEXECDIR/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u +Mfax500, P=LIBEXECDIR/fax500, F=DFMSmnXuh, A=fax500 -f $f -h $h -m $n@$w $u .fi .LP This defines how mail500/fax500 will be treated by sendmail and what @@ -285,3 +288,8 @@ but not to fax500. .BR ldap(3), .BR sendmail.cf(5), .BR sendmail(8), +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/rcpt500.8 b/doc/man/man8/rcpt500.8 index 3131812bb8..6003dee210 100644 --- a/doc/man/man8/rcpt500.8 +++ b/doc/man/man8/rcpt500.8 @@ -1,8 +1,11 @@ -.TH RCPT500 8C "16 December 1994" "U-M LDAP LDVERSION" +.TH RCPT500 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME rcpt500 \- mail to X.500 gateway program .SH SYNOPSIS -.B ETCDIR/rcpt500 [\-l] [\-h ldaphost] [\-p ldapport] +.B LIBEXECDIR/rcpt500 [\-l] [\-h ldaphost] [\-p ldapport] .B [\-b searchbase] [\-a] [\-U] [\-z sizelimit] [\-u dapuser] .B [\-f filterfile] [\-t templatefile] [\-c rdncount] .SH DESCRIPTION @@ -27,7 +30,7 @@ invoked whenever mail is sent to the address \fInamelookup\fP on your host: .nf .fi .ft tt - namelookup: "|ETCDIR/rcpt500 -l" + namelookup: "|LIBEXECDIR/rcpt500 -l" .ft .fi .SH OPTIONS @@ -77,10 +80,15 @@ for your site. .SH FILES .PD 0 .TP 20 -.B ETCDIR/rcpt500.help +.B DATADIR/rcpt500.help help file .PD .SH "SEE ALSO" .BR ldap (3), .BR aliases (5), .BR sendmail (8) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/doc/man/man8/slapadd.8 b/doc/man/man8/slapadd.8 index 15dee333ae..3c066c2cf7 100644 --- a/doc/man/man8/slapadd.8 +++ b/doc/man/man8/slapadd.8 @@ -1,4 +1,7 @@ .TH SLAPADD 8C "17 August 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slapadd \- Add entries to a SLAPD database .SH SYNOPSIS diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8 index 049041d9da..96a24e7463 100644 --- a/doc/man/man8/slapcat.8 +++ b/doc/man/man8/slapcat.8 @@ -1,4 +1,7 @@ .TH SLAPCAT 8C "17 August 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slapcat \- SLAPD database to LDIF utility .SH SYNOPSIS diff --git a/doc/man/man8/slapd.8 b/doc/man/man8/slapd.8 index 6fc43e11ba..1e353dd3b5 100644 --- a/doc/man/man8/slapd.8 +++ b/doc/man/man8/slapd.8 @@ -1,4 +1,7 @@ -.TH SLAPD 8C "3 April 1999" "OpenLDAP LDVERSION" +.TH SLAPD 8C "19 September 1999" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slapd \- Stand-alone LDAP Daemon .SH SYNOPSIS @@ -6,9 +9,7 @@ slapd \- Stand-alone LDAP Daemon .B [\-f slapd\-config\-file] .B [\-h URLs] .B [\-d debug\-level] -.B [\-p port\-number] -.B [\-P tls\-port\-number] -.B [\-s syslog\-level] [\-l syslog\-local\-user] +.B [\-n service\-name] [\-s syslog\-level] [\-l syslog\-local\-user] .B [\-u user] [\-g group] .B .SH DESCRIPTION @@ -72,6 +73,10 @@ at what level debugging statements should be logged to the .BR syslog (8) facility. .TP +.BI \-n " service\-name" +Specifies the service name for logging and other purposes. Defaults +to basename of argv[0], i.e.: "slapd". +.TP .BI \-l " syslog\-local\-user" Selects the local user of the .BR syslog (8) @@ -109,25 +114,6 @@ a DN or other optional parameters. Hosts may be specified in either Internet '.' format (preferred) or by name. Ports, if specfied, must be numeric. .TP -.BI \-p " port\-number" -.B slapd -will use on the default port (389) for LDAP URLs unless this -option is given to override the default. -A numeric port number is expected. -.TP -.BI \-P " tls\-port\-number" -.B slapd -will use on the default port (636) for LDAPS (LDAP over TLS) URLs -unless this option is given to override the default. A numeric port -number is expected. -.TP -.BI \-P " port\-number" -Changes the port where -.B slapd -will expect LDAP over raw TLS connections. If this option is not given, -the default port for this purpose (636) will be used. A numeric port -number is expected. -.TP .BI \-u " user" .B slapd will run slapd with the specified user name or id, and that user's @@ -172,8 +158,7 @@ on voluminous debugging which will be printed on standard error, type: .LP "The SLAPD and SLURPD Administrator's Guide" .SH BUGS -When using the LDBM database backend, the Modify RDN operation does not -update the attribute values in the entry that are affected by the change. +See http://www.openldap.org/its/ .SH ACKNOWLEDGEMENTS .B OpenLDAP is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). diff --git a/doc/man/man8/slurpd.8 b/doc/man/man8/slurpd.8 index 51c8c14b0d..2b8fea8b5d 100644 --- a/doc/man/man8/slurpd.8 +++ b/doc/man/man8/slurpd.8 @@ -1,4 +1,7 @@ .TH SLURPD 8C "22 September 1998" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 1998-2000 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME slurpd \- Standalone LDAP Update Replication Daemon .SH SYNOPSIS diff --git a/doc/rfc/rfc1488.txt b/doc/rfc/rfc1488.txt deleted file mode 100644 index ecafe75bfd..0000000000 --- a/doc/rfc/rfc1488.txt +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - -Network Working Group T. Howes -Request for Comments: 1488 University of Michigan - S. Kille - ISODE Consortium - W. Yeong - Performance Systems International - C. Robbins - NeXor Ltd. - July 1993 - - - The X.500 String Representation of Standard Attribute Syntaxes - -Status of this Memo - - This RFC specifies an IAB standards track protocol for the Internet - community, and requests discussion and suggestions for improvements. - Please refer to the current edition of the "IAB Official Protocol - Standards" for the standardization state and status of this protocol. - Distribution of this memo is unlimited. - -Abstract - - The Lightweight Directory Access Protocol (LDAP) [9] requires that - the contents of AttributeValue fields in protocol elements be octet - strings. This document defines the requirements that must be - satisfied by encoding rules used to render Directory attribute - syntaxes into a form suitable for use in the LDAP, then goes on to - define the encoding rules for the standard set of attribute syntaxes - defined in [1,2] and [3]. - -1. Attribute Syntax Encoding Requirements - - This section defines general requirements for lightweight directory - protocol attribute syntax encodings. All documents defining attribute - syntax encodings for use by the lightweight directory protocols are - expected to conform to these requirements. - - The encoding rules defined for a given attribute syntax must produce - octet strings. To the greatest extent possible, encoded octet - strings should be usable in their native encoded form for display - purposes. In particular, encoding rules for attribute syntaxes - defining non-binary values should produce strings that can be - displayed with little or no translation by clients implementing the - lightweight directory protocols. - - - - - - -Howes, Kille, Yeong & Robbins [Page 1] - -RFC 1488 X.500 Syntax Encoding July 1993 - - -2. Standard Attribute Syntax Encodings - - For the purposes of defining the encoding rules for the standard - attribute syntaxes, the following auxiliary BNF definitions will be - used: - - ::= 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | - 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | - 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | - 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | - 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | - 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' - - ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' - - ::= | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | - 'A' | 'B' | 'C' | 'D' | 'E' | 'F' - - ::= | | '-' - -

::= | | ''' | '(' | ')' | '+' | ',' | '-' | '.' | - '/' | ':' | '?' | ' ' - - ::= The ASCII newline character with hexadecimal value 0x0A - - ::= | - - ::= | - - ::= | - - ::= | - - ::=

|

- - ::= ' ' | ' ' - -2.1. Undefined - - Values of type Undefined are encoded as if they were values of type - Octet String. - -2.2. Case Ignore String - - A string of type caseIgnoreStringSyntax is encoded as the string - value itself. - - - - - -Howes, Kille, Yeong & Robbins [Page 2] - -RFC 1488 X.500 Syntax Encoding July 1993 - - -2.3. Case Exact String - - The encoding of a string of type caseExactStringSyntax is the string - value itself. - -2.4. Printable String - - The encoding of a string of type printableStringSyntax is the string - value itself. - -2.5. Numeric String - - The encoding of a string of type numericStringSyntax is the string - value itself. - -2.6. Octet String - - The encoding of a string of type octetStringSyntax is the string - value itself. - -2.7. Case Ignore IA5 String - - The encoding of a string of type caseIgnoreIA5String is the string - value itself. - -2.8. IA5 String - - The encoding of a string of type iA5StringSyntax is the string value - itself. - -2.9. T61 String - - The encoding of a string of type t61StringSyntax is the string value - itself. - -2.10. Case Ignore List - - Values of type caseIgnoreListSyntax are encoded according to the - following BNF: - - ::= | - '$' - - ::= a string encoded according to the rules - for Case Ignore String as above. - - - - - - -Howes, Kille, Yeong & Robbins [Page 3] - -RFC 1488 X.500 Syntax Encoding July 1993 - - -2.11. Case Exact List - - Values of type caseExactListSyntax are encoded according to the - following BNF: - - ::= | - '$' - - ::= a string encoded according to the rules for - Case Exact String as above. - -2.12. Distinguished Name - - Values of type distinguishedNameSyntax are encoded to have the - representation defined in [5]. - -2.13. Boolean - - Values of type booleanSyntax are encoded according to the following - BNF: - - ::= "TRUE" | "FALSE" - - Boolean values have an encoding of "TRUE" if they are logically true, - and have an encoding of "FALSE" otherwise. - -2.14. Integer - - Values of type integerSyntax are encoded as the decimal - representation of their values, with each decimal digit represented - by the its character equivalent. So the digit 1 is represented by the - character - -2.15. Object Identifier - - Values of type objectIdentifierSyntax are encoded according to the - following BNF: - - ::= | '.' | - - ::= - - ::= | '.' - - In the above BNF, is the syntactic representation of an - object descriptor. When encoding values of type - objectIdentifierSyntax, the first encoding option should be used in - preference to the second, which should be used in preference to the - - - -Howes, Kille, Yeong & Robbins [Page 4] - -RFC 1488 X.500 Syntax Encoding July 1993 - - - third wherever possible. That is, in encoding object identifiers, - object descriptors (where assigned and known by the implementation) - should be used in preference to numeric oids to the greatest extent - possible. For example, in encoding the object identifier representing - an organizationName, the descriptor "organizationName" is preferable - to "ds.4.10", which is in turn preferable to the string "2.5.4.10". - -2.16. Telephone Number - - Values of type telephoneNumberSyntax are encoded as if they were - Printable String types. - -2.17. Telex Number - - Values of type telexNumberSyntax are encoded according to the - following BNF: - - ::= '$' '$' - - ::= - - ::= - - ::= - - In the above, is the syntactic representation of the - number portion of the TELEX number being encoded, is the - TELEX country code, and is the answerback code of a - TELEX terminal. - -2.18. Teletex Terminal Identifier - - Values of type teletexTerminalIdentifier are encoded according to the - following BNF: - - ::= 0*( '$' ) - - In the above, the first is the encoding of the - first portion of the teletex terminal identifier to be encoded, and - the subsequent 0 or more are subsequent portions - of the teletex terminal identifier. - -2.19. Facsimile Telephone Number - - Values of type FacsimileTelephoneNumber are encoded according to the - following BNF: - - ::= [ '$' ] - - - -Howes, Kille, Yeong & Robbins [Page 5] - -RFC 1488 X.500 Syntax Encoding July 1993 - - - ::= | '$' - - ::= 'twoDimensional' | 'fineResolution' | 'unlimitedLength' | - 'b4Length' | 'a3Width' | 'b4Width' | 'uncompressed' - - In the above, the first is the actual fax number, - and the tokens represent fax parameters. - -2.20. Presentation Address - - Values of type PresentationAddress are encoded to have the - representation described in [6]. - -2.21. UTC Time - - Values of type uTCTimeSyntax are encoded as if they were Printable - Strings with the strings containing a UTCTime value. - -2.22. Guide (search guide) - - Values of type Guide, such as values of the searchGuide attribute, - are encoded according to the following BNF: - - ::= [ '#' ] - - ::= an encoded value of type objectIdentifierSyntax - - ::= | | '!' - - ::= [ '(' ] '&' [ ')' ] | - [ '(' ] '|' [ ')' ] - - ::= [ '(' ] '$' [ ')' ] - - ::= "EQ" | "SUBSTR" | "GE" | "LE" | "APPROX" - -2.23. Postal Address - -Values of type PostalAddress are encoded according to the following BNF: - - ::= | '$' - - In the above, each component of a postal address value is - encoded as a value of type t61StringSyntax. - - - - - - - -Howes, Kille, Yeong & Robbins [Page 6] - -RFC 1488 X.500 Syntax Encoding July 1993 - - -2.24. User Password - - Values of type userPasswordSyntax are encoded as if they were of type - octetStringSyntax. - -2.25. User Certificate - - Values of type userCertificate are encoded according to the following - BNF: - - ::= '#' '#' '#' - '#' - - ::= - - ::= an encoded Distinguished Name - - ::= '#' - - ::= - - ::= - - ::= | | - '{ASN}' - - ::= an encoded Distinguished Name - - ::= '#' - - ::= | '-' - - ::= '#' - - ::= an encoded UTCTime value - - ::= | - -2.26. CA Certificate - - Values of type cACertificate are encoded as if the values were of - type userCertificate. - -2.27. Authority Revocation List - - Values of type authorityRevocationList are encoded according to the - following BNF: - - - - -Howes, Kille, Yeong & Robbins [Page 7] - -RFC 1488 X.500 Syntax Encoding July 1993 - - - ::= '#' '#' - [ '#' ] - - ::= '#' - [ '#' 0*() '#'] - - ::= '#' '#' - '#' - - The syntactic components , , , - , and have the same definitions as in - the BNF for the userCertificate attribute syntax. - -2.28. Certificate Revocation List - - Values of type certificateRevocationList are encoded as if the values - were of type authorityRevocationList. - -2.29. Cross Certificate Pair - - Values of type crossCertificatePair are encoded according to the - following BNF: - - ::= '|' - - The syntactic component has the same definition as in - the BNF for the userCertificate attribute syntax. - -2.30. Delivery Method - - Values of type deliveryMethod are encoded according to the following - BNF: - - ::= | '$' - - ::= 'any' | 'mhs' | 'physical' | 'telex' | 'teletex' | - 'g3fax' | 'g4fax' | 'ia5' | 'videotex' | 'telephone' - -2.31. Other Mailbox - - Values of the type otherMailboxSyntax are encoded according to the - following BNF: - - ::= '$' - - ::= an encoded Printable String - - ::= an encoded IA5 String - - - -Howes, Kille, Yeong & Robbins [Page 8] - -RFC 1488 X.500 Syntax Encoding July 1993 - - - In the above, represents the type of mail system in - which the mailbox resides, for example "Internet" or "MCIMail"; and - is the actual mailbox in the mail system defined by - . - -2.32. Mail Preference - - Values of type mailPreferenceOption are encoded according to the - following BNF: - - ::= "NO-LISTS" | "ANY-LIST" | "PROFESSIONAL-LISTS" - -2.33. MHS OR Address - - Values of type MHS OR Address are encoded as strings, according to - the format defined in [10]. - -2.34. Photo - - Values of type Photo are encoded as if they were octet strings - containing JPEG images in the JPEG File Interchange Format (JFIF), as - described in [8]. - -2.35. Fax - - Values of type Fax are encoded as if they were octet strings - containing Group 3 Fax images as defined in [7]. - -3. Acknowledgements - - Many of the attribute syntax encodings defined in this document are - adapted from those used in the QUIPU X.500 implementation. The - contribu- tions of the authors of the QUIPU implementation in the - specification of the QUIPU syntaxes [4] are gratefully acknowledged. - -4. Bibliography - - [1] The Directory: Selected Attribute Syntaxes. CCITT, - Recommendation X.520. - - [2] Information Processing Systems -- Open Systems Interconnection -- - The Directory: Selected Attribute Syntaxes. - - [3] Barker, P., and S. Kille, "The COSINE and Internet X.500 Schema", - RFC 1274, University College London, November 1991. - - [4] The ISO Development Environment: User's Manual -- Volume 5: - QUIPU. Colin Robbins, Stephen E. Kille. - - - -Howes, Kille, Yeong & Robbins [Page 9] - -RFC 1488 X.500 Syntax Encoding July 1993 - - - [5] Kille, S., "A String Representation of Distinguished Names", RFC - 1485, July 1993. - - [6] Kille, S., "A String Representation for Presentation Addresses", - RFC 1278, University College London, November 1991. - - [7] Terminal Equipment and Protocols for Telematic Services - - Standardization of Group 3 facsimile apparatus for document - transmission. CCITT, Recommendation T.4. - - [8] JPEG File Interchange Format (Version 1.02). Eric Hamilton, C- - Cube Microsystems, Milpitas, CA, September 1, 1992. - - [9] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access - Protocol", RFC 1487, Performance Systems International, - University of Michigan, ISODE Consortium, July 1993. - - [10] Kille, S., "Mapping between X.400(1988)/ISO 10021 and RFC 822", - RFC 1327, University College London, May 1992. - -5. Security Considerations - - Security issues are not discussed in this memo. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Howes, Kille, Yeong & Robbins [Page 10] - -RFC 1488 X.500 Syntax Encoding July 1993 - - -6. Authors' Addresses - - Tim Howes - University of Michigan - ITD Research Systems - 535 W William St. - Ann Arbor, MI 48103-4943 - USA - - Phone: +1 313 747-4454 - EMail: tim@umich.edu - - - Steve Kille - ISODE Consortium - PO Box 505 - London - SW11 1DX - UK - - Phone: +44-71-223-4062 - EMail: S.Kille@isode.com - - - Wengyik Yeong - PSI, Inc. - 510 Huntmar Park Drive - Herndon, VA 22070 - USA - - Phone: +1 703-450-8001 - EMail: yeongw@psilink.com - - - Colin Robbins - NeXor Ltd - University Park - Nottingham - NG7 2RD - UK - - - - - - - - - - - -Howes, Kille, Yeong & Robbins [Page 11] - \ No newline at end of file diff --git a/doc/rfc/rfc1558.txt b/doc/rfc/rfc1558.txt deleted file mode 100644 index 1bb5bd9647..0000000000 --- a/doc/rfc/rfc1558.txt +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - -Network Working Group T. Howes -Request for Comments: 1558 University of Michigan -Category: Informational December 1993 - - - A String Representation of LDAP Search Filters - -Status of this Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -Abstract - - The Lightweight Directory Access Protocol (LDAP) [1] defines a - network representation of a search filter transmitted to an LDAP - server. Some applications may find it useful to have a common way of - representing these search filters in a human-readable form. This - document defines a human-readable string format for representing LDAP - search filters. - -1. LDAP Search Filter Definition - - An LDAP search filter is defined in [1] as follows: - - Filter ::= CHOICE { - and [0] SET OF Filter, - or [1] SET OF Filter, - not [2] Filter, - equalityMatch [3] AttributeValueAssertion, - substrings [4] SubstringFilter, - greaterOrEqual [5] AttributeValueAssertion, - lessOrEqual [6] AttributeValueAssertion, - present [7] AttributeType, - approxMatch [8] AttributeValueAssertion - } - - SubstringFilter ::= SEQUENCE { - type AttributeType, - SEQUENCE OF CHOICE { - initial [0] LDAPString, - any [1] LDAPString, - final [2] LDAPString - } - } - - - - - -Howes [Page 1] - -RFC 1558 Representation of LDAP Filters December 1993 - - - AttributeValueAssertion ::= SEQUENCE - attributeType AttributeType, - attributeValue AttributeValue - } - - AttributeType ::= LDAPString - - AttributeValue ::= OCTET STRING - - LDAPString ::= OCTET STRING - - where the LDAPString above is limited to the IA5 character set. The - AttributeType is a string representation of the attribute object - identifier in dotted OID format (e.g., "2.5.4.10"), or the shorter - string name of the attribute (e.g., "organizationName", or "o"). The - AttributeValue OCTET STRING has the form defined in [2]. The Filter - is encoded for transmission over a network using the Basic Encoding - Rules defined in [3], with simplifications described in [1]. - -2. String Search Filter Definition - - The string representation of an LDAP search filter is defined by the - following BNF. It uses a prefix format. - - ::= '(' ')' - ::= | | | - ::= '&' - ::= '|' - ::= '!' - ::= | - ::= | | - ::= - ::= | | | - ::= '=' - ::= '~=' - ::= '>=' - ::= '<=' - ::= '=*' - ::= '=' - ::= NULL | - ::= '*' - ::= NULL | '*' - ::= NULL | - - is a string representing an AttributeType, and has the format - defined in [1]. is a string representing an AttributeValue, - or part of one, and has the form defined in [2]. If a must - contain one of the characters '*' or '(' or ')', these characters - - - -Howes [Page 2] - -RFC 1558 Representation of LDAP Filters December 1993 - - - should be escaped by preceding them with the backslash '\' character. - -3. Examples - - This section gives a few examples of search filters written using - this notation. - - (cn=Babs Jensen) - (!(cn=Tim Howes)) - (&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*))) - (o=univ*of*mich*) - -4. Security Considerations - - Security issues are not discussed in this memo. - -5. References - - [1] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access - Protocol", RFC 1487, Performance Systems International, - University of Michigan, ISODE Consortium, July 1993. - - [2] Howes, T., Kille, S., Yeong, W., and C. Robbins, "The String - Representation of Standard Attribute Syntaxes", RFC 1488, - University of Michigan, ISODE Consortium, Performance Systems - International, NeXor Ltd., July 1993. - - [3] "Specification of Basic Encoding Rules for Abstract Syntax - Notation One (ASN.1)", CCITT Recommendation X.209, 1988. - -6. Author's Address - - Tim Howes - University of Michigan - ITD Research Systems - 535 W William St. - Ann Arbor, MI 48103-4943 - USA - - Phone: +1 313 747-4454 - EMail: tim@umich.edu - - - - - - - - - - -Howes [Page 3] - \ No newline at end of file diff --git a/doc/rfc/rfc2119.txt b/doc/rfc/rfc2119.txt new file mode 100644 index 0000000000..e31fae47fd --- /dev/null +++ b/doc/rfc/rfc2119.txt @@ -0,0 +1,171 @@ + + + + + + +Network Working Group S. Bradner +Request for Comments: 2119 Harvard University +BCP: 14 March 1997 +Category: Best Current Practice + + + Key words for use in RFCs to Indicate Requirement Levels + +Status of this Memo + + This document specifies an Internet Best Current Practices for the + Internet Community, and requests discussion and suggestions for + improvements. Distribution of this memo is unlimited. + +Abstract + + In many standards track documents several words are used to signify + the requirements in the specification. These words are often + capitalized. This document defines these words as they should be + interpreted in IETF documents. Authors who follow these guidelines + should incorporate this phrase near the beginning of their document: + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL + NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + RFC 2119. + + Note that the force of these words is modified by the requirement + level of the document in which they are used. + +1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that the + definition is an absolute requirement of the specification. + +2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the + definition is an absolute prohibition of the specification. + +3. SHOULD This word, or the adjective "RECOMMENDED", mean that there + may exist valid reasons in particular circumstances to ignore a + particular item, but the full implications must be understood and + carefully weighed before choosing a different course. + +4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that + there may exist valid reasons in particular circumstances when the + particular behavior is acceptable or even useful, but the full + implications should be understood and the case carefully weighed + before implementing any behavior described with this label. + + + + + +Bradner Best Current Practice [Page 1] + +RFC 2119 RFC Key Words March 1997 + + +5. MAY This word, or the adjective "OPTIONAL", mean that an item is + truly optional. One vendor may choose to include the item because a + particular marketplace requires it or because the vendor feels that + it enhances the product while another vendor may omit the same item. + An implementation which does not include a particular option MUST be + prepared to interoperate with another implementation which does + include the option, though perhaps with reduced functionality. In the + same vein an implementation which does include a particular option + MUST be prepared to interoperate with another implementation which + does not include the option (except, of course, for the feature the + option provides.) + +6. Guidance in the use of these Imperatives + + Imperatives of the type defined in this memo must be used with care + and sparingly. In particular, they MUST only be used where it is + actually required for interoperation or to limit behavior which has + potential for causing harm (e.g., limiting retransmisssions) For + example, they must not be used to try to impose a particular method + on implementors where the method is not required for + interoperability. + +7. Security Considerations + + These terms are frequently used to specify behavior with security + implications. The effects on security of not implementing a MUST or + SHOULD, or doing something the specification says MUST NOT or SHOULD + NOT be done may be very subtle. Document authors should take the time + to elaborate the security implications of not following + recommendations or requirements as most implementors will not have + had the benefit of the experience and discussion that produced the + specification. + +8. Acknowledgments + + The definitions of these terms are an amalgam of definitions taken + from a number of RFCs. In addition, suggestions have been + incorporated from a number of people including Robert Ullmann, Thomas + Narten, Neal McBurnett, and Robert Elz. + + + + + + + + + + + + +Bradner Best Current Practice [Page 2] + +RFC 2119 RFC Key Words March 1997 + + +9. Author's Address + + Scott Bradner + Harvard University + 1350 Mass. Ave. + Cambridge, MA 02138 + + phone - +1 617 495 3864 + + email - sob@harvard.edu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Bradner Best Current Practice [Page 3] + diff --git a/doc/rfc/rfc2222.txt b/doc/rfc/rfc2222.txt new file mode 100644 index 0000000000..2b0a2abc10 --- /dev/null +++ b/doc/rfc/rfc2222.txt @@ -0,0 +1,899 @@ + + + + + + +Network Working Group J. Myers +Request for Comments: 2222 Netscape Communications +Category: Standards Track October 1997 + + + Simple Authentication and Security Layer (SASL) + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1997). All Rights Reserved. + +Table of Contents + + 1. Abstract .............................................. 2 + 2. Organization of this Document ......................... 2 + 2.1. How to Read This Document ............................. 2 + 2.2. Conventions Used in this Document ..................... 2 + 2.3. Examples .............................................. 3 + 3. Introduction and Overview ............................. 3 + 4. Profiling requirements ................................ 4 + 5. Specific issues ....................................... 5 + 5.1. Client sends data first ............................... 5 + 5.2. Server returns success with additional data ........... 5 + 5.3. Multiple authentications .............................. 5 + 6. Registration procedures ............................... 6 + 6.1. Comments on SASL mechanism registrations .............. 6 + 6.2. Location of Registered SASL Mechanism List ............ 6 + 6.3. Change Control ........................................ 7 + 6.4. Registration Template ................................. 7 + 7. Mechanism definitions ................................. 8 + 7.1. Kerberos version 4 mechanism .......................... 8 + 7.2. GSSAPI mechanism ...................................... 9 + 7.2.1 Client side of authentication protocol exchange ....... 9 + 7.2.2 Server side of authentication protocol exchange ....... 10 + 7.2.3 Security layer ........................................ 11 + 7.3. S/Key mechanism ....................................... 11 + 7.4. External mechanism .................................... 12 + 8. References ............................................ 13 + 9. Security Considerations ............................... 13 + 10. Author's Address ...................................... 14 + + + +Myers Standards Track [Page 1] + +RFC 2222 SASL October 1997 + + + Appendix A. Relation of SASL to Transport Security .......... 15 + Full Copyright Statement .................................... 16 + +1. Abstract + + This document describes a method for adding authentication support to + connection-based protocols. To use this specification, a protocol + includes a command for identifying and authenticating a user to a + server and for optionally negotiating protection of subsequent + protocol interactions. If its use is negotiated, a security layer is + inserted between the protocol and the connection. This document + describes how a protocol specifies such a command, defines several + mechanisms for use by the command, and defines the protocol used for + carrying a negotiated security layer over the connection. + +2. Organization of this Document + +2.1. How to Read This Document + + This document is written to serve two different audiences, protocol + designers using this specification to support authentication in their + protocol, and implementors of clients or servers for those protocols + using this specification. + + The sections "Introduction and Overview", "Profiling requirements", + and "Security Considerations" cover issues that protocol designers + need to understand and address in profiling this specification for + use in a specific protocol. + + Implementors of a protocol using this specification need the + protocol-specific profiling information in addition to the + information in this document. + +2.2. Conventions Used in this Document + + In examples, "C:" and "S:" indicate lines sent by the client and + server respectively. + + The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" + in this document are to be interpreted as defined in "Key words for + use in RFCs to Indicate Requirement Levels" [RFC 2119]. + + + + + + + + + + +Myers Standards Track [Page 2] + +RFC 2222 SASL October 1997 + + +2.3. Examples + + Examples in this document are for the IMAP profile [RFC 2060] of this + specification. The base64 encoding of challenges and responses, as + well as the "+ " preceding the responses are part of the IMAP4 + profile, not part of the SASL specification itself. + +3. Introduction and Overview + + The Simple Authentication and Security Layer (SASL) is a method for + adding authentication support to connection-based protocols. To use + this specification, a protocol includes a command for identifying and + authenticating a user to a server and for optionally negotiating a + security layer for subsequent protocol interactions. + + The command has a required argument identifying a SASL mechanism. + SASL mechanisms are named by strings, from 1 to 20 characters in + length, consisting of upper-case letters, digits, hyphens, and/or + underscores. SASL mechanism names must be registered with the IANA. + Procedures for registering new SASL mechanisms are given in the + section "Registration procedures" + + If a server supports the requested mechanism, it initiates an + authentication protocol exchange. This consists of a series of + server challenges and client responses that are specific to the + requested mechanism. The challenges and responses are defined by the + mechanisms as binary tokens of arbitrary length. The protocol's + profile then specifies how these binary tokens are then encoded for + transfer over the connection. + + After receiving the authentication command or any client response, a + server may issue a challenge, indicate failure, or indicate + completion. The protocol's profile specifies how the server + indicates which of the above it is doing. + + After receiving a challenge, a client may issue a response or abort + the exchange. The protocol's profile specifies how the client + indicates which of the above it is doing. + + During the authentication protocol exchange, the mechanism performs + authentication, transmits an authorization identity (frequently known + as a userid) from the client to server, and negotiates the use of a + mechanism-specific security layer. If the use of a security layer is + agreed upon, then the mechanism must also define or negotiate the + maximum cipher-text buffer size that each side is able to receive. + + + + + + +Myers Standards Track [Page 3] + +RFC 2222 SASL October 1997 + + + The transmitted authorization identity may be different than the + identity in the client's authentication credentials. This permits + agents such as proxy servers to authenticate using their own + credentials, yet request the access privileges of the identity for + which they are proxying. With any mechanism, transmitting an + authorization identity of the empty string directs the server to + derive an authorization identity from the client's authentication + credentials. + + If use of a security layer is negotiated, it is applied to all + subsequent data sent over the connection. The security layer takes + effect immediately following the last response of the authentication + exchange for data sent by the client and the completion indication + for data sent by the server. Once the security layer is in effect, + the protocol stream is processed by the security layer into buffers + of cipher-text. Each buffer is transferred over the connection as a + stream of octets prepended with a four octet field in network byte + order that represents the length of the following buffer. The length + of the cipher-text buffer must be no larger than the maximum size + that was defined or negotiated by the other side. + +4. Profiling requirements + + In order to use this specification, a protocol definition must supply + the following information: + + 1. A service name, to be selected from the IANA registry of "service" + elements for the GSSAPI host-based service name form [RFC 2078]. + + 2. A definition of the command to initiate the authentication + protocol exchange. This command must have as a parameter the + mechanism name being selected by the client. + + The command SHOULD have an optional parameter giving an initial + response. This optional parameter allows the client to avoid a + round trip when using a mechanism which is defined to have the + client send data first. When this initial response is sent by the + client and the selected mechanism is defined to have the server + start with an initial challenge, the command fails. See section + 5.1 of this document for further information. + + 3. A definition of the method by which the authentication protocol + exchange is carried out, including how the challenges and + responses are encoded, how the server indicates completion or + failure of the exchange, how the client aborts an exchange, and + how the exchange method interacts with any line length limits in + the protocol. + + + + +Myers Standards Track [Page 4] + +RFC 2222 SASL October 1997 + + + 4. Identification of the octet where any negotiated security layer + starts to take effect, in both directions. + + 5. A specification of how the authorization identity passed from the + client to the server is to be interpreted. + +5. Specific issues + +5.1. Client sends data first + + Some mechanisms specify that the first data sent in the + authentication protocol exchange is from the client to the server. + + If a protocol's profile permits the command which initiates an + authentication protocol exchange to contain an initial client + response, this parameter SHOULD be used with such mechanisms. + + If the initial client response parameter is not given, or if a + protocol's profile does not permit the command which initiates an + authentication protocol exchange to contain an initial client + response, then the server issues a challenge with no data. The + client's response to this challenge is then used as the initial + client response. (The server then proceeds to send the next + challenge, indicates completion, or indicates failure.) + +5.2. Server returns success with additional data + + Some mechanisms may specify that server challenge data be sent to the + client along with an indication of successful completion of the + exchange. This data would, for example, authenticate the server to + the client. + + If a protocol's profile does not permit this server challenge to be + returned with a success indication, then the server issues the server + challenge without an indication of successful completion. The client + then responds with no data. After receiving this empty response, the + server then indicates successful completion. + +5.3. Multiple authentications + + Unless otherwise stated by the protocol's profile, only one + successful SASL negotiation may occur in a protocol session. In this + case, once an authentication protocol exchange has successfully + completed, further attempts to initiate an authentication protocol + exchange fail. + + + + + + +Myers Standards Track [Page 5] + +RFC 2222 SASL October 1997 + + + In the case that a profile explicitly permits multiple successful + SASL negotiations to occur, then in no case may multiple security + layers be simultaneously in effect. If a security layer is in effect + and a subsequent SASL negotiation selects no security layer, the + original security layer remains in effect. If a security layer is in + effect and a subsequent SASL negotiation selects a second security + layer, then the second security layer replaces the first. + +6. Registration procedures + + Registration of a SASL mechanism is done by filling in the template + in section 6.4 and sending it in to iana@isi.edu. IANA has the right + to reject obviously bogus registrations, but will perform no review + of clams made in the registration form. + + There is no naming convention for SASL mechanisms; any name that + conforms to the syntax of a SASL mechanism name can be registered. + + While the registration procedures do not require it, authors of SASL + mechanisms are encouraged to seek community review and comment + whenever that is feasible. Authors may seek community review by + posting a specification of their proposed mechanism as an internet- + draft. SASL mechanisms intended for widespread use should be + standardized through the normal IETF process, when appropriate. + +6.1. Comments on SASL mechanism registrations + + Comments on registered SASL mechanisms should first be sent to the + "owner" of the mechanism. Submitters of comments may, after a + reasonable attempt to contact the owner, request IANA to attach their + comment to the SASL mechanism registration itself. If IANA approves + of this the comment will be made accessible in conjunction with the + SASL mechanism registration itself. + +6.2. Location of Registered SASL Mechanism List + + SASL mechanism registrations will be posted in the anonymous FTP + directory "ftp://ftp.isi.edu/in-notes/iana/assignments/sasl- + mechanisms/" and all registered SASL mechanisms will be listed in the + periodically issued "Assigned Numbers" RFC [currently STD 2, RFC + 1700]. The SASL mechanism description and other supporting material + may also be published as an Informational RFC by sending it to "rfc- + editor@isi.edu" (please follow the instructions to RFC authors [RFC + 2223]). + + + + + + + +Myers Standards Track [Page 6] + +RFC 2222 SASL October 1997 + + +6.3. Change Control + + Once a SASL mechanism registration has been published by IANA, the + author may request a change to its definition. The change request + follows the same procedure as the registration request. + + The owner of a SASL mechanism may pass responsibility for the SASL + mechanism to another person or agency by informing IANA; this can be + done without discussion or review. + + The IESG may reassign responsibility for a SASL mechanism. The most + common case of this will be to enable changes to be made to + mechanisms where the author of the registration has died, moved out + of contact or is otherwise unable to make changes that are important + to the community. + + SASL mechanism registrations may not be deleted; mechanisms which are + no longer believed appropriate for use can be declared OBSOLETE by a + change to their "intended use" field; such SASL mechanisms will be + clearly marked in the lists published by IANA. + + The IESG is considered to be the owner of all SASL mechanisms which + are on the IETF standards track. + +6.4. Registration Template + + To: iana@iana.org + Subject: Registration of SASL mechanism X + + SASL mechanism name: + + Security considerations: + + Published specification (optional, recommended): + + Person & email address to contact for further information: + + Intended usage: + + (One of COMMON, LIMITED USE or OBSOLETE) + + Author/Change controller: + + (Any other information that the author deems interesting may be + added below this line.) + + + + + + +Myers Standards Track [Page 7] + +RFC 2222 SASL October 1997 + + +7. Mechanism definitions + + The following mechanisms are hereby defined. + +7.1. Kerberos version 4 mechanism + + The mechanism name associated with Kerberos version 4 is + "KERBEROS_V4". + + The first challenge consists of a random 32-bit number in network + byte order. The client responds with a Kerberos ticket and an + authenticator for the principal "service.hostname@realm", where + "service" is the service name specified in the protocol's profile, + "hostname" is the first component of the host name of the server with + all letters in lower case, and where "realm" is the Kerberos realm of + the server. The encrypted checksum field included within the + Kerberos authenticator contains the server provided challenge in + network byte order. + + Upon decrypting and verifying the ticket and authenticator, the + server verifies that the contained checksum field equals the original + server provided random 32-bit number. Should the verification be + successful, the server must add one to the checksum and construct 8 + octets of data, with the first four octets containing the incremented + checksum in network byte order, the fifth octet containing a bit-mask + specifying the security layers supported by the server, and the sixth + through eighth octets containing, in network byte order, the maximum + cipher-text buffer size the server is able to receive. The server + must encrypt using DES ECB mode the 8 octets of data in the session + key and issue that encrypted data in a second challenge. The client + considers the server authenticated if the first four octets of the + un-encrypted data is equal to one plus the checksum it previously + sent. + + The client must construct data with the first four octets containing + the original server-issued checksum in network byte order, the fifth + octet containing the bit-mask specifying the selected security layer, + the sixth through eighth octets containing in network byte order the + maximum cipher-text buffer size the client is able to receive, and + the following octets containing the authorization identity. The + client must then append from one to eight zero-valued octets so that + the length of the data is a multiple of eight octets. The client must + then encrypt using DES PCBC mode the data with the session key and + respond with the encrypted data. The server decrypts the data and + verifies the contained checksum. The server must verify that the + principal identified in the Kerberos ticket is authorized to connect + as that authorization identity. After this verification, the + authentication process is complete. + + + +Myers Standards Track [Page 8] + +RFC 2222 SASL October 1997 + + + The security layers and their corresponding bit-masks are as follows: + + 1 No security layer + 2 Integrity (krb_mk_safe) protection + 4 Privacy (krb_mk_priv) protection + + Other bit-masks may be defined in the future; bits which are not + understood must be negotiated off. + + EXAMPLE: The following are two Kerberos version 4 login scenarios to + the IMAP4 protocol (note that the line breaks in the sample + authenticators are for editorial clarity and are not in real + authenticators) + + S: * OK IMAP4 Server + C: A001 AUTHENTICATE KERBEROS_V4 + S: + AmFYig== + C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT + +nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd + WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh + S: + or//EoAADZI= + C: DiAF5A4gA+oOIALuBkAAmw== + S: A001 OK Kerberos V4 authentication successful + + + S: * OK IMAP4 Server + C: A001 AUTHENTICATE KERBEROS_V4 + S: + gcfgCA== + C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT + +nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd + WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh + S: A001 NO Kerberos V4 authentication failed + +7.2. GSSAPI mechanism + + The mechanism name associated with all mechanisms employing the + GSSAPI [RFC 2078] is "GSSAPI". + +7.2.1 Client side of authentication protocol exchange + + The client calls GSS_Init_sec_context, passing in 0 for + input_context_handle (initially) and a targ_name equal to output_name + from GSS_Import_Name called with input_name_type of + GSS_C_NT_HOSTBASED_SERVICE and input_name_string of + "service@hostname" where "service" is the service name specified in + the protocol's profile, and "hostname" is the fully qualified host + name of the server. The client then responds with the resulting + output_token. If GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED, + + + +Myers Standards Track [Page 9] + +RFC 2222 SASL October 1997 + + + then the client should expect the server to issue a token in a + subsequent challenge. The client must pass the token to another call + to GSS_Init_sec_context, repeating the actions in this paragraph. + + When GSS_Init_sec_context returns GSS_S_COMPLETE, the client takes + the following actions: If the last call to GSS_Init_sec_context + returned an output_token, then the client responds with the + output_token, otherwise the client responds with no data. The client + should then expect the server to issue a token in a subsequent + challenge. The client passes this token to GSS_Unwrap and interprets + the first octet of resulting cleartext as a bit-mask specifying the + security layers supported by the server and the second through fourth + octets as the maximum size output_message to send to the server. The + client then constructs data, with the first octet containing the + bit-mask specifying the selected security layer, the second through + fourth octets containing in network byte order the maximum size + output_message the client is able to receive, and the remaining + octets containing the authorization identity. The client passes the + data to GSS_Wrap with conf_flag set to FALSE, and responds with the + generated output_message. The client can then consider the server + authenticated. + +7.2.2 Server side of authentication protocol exchange + + The server passes the initial client response to + GSS_Accept_sec_context as input_token, setting input_context_handle + to 0 (initially). If GSS_Accept_sec_context returns + GSS_S_CONTINUE_NEEDED, the server returns the generated output_token + to the client in challenge and passes the resulting response to + another call to GSS_Accept_sec_context, repeating the actions in this + paragraph. + + When GSS_Accept_sec_context returns GSS_S_COMPLETE, the client takes + the following actions: If the last call to GSS_Accept_sec_context + returned an output_token, the server returns it to the client in a + challenge and expects a reply from the client with no data. Whether + or not an output_token was returned (and after receipt of any + response from the client to such an output_token), the server then + constructs 4 octets of data, with the first octet containing a bit- + mask specifying the security layers supported by the server and the + second through fourth octets containing in network byte order the + maximum size output_token the server is able to receive. The server + must then pass the plaintext to GSS_Wrap with conf_flag set to FALSE + and issue the generated output_message to the client in a challenge. + The server must then pass the resulting response to GSS_Unwrap and + interpret the first octet of resulting cleartext as the bit-mask for + the selected security layer, the second through fourth octets as the + maximum size output_message to send to the client, and the remaining + + + +Myers Standards Track [Page 10] + +RFC 2222 SASL October 1997 + + + octets as the authorization identity. The server must verify that + the src_name is authorized to authenticate as the authorization + identity. After these verifications, the authentication process is + complete. + +7.2.3 Security layer + + The security layers and their corresponding bit-masks are as follows: + + 1 No security layer + 2 Integrity protection. + Sender calls GSS_Wrap with conf_flag set to FALSE + 4 Privacy protection. + Sender calls GSS_Wrap with conf_flag set to TRUE + + Other bit-masks may be defined in the future; bits which are not + understood must be negotiated off. + +7.3. S/Key mechanism + + The mechanism name associated with S/Key [RFC 1760] using the MD4 + digest algorithm is "SKEY". + + The client sends an initial response with the authorization identity. + + The server then issues a challenge which contains the decimal + sequence number followed by a single space and the seed string for + the indicated authorization identity. The client responds with the + one-time-password, as either a 64-bit value in network byte order or + encoded in the "six English words" format. + + The server must verify the one-time-password. After this + verification, the authentication process is complete. + + S/Key authentication does not provide for any security layers. + + EXAMPLE: The following are two S/Key login scenarios in the IMAP4 + protocol. + + S: * OK IMAP4 Server + C: A001 AUTHENTICATE SKEY + S: + + C: bW9yZ2Fu + S: + OTUgUWE1ODMwOA== + C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA== + S: A001 OK S/Key authentication successful + + + + + +Myers Standards Track [Page 11] + +RFC 2222 SASL October 1997 + + + S: * OK IMAP4 Server + C: A001 AUTHENTICATE SKEY + S: + + C: c21pdGg= + S: + OTUgUWE1ODMwOA== + C: BsAY3g4gBNo= + S: A001 NO S/Key authentication failed + + The following is an S/Key login scenario in an IMAP4-like protocol + which has an optional "initial response" argument to the AUTHENTICATE + command. + + S: * OK IMAP4-Like Server + C: A001 AUTHENTICATE SKEY bW9yZ2Fu + S: + OTUgUWE1ODMwOA== + C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA== + S: A001 OK S/Key authentication successful + +7.4. External mechanism + + The mechanism name associated with external authentication is + "EXTERNAL". + + The client sends an initial response with the authorization identity. + + The server uses information, external to SASL, to determine whether + the client is authorized to authenticate as the authorization + identity. If the client is so authorized, the server indicates + successful completion of the authentication exchange; otherwise the + server indicates failure. + + The system providing this external information may be, for example, + IPsec or TLS. + + If the client sends the empty string as the authorization identity + (thus requesting the authorization identity be derived from the + client's authentication credentials), the authorization identity is + to be derived from authentication credentials which exist in the + system which is providing the external authentication. + + + + + + + + + + + + +Myers Standards Track [Page 12] + +RFC 2222 SASL October 1997 + + +8. References + + [RFC 2060] Crispin, M., "Internet Message Access Protocol - Version + 4rev1", RFC 2060, December 1996. + + [RFC 2078] Linn, J., "Generic Security Service Application Program + Interface, Version 2", RFC 2078, January 1997. + + [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", RFC 2119, March 1997. + + [RFC 2223] Postel, J., and J. Reynolds, "Instructions to RFC + Authors", RFC 2223, October 1997. + + [RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC + 1760, February 1995. + + [RFC 1700] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, + RFC 1700, October 1994. + +9. Security Considerations + + Security issues are discussed throughout this memo. + + The mechanisms that support integrity protection are designed such + that the negotiation of the security layer and authorization identity + is integrity protected. When the client selects a security layer + with at least integrity protection, this protects against an active + attacker hijacking the connection and modifying the authentication + exchange to negotiate a plaintext connection. + + When a server or client supports multiple authentication mechanisms, + each of which has a different security strength, it is possible for + an active attacker to cause a party to use the least secure mechanism + supported. To protect against this sort of attack, a client or + server which supports mechanisms of different strengths should have a + configurable minimum strength that it will use. It is not sufficient + for this minimum strength check to only be on the server, since an + active attacker can change which mechanisms the client sees as being + supported, causing the client to send authentication credentials for + its weakest supported mechanism. + + + + + + + + + + +Myers Standards Track [Page 13] + +RFC 2222 SASL October 1997 + + + The client's selection of a SASL mechanism is done in the clear and + may be modified by an active attacker. It is important for any new + SASL mechanisms to be designed such that an active attacker cannot + obtain an authentication with weaker security properties by modifying + the SASL mechanism name and/or the challenges and responses. + + Any protocol interactions prior to authentication are performed in + the clear and may be modified by an active attacker. In the case + where a client selects integrity protection, it is important that any + security-sensitive protocol negotiations be performed after + authentication is complete. Protocols should be designed such that + negotiations performed prior to authentication should be either + ignored or revalidated once authentication is complete. + +10. Author's Address + + John G. Myers + Netscape Communications + 501 E. Middlefield Road + Mail Stop MV-029 + Mountain View, CA 94043-4042 + + EMail: jgmyers@netscape.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Myers Standards Track [Page 14] + +RFC 2222 SASL October 1997 + + +Appendix A. Relation of SASL to Transport Security + + Questions have been raised about the relationship between SASL and + various services (such as IPsec and TLS) which provide a secured + connection. + + Two of the key features of SASL are: + + 1. The separation of the authorization identity from the identity in + the client's credentials. This permits agents such as proxy + servers to authenticate using their own credentials, yet request + the access privileges of the identity for which they are proxying. + + 2. Upon successful completion of an authentication exchange, the + server knows the authorization identity the client wishes to use. + This allows servers to move to a "user is authenticated" state in + the protocol. + + These features are extremely important to some application protocols, + yet Transport Security services do not always provide them. To + define SASL mechanisms based on these services would be a very messy + task, as the framing of these services would be redundant with the + framing of SASL and some method of providing these important SASL + features would have to be devised. + + Sometimes it is desired to enable within an existing connection the + use of a security service which does not fit the SASL model. (TLS is + an example of such a service.) This can be done by adding a command, + for example "STARTTLS", to the protocol. Such a command is outside + the scope of SASL, and should be different from the command which + starts a SASL authentication protocol exchange. + + In certain situations, it is reasonable to use SASL underneath one of + these Transport Security services. The transport service would + secure the connection, either service would authenticate the client, + and SASL would negotiate the authorization identity. The SASL + negotiation would be what moves the protocol from "unauthenticated" + to "authenticated" state. The "EXTERNAL" SASL mechanism is + explicitly intended to handle the case where the transport service + secures the connection and authenticates the client and SASL + negotiates the authorization identity. + + When using SASL underneath a sufficiently strong Transport Security + service, a SASL security layer would most likely be redundant. The + client and server would thus probably want to negotiate off the use + of a SASL security layer. + + + + + +Myers Standards Track [Page 15] + +RFC 2222 SASL October 1997 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1997). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implmentation may be prepared, copied, published + andand distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Myers Standards Track [Page 16] + diff --git a/doc/rfc/rfc2649.txt b/doc/rfc/rfc2649.txt new file mode 100644 index 0000000000..fb5f38eab8 --- /dev/null +++ b/doc/rfc/rfc2649.txt @@ -0,0 +1,563 @@ + + + + + + +Network Working Group B. Greenblatt +Request for Comments: 2649 P. Richard +Category: Experimental August 1999 + + + An LDAP Control and Schema for Holding Operation Signatures + +Status of this Memo + + This memo defines an Experimental Protocol for the Internet + community. It does not specify an Internet standard of any kind. + Discussion and suggestions for improvement are requested. + Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + In many environments clients require the ability to validiate the + source and integrity of information provided by the directory. This + document describes an LDAP message control which allows for the + retrieval of digitally signed information. This document defines an + LDAP v3 based mechanism for signing directory operations in order to + create a secure journal of changes that have been made to each + directory entry. Both client and server based signatures are + supported. An object class for subsequent retrieval are "journal + entries" is also defined. This document specifies LDAP v3 controls + that enable this functionality. It also defines an LDAP v3 schema + that allows for subsequent browsing of the journal information. + +Table of Contents + + 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 + 1.1 Audit Trail Mechanism . . . . . . . . . . . . . . . . . . . 2 + 1.2. Handling the Delete Operation . . . . . . . . . . . . . . . 5 + 2. Signed Results Mechanism . . . . . . . . . . . . . . . . . . 6 + 3. Security Considerations and Other Notes . . . . . . . . . . 7 + 4. References . . . . . . . . . . . . . . . . . . . . . . . . . 8 + 5. Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 9 + 6. Full Copyright Statement . . . . . . . . . . . . . . . . . . 10 + + + + + + + + + +Greenblatt & Richard Experimental [Page 1] + +RFC 2649 LDAP Control and Schema August 1999 + + +1. Introduction + + In many environments clients require the ability to validiate the + source and integrity of information provided by the directory. This + document describes an LDAP message control which allows for the + retrieval of digitally signed information. The perspective of this + document is that the origin of the information that is stored in LDAP + v3 accessible directories is the LDAP v3 client that creates the + information. The source and integrity of the information is + guaranteed by allowing for the digital signing of the operations that + make changes to entries in the directory. The source and integrity + of an individual LDAP connection can be guaranteed by making use of + an underlying session layer that provides such services, such as TLS. + Note that the integrity of an individual connection does not, in and + of itself guarantee the integrity of the data that comes across the + connection. This is due to the fact that the LDAP server is only + capable of providing information that it has stored. In distributed + and replicated environments, the fact that an entry has been + successfully retrieved from a server may not be completely + reassuring, if the entry in question was replicated from an untrusted + domain. + + By making use of public key technology, and creating digitally signed + transactions that are created by the LDAP v3 client as entries are + created and modified, a complete journal of the history of the entry + is available. Since each entry in the journal has been digitally + signed with the private key of the creator, or modifier of the entry, + the source and integrity of the directory entry can be validated by + verifying the signature of each entry in the journal. Note that not + all of the journal entries will have been signed by the same user. + +1.1. Audit Trail Mechanism + + Signed directory operations is a straightforward application of + S/MIME technology that also leverages the extensible framework that + is provided by LDAP version 3. LDAP version 3 is defined in [4], and + S/MIME is defined in [2]. The security used in S/MIME is based in + the definitions in [1]. The basic idea is that the submitter of an + LDAP operation that changes the directory information includes an + LDAP version 3 control that includes either a signature of the + operation, or a request that the LDAP server sign the operation on + the behalf of the LDAP client. The result of the operation (in + addition to the change of the directory information), is additional + information that is attached to directory objects, that includes the + audit trail of signed operations. The LDAP control is (OID = + 1.2.840.113549.6.0.0): + + + + + +Greenblatt & Richard Experimental [Page 2] + +RFC 2649 LDAP Control and Schema August 1999 + + + SignedOperation ::= CHOICE { + signbyServer NULL, + signatureIncluded OCTET STRING + } + + If the SignatureIncluded CHOICE is used, then the OCTET string is + just an S/MIME message of the multipart/signed variety, that is + composed of a single piece, that is the signature of the directory + operation. Multipart/signed MIME objects are defined in [3]. If the + SignbyServer CHOICE us used, then the LDAP server creates the + signature on behalf of the client, using its own identity and not the + identity of the client, in order to produce the audit trail entry. + In either case the successful result of processing the control is the + creation of additional information in the directory entry that is + being modified or created. The signature of the LDAP operation is + computed on the LDAPMessage prior to the inclusion of the + SignedOperation control. The procedure is as follows: + + - Build LDAPMessage without the SignedOperation control + - Compute signature on the above LDAPMessage + - Create new LDAPMessage that includes the old MessageID, + protocolOp and any control fields from the previous LDAPMessage, + plus the computed signature formatted as an S/MIME message. + + No control is defined for the server to return in the LDAPResult as + defined in [4]. The LDAP server MAY attempt to parse and verify the + signature included in the SignedOperation control, but is not + required to. The server can accept the signed operation without + verifying the signature. Signature verification can be quite a + lengthy operation, requiring complex certificate chain traversals. + This allows a more timely creation of the audit trail by the server. + Any LDAP client browsing the directory that retrieves the 'Changes' + (defined in the following paragraphs) attributes, should verify the + signature of each value according to the local signature verification + policies. Even if the LDAP server verifies the signature contained + in the singed operation, the LDAP client has no way of knowing what + policies were followed by the server in order to verify the + signature. + + If the LDAP server is unable to verify the signature and wishes to + return an error then the error code unwillingToPerform(53) should be + returned, and the entire LDAP operation fails. In this situation, an + appropriate message (e.g. "Unable to verify signature") MAY be + included in the errorMessage of the LDAPResult. The SignedOperation + Control MAY be marked CRITICAL, and if it is CRITICAL then if the + LDAP Server performs the LDAP operation, then must include the + signature in the signedAuditTrail information. + + + + +Greenblatt & Richard Experimental [Page 3] + +RFC 2649 LDAP Control and Schema August 1999 + + + The schema definition for the signedAuditTrail information is: + + ( 1.2.840.113549.6.1.0 + NAME 'signedAuditTrail' + SUP top + AUXILIARY + MUST ( + Changes + ) + ) + + The format of the Changes attribute is: + + ( 1.2.840.113549.6.2.0 + NAME 'Changes' + DESC 'a set of changes applied to an entry' + SYNTAX 'Binary' ) + + The actual format of the Changes attribute is: + + Changes ::= SEQUENCE { + sequenceNumber [0] INTEGER (0 .. maxInt), + signedOperation [1] OCTET STRING } + + The SignedOperation attribute is a multipart/signed S/MIME message. + Part 1 of the message is the directory operation, and part 2 is the + signature. Sequence number 0 (if present) always indicates the + starting point directory object as represented by the definitions in + "A MIME Content-Type for Directory Information", as defined in [5]. + Subsequent sequence numbers indicate the sequence of changes that + have been made to this directory object. Note that the sequence of + the changes can be verified due to the fact that the signed directory + object will have a timestamp as part of the signature object, and + that the sequence numbering as part of the change attribute should be + considered to be an unverified aid to the LDAP client. Sequence + numbers are meaningful only within the context of a single directory + entry, and LDAP servers are not expected to maintain these sequence + numbers across all entries in the directory. + + Some LDAP servers will only allow operations that include the + SignedOperation control. This is indicated by the inclusion of a + 'signedDirectoryOperationSupport' attribute in the rootDSE. This + attribute is defined as: + + + + + + + + +Greenblatt & Richard Experimental [Page 4] + +RFC 2649 LDAP Control and Schema August 1999 + + + 1.2.840.113549.6.2.2 + NAME 'signedDirectoryOperationSupport' + DESC 'how many of the LDAP operations must be signed' + SYNTAX 'Integer' SINGLE-VALUE ) + + The 'signedDirectoryOperationSupport' attribute above may have one of + the values, '0', '1' or '2' with the following meanings: + + - '0' Directory Operations may be signed + - '1' Directory Operations must always be signed + - '2' Directory Operations must never be signed + + Some LDAP servers will desire that the audit trail be continuous, and + not contain any gaps that would result from unsigned operations. + Such server will include a signature on each LDAP operation that + changes a directory entry, even when the LDAP client does not include + a signed-Operation control. + +1.2. Handling the Delete Operation + + The LDAP Delete operation represents an interesting case for Signed + Directory Operations. This is due to the case that subsequent to the + successful completion of the Delete Operation, the object that would + have held the latest 'Changes' attribute no longer exists. In order + to handle this situation, a new object class is defined to represent + a directory object that has been deleted. + + ( 1.2.840.113549.6.1.2 + NAME 'zombieObject' + SUP top + STRUCTURAL + MUST ( + Cn $ Changes $ OriginalObject + ) + ) + + The format of the OriginalObject attribute is: + + ( 1.2.840.113549.6.2.1 + NAME OriginalObject + DESC 'The LDAP URL of an object that has been deleted from the + directory' SYNTAX 'Binary' ) + + The OriginalObject attribute contains the URL of the object that was + deleted from the directory. It is formatted in accordance with RFC + 2255. Directory servers that comply with this specification SHOULD + create a zombieObject when performing the delete Operation that + contains a SignedOperation LDAPControl. The Cn attribute of the + + + +Greenblatt & Richard Experimental [Page 5] + +RFC 2649 LDAP Control and Schema August 1999 + + + zombieObject is synthesized by the LDAP server, and may or may not be + related to the original name of the directory entry that was deleted. + All changes attributes that were attached to the original entry are + copied over to the zombieObject. In addition the LDAP Server MUST + attach the signature of the Delete operation as the last successful + change that was made to the entry. + +2. Signed Results Mechanism + + A control is also defined that allows the LDAP v3 client to request + that the server sign the results that it returns. It is intended + that this control is primarily used in concert with the LDAPSearch + operation. This control MAY be marked as CRITICAL. If it is marked + as CRITICAL and the LDAP Server supports this operation, then all + search results MUST be returned with a signature as attached in the + SignedResult control if it is willing to sign results for this user. + If the server supports this control but does not wish to sign the + results for this user then the error code unwillingToPerform(53) + should be returned, and the LDAP search will have failed. In this + situation, an appropriate message (e.g. "Unwilling to sign results + for you!") MUST be included in the errorMessage of the LDAPResult. + If the LDAPSigType has the value FALSE then the client is requesting + that the server not sign this operation. This may be done in + situations where servers are configured to always sign their + operations. + + The LDAP control to include in the LDAP request is (OID = + 1.2.840.113549.6.0.1): + + DemandSignedResult ::= LDAPSigType + + LDAPSigType ::= BOOLEAN + + In response to a DemandSignedResult control, the LDAP v3 server will + return a SignedResult control in addition to the normal result as + defined by the operation (assuming that the server understands the + con- trol, and is willing to perform it). The SignedResult control + MUST NOT be marked CRITICAL. Some LDAP v3 servers may be configured + to sign all of their operations. In this situation the server always + returns a SignedResult control, unless instructed otherwise by the + DemandSigne-dResult Control. Since the SignedResult control is not + marked critical, the LDAP client is allowed to ignore it. The + signature field below includes the signature of the enitre LDAPResult + formatted as an S/MIME pkcs-7/signature object, as defined in [2]. + + + + + + + +Greenblatt & Richard Experimental [Page 6] + +RFC 2649 LDAP Control and Schema August 1999 + + + The procedure for creating the signature of the signedResult control + is the same as the procedure for the creation of the signedOperation + control. The LDAP control in the LDAP response is (OID = + 1.2.840.113549.6.0.2): + + SignedResult ::= CHOICE { + signature OCTET STRING } + +3. Security Considerations and Other Notes + + The base OIDs are: + + rsadsiLdap ::= {1 2 840 113549 6} + rsadsiLdapControls ::= {1 2 840 113549 6 0} + rsadsiLdapObjectClasses ::= {1 2 840 113549 6 1} + rsadsiLdapAttributes ::= {1 2 840 113549 6 2} + + + The complete ASN.1 module for this specification is: + + SIGNEDOPERATIONS DEFINITIONS ::= + BEGIN + + SignedOperation ::= CHOICE { + signbyServer NULL, + signatureIncluded OCTET STRING + } + + Changes ::= SEQUENCE { + sequenceNumber [0] INTEGER (0 .. maxInt), + signedOperation [1] OCTET STRING } + + DemandSignedResult ::= LDAPSigType + + LDAPSigType ::= BOOLEAN + + SignedResult ::= CHOICE { + signature OCTET STRING } + + + END + + + + + + + + + + +Greenblatt & Richard Experimental [Page 7] + +RFC 2649 LDAP Control and Schema August 1999 + + + If any of the controls in this specification are supported by an LDAP + v3 server then that server MUST make available its certificate (if + any) in the userCertificate attribute of its rootDSE object. The + UserCertificate attribute is defined in [6], and contains the public + key of the server that is used in the creation of the various + signatures defined in this specification. + + It is not the intention of this specification to provide a mechanism + that guarantees the origin and integrity of LDAP v3 operations. Such + a service is best provided by the use of an underlying protocol such + as TLS [8]. TLS defines additional features such as encryption and + compression. This specification does not define support for + encrypted operations. + + This memo proposes protocol elements for transmission and storage of + the digital signatures of LDAP operations. Though the LDAP server + may have verified the operation signatures prior to their storage and + subsequent retrieval, it is prudent for LDAP clients to verify the + signatures contained in the chained attribute upon their retrieval. + The issuing Certification Authorities of the signer's certificate + should also be consulted in order to determine if the signer's + private key has been compromised or the certificate has been + otherwise revoked. Security considerations are discussed throughout + this memo. + +4. References + + [1] Kaliski, B., "PKCS 7: Cryptographic Message Syntax Version 1-5", + RFC 2315, March 1998. + + [2] Dusse, S., Hoffman, P., Ramsdell, B., Lundblade, L. and L. + Repka., "S/MIME Version 2 Message Specification", RFC 2311, March + 1998. + + [3] Galvin, J., Murphy, S., Crocker, S. and N. Freed, "Security + Multiparts for MIME: Multipart/Signed and Multipart/Encrypted", + RFC 1847, October 1995. + + [4] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access + Protocol (v3)", RFC 2251, December 1997. + + [5] Howes, T., Smith, M. and F. Dawson, "A MIME Content-Type for + Directory Information", RFC 2425, September 1998. + + [6] Wahl, M., "A Summary of the X.500(96) User Schema for use with + LDAPv3", RFC 2256, December 1997. + + + + + +Greenblatt & Richard Experimental [Page 8] + +RFC 2649 LDAP Control and Schema August 1999 + + + [7] Howes, T. and M. Smith, "The LDAP URL Format", RFC 2255, December + 1997. + + [8] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC + 2246, January 1999. + +5. Authors' Addresses + + Bruce Greenblatt + San Jose, CA 95119 + USA + + Phone: +1-408-224-5349 + EMail: bgreenblatt@directory-applications.com + + + Pat Richard + Xcert Software, Inc. + Suite 1001 - 701 W. Georgia + Vancouver, BC + CANADA V6G 1C9 + + EMail: patr@xcert.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Greenblatt & Richard Experimental [Page 9] + +RFC 2649 LDAP Control and Schema August 1999 + + +6. Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Greenblatt & Richard Experimental [Page 10] + diff --git a/doc/rfc/rfc2657.txt b/doc/rfc/rfc2657.txt new file mode 100644 index 0000000000..d23a877081 --- /dev/null +++ b/doc/rfc/rfc2657.txt @@ -0,0 +1,675 @@ + + + + + + +Network Working Group R. Hedberg +Request for Comment: 2657 Catalogix +Category: Experimental August 1999 + + + LDAPv2 Client vs. the Index Mesh + +Status of this Memo + + This memo defines an Experimental Protocol for the Internet + community. It does not specify an Internet standard of any kind. + Discussion and suggestions for improvement are requested. + Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + LDAPv2 clients as implemented according to RFC 1777 [1] have no + notion on referral. The integration between such a client and an + Index Mesh, as defined by the Common Indexing Protocol [2], heavily + depends on referrals and therefore needs to be handled in a special + way. This document defines one possible way of doing this. + +1. Background + + During the development of the Common Indexing Protocol (CIP), one of + the underlying assumptions was that the interaction between clients + and the Index Mesh Servers [1] would heavily depend on the passing of + referrals. Protocols like LDAPv2 [2] that lack this functionality + need to compensate for it by some means. The way chosen in this memo + is to add more intelligence into the client. There are two reasons + behind this decision. First, this is not a major enhancement that is + needed and secondly, that the intelligence when dealing with the + Index Mesh, with or the knowledge about referrals, eventually has to + go into the client. + +2. The clients view of the Index Mesh + + If a LDAPv2 client is going to be able to interact with the Index + Mesh, the Mesh has to appear as something that is understandable to + the client. Basically, this consists of representing the index + servers and their contained indexes in a defined directory + information tree (DIT) [3,4] structure and a set of object classes + and attribute types that have been proven to be useful in this + context. + + + +Hedberg Experimental [Page 1] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +2.1 The CIP Object Classes + + Object class descriptions are written according to the BNF defined in + [5]. + +2.1.1 cIPIndex + + The cIPIndex objectClass, if present in a entry, allows it to hold + one indexvalue and information connected to this value. + + ( 1.2.752.17.3.9 + NAME 'cIPIndex' + SUP 'top' + STRUCTURAL + MUST ( extendedDSI $ idx ) + MAY ( indexOCAT ) + ) + +2.1.2 cIPDataSet + + The cIPDataSet objectClass, if present in a entry, allows it to hold + information concerning one DataSet. + + ( 1.2.752.17.3.10 + NAME 'cIPDataSet' + SUP 'top' + STRUCTURAL + MUST ( dSI $ searchBase ) + MAY ( indexOCAT $ description $ indexType $ + accessPoint $ protocolVersion $ polledBy $ + updateIntervall $ securityOption $ + supplierURI $ consumerURI $ baseURI $ + attributeNamespace $ consistencyBase + ) + ) + +2.2 The CIP attributeTypes + + The attributes idx, indexOCAT, extendedDSI, description, + cIPIndexType, baseURI, dSI are used by a client accessing the index + server. The other attributes (accesspoint, protocolVersion, + polledBy, updateIntervall, consumerURI, supplierURI and + securityOption, attributeNamespace, consistencyBase) are all for + usage in server to server interactions. + + + + + + + +Hedberg Experimental [Page 2] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +2.2.1 idx + + The index value, normally used as part of the RDN. + + ( 1.2.752.17.1.20 + NAME 'idx' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + SINGLE-VALUE + ) + +2.2.2 dSI + + DataSet Identifier, a unique identifier for one particular set of + information. This should be an OID, but stored in a stringformat. + + ( 1.2.752.17.1.21 + NAME 'dSI' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + ) + +2.2.3 indexOCAT + + Describes the type of data that is stored in this entry, by using + objectcClasses and attributeTypes. The information is stored as a + objectClass name followed by a space and then an attributeType name. + A typical example when dealing with whitepages information would be + "person cn". + + ( 1.2.752.17.1.28 + NAME 'indexOCAT' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + ) + +2.2.5 supplierURI + + A URI describing which protocols, hostnames and ports should be used + by an indexserver to interact with servers carrying indexinformation + representing this dataSet. + + ( 1.2.752.17.1.22 + NAME 'supplierURI' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + ) + + + + +Hedberg Experimental [Page 3] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +2.2.6 baseURI + + The attribute value for this attribute is a LDAP URI. One can + envisage other URI syntaxes, if the client knows about more access + protocols besides LDAP, and the interaction between the client and + the server can not use referrals for some reason. + + ( 1.2.752.17.1.26 + NAME 'baseURI' + EQUALITY caseExactIA5Match + SYNTAX IA5String + ) + +2.2.7 protocolVersion + + At present, the Common Indexing Protocol version should be 3. + + ( 1.2.752.17.1.27 + NAME 'protocolVersion' + EQUALITY numericStringMatch + SYNTAX numericString + ) + +2.2.8 cIPIndexType + + The type of index Object that is used to pass around index + information. + + ( 1.2.752.17.1.29 + NAME 'cIPIndexType' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + ) + +2.2.10 polledBy + + The Distinguished Name of Index servers that polls data from this + indexserver. + + ( 1.2.752.17.1.30 + NAME 'polledBy' + EQUALITY distinguishedNameMatch + SYNTAX DN + ) + + + + + + + +Hedberg Experimental [Page 4] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +2.2.11 updateIntervall + + The maximum duration in seconds between the generation of two updates + by the supplier server. + + ( 1.2.752.17.1.31 + Name 'updateIntervall' + EQUALITY numericStringMatch + SYNTAX numericString + SINGLE-VALUE + ) + +2.2.12 securityOption + + Whether and how the supplier server should sign and encrypt the + update before sending it to the consumer server. + + ( 1.2.752.17.1.32 + NAME 'securityOption' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + SINGLE-VALUE + ) + +2.2.13 extendedDSI + + DataSet Identifier possibly followed by a space and a taglist, the + later as specified by [6]. + + ( 1.2.752.17.1.33 + NAME 'extendedDSI' + EQUALITY caseIgnoreIA5Match + SYNTAX IA5String + ) + +2.2.14 consumerURI + + A URI describing which means a server can accept indexinformation. + An example being a mailto URI for MIME email based index transport. + + ( 1.2.752.17.1.34 + NAME 'consumerURI' + EQUALITY caseExactIA5Match + SYNTAX IA5String + ) + + + + + + +Hedberg Experimental [Page 5] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +2.2.15 attributeNamespace + + Any consumer supplier pair has to agree on what attribute that should + be used and also possibly the meaning of the attributenames. The + value of this attribute should, for example, be a URI pointing to a + document wherein the agreement is described. + + ( 1.2.752.17.1.35 NAME 'attributeNamespace' EQUALITY + caseExactIA5Match SYNTAX IA5String + ) + +2.2.16 consistencyBase + + This attribute is specifically used by consumer supplier pairs that + use the tagged index object [6]. + + ( 1.2.752.17.1.36 + NAME 'consistencyBase' + EQUALITY caseExactIA5Match + SYNTAX IA5String + ) + +3. The interaction between a client and the Index Mesh + + A client interaction with the Index Mesh consists of a couple of + rather well defined actions. The first being to find a suitable index + to start with, then to transverse the Index Mesh and finally to query + the servers holding the original data. Note when reading this text + that what is discussed here is the client's perception of the DIT, + how it is in fact implemented is not discussed. + +3.1 Finding a Index Mesh + + This approach depends on the fact that every index server partaking + in an Index Mesh is represented in the DIT by a entry of the type + cIPDataSet, and has a distinguished name (DN) which most significant + relative distinguished name (RDN) has the attributetype dSI. + Therefore, finding a suitable indexserver to start the search from is + a matter of searching the DIT at a suitable place for objects with + the objectClass cIPIndexObject. Every found entry can then be + evaluated by looking at the description value as well as the + indexOCAT value. The description string should be a human readable + and understandable text that describes what the index server is + indexing. An example of such a string could be, "This index covers + all employees at Swedish Universities and University Colleges that + has an email account". The indexOCAT attribute supplies information + about which kind of entries and which attributes within these entries + that the index information has emanated from. For example, if the + + + +Hedberg Experimental [Page 6] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + + indexOCAT attribute value is "person cn", one can deduce that this is + an index over persons and not over roles, and that it is the + attribute commonName that is indexed. + +3.2 Searching the mesh + + Each index server has its information represented in the DIT as a + very flat tree. In fact, it is only one level deep. + + + 0 Indexservers cIPDataSet + /|\ + / | \ + / | \ + 0 0 + cIPDataSet entries cIPIndex entries + one for each DataSet one for each index value + that this server has that this indexserver + gathered indexes from. has. + + A search then consists of a set of searches. The first being the + search for the index entries that contains an indexvalue that matches + what the user is looking for, and the second a search based on the + DSI information in the extendedDSI attribute values returned from the + first search. In the case of the the cIPIndexType being tagged- + index, the taglists should be compared to find which DSI it might be + useful to pose further queries to. + + When doing these types of searches, the client should be aware of the + fact that the index values disregarding their origin (attributeTypes) + always are stored in the index server as values of the idx attribute. + + The object of the second search is to get information on the + different DataSet involved, and should normally be performed as a + read. Since the DataSet information probably will remain quite stable + over time, this information lends itself very well to caching. If at + this stage there is more than one DataSet involved, the User + interface might use the description value to aid the user in choosing + which one to proceed with. The content of the searchBase value of + the DataSet tells the client whether it represents another index + server (the most significant part of the dn is a dSI attribute) or if + it is a end server. + + + + + + + + + +Hedberg Experimental [Page 7] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +3.3 Querying the end server + + When finally reaching the end server/servers that probably has the + sought for information, the information in the indexOCAT attribute + can be used to produce an appropriate filter. If a search for "Rol*" + in an index having an indexOCAT attribute value of "person cn" + returns an idx entry with the idx value of "Roland", then an + appropriate filter to use might be "&(|(cn=* roland *)(cn=roland + *)(cn=* roland))(objectclass=person)". A complete example of a + search process is given in Appendix A. + +4. Security Considerations + + Since this memo deals with client behavior, it does not add anything + that either enhances or diminishes the security features that exists + in LDAPv2. + +5. Internationalization + + As with security, this memo neither enhances or diminishes the + handling of internationalization in LDAPv2. + +6. References + + [1] Yeong, W., Howes, T. and S. Kille, "Lightweight Directory Access + Protocol", RFC 1777, March 1995. + + [2] Allen, J. and M. Mealling "The Architecture of the Common + Indexing Protocol (CIP)", RFC 2651, August 1999. + + [3] The Directory: Overview of Concepts, Models and Service. CCITT + Recommendation X.500, 1988. + + [4] Information Processing Systems -- Open Systems Interconnection -- + The Directory: Overview of Concepts, Models and Service. ISO/IEC + JTC 1/SC21; International Standard 9594-1, 1988. + + [5] Wahl, M., Coulbeck, A., Howes, T. and S. Kille, "Lightweight + Directory Access Protocol (v3): Attribute Syntax Definitions", + RFC 2252, December 1997. + + [6] Hedberg, R., Greenblatt, B., Moats, R. and M. Wahl, "A Tagged + Index Object for use in the Common Indexing Protocol", RFC 2654, + August 1999. + + + + + + + +Hedberg Experimental [Page 8] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +7. Author's Address + + Roland Hedberg + Catalogix + Dalsveien 53 + 0387 Oslo, Norway + + Phone: +47 23 08 29 96 + EMail: roland@catalogix.ac.se + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Hedberg Experimental [Page 9] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +Appendix A - Sample Session + + Below is a sample of a session between a LDAPv2 client and an index + server mesh as specified in this memo. + + The original question of the session is to find the email address of + a person by the name, "Roland Hedberg", who is working at "Umea + University" in Sweden. + + Step 1. + + A singlelevel search with the baseaddress "c=SE" and the filter + "(objectclass=cipDataset)" was issued. + + The following results were received: + + DN: dSI=1.2.752.17.5.0,c=SE + dsi= 1.2.752.17.5.0 + description= "index over employees with emailaddresses within Swedish + higher education" + indexOCAT= "cn person" + cIPIndexType= "x-tagged-index-1" ; + searchBase= "dsi=1.2.752.17.5.0,c=SE" + protocolVersion = 3 + + DN: dSI=1.2.752.23.1.3,c=SE + dsi= 1.2.752.23.1.3 + description= "index over Swedish lawyers" + indexOCAT= "cn person" + cIPIndexType= "x-tagged-index-1" ; + searchBase= "dsi=1.2.752.23.1.3,c=SE" + protocolVersion = 3 + + Step 2. + + Since the first index seemed to cover the interesting population, a + single level search with the baseaddress "dsi=1.2.752.17.5.0,c=SE" + and the filter "(|(idx=roland)(idx=hedberg))" was issued. + + The following results were received: + + DN: idx=Roland,dSI=1.2.752.17.5.0,c=SE + idx= Roland + extendedDSI= 1.2.752.17.5.10 1,473,612,879,1024 + extendedDSI= 1.2.752.17.5.14 35,78,150,200 + extendedDSI= 1.2.752.17.5.16 187,2031,3167,5284,6034-6040 + extendedDSI= 1.2.752.17.5.17 17 + + + + +Hedberg Experimental [Page 10] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + + DN: idx=Hedberg,dSI=1.2.752.17.5.0,c=SE + idx= Hedberg + extendedDSI= 1.2.752.17.5.8 24,548-552,1066 + extendedDSI= 1.2.752.17.5.10 473,512,636,777,1350 + extendedDSI= 1.2.752.17.5.14 84,112,143,200 + extendedDSI= 1.2.752.17.5.15 1890-1912 + extendedDSI= 1.2.752.17.5.17 44 + + A comparison between the two sets of extendedDSIs shows that two + datasets 1.2.752.17.5.10 and 1.2.752.17.5.14 contains persons named + "Roland" and "Hedberg". Therefore, the next step would be to see what + the datasets represent. A comparison like this should normally not + be left to the user. + + Step. 3 + + Two baselevel searches, one for + "dsi=1.2.752.17.5.10,dsi=1.2.752.17.5.0,c=SE" and the other for + "dsi=1.2.752.17.5.14,dsi=1.2.752.17.5.0,c=SE" with the filter + "(objectclass=cipdataset)" were issued. + + The following results were received: + + DN: dSI=1.2.752.17.5.10,dSI=1.2.752.17.5.0,c=SE + dsi= 1.2.752.17.5.10 + description= "Employees at Umea University,Sweden" + indexOCAT= "person cn" + searchBase= "o=Umea Universitet,c=SE" + + respectively + + DN: dSI=1.2.752.17.5.14,dSI=1.2.752.17.5.0,c=SE + dsi= 1.2.752.17.5.14 + description= "Employees at Lund University,Sweden" + indexOCAT= "person cn" + searchBase= "o=Lunds Universitet,c=SE" + + Step 4 + + Based on the descriptions for the two datasets, "1.2.752.17.5.10" was + chosen as the best to proceed with. From the searchbase attribute + value, it was clear that this was a base server. The query now has + to be somewhat modified. One possibility would be to issue a query + with the baseobject "o=Umea Universitet,c=SE" and the filter + "(&(cn=Roland Hedberg)(objectclass=person))" + + + + + + +Hedberg Experimental [Page 11] + +RFC 2657 LDAPv2 vs. Index Mesh August 1999 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Hedberg Experimental [Page 12] + diff --git a/doc/rfc/rfc2696.txt b/doc/rfc/rfc2696.txt new file mode 100644 index 0000000000..4ccc4c169a --- /dev/null +++ b/doc/rfc/rfc2696.txt @@ -0,0 +1,395 @@ + + + + + + +Network Working Group C. Weider +Request for Comments: 2696 A. Herron +Category: Informational A. Anantha + Microsoft + T. Howes + Netscape + September 1999 + + + LDAP Control Extension for Simple Paged Results Manipulation + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +1. Abstract + + This document describes an LDAPv3 control extension for simple paging + of search results. This control extension allows a client to control + the rate at which an LDAP server returns the results of an LDAP + search operation. This control may be useful when the LDAP client has + limited resources and may not be able to process the entire result + set from a given LDAP query, or when the LDAP client is connected + over a low-bandwidth connection. Other operations on the result set + are not defined in this extension. This extension is not designed to + provide more sophisticated result set management. + + The key words "MUST", "SHOULD", and "MAY" used in this document are + to be interpreted as described in [bradner97]. + +2. The Control + + This control is included in the searchRequest and searchResultDone + messages as part of the controls field of the LDAPMessage, as defined + in Section 4.1.12 of [LDAPv3]. The structure of this control is as + follows: + + + + + + + + + +Weider, et al. Informational [Page 1] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + +pagedResultsControl ::= SEQUENCE { + controlType 1.2.840.113556.1.4.319, + criticality BOOLEAN DEFAULT FALSE, + controlValue searchControlValue +} + +The searchControlValue is an OCTET STRING wrapping the BER-encoded +version of the following SEQUENCE: + +realSearchControlValue ::= SEQUENCE { + size INTEGER (0..maxInt), + -- requested page size from client + -- result set size estimate from server + cookie OCTET STRING +} + +3. Client-Server Interaction + + An LDAP client application that needs to control the rate at which + results are returned MAY specify on the searchRequest a + pagedResultsControl with size set to the desired page size and cookie + set to the zero-length string. The page size specified MAY be greater + than zero and less than the sizeLimit value specified in the + searchRequest. + + If the page size is greater than or equal to the sizeLimit value, the + server should ignore the control as the request can be satisfied in a + single page. If the server does not support this control, the server + MUST return an error of unsupportedCriticalExtension if the client + requested it as critical, otherwise the server SHOULD ignore the + control. The remainder of this section assumes the server does not + ignore the client's pagedResultsControl. + + Each time the server returns a set of results to the client when + processing a search request containing the pagedResultsControl, the + server includes the pagedResultsControl control in the + searchResultDone message. In the control returned to the client, the + size MAY be set to the server's estimate of the total number of + entries in the entire result set. Servers that cannot provide such an + estimate MAY set this size to zero (0). The cookie MUST be set to an + empty value if there are no more entries to return (i.e., the page of + search results returned was the last), or, if there are more entries + to return, to an octet string of the server's choosing,used to resume + the search. + + The client MUST consider the cookie to be an opaque structure and + make no assumptions about its internal organization or value. When + the client wants to retrieve more entries for the result set, it MUST + + + +Weider, et al. Informational [Page 2] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + + send to the server a searchRequest with all values identical to the + initial request with the exception of the messageID, the cookie, and + optionally a modified pageSize. The cookie MUST be the octet string + on the last searchResultDone response returned by the server. + Returning cookies from previous searchResultDone responses besides + the last one is undefined, as the server implementation may restrict + cookies from being reused. + + The server will then return the next set of results from the whole + result set. This interaction will continue until the client has + retrieved all the results, in which case the cookie in the + searchResultDone field will be empty, or until the client abandons + the search sequence as described below. Once the paged search + sequence has been completed, the cookie is no longer valid and MUST + NOT be used. + + A sequence of paged search requests is abandoned by the client + sending a search request containing a pagedResultsControl with the + size set to zero (0) and the cookie set to the last cookie returned + by the server. A client MAY use the LDAP Abandon operation to + abandon one paged search request in progress, but this is discouraged + as it MAY invalidate the client's cookie. + + If, for any reason, the server cannot resume a paged search operation + for a client, then it SHOULD return the appropriate error in a + searchResultDone entry. If this occurs, both client and server should + assume the paged result set is closed and no longer resumable. + + A client may have any number of outstanding search requests pending, + any of which may have used the pagedResultsControl. A server + implementation which requires a limit on the number of outstanding + paged search requests from a given client MAY either return + unwillingToPerform when the client attempts to create a new paged + search request, or age out an older result set. If the server + implementation ages out an older paged search request, it SHOULD + return "unwilling to perform" if the client attempts to resume the + paged search that was aged out. + + A client may safely assume that all entries that satisfy a given + search query are returned once and only once during the set of paged + search requests/responses necessary to enumerate the entire result + set, unless the result set for that query has changed since the + searchRequest starting the request/response sequence was processed. + In that case, the client may receive a given entry multiple times + and/or may not receive all entries matching the given search + criteria. + + + + + +Weider, et al. Informational [Page 3] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + +4. Example + + The following example illustrates the client-server interaction + between a client doing a search requesting a page size limit of 3. + The entire result set returned by the server contains 5 entries. + + Lines beginning with "C:" indicate requests sent from client to + server. Lines beginning with "S:" indicate responses sent from server + to client. Lines beginning with "--" are comments to help explain the + example. + + -- Client sends a search request asking for paged results + -- with a page size of 3. + C: SearchRequest + pagedResultsControl(3,"") + -- Server responds with three entries plus an indication + -- of 5 total entries in the search result and an opaque + -- cooking to be used by the client when retrieving subsequent + -- pages. + S: SearchResultEntry + S: SearchResultEntry + S: SearchResultEntry + S: SearchResultDone + pagedResultsControl(5, "opaque") + -- Client sends an identical search request (except for + -- message id), returning the opaque cooking, asking for + -- the next page. + C: SearchRequest + PagedResultsControl(3, "opaque") + -- Server responds with two entries plus an indication + -- that there are no more entries (null cookie). + S: SearchResultEntry + S: SearchResultEntry + S: SearchResultDone + pagedResultsControl(5,"") + +5. Relationship to X.500 + + For LDAP servers providing a front end to X.500 (93) directories, the + paged results control defined in this document may be mapped directly + onto the X.500 (93) PagedResultsRequest defined in X.511 [x500]. The + size parameter may be mapped onto pageSize. The cookie parameter may + be mapped onto queryReference. The sortKeys and reverse fields in + the X.500 PagedResultsRequest are excluded. + + + + + + + + + + + +Weider, et al. Informational [Page 4] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + +6. Security Considerations + + Server implementors should consider the resources used when clients + send searches with the simple paged control, to ensure that a + client's misuse of this control does not lock out other legitimate + operations. + + Servers implementations may enforce an overriding sizelimit, to + prevent the retrieval of large portions of a publically-accessible + directory. + + Clients can, using this control, determine how many entries match a + particular filter, before the entries are returned to the client. + This may require special processing in servers which perform access + control checks on entries to determine whether the existence of the + entry can be disclosed to the client. + +7. References + + [LDAPv3] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory + Access Protocol (v3)", RFC 2251, December 1997. + + [Bradner97] Bradner, S., "Key Words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + + + + + + + + + + + + + + + + + + + + + + + + + + +Weider, et al. Informational [Page 5] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + +8. Authors' Addresses + + Chris Weider + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052 + USA + + Phone: +1 425 882-8080 + EMail: cweider@microsoft.com + + + Andy Herron + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052 + USA + + Phone: +1 425 882-8080 + EMail: andyhe@microsoft.com + + + Anoop Anantha + Microsoft Corp. + 1 Microsoft Way + Redmond, WA 98052 + USA + + Phone: +1 425 882-8080 + EMail: anoopa@microsoft.com + + + Tim Howes + Netscape Communications Corp. + 501 E. Middlefield Road + Mountain View, CA 94043 + USA + + Phone: +1 415 937-2600 + EMail: howes@netscape.com + + + + + + + + + + + +Weider, et al. Informational [Page 6] + +RFC 2696 LDAP Control Ext. for Simple Paged Results September 1999 + + +9. Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Weider, et al. Informational [Page 7] + diff --git a/doc/rfc/rfc2713.txt b/doc/rfc/rfc2713.txt new file mode 100644 index 0000000000..ca88d30390 --- /dev/null +++ b/doc/rfc/rfc2713.txt @@ -0,0 +1,1179 @@ + + + + + + +Network Working Group V. Ryan +Request for Comments: 2713 S. Seligman +Category: Informational R. Lee + Sun Microsystems, Inc. + October 1999 + + + Schema for Representing Java(tm) Objects in an LDAP Directory + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + This document defines the schema for representing Java(tm) objects in + an LDAP directory [LDAPv3]. It defines schema elements to represent + a Java serialized object [Serial], a Java marshalled object [RMI], a + Java remote object [RMI], and a JNDI reference [JNDI]. + +1. Introduction + + This document assumes that the reader has a general knowledge of the + Java programming language [Java]. For brevity we use the term "Java + object" in place of "object in the Java programming language" + throughout this text. + + Traditionally, LDAP directories have been used to store data. Users + and programmers think of the directory as a hierarchy of directory + entries, each containing a set of attributes. You look up an entry + from the directory and extract the attribute(s) of interest. For + example, you can look up a person's telephone number from the + directory. Alternatively, you can search the directory for entries + with a particular set of attributes. For example, you can search for + all persons in the directory with the surname "Smith". + + For applications written in the Java programming language, a kind of + data that is typically shared are Java objects themselves. For such + applications, it makes sense to be able to use the directory as a + repository for Java objects. The directory provides a centrally + administered, and possibly replicated, service for use by Java + applications distributed across the network. + + + +Ryan, et al. Informational [Page 1] + +RFC 2713 Schema for Java Objects October 1999 + + + For example, an application server might use the directory for + "registering" objects representing the services that it manages, so + that a client can later search the directory to locate those services + as it needs. + + The motivation for this document is to define a common way for + applications to store and retrieve Java objects from the directory. + Using this common schema, any Java application that needs to read or + store Java objects in the directory can do so in an interoperable + way. + +2 Representation of Java Objects + + This document defines schema elements to represent three types of + Java objects: a Java serialized object, a Java marshalled object, + and a JNDI reference. A Java remote object is stored as either a Java + marshalled object or a JNDI reference. + +2.1 Common Representations + + A Java object is stored in the LDAP directory by using the object + class javaObject. This is the base class from which other Java object + related classes derive: javaSerializedObject, javaMarshalledObject, + and javaNamingReference. javaObject is an abstract object class, + which means that a javaObject cannot exist by itself in the + directory; only auxiliary or structural subclasses of it can exist in + the directory. + + The object class javaContainer represents a directory entry dedicated + to storing a Java object. It is a structural object class. In cases + where a subclass of javaObject is mixed in with another structural + object class, javaContainer is not required. + + The definitions for the object classes javaObject and javaContainer + are presented in Section 4. + + The javaObject class has one mandatory attribute (javaClassName) and + four optional attributes (javaClassNames, javaCodebase, javaDoc, + description). javaClassName is a single valued attribute that is + used to store the fully qualified name of the object's Java class + (for example, "java.lang.String"). This may be the object's most + derived class's name, but does not have to be; that of a superclass + or interface in some cases might be most appropriate. This attribute + is intended for storing the name of the object's "distinguished" + class, that is, the class or interface with which the object should + be identified. + + + + + +Ryan, et al. Informational [Page 2] + +RFC 2713 Schema for Java Objects October 1999 + + + javaClassNames is a multivalued attribute that is used to store the + fully qualified names of the object's Java classes and interfaces + (for example, "java.lang.Byte"). Like all multivalued attributes, the + javaClassNames attribute's values are unordered and so no one value + is more "distinguished" than the others. This attribute is intended + for storing an object's class and interface names and those of its + ancestor classes and interfaces, although the list of values does not + have to be complete. If the javaClassNames attribute is present, it + should include the value of javaClassName. + + For example, suppose an object is stored in the directory with a + javaClassName attribute of "java.io.FilePermission", and a + javaClassNames attribute of {"java.security.Permission", + "java.io.FilePermission", "java.security.Guard", + "java.io.Serializable"}. An application searching a directory for + Java objects might use javaClassName to produce a summary of the + names and types of Java objects in that directory. Another + application might use the javaClassNames attribute to find, for + example, all java.security.Permission objects. + + javaCodebase is a multivalued attribute that is used to store the + location(s) of the object's class definition. javaDoc is used to + store a pointer (URL) to the Java documentation for the class. + description is used to store a textual description of a Java object + and is defined in [v3Schema]. The definitions of these attributes are + presented in Section 3. + +2.2 Serialized Objects + + To "serialize" an object means to convert its state into a byte + stream in such a way that the byte stream can be converted back into + a copy of the object. A Java object is "serializable" if its class + or any of its superclasses implements either the java.io.Serializable + interface or its subinterface java.io.Externalizable. + "Deserialization" is the process of converting the serialized form of + an object back into a copy of the object. When an object is + serialized, the entire tree of objects rooted at the object is also + serialized. When it is deserialized, the tree is reconstructed. For + example, suppose a serializable Book object contains (a serializable + field of) an array of Page objects. When a Book object is + serialized, so is the array of Page objects. + + The Java platform specifies a default algorithm by which serializable + objects are serialized. A Java class can also override this default + serialization with its own algorithm. [Serial] describes object + serialization in detail. + + + + + +Ryan, et al. Informational [Page 3] + +RFC 2713 Schema for Java Objects October 1999 + + + When an object is serialized, information that identifies its class + is recorded in the serialized stream. However, the class's definition + ("class file") itself is not recorded. It is the responsibility of + the system that is deserializing the object to determine the + mechanism to use for locating and loading the associated class + definitions. For example, the Java application might include in its + classpath a JAR file containing the class definitions of the + serialized object, or load the class definitions using information + from the directory, as explained below. + +2.2.1 Representation in the Directory + + A serialized object is represented in the directory by the attributes + javaClassName, javaClassNames, javaCodebase, and javaSerializedData, + as defined in Section 3. The mandatory attribute, + javaSerializedData, contains the serialized form of the object. + Although the serialized form already contains the class name, the + mandatory javaClassName attribute also records the class name of the + serialized object so that applications can determined class + information without having to first deserialize the object. The + optional javaClassNames attribute is used to record additional class + information about the serialized object. The optional javaCodebase + attribute is used to record the locations of the class definitions + needed to deserialize the serialized object. + + A directory entry that contains a serialized object is represented by + the object class javaSerializedObject, which is a subclass of + javaObject. javaSerializedObject is an auxiliary object class, which + means that it needs to be mixed in with a structural object class. + javaSerializedObject's definition is given in Section 4. + +2.3 Marshalled Objects + + To "marshal" an object means to record its state and codebase(s) in + such a way that when the marshalled object is "unmarshalled," a copy + of the original object is obtained, possibly by automatically loading + the class definitions of the object. You can marshal any object that + is serializable or remote (that is, implements the java.rmi.Remote + interface). Marshalling is like serialization, except marshalling + also records codebases. Marshalling is different from serialization + in that marshalling treats remote objects specially. If an object is + a java.rmi.Remote object, marshalling records the remote object's + "stub" (see Section 2.5), instead of the remote object itself. Like + serialization, when an object is marshalled, the entire tree of + objects rooted at the object is marshalled. When it is unmarshalled, + the tree is reconstructed. + + + + + +Ryan, et al. Informational [Page 4] + +RFC 2713 Schema for Java Objects October 1999 + + + A "marshalled" object is the represented by the + java.rmi.MarshalledObject class. Here's an example of how to create + MarshalledObjects for serializable and remote objects: + + java.io.Serializable sobj = ...; + java.rmi.MarshalledObject mobj1 = + new java.rmi.MarshalledObject(sobj); + + java.rmi.Remote robj = ...; + java.rmi.MarshalledObject mobj2 = + new java.rmi.MarshalledObject(robj); + + Then, to retrieve the original objects from the MarshalledObjects, do + as follows: + + java.io.Serializable sobj = (java.io.Serializable) mobj1.get(); + java.io.Remote rstub = (java.io.Remote) mobj2.get(); + + MarshalledObject is available only on the Java 2 Platform, Standard + Edition, v1.2, and higher releases. + +2.3.1 Representation in the Directory + + A marshalled object is represented in the directory by the attributes + javaClassName, javaClassNames, and javaSerializedData, as defined in + Section 3. The mandatory attribute, javaSerializedData, contains the + serialized form of the marshalled object (that is, the serialized + form of a MarshalledObject instance). The mandatory javaClassName + attribute records the distinguished class name of the object before + it has been marshalled. The optional javaClassNames attribute is + used to record additional class information about the object before + it has been marshalled. + + A directory entry that contains a marshalled object is represented by + the object class javaMarshalledObject, which is a subclass of + javaObject. javaMarshalledObject is an auxiliary object class, which + means that it needs to be mixed in with a structural object class. + javaMarshalledObject's definition is given in Section 4. + + As evident in this description, a javaMarshalledObject differs from a + javaSerializedObject only in the interpretation of the javaClassName + and javaClassNames attributes. + + + + + + + + + +Ryan, et al. Informational [Page 5] + +RFC 2713 Schema for Java Objects October 1999 + + +2.4 JNDI References + + Java Naming and Directory Interface(tm) (JNDI) is a directory access + API specified in the Java programming language [JNDI]. It provides + an object-oriented view of the directory, allowing Java objects to be + added to and retrieved from the directory without requiring the + client to manage data representation issues. + + JNDI defines the notion of a "reference" for use when an object + cannot be stored in the directory directly, or when it is + inappropriate or undesirable to do so. An object with an associated + reference is stored in the directory indirectly, by storing its + reference instead. + +2.4.1 Contents of a Reference + + A JNDI reference is a Java object of class javax.naming.Reference. + It consists of class information about the object being referenced + and an ordered list of addresses. An address is a Java object of + class javax.naming.RefAddr. Each address contains information on how + to construct the object. + + A common use for JNDI references is to represent connections to a + network service such as a database, directory, or file system. Each + address may then identify a "communications endpoint" for that + service, containing information on how to contact the service. + Multiple addresses may arise for various reasons, such as replication + or the object offering interfaces over more than one communication + mechanism. + + A reference also contains information to assist in the creation of an + instance of the object to which the reference refers. It contains + the Java class name of that object, and the class name and location + of the object factory to be used to create the object. The + procedures for creating an object given its reference and the reverse + are described in [JNDI]. + +2.4.2 Representation in the Directory + + A JNDI reference is stored in the directory by using the attributes + javaClassName, javaClassNames, javaCodebase, javaReferenceAddress, + and javaFactory, defined in Section 3. These attributes store + information corresponding to the contents of a reference described + above. javaReferenceAddress is a multivalued optional attribute for + storing reference addresses. javaFactory is the optional attribute + for storing the object factory's fully qualified class name. The + mandatory javaClassName attribute is used to store the name of the + distinguished class of the object. The optional javaClassNames + + + +Ryan, et al. Informational [Page 6] + +RFC 2713 Schema for Java Objects October 1999 + + + attribute is used to record additional class and interface names. + The optional javaCodebase attribute is used to store the locations of + the object factory's and the object's class definitions. + + A directory entry containing a JNDI reference is represented by the + object class javaNamingReference, which is a subclass of javaObject. + javaNamingReference is an auxiliary object class, which means that it + needs to be mixed in with a structural object class. + javaNamingReference's definition is given in Section 4. + +2.5 Remote Objects + + The Java Remote Method Invocation (RMI) system [RMI] is a mechanism + that enables an object on one Java virtual machine to invoke methods + on an object in another Java virtual machine. Any object whose + methods can be invoked in this way must implement the java.rmi.Remote + interface. When such an object is invoked, its arguments are + marshalled and sent from the local virtual machine to the remote one, + where the arguments are unmarshalled and used. When the method + terminates, the results are marshalled from the remote machine and + sent to the caller's virtual machine. + + To make a remote object accessible to other virtual machines, a + program typically registers it with the RMI registry. The program + supplies to the RMI registry the string name of the remote object and + the remote object itself. When a program wants to access a remote + object, it supplies the object's string name to the RMI registry on + the same machine as the remote object. The RMI registry returns to + the caller a reference (called "stub") to the remote object. When + the program receives the stub for the remote object, it can invoke + methods on the remote object (through the stub). A program can also + obtain references to remote objects as a result of remote calls to + other remote objects or from other naming services. For example, the + program can look up a reference to a remote object from an LDAP + server that supports the schema defined in this document. + + The string name accepted by the RMI registry has the syntax + "rmi://hostname:port/remoteObjectName", where "hostname" and "port" + identify the machine and port on which the RMI registry is running, + respectively, and "remoteObjectName" is the string name of the remote + object. "hostname", "port", and the prefix, "rmi:", are optional. If + "hostname" is not specified, it defaults to the local host. If + "port" is not specified, it defaults to 1099. If "remoteObjectName" + is not specified, then the object being named is the RMI registry + itself. See [RMI] for details. + + + + + + +Ryan, et al. Informational [Page 7] + +RFC 2713 Schema for Java Objects October 1999 + + + RMI can be supported using different protocols: the Java Remote + Method Protocol (JRMP) and the Internet Inter-ORB Protocol (IIOP). + The JRMP is a specialized protocol designed for RMI; the IIOP is the + standard protocol for communication between CORBA objects [CORBA]. + RMI over IIOP allows Java remote objects to communicate with CORBA + objects which might be written in a non-Java programming language + [RMI-IIOP]. + +2.5.1 Representation in the Directory + + Remote objects that use the IIOP are represented in the directory as + CORBA object references [CORBA-LDAP]. Remote objects that use the + JRMP are represented in the directory in one of two ways: as a + marshalled object, or as a JNDI reference. + + A marshalled object records the codebases of the remote object's stub + and any serializable or remote objects that it references, and + replaces remote objects with their stubs. To store a Remote object + as a marshalled object (java.rmi.MarshalledObject), you first create + a java.rmi.MarshalledObject instance for it. + + java.rmi.Remote robj = ...; + java.rmi.MarshalledObject mobj = + new java.rmi.MarshalledObject(robj); + + You can then store the MarshalledObject instance as a + javaMarshalledObject. The javaClassName attribute should contain the + fully qualified name of the distinguished class of the remote object. + The javaClassNames attribute should contain the names of the classes + and interfaces of the remote object. To read the remote object back + from the directory, first deserialize the contents of the + javaSerializedData to get a MarshalledObject (mobj), then retrieve it + from the MarshalledObject as follows: + + java.rmi.Remote robj = (java.rmi.Remote)mobj.get(); + + This returns the remote stub, which you can then use to invoke remote + methods. + + MarshalledObject is available only on the Java 2 Platform, Standard + Edition, v1.2 and higher releases. Therefore, a remote object stored + as a MarshalledObject can only be read by clients using the the Java + 2 Platform, Standard Edition, v1.2 or higher releases. + + + + + + + + +Ryan, et al. Informational [Page 8] + +RFC 2713 Schema for Java Objects October 1999 + + + To store a remote object as a JNDI reference, you first create a + javax.naming.Reference object instance for it using the remote + object's string name as it has been, or will be, recorded with the + RMI registry, with the additional restriction that the "rmi:" prefix + must be present. Here's an example: + + javax.naming.Reference ref = new javax.naming.Reference( + obj.getClass().getName(), + new javax.naming.StringRefAddr("URL", + "rmi://rserver/AppRemoteObjectX")); + + You then store the javax.naming.Reference instance as a + javaNamingReference. The advantage of using a JNDI reference is that + this can be done without a reference to the remote object. In fact, + the remote object does not have to exist at the time that this + recording in the directory is made. The remote object needs to exist + and be bound with the RMI registry when the object is looked up from + the directory. + +2.6 Serialized Objects Vs. Marshalled Objects Vs. References + + The object classes defined in this document store different aspects + of the Java objects. + + A javaSerializedObject or a serializable object stored as a + javaMarshalledObject represents the object itself, while a + javaNamingReference or a remote object stored as a + javaMarshalledObject represents a "pointer" to the object. + + When storing a serializable object in the directory, you have a + choice of storing it as a javaSerializedObject or a + javaMarshalledObject. The javaSerializedObject object class provides + the basic way in which to store serializable objects. When you create + an LDAP entry using the javaSerializableObject object class, you must + explicitly set the javaCodebase attribute if you want readers of that + entry to know where to load the class definitions of the object. When + you create an LDAP entry using the javaMarshalledObject object class, + you use the MarshalledObject class. The MarshalledObject class uses + the RMI infrastructure available on the Java platform to automate how + codebase information is gathered and recorded, thus freeing you from + having to set the javaCodebase attribute. On the other hand, the + javaCodebase attribute is human-readable and can be updated easily by + using text-based tools without having to change other parts of the + entry. This allows you, for instance, to move the class definitions + to another location and then update the javaCodebase attribute to + reflect the move without having to update the serialized object + itself. + + + + +Ryan, et al. Informational [Page 9] + +RFC 2713 Schema for Java Objects October 1999 + + + A javaNamingReference provides a way of recording address information + about an object which itself is not directly stored in the directory. + A remote object stored as a javaMarshalledObject also records address + information (the object's "stub") of an object which itself is not + directory stored in the directory. In other words, you can think of + these as compact representations of the information required to + access the object. + + A javaNamingReference typically consists of a small number of human- + readable strings. Standard text-based tools for directory + administration may therefore be used to add, read, or modify + reference entries -- if so desired -- quite easily. Serialized and + marshalled objects are not intended to be read or manipulated + directly by humans. + +3 Attribute Type Definitions + + The following attribute types are defined in this document: + + javaClassName + javaClassNames + javaCodebase + javaSerializedData + javaFactory + javaReferenceAddress + javaDoc + +3.1 javaClassName + + This attribute stores the fully qualified name of the Java object's + "distinguished" class or interface (for example, "java.lang.String"). + It is a single-valued attribute. This attribute's syntax is ' + Directory String' and its case is significant. + + ( 1.3.6.1.4.1.42.2.27.4.1.6 + NAME 'javaClassName' + DESC 'Fully qualified name of distinguished Java class or + interface' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + + + + + + + + + +Ryan, et al. Informational [Page 10] + +RFC 2713 Schema for Java Objects October 1999 + + +3.2 javaCodebase + + This attribute stores the Java class definition's locations. It + specifies the locations from which to load the class definition for + the class specified by the javaClassName attribute. Each value of + the attribute contains an ordered list of URLs, separated by spaces. + For example, a value of "url1 url2 url3" means that the three + (possibly interdependent) URLs (url1, url2, and url3) form the + codebase for loading in the Java class definition. + + If the javaCodebase attribute contains more than one value, each + value is an independent codebase. That is, there is no relationship + between the URLs in one value and those in another; each value can be + viewed as an alternate source for loading the Java class definition. + See [Java] for information regarding class loading. + + This attribute's syntax is 'IA5 String' and its case is significant. + + ( 1.3.6.1.4.1.42.2.27.4.1.7 + NAME 'javaCodebase' + DESC 'URL(s) specifying the location of class definition' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +3.3 javaClassNames + + This attribute stores the Java object's fully qualified class or + interface names (for example, "java.lang.String"). It is a + multivalued attribute. When more than one value is present, each is + the name of a class or interface, or ancestor class or interface, of + this object. + + This attribute's syntax is 'Directory String' and its case is + significant. + + ( 1.3.6.1.4.1.42.2.27.4.1.13 + NAME 'javaClassNames' + DESC 'Fully qualified Java class or interface name' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + + + + + + + + +Ryan, et al. Informational [Page 11] + +RFC 2713 Schema for Java Objects October 1999 + + +3.4 javaSerializedData + + This attribute stores the serialized form of a Java object. The + serialized form is described in [Serial]. + + This attribute's syntax is 'Octet String'. + + ( 1.3.6.1.4.1.42.2.27.4.1.8 + NAME 'javaSerializedData + DESC 'Serialized form of a Java object' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + SINGLE-VALUE + ) + +3.5 javaFactory + + This attribute stores the fully qualified class name of the object + factory (for example, "com.wiz.jndi.WizObjectFactory") that can be + used to create an instance of the object identified by the + javaClassName attribute. + + This attribute's syntax is 'Directory String' and its case is + significant. + + ( 1.3.6.1.4.1.42.2.27.4.1.10 + NAME 'javaFactory' + DESC 'Fully qualified Java class name of a JNDI object factory' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +3.6 javaReferenceAddress + + This attribute represents the sequence of addresses of a JNDI + reference. Each of its values represents one address, a Java object + of type javax.naming.RefAddr. Its value is a concatenation of the + address type and address contents, preceded by a sequence number (the + order of addresses in a JNDI reference is significant). For example: + + #0#TypeA#ValA + #1#TypeB#ValB + #2#TypeC##rO0ABXNyABpq... + + In more detail, the value is encoded as follows: + + + + + + +Ryan, et al. Informational [Page 12] + +RFC 2713 Schema for Java Objects October 1999 + + + The delimiter is the first character of the value. For readability + the character '#' is recommended when it is not otherwise used + anywhere in the value, but any character may be used subject to + restrictions given below. + + The first delimiter is followed by the sequence number. The sequence + number of an address is its position in the JNDI reference, with the + first address being numbered 0. It is represented by its shortest + string form, in decimal notation. + + The sequence number is followed by a delimiter, then by the address + type, and then by another delimiter. If the address is of Java class + javax.naming.StringRefAddr, then this delimiter is followed by the + value of the address contents (which is a string). Otherwise, this + delimiter is followed immediately by another delimiter, and then by + the Base64 encoding of the serialized form of the entire address. + + The delimiter may be any character other than a digit or a character + contained in the address type. In addition, if the address contents + is a string, the delimiter may not be the first character of that + string. + + This attribute's syntax is 'Directory String' and its case is + significant. It can contain multiple values. + + ( 1.3.6.1.4.1.42.2.27.4.1.11 + NAME 'javaReferenceAddress' + DESC 'Addresses associated with a JNDI Reference' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + +3.7 javaDoc + + This attribute stores a pointer to the Java documentation for the + class. It's value is a URL. For example, the following URL points to + the specification of the java.lang.String class: + http://java.sun.com/products/jdk/1.2/docs/api/java/lang/String.html + + This attribute's syntax is 'IA5 String' and its case is significant. + + ( 1.3.6.1.4.1.42.2.27.4.1.12 + NAME 'javaDoc' + DESC 'The Java documentation for the class' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + + + +Ryan, et al. Informational [Page 13] + +RFC 2713 Schema for Java Objects October 1999 + + +4 Object Class Definitions + + The following object classes are defined in this document: + + javaContainer + javaObject + javaSerializedObject + javaMarshalledObject + javaNamingReference + +4.1 javaContainer + + This structural object class represents a container for a Java + object. + + ( 1.3.6.1.4.1.42.2.27.4.2.1 + NAME 'javaContainer' + DESC 'Container for a Java object' + SUP top + STRUCTURAL + MUST ( cn ) + ) + +4.2 javaObject + + This abstract object class represents a Java object. A javaObject + cannot exist in the directory; only auxiliary or structural + subclasses of it can exist in the directory. + + ( 1.3.6.1.4.1.42.2.27.4.2.4 + NAME 'javaObject' + DESC 'Java object representation' + SUP top + ABSTRACT + MUST ( javaClassName ) + MAY ( javaClassNames $ + javaCodebase $ + javaDoc $ + description ) + ) + + + + + + + + + + + +Ryan, et al. Informational [Page 14] + +RFC 2713 Schema for Java Objects October 1999 + + +4.3 javaSerializedObject + + This auxiliary object class represents a Java serialized object. It + must be mixed in with a structural object class. + + ( 1.3.6.1.4.1.42.2.27.4.2.5 + NAME 'javaSerializedObject' + DESC 'Java serialized object' + SUP javaObject + AUXILIARY + MUST ( javaSerializedData ) + ) + +4.4 javaMarshalledObject + + This auxiliary object class represents a Java marshalled object. It + must be mixed in with a structural object class. + + ( 1.3.6.1.4.1.42.2.27.4.2.8 + NAME 'javaMarshalledObject' + DESC 'Java marshalled object' + SUP javaObject + AUXILIARY + MUST ( javaSerializedData ) + ) + +4.5 javaNamingReference + + This auxiliary object class represents a JNDI reference. It must be + mixed in with a structural object class. + + ( 1.3.6.1.4.1.42.2.27.4.2.7 + NAME 'javaNamingReference' + DESC 'JNDI reference' + SUP javaObject + AUXILIARY + MAY ( javaReferenceAddress $ + javaFactory ) + ) + + + + + + + + + + + + +Ryan, et al. Informational [Page 15] + +RFC 2713 Schema for Java Objects October 1999 + + +5. Security Considerations + + Serializing an object and storing it into the directory enables (a + copy of) the object to be examined and used outside the environment + in which it was originally created. The directory entry containing + the serialized object could be read and modified within the + constraints imposed by the access control mechanisms of the + directory. If an object contains sensitive information or + information that could be misused outside of the context in which it + was created, the object should not be stored in the directory. For + more details on security issues relating to serialization in general, + see [Serial]. + +6. Acknowledgements + + We would like to thank Joseph Fialli, Peter Jones, Roger Riggs, Bob + Scheifler, and Ann Wollrath of Sun Microsystems for their comments + and suggestions. + +7. References + + [CORBA] The Object Management Group, "Common Object Request + Broker Architecture Specification 2.0," + http://www.omg.org + + [CORBA-LDAP] Ryan, V., Lee, R. and S. Seligman, "Schema for + Representing CORBA Object References in an LDAP + Directory", RFC 2714, October 1999. + + [Java] Ken Arnold and James Gosling, "The Java(tm) Programming + Language," Second Edition, ISBN 0-201-31006-6. + + [JNDI] Java Software, Sun Microsystems, Inc., "The Java(tm) + Naming and Directory Interface (tm) Specification," + February 1998. http://java.sun.com/products/jndi/ + + [LDAPv3] Wahl, M., Howes, T. and S. Kille, "Lightweight + Directory Access Protocol (v3)", RFC 2251, December + 1997. + + [RMI] Java Software, Sun Microsystems, Inc., "Remote Method + Invocation," November 1998. + http://java.sun.com/products/jdk/1.2/docs/guide/rmi + + + + + + + + +Ryan, et al. Informational [Page 16] + +RFC 2713 Schema for Java Objects October 1999 + + + [RMI-IIOP] IBM and Java Software, Sun Microsystems, Inc., "RMI over + IIOP", June 1999. + http://java.sun.com/products/rmi-iiop/ + + [Serial] Java Software, Sun Microsystems, Inc., "Object + Serialization Specification," November 1998. + http://java.sun.com/products/jdk/1.2/docs/guide/ + serialization + + [v3Schema] Wahl, M., "A Summary of the X.500(96) User Schema for + use with LDAPv3", RFC 2256, December 1997. + +8. Authors' Addresses + + Vincent Ryan + Sun Microsystems, Inc. + Mail Stop EDUB03 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +353 1 819 9151 + EMail: vincent.ryan@ireland.sun.com + + + Scott Seligman + Sun Microsystems, Inc. + Mail Stop UCUP02-209 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +1 408 863 3222 + EMail: scott.seligman@eng.sun.com + + + Rosanna Lee + Sun Microsystems, Inc. + Mail Stop UCUP02-206 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +1 408 863 3221 + EMail: rosanna.lee@eng.sun.com + + + + + + +Ryan, et al. Informational [Page 17] + +RFC 2713 Schema for Java Objects October 1999 + + +Appendix - LDAP Schema + + -- Attribute types -- + + ( 1.3.6.1.4.1.42.2.27.4.1.6 + NAME 'javaClassName' + DESC 'Fully qualified name of distinguished Java class or interface' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.7 + NAME 'javaCodebase' + DESC 'URL(s) specifying the location of class definition' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.8 + NAME 'javaSerializedData' + DESC 'Serialized form of a Java object' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + SINGLE-VALUE + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.10 + NAME 'javaFactory' + DESC 'Fully qualified Java class name of a JNDI object factory' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.11 + NAME 'javaReferenceAddress' + DESC 'Addresses associated with a JNDI Reference' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.12 + NAME 'javaDoc' + DESC 'The Java documentation for the class' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + + + +Ryan, et al. Informational [Page 18] + +RFC 2713 Schema for Java Objects October 1999 + + + ( 1.3.6.1.4.1.42.2.27.4.1.13 + NAME 'javaClassNames' + DESC 'Fully qualified Java class or interface name' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + -- from RFC-2256 -- + + ( 2.5.4.13 + NAME 'description' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} + ) + + -- Object classes -- + + ( 1.3.6.1.4.1.42.2.27.4.2.1 + NAME 'javaContainer' + DESC 'Container for a Java object' + SUP top + STRUCTURAL + MUST ( cn ) + ) + + ( 1.3.6.1.4.1.42.2.27.4.2.4 + NAME 'javaObject' + DESC 'Java object representation' + SUP top + ABSTRACT + MUST ( javaClassName ) + MAY ( javaClassNames $ javaCodebase $ javaDoc $ description ) + ) + + ( 1.3.6.1.4.1.42.2.27.4.2.5 + NAME 'javaSerializedObject' + DESC 'Java serialized object' + SUP javaObject + AUXILIARY + MUST ( javaSerializedData ) + ) + + + + + + + + + +Ryan, et al. Informational [Page 19] + +RFC 2713 Schema for Java Objects October 1999 + + + ( 1.3.6.1.4.1.42.2.27.4.2.7 + NAME 'javaNamingReference' + DESC 'JNDI reference' + SUP javaObject + AUXILIARY + MAY ( javaReferenceAddress $ javaFactory ) + ) + + ( 1.3.6.1.4.1.42.2.27.4.2.8 + NAME 'javaMarshalledObject' + DESC 'Java marshalled object' + SUP javaObject + AUXILIARY + MUST ( javaSerializedData ) + ) + + -- Matching rule from ISO X.520 -- + + ( 2.5.13.5 + NAME 'caseExactMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 20] + +RFC 2713 Schema for Java Objects October 1999 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 21] + diff --git a/doc/rfc/rfc2714.txt b/doc/rfc/rfc2714.txt new file mode 100644 index 0000000000..172ff30c90 --- /dev/null +++ b/doc/rfc/rfc2714.txt @@ -0,0 +1,563 @@ + + + + + + +Network Working Group V. Ryan +Request for Comments: 2714 R. Lee +Category: Informational S. Seligman + Sun Microsystems, Inc. + October 1999 + + + Schema for Representing CORBA Object References in an LDAP Directory + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + CORBA [CORBA] is the Common Object Request Broker Architecture + defined by the Object Management Group. This document defines the + schema for representing CORBA object references in an LDAP directory + [LDAPv3]. + +1. Introduction + + This document assumes that the reader has a general understanding of + CORBA. + + Traditionally, LDAP directories have been used to store data. Users + and programmers think of the directory as a hierarchy of directory + entries, each containing a set of attributes. You look up an entry + from the directory and extract the attribute(s) of interest. For + example, you can look up a person's telephone number from the + directory. Alternatively, you can search the directory for entries + with a particular set of attributes. For example, you can search for + all persons in the directory with the surname "Smith". + + CORBA applications require access to CORBA objects. Traditionally, + CORBA applications have used the COS Naming service for storage and + retrieval of CORBA object references. When deployed in environments + with a directory, CORBA applications should be able to use the + directory as a repository for CORBA object references. The directory + provides a centrally administered, and possibly replicated, service + for use by CORBA applications distributed across the network. + + + + +Ryan, et al. Informational [Page 1] + +RFC 2714 Schema for CORBA Object References October 1999 + + + For example, an application server may use the directory for + "registering" CORBA objects representing the services that it + manages, so that a client can later search the directory to locate + those services as it needs. + + The motivation for this document is to define a common way for + applications to store and retrieve CORBA object references from the + directory. Using this common schema, any CORBA application that + needs to read or store CORBA object references in the directory can + do so in an interoperable way. + + Note that this schema is defined for storing CORBA "object + references," not CORBA objects in general. There might be other ways + to store CORBA objects in an LDAP directory but they are not covered + by this schema. + +2. Representation of CORBA Object References + + This document defines schema elements to represent a CORBA object + reference in LDAP directory. Applications in possession of a + reference to an object can invoke calls on that object. Such a + reference is termed an "interoperable object reference," or IOR. + Access to CORBA objects by using IORs is achieved transparently to + the application, by means of the General Inter-ORB Protocol. + + A CORBA object reference is represented in the directory by the + object class corbaObjectReference. corbaObjectReference is a subclass + of the abstract corbaObject object class. corbaObjectReference is an + auxiliary object class, which means that it needs to be mixed in with + a structural object class. + + The object class corbaContainer is used in a directory entry which + represents a CORBA object or object reference. It is a structural + object class, and when representing an object reference, the + corbaObjectReference object class would also need to be present in + the entry. corbaContainer is not required when a subclass of + corbaObject (such as corbaObjectReference) is mixed in with another + structural object class. + + The definitions for the object classes corbaObject, + corbaObjectReference, and corbaContainer are presented in Section 4. + + The corbaObject class has two optional attributes: corbaRepositoryId + and description. corbaRepositoryId is a multivalued attribute that + is used to store the repository ids of the interfaces implemented by + a CORBA object. description is used to store a textual description + of a CORBA object. + + + + +Ryan, et al. Informational [Page 2] + +RFC 2714 Schema for CORBA Object References October 1999 + + + The corbaObjectReference class has one mandatory attribute: corbaIor. + corbaIor is used to store the object's stringified IOR. + + corbaIor and corbaRepositoryId are defined in Section 3; description + is defined in [v3Schema]. + +3. Attribute Type Definitions + + The following attribute types are defined in this document: + + corbaIor + corbaRepositoryId + +3.1 corbaIor + + This attribute stores the string representation of the interoperable + object reference (IOR) for a CORBA object. An IOR is an opaque handle + for the object which contains the information necessary to locate the + object, even if the object is in another ORB. + + This attribute's syntax is 'IA5 String' and its case is + insignificant. + + ( 1.3.6.1.4.1.42.2.27.4.1.14 + NAME 'corbaIor' + DESC 'Stringified interoperable object reference of a CORBA object' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +3.2 corbaRepositoryId + + Each CORBA interface has a unique "repository id" (also called "type + id") that identifies the interface. A CORBA object has one or more + repository ids, one for each interface that it implements. + + The format of a repository id can be any string, but the OMG + specifies four standard formats: + + a. IDL-style + + IDL:Prefix/ModuleName/InterfaceName:VersionNumber + + + + + + + + +Ryan, et al. Informational [Page 3] + +RFC 2714 Schema for CORBA Object References October 1999 + + + For example, the repository id for the "NamingContext" in OMG's COS + Naming module is: "IDL:omg.org/CosNaming/NamingContext:1.0". + + b. RMI-style + + RMI:ClassName:HashCode[:SUID] + + This format is used by RMI-IIOP remote objects [RMI-IIOP]. + "ClassName" is the fully qualified name of the class (for example, + "java.lang.String"). "HashCode" is the object's hash code (that is, + that obtained by invoking the "hashCode()" method). "SUID" is the + "stream unique identifier", which is a 64-bit number that uniquely + identifies the serialization version of the class; SUID is optional + in the repository id. + + c. DCE-style + + DCE:UUID + + This format is used for DCE/CORBA interoperability [CORBA-DCE]. + "UUID" represents a DCE UUID. + + d. "local" + + This format is defined by the local Object Request Broker (ORB). + + The corbaRepositoryId attribute is a multivalued attribute; each + value records a single repository id of an interface implemented by + the CORBA object. This attribute need not contain a complete list of + the interfaces implemented by the CORBA object. + + This attribute's syntax is 'Directory String' and its case is + significant. The values of this attribute are encoded using UTF-8. + Some values may require translation from their native representation + in order to be correctly encoded using UTF-8. + + ( 1.3.6.1.4.1.42.2.27.4.1.15 + NAME 'corbaRepositoryId' + DESC 'Repository ids of interfaces implemented by a CORBA object' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + + + + + + + + +Ryan, et al. Informational [Page 4] + +RFC 2714 Schema for CORBA Object References October 1999 + + +4. Object Class Definitions + + The following object classes are defined in this document: + + corbaContainer + corbaObject + corbaObjectReference + +4.1 corbaContainer + + This structural object class represents a container for a CORBA + object. + + ( 1.3.6.1.4.1.42.2.27.4.2.10 + NAME 'corbaContainer' + DESC 'Container for a CORBA object' + SUP top + STRUCTURAL + MUST ( cn ) + ) + +4.2 corbaObject + + This abstract object class is the root class for representing a CORBA + object. + + ( 1.3.6.1.4.1.42.2.27.4.2.9 + NAME 'corbaObject' + DESC 'CORBA object representation' + SUP top + ABSTRACT + MAY ( corbaRepositoryId $ description ) + ) + +4.3 corbaObjectReference + + This auxiliary object class represents a CORBA object reference. It + must be mixed in with a structural object class. + + ( 1.3.6.1.4.1.42.2.27.4.2.11 + NAME 'corbaObjectReference' + DESC 'CORBA interoperable object reference' + SUP corbaObject + AUXILIARY + MUST ( corbaIor ) + ) + + + + + +Ryan, et al. Informational [Page 5] + +RFC 2714 Schema for CORBA Object References October 1999 + + +5. Security Considerations + + Obtaining a reference to an object and storing it in the directory + may make a handle to the object available to a wider audience. This + may have security implications. + +6. Acknowledgements + + We would like to thank Sanjeev Krishnan of Sun Microsystems, Simon + Nash of IBM, and Jeffrey Spirn of Oracle for their comments and + suggestions. + +7. References + + [CORBA] The Object Management Group, "Common Object Request + Broker Architecture Specification 2.2", + http://www.omg.org + + [CORBA-DCE] Distributed Systems Technology Center and Digital + Equipment Corporation, "DCE/CORBA Interworking + Specification", May 1998. + http://www.omg.org/library/schedule/ + DCE_CORBA_Interworking_RFP.html + + [LDAPv3] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory + Access Protocol (v3)", RFC 2251, December 1997. + + [RMI-IIOP] IBM and Java Software, Sun Microsystems, Inc., "RMI over + IIOP", June 1999. http://java.sun.com/products/rmi- + iiop/index.html + + [v3Schema] Wahl, M., "A Summary of the X.500(96) User Schema for use + with LDAPv3", RFC 2256, December 1997. + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 6] + +RFC 2714 Schema for CORBA Object References October 1999 + + +8. Authors' Addresses + + Vincent Ryan + Sun Microsystems, Inc. + Mail Stop EDUB03 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +353 1 819 9151 + EMail: vincent.ryan@ireland.sun.com + + + Rosanna Lee + Sun Microsystems, Inc. + Mail Stop UCUP02-206 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +1 408 863 3221 + EMail: rosanna.lee@eng.sun.com + + + Scott Seligman + Sun Microsystems, Inc. + Mail Stop UCUP02-209 + 901 San Antonio Road + Palo Alto, CA 94303 + USA + + Phone: +1 408 863 3222 + EMail: scott.seligman@eng.sun.com + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 7] + +RFC 2714 Schema for CORBA Object References October 1999 + + +9. Appendix - LDAP Schema + + -- Attribute types -- + + ( 1.3.6.1.4.1.42.2.27.4.1.14 + NAME 'corbaIor' + DESC 'Stringified interoperable object reference of a CORBA object' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + ( 1.3.6.1.4.1.42.2.27.4.1.15 + NAME 'corbaRepositoryId' + DESC 'Repository ids of interfaces implemented by a CORBA object' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + -- from RFC-2256 -- + + ( 2.5.4.13 + NAME 'description' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} + ) + + -- Object classes -- + + ( 1.3.6.1.4.1.42.2.27.4.2.9 + NAME 'corbaObject' + DESC 'CORBA object representation' + SUP top + ABSTRACT + MAY ( corbaRepositoryId $ description ) + ) + + ( 1.3.6.1.4.1.42.2.27.4.2.10 + NAME 'corbaContainer' + DESC 'Container for a CORBA object' + SUP top + STRUCTURAL + MUST ( cn ) + ) + + + + + + +Ryan, et al. Informational [Page 8] + +RFC 2714 Schema for CORBA Object References October 1999 + + + ( 1.3.6.1.4.1.42.2.27.4.2.11 + NAME 'corbaObjectReference' + DESC 'CORBA interoperable object reference' + SUP corbaObject + AUXILIARY + MUST ( corbaIor ) + ) + + -- Matching rule from ISO X.520 -- + + ( 2.5.13.5 + NAME 'caseExactMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 9] + +RFC 2714 Schema for CORBA Object References October 1999 + + +10. Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Ryan, et al. Informational [Page 10] + diff --git a/doc/rfc/rfc2798.txt b/doc/rfc/rfc2798.txt new file mode 100644 index 0000000000..3ad08a2359 --- /dev/null +++ b/doc/rfc/rfc2798.txt @@ -0,0 +1,1123 @@ + + + + + + +Network Working Group M. Smith +Request for Comments: 2798 Netscape Communications +Category: Informational April 2000 + + + Definition of the inetOrgPerson LDAP Object Class + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + While the X.500 standards define many useful attribute types [X520] + and object classes [X521], they do not define a person object class + that meets the requirements found in today's Internet and Intranet + directory service deployments. We define a new object class called + inetOrgPerson for use in LDAP and X.500 directory services that + extends the X.521 standard organizationalPerson class to meet these + needs. + + + + + + + + + + + + + + + + + + + + + + + + + +Smith Informational [Page 1] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +Table of Contents + + 1. Background and Intended Usage...............................2 + 2. New Attribute Types Used in the inetOrgPerson Object Class..3 + 2.1. Vehicle license or registration plate....................3 + 2.2. Department number........................................3 + 2.3. Display Name.............................................4 + 2.4. Employee Number..........................................4 + 2.5. Employee Type............................................4 + 2.6. JPEG Photograph..........................................5 + 2.7. Preferred Language.......................................5 + 2.8. User S/MIME Certificate..................................5 + 2.9. User PKCS #12............................................6 + 3. Definition of the inetOrgPerson Object Class................6 + 4. Example of an inetOrgPerson Entry...........................7 + 5. Security Considerations.....................................8 + 6. Acknowledgments.............................................8 + 7. Bibliography................................................8 + 8. Author's Address............................................9 + 9. Appendix A - inetOrgPerson Schema Summary..................10 + 9.1. Attribute Types..........................................10 + 9.1.1. New attribute types that are defined in this document.10 + 9.1.2. Attribute types from RFC 2256.........................12 + 9.1.3. Attribute types from RFC 1274.........................15 + 9.1.4. Attribute type from RFC 2079..........................16 + 9.2. Syntaxes.................................................17 + 9.2.1. Syntaxes from RFC 2252................................17 + 9.2.2. Syntaxes from RFC 2256................................17 + 9.3. Matching Rules...........................................17 + 9.3.1. Matching rules from RFC 2252..........................17 + 9.3.2. Matching rule from RFC 2256...........................18 + 9.3.3. Additional matching rules from X.520..................18 + 9.3.4. Matching rules not defined in any referenced document.19 + 10. Full Copyright Statement...................................20 + +1. Background and Intended Usage + + The inetOrgPerson object class is a general purpose object class that + holds attributes about people. The attributes it holds were chosen + to accommodate information requirements found in typical Internet and + Intranet directory service deployments. The inetOrgPerson object + class is designed to be used within directory services based on the + LDAP [RFC2251] and the X.500 family of protocols, and it should be + useful in other contexts as well. There is no requirement for + directory services implementors to use the inetOrgPerson object + class; it is simply presented as well-documented class that + implementors can choose to use if they find it useful. + + + + +Smith Informational [Page 2] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + The attribute type and object class definitions in this document are + written using the BNF form of AttributeTypeDescription and + ObjectClassDescription given in [RFC2252]. In some cases lines have + been folded for readability. + + Attributes that are referenced but not defined in this document are + included in one of the following documents: + + The COSINE and Internet X.500 Schema [RFC1274] + + Definition of an X.500 Attribute Type and an Object Class to Hold + Uniform Resource Identifiers (URIs) [RFC2079] + + A Summary of the X.500(96) User Schema for use with LDAPv3 + [RFC2256] + + See Appendix A for a summary of the attribute types, associated + syntaxes, and matching rules used in this document. + +2. New Attribute Types Used in the inetOrgPerson Object Class + +2.1. Vehicle license or registration plate. + + This multivalued field is used to record the values of the license or + registration plate associated with an individual. + + ( 2.16.840.1.113730.3.1.1 NAME 'carLicense' + DESC 'vehicle license or registration plate' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +2.2. Department number + + Code for department to which a person belongs. This can also be + strictly numeric (e.g., 1234) or alphanumeric (e.g., ABC/123). + + ( 2.16.840.1.113730.3.1.2 + NAME 'departmentNumber' + DESC 'identifies a department within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + + + + + + + +Smith Informational [Page 3] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +2.3. Display Name + + When displaying an entry, especially within a one-line summary list, + it is useful to be able to identify a name to be used. Since other + attribute types such as 'cn' are multivalued, an additional attribute + type is needed. Display name is defined for this purpose. + + ( 2.16.840.1.113730.3.1.241 + NAME 'displayName' + DESC 'preferred name of a person to be used when displaying entries' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + +2.4. Employee Number + + Numeric or alphanumeric identifier assigned to a person, typically + based on order of hire or association with an organization. Single + valued. + + ( 2.16.840.1.113730.3.1.3 + NAME 'employeeNumber' + DESC 'numerically identifies an employee within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + +2.5. Employee Type + + Used to identify the employer to employee relationship. Typical + values used will be "Contractor", "Employee", "Intern", "Temp", + "External", and "Unknown" but any value may be used. + + ( 2.16.840.1.113730.3.1.4 + NAME 'employeeType' + DESC 'type of employment for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + + + + + + + + + +Smith Informational [Page 4] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +2.6. JPEG Photograph + + Used to store one or more images of a person using the JPEG File + Interchange Format [JFIF]. + + ( 0.9.2342.19200300.100.1.60 + NAME 'jpegPhoto' + DESC 'a JPEG image' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 ) + + Note that the jpegPhoto attribute type was defined for use in the + Internet X.500 pilots but no referencable definition for it could be + located. + +2.7. Preferred Language + + Used to indicate an individual's preferred written or spoken + language. This is useful for international correspondence or human- + computer interaction. Values for this attribute type MUST conform to + the definition of the Accept-Language header field defined in + [RFC2068] with one exception: the sequence "Accept-Language" ":" + should be omitted. This is a single valued attribute type. + + ( 2.16.840.1.113730.3.1.39 + NAME 'preferredLanguage' + DESC 'preferred written or spoken language for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + ) + +2.8. User S/MIME Certificate + + A PKCS#7 [RFC2315] SignedData, where the content that is signed is + ignored by consumers of userSMIMECertificate values. It is + recommended that values have a `contentType' of data with an absent + `content' field. Values of this attribute contain a person's entire + certificate chain and an smimeCapabilities field [RFC2633] that at a + minimum describes their SMIME algorithm capabilities. Values for + this attribute are to be stored and requested in binary form, as + 'userSMIMECertificate;binary'. If available, this attribute is + preferred over the userCertificate attribute for S/MIME applications. + + ( 2.16.840.1.113730.3.1.40 + NAME 'userSMIMECertificate' + DESC 'PKCS#7 SignedData used to support S/MIME' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) + + + +Smith Informational [Page 5] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +2.9. User PKCS #12 + + PKCS #12 [PKCS12] provides a format for exchange of personal identity + information. When such information is stored in a directory service, + the userPKCS12 attribute should be used. This attribute is to be + stored and requested in binary form, as 'userPKCS12;binary'. The + attribute values are PFX PDUs stored as binary data. + +( 2.16.840.1.113730.3.1.216 + NAME 'userPKCS12' + DESC 'PKCS #12 PFX PDU for exchange of personal identity information' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) + +3. Definition of the inetOrgPerson Object Class + + The inetOrgPerson represents people who are associated with an + organization in some way. It is a structural class and is derived + from the organizationalPerson class which is defined in X.521 [X521]. + +( 2.16.840.1.113730.3.2.2 + NAME 'inetOrgPerson' + SUP organizationalPerson + STRUCTURAL + MAY ( + audio $ businessCategory $ carLicense $ departmentNumber $ + displayName $ employeeNumber $ employeeType $ givenName $ + homePhone $ homePostalAddress $ initials $ jpegPhoto $ + labeledURI $ mail $ manager $ mobile $ o $ pager $ + photo $ roomNumber $ secretary $ uid $ userCertificate $ + x500uniqueIdentifier $ preferredLanguage $ + userSMIMECertificate $ userPKCS12 + ) +) + + For reference, we list the following additional attribute types that + are part of the inetOrgPerson object class. These attribute types + are inherited from organizationalPerson (which in turn is derived + from the person object class): + + + + + + + + + + + + + +Smith Informational [Page 6] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + MUST ( + cn $ objectClass $ sn + ) + MAY ( + description $ destinationIndicator $ facsimileTelephoneNumber $ + internationaliSDNNumber $ l $ ou $ physicalDeliveryOfficeName $ + postalAddress $ postalCode $ postOfficeBox $ + preferredDeliveryMethod $ registeredAddress $ seeAlso $ + st $ street $ telephoneNumber $ teletexTerminalIdentifier $ + telexNumber $ title $ userPassword $ x121Address + ) + +4. Example of an inetOrgPerson Entry + + The following example is expressed using the LDIF notation defined in + [LDIF]. + + version: 1 + dn: cn=Barbara Jensen,ou=Product Development,dc=siroe,dc=com + objectClass: top + objectClass: person + objectClass: organizationalPerson + objectClass: inetOrgPerson + cn: Barbara Jensen + cn: Babs Jensen + displayName: Babs Jensen + sn: Jensen + givenName: Barbara + initials: BJJ + title: manager, product development + uid: bjensen + mail: bjensen@siroe.com + telephoneNumber: +1 408 555 1862 + facsimileTelephoneNumber: +1 408 555 1992 + mobile: +1 408 555 1941 + roomNumber: 0209 + carLicense: 6ABC246 + o: Siroe + ou: Product Development + departmentNumber: 2604 + employeeNumber: 42 + employeeType: full time + preferredLanguage: fr, en-gb;q=0.8, en;q=0.7 + labeledURI: http://www.siroe.com/users/bjensen My Home Page + + + + + + + +Smith Informational [Page 7] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +5. Security Considerations + + Attributes of directory entries are used to provide descriptive + information about the real-world objects they represent, which can be + people, organizations or devices. Most countries have privacy laws + regarding the publication of information about people. + + Transfer of cleartext passwords are strongly discouraged where the + underlying transport service cannot guarantee confidentiality and may + result in disclosure of the password to unauthorized parties. + +6. Acknowledgments + + The Netscape Directory Server team created the inetOrgPerson object + class based on experience and customer requirements. Anil Bhavnani + and John Kristian in particular deserve credit for all of the early + design work. + + Many members of the Internet community, in particular those in the + IETF ASID and LDAPEXT groups, also contributed to the design of this + object class. + +7. Bibliography + + [JFIF] E. Hamilton, "JPEG File Interchange Format (Version 1.02)", + C-Cube Microsystems, Milpitas, CA, September 1, 1992. + + [LDIF] G. Good, "The LDAP Data Interchange Format (LDIF) - + Technical Specification", Work in Progress. + + [PKCS12] "PKCS #12: Personal Information Exchange Standard", Version + 1.0 Draft, 30 April 1997. + + [RFC1274] Barker, P. and S. Kille, "The COSINE and Internet X.500 + Schema", RFC 1274, November 1991. + + [RFC1847] Galvin, J., Murphy, S., Crocker, S. and N. Freed, "Security + Multiparts for MIME: Multipart/Signed and + Multipart/Encrypted", RFC 1847, October 1995. + + [RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T. + Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC + 2068, January 1997. + + [RFC2079] Smith, M., "Definition of an X.500 Attribute Type and an + Object Class to Hold Uniform Resource Identifiers (URIs)", + RFC 2079, January 1997. + + + + +Smith Informational [Page 8] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + [RFC2251] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory + Access Protocol (v3)", RFC 2251, December 1997. + + [RFC2252] Wahl, M., Coulbeck, A., Howes, T., Kille, S., Yeong, W. and + C. Robbins, "Lightweight Directory Access Protocol (v3): + Attribute Syntax Definitions", RFC 2252, December 1997. + + [RFC2256] Wahl, M., "A Summary of the X.500(96) User Schema for use + with LDAPv3", RFC 2256, December 1997. + + [RFC2315] Kaliski, B., "PKCS #7: Cryptographic Message Syntax Version + 1.5", RFC 2315, March 1998. + + [RFC2633] Ramsdell, B., "S/MIME Version 3 Message Specification", RFC + 2633, June 1999. + + [X520] ITU-T Rec. X.520, "The Directory: Selected Attribute + Types", 1996. + + [X521] ITU-T Rec. X.521, "The Directory: Selected Object Classes", + 1996. + +8. Author's Address + + Mark Smith + Netscape Communications Corp. + 501 E. Middlefield Rd., Mailstop MV068 + Mountain View, CA 94043, USA + + Phone: +1 650 937-3477 + EMail: mcs@netscape.com + + + + + + + + + + + + + + + + + + + + +Smith Informational [Page 9] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +9. Appendix A - inetOrgPerson Schema Summary + + This appendix provides definitions of all the attribute types + included in the inetOrgPerson object class along with their + associated syntaxes and matching rules. + +9.1. Attribute Types + +9.1.1. New attribute types that are defined in this document + + ( 2.16.840.1.113730.3.1.1 NAME 'carLicense' + DESC 'vehicle license or registration plate' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + ( 2.16.840.1.113730.3.1.2 + NAME 'departmentNumber' + DESC 'identifies a department within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + ( 2.16.840.1.113730.3.1.241 + NAME 'displayName' + DESC 'preferred name of a person to be used when displaying entries' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + + ( 2.16.840.1.113730.3.1.3 + NAME 'employeeNumber' + DESC 'numerically identifies an employee within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + + ( 2.16.840.1.113730.3.1.4 + NAME 'employeeType' + DESC 'type of employment for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + + + + + +Smith Informational [Page 10] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 0.9.2342.19200300.100.1.60 + NAME 'jpegPhoto' + DESC 'a JPEG image' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 ) + Note: The jpegPhoto attribute type was defined for use in the + Internet X.500 pilots but no referencable definition for it + could be located. + + ( 2.16.840.1.113730.3.1.39 + NAME 'preferredLanguage' + DESC 'preferred written or spoken language for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + + ( 2.16.840.1.113730.3.1.40 + NAME 'userSMIMECertificate' + DESC 'signed message used to support S/MIME' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) + + ( 2.16.840.1.113730.3.1.216 + NAME 'userPKCS12' + DESC 'PKCS #12 PFX PDU for exchange of personal identity information' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) + +9.1.2. Attribute types from RFC 2256 + + Note that the original definitions of these types can be found in + X.520. + + ( 2.5.4.15 + NAME 'businessCategory' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) + + ( 2.5.4.3 + NAME 'cn' + SUP name ) + + ( 2.5.4.13 + NAME 'description' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} ) + + + + + +Smith Informational [Page 11] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 2.5.4.27 + NAME 'destinationIndicator' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} ) + + ( 2.5.4.23 + NAME 'facsimileTelephoneNumber' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 ) + + ( 2.5.4.42 + NAME 'givenName' + SUP name ) + + ( 2.5.4.43 + NAME 'initials' + SUP name ) + + ( 2.5.4.25 + NAME 'internationaliSDNNumber' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} ) + + ( 2.5.4.7 + NAME 'l' + SUP name ) + + ( 2.5.4.0 + NAME 'objectClass' + EQUALITY objectIdentifierMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 ) + + ( 2.5.4.10 + NAME 'o' + SUP name ) + + ( 2.5.4.11 + NAME 'ou' + SUP name ) + + ( 2.5.4.19 + NAME 'physicalDeliveryOfficeName' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) + + + + + +Smith Informational [Page 12] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 2.5.4.18 + NAME 'postOfficeBox' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} ) + + ( 2.5.4.16 + NAME 'postalAddress' + EQUALITY caseIgnoreListMatch + SUBSTR caseIgnoreListSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) + + ( 2.5.4.17 + NAME 'postalCode' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} ) + + ( 2.5.4.28 + NAME 'preferredDeliveryMethod' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.14 + SINGLE-VALUE ) + + ( 2.5.4.26 + NAME 'registeredAddress' + SUP postalAddress + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) + + ( 2.5.4.34 + NAME 'seeAlso' + SUP distinguishedName ) + + ( 2.5.4.4 + NAME 'sn' + SUP name ) + + ( 2.5.4.8 + NAME 'st' + SUP name ) + + ( 2.5.4.9 + NAME 'street' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) + + + + + + +Smith Informational [Page 13] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 2.5.4.20 + NAME 'telephoneNumber' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} ) + + ( 2.5.4.22 + NAME 'teletexTerminalIdentifier' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 ) + + ( 2.5.4.21 + NAME 'telexNumber' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 ) + + ( 2.5.4.12 + NAME 'title' + SUP name ) + + ( 2.5.4.36 + NAME 'userCertificate' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 ) + + ( 2.5.4.35 + NAME 'userPassword' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} ) + + ( 2.5.4.24 + NAME 'x121Address' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} ) + + ( 2.5.4.45 + NAME 'x500UniqueIdentifier' + EQUALITY bitStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 ) + + Some attribute types included in inetOrgPerson are derived from the + 'name' and 'distinguishedName' attribute supertypes: + + ( 2.5.4.41 + NAME 'name' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} ) + + + + + +Smith Informational [Page 14] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 2.5.4.49 + NAME 'distinguishedName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + +9.1.3. Attribute types from RFC 1274 + + ( 0.9.2342.19200300.100.1.55 + NAME 'audio' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{250000} ) + Note: The syntax used here for the audio attribute type is Octet + String. RFC 1274 uses a syntax called audio which is not defined + in RFC 1274. + + ( 0.9.2342.19200300.100.1.20 + NAME 'homePhone' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) + Note: RFC 1274 uses the longer name 'homeTelephoneNumber'. + + ( 0.9.2342.19200300.100.1.39 + NAME 'homePostalAddress' + EQUALITY caseIgnoreListMatch + SUBSTR caseIgnoreListSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) + + ( 0.9.2342.19200300.100.1.3 + NAME 'mail' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) + Note: RFC 1274 uses the longer name 'rfc822Mailbox' and syntax OID + of 0.9.2342.19200300.100.3.5. All recent LDAP documents and most + deployed LDAP implementations refer to this attribute as 'mail' + and define the IA5 String syntax using using the OID + 1.3.6.1.4.1.1466.115.121.1.26, as is done here. + + ( 0.9.2342.19200300.100.1.10 + NAME 'manager' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + + + + + + + +Smith Informational [Page 15] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 0.9.2342.19200300.100.1.41 + NAME 'mobile' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) + Note: RFC 1274 uses the longer name 'mobileTelephoneNumber'. + + ( 0.9.2342.19200300.100.1.42 + NAME 'pager' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) + Note: RFC 1274 uses the longer name 'pagerTelephoneNumber'. + + ( 0.9.2342.19200300.100.1.7 + NAME 'photo' ) + Note: Photo attribute values are encoded in G3 fax format with an + ASN.1 wrapper. Please refer to RFC 1274 section 9.3.7 for + detailed syntax information for this attribute. + + ( 0.9.2342.19200300.100.1.6 + NAME 'roomNumber' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) + + ( 0.9.2342.19200300.100.1.21 + NAME 'secretary' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + ( 0.9.2342.19200300.100.1.1 + NAME 'uid' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) + Note: RFC 1274 uses the longer name 'userid'. + +9.1.4. Attribute type from RFC 2079 + + ( 1.3.6.1.4.1.250.1.57 + NAME 'labeledURI' + EQUALITY caseExactMatch + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + + + + + +Smith Informational [Page 16] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +9.2. Syntaxes + +9.2.1. Syntaxes from RFC 2252 + + ( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' ) + + ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' ) + + ( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' ) + + ( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' ) + + ( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' ) + + ( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' ) + + ( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' ) + + ( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' ) + +9.2.2. Syntaxes from RFC 2256 + + ( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' ) + + ( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' ) + + ( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' ) + + ( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' ) + +9.3. Matching Rules + +9.3.1. Matching rules from RFC 2252 + + Note that the original definition of many of these matching rules can + be found in X.520. + + + + + +Smith Informational [Page 17] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + ( 2.5.13.16 NAME 'bitStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 ) + + ( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + ( 2.5.13.11 NAME 'caseIgnoreListMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) + + ( 2.5.13.2 NAME 'caseIgnoreMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + ( 2.5.13.1 NAME 'distinguishedNameMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + ( 2.5.13.8 NAME 'numericStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 ) + + ( 2.5.13.0 NAME 'objectIdentifierMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 ) + + ( 2.5.13.20 NAME 'telephoneNumberMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) + +9.3.2. Matching rule from RFC 2256 + + Note that the original definition of this matching rule can be found + in X.520. + + ( 2.5.13.17 NAME 'octetStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + +9.3.3. Additional matching rules from X.520 + + caseExactMatch + + ( 2.5.13.5 NAME 'caseExactMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + This rule determines whether a presented string exactly matches an + attribute value of syntax DirectoryString. It is identical to + caseIgnoreMatch except that case is not ignored. Multiple adjoining + whitespace characters are treated the same as an individual space, + and leading and trailing whitespace is ignored. + + + + + + + +Smith Informational [Page 18] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + + caseExactSubstringsMatch + + ( 2.5.13.7 NAME 'caseExactSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 ) + + This rules determines whether the initial, any and final substring + elements in a presented value are present in an attribute value of + syntax DirectoryString. It is identical to caseIgnoreSubstringsMatch + except that case is not ignored. + + caseIgnoreListSubstringsMatch + + ( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 ) + + This rule compares a presented substring with an attribute value + which is a sequence of DirectoryStrings, but where the case of + letters is not significant for comparison purposes. A presented + value matches a stored value if and only if the presented value + matches the string formed by concatenating the strings of the stored + value. Matching is done according to the caseIgnoreSubstringsMatch + rule except that none of the initial, final, or any values of the + presented value match a substring of the concatenated string which + spans more than one of the strings of the stored value. + +9.3.4. Matching rules not defined in any referenced document + + caseIgnoreIA5SubstringsMatch + + ( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 ) + + This rules determines whether the initial, any and final substring + elements in a presented value are present in an attribute value of + syntax IA5 String without regard to the case of the letters in the + strings. It is expected that this matching rule will be added to an + update of RFC 2252. + + + + + + + + + + + + + + +Smith Informational [Page 19] + +RFC 2798 The LDAP inetOrgPerson Object Class April 2000 + + +10. Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Smith Informational [Page 20] + diff --git a/doc/rfc/rfc2829.txt b/doc/rfc/rfc2829.txt new file mode 100644 index 0000000000..343e153c8e --- /dev/null +++ b/doc/rfc/rfc2829.txt @@ -0,0 +1,899 @@ + + + + + + +Network Working Group M. Wahl +Request for Comments: 2829 Sun Microsystems, Inc. +Category: Standards Track H. Alvestrand + EDB Maxware + J. Hodges + Oblix, Inc. + R. Morgan + University of Washington + May 2000 + + + Authentication Methods for LDAP + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + This document specifies particular combinations of security + mechanisms which are required and recommended in LDAP [1] + implementations. + +1. Introduction + + LDAP version 3 is a powerful access protocol for directories. + + It offers means of searching, fetching and manipulating directory + content, and ways to access a rich set of security functions. + + In order to function for the best of the Internet, it is vital that + these security functions be interoperable; therefore there has to be + a minimum subset of security functions that is common to all + implementations that claim LDAPv3 conformance. + + Basic threats to an LDAP directory service include: + + (1) Unauthorized access to data via data-fetching operations, + + + + + +Wahl, et al. Standards Track [Page 1] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + (2) Unauthorized access to reusable client authentication + information by monitoring others' access, + + (3) Unauthorized access to data by monitoring others' access, + + (4) Unauthorized modification of data, + + (5) Unauthorized modification of configuration, + + (6) Unauthorized or excessive use of resources (denial of + service), and + + (7) Spoofing of directory: Tricking a client into believing that + information came from the directory when in fact it did not, + either by modifying data in transit or misdirecting the + client's connection. + + Threats (1), (4), (5) and (6) are due to hostile clients. Threats + (2), (3) and (7) are due to hostile agents on the path between client + and server, or posing as a server. + + The LDAP protocol suite can be protected with the following security + mechanisms: + + (1) Client authentication by means of the SASL [2] mechanism + set, possibly backed by the TLS credentials exchange + mechanism, + + (2) Client authorization by means of access control based on the + requestor's authenticated identity, + + (3) Data integrity protection by means of the TLS protocol or + data-integrity SASL mechanisms, + + (4) Protection against snooping by means of the TLS protocol or + data-encrypting SASL mechanisms, + + (5) Resource limitation by means of administrative limits on + service controls, and + + (6) Server authentication by means of the TLS protocol or SASL + mechanism. + + At the moment, imposition of access controls is done by means outside + the scope of the LDAP protocol. + + In this document, the term "user" represents any application which is + an LDAP client using the directory to retrieve or store information. + + + +Wahl, et al. Standards Track [Page 2] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [3]. + +2. Example deployment scenarios + + The following scenarios are typical for LDAP directories on the + Internet, and have different security requirements. (In the + following, "sensitive" means data that will cause real damage to the + owner if revealed; there may be data that is protected but not + sensitive). This is not intended to be a comprehensive list, other + scenarios are possible, especially on physically protected networks. + + (1) A read-only directory, containing no sensitive data, + accessible to "anyone", and TCP connection hijacking or IP + spoofing is not a problem. This directory requires no + security functions except administrative service limits. + + (2) A read-only directory containing no sensitive data; read + access is granted based on identity. TCP connection + hijacking is not currently a problem. This scenario requires + a secure authentication function. + + (3) A read-only directory containing no sensitive data; and the + client needs to ensure that the directory data is + authenticated by the server and not modified while being + returned from the server. + + (4) A read-write directory, containing no sensitive data; read + access is available to "anyone", update access to properly + authorized persons. TCP connection hijacking is not + currently a problem. This scenario requires a secure + authentication function. + + (5) A directory containing sensitive data. This scenario + requires session confidentiality protection AND secure + authentication. + +3. Authentication and Authorization: Definitions and Concepts + + This section defines basic terms, concepts, and interrelationships + regarding authentication, authorization, credentials, and identity. + These concepts are used in describing how various security approaches + are utilized in client authentication and authorization. + + + + + + + +Wahl, et al. Standards Track [Page 3] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +3.1. Access Control Policy + + An access control policy is a set of rules defining the protection of + resources, generally in terms of the capabilities of persons or other + entities accessing those resources. A common expression of an access + control policy is an access control list. Security objects and + mechanisms, such as those described here, enable the expression of + access control policies and their enforcement. Access control + policies are typically expressed in terms of access control + attributes as described below. + +3.2. Access Control Factors + + A request, when it is being processed by a server, may be associated + with a wide variety of security-related factors (section 4.2 of [1]). + The server uses these factors to determine whether and how to process + the request. These are called access control factors (ACFs). They + might include source IP address, encryption strength, the type of + operation being requested, time of day, etc. Some factors may be + specific to the request itself, others may be associated with the + connection via which the request is transmitted, others (e.g. time of + day) may be "environmental". + + Access control policies are expressed in terms of access control + factors. E.g., a request having ACFs i,j,k can perform operation Y + on resource Z. The set of ACFs that a server makes available for such + expressions is implementation-specific. + +3.3. Authentication, Credentials, Identity + + Authentication credentials are the evidence supplied by one party to + another, asserting the identity of the supplying party (e.g. a user) + who is attempting to establish an association with the other party + (typically a server). Authentication is the process of generating, + transmitting, and verifying these credentials and thus the identity + they assert. An authentication identity is the name presented in a + credential. + + There are many forms of authentication credentials -- the form used + depends upon the particular authentication mechanism negotiated by + the parties. For example: X.509 certificates, Kerberos tickets, + simple identity and password pairs. Note that an authentication + mechanism may constrain the form of authentication identities used + with it. + + + + + + + +Wahl, et al. Standards Track [Page 4] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +3.4. Authorization Identity + + An authorization identity is one kind of access control factor. It + is the name of the user or other entity that requests that operations + be performed. Access control policies are often expressed in terms + of authorization identities; e.g., entity X can perform operation Y + on resource Z. + + The authorization identity bound to an association is often exactly + the same as the authentication identity presented by the client, but + it may be different. SASL allows clients to specify an authorization + identity distinct from the authentication identity asserted by the + client's credentials. This permits agents such as proxy servers to + authenticate using their own credentials, yet request the access + privileges of the identity for which they are proxying [2]. Also, + the form of authentication identity supplied by a service like TLS + may not correspond to the authorization identities used to express a + server's access control policy, requiring a server-specific mapping + to be done. The method by which a server composes and validates an + authorization identity from the authentication credentials supplied + by a client is implementation-specific. + +4. Required security mechanisms + + It is clear that allowing any implementation, faced with the above + requirements, to pick and choose among the possible alternatives is + not a strategy that is likely to lead to interoperability. In the + absence of mandates, clients will be written that do not support any + security function supported by the server, or worse, support only + mechanisms like cleartext passwords that provide clearly inadequate + security. + + Active intermediary attacks are the most difficult for an attacker to + perform, and for an implementation to protect against. Methods that + protect only against hostile client and passive eavesdropping attacks + are useful in situations where the cost of protection against active + intermediary attacks is not justified based on the perceived risk of + active intermediary attacks. + + Given the presence of the Directory, there is a strong desire to see + mechanisms where identities take the form of a Distinguished Name and + authentication data can be stored in the directory; this means that + either this data is useless for faking authentication (like the Unix + "/etc/passwd" file format used to be), or its content is never passed + across the wire unprotected - that is, it's either updated outside + the protocol or it is only updated in sessions well protected against + snooping. It is also desirable to allow authentication methods to + + + + +Wahl, et al. Standards Track [Page 5] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + carry authorization identities based on existing forms of user + identities for backwards compatibility with non-LDAP-based + authentication services. + + Therefore, the following implementation conformance requirements are + in place: + + (1) For a read-only, public directory, anonymous authentication, + described in section 5, can be used. + + (2) Implementations providing password-based authenticated + access MUST support authentication using the DIGEST-MD5 SASL + mechanism [4], as described in section 6.1. This provides + client authentication with protection against passive + eavesdropping attacks, but does not provide protection + against active intermediary attacks. + + (3) For a directory needing session protection and + authentication, the Start TLS extended operation [5], and + either the simple authentication choice or the SASL EXTERNAL + mechanism, are to be used together. Implementations SHOULD + support authentication with a password as described in + section 6.2, and SHOULD support authentication with a + certificate as described in section 7.1. Together, these + can provide integrity and disclosure protection of + transmitted data, and authentication of client and server, + including protection against active intermediary attacks. + + If TLS is negotiated, the client MUST discard all information about + the server fetched prior to the TLS negotiation. In particular, the + value of supportedSASLMechanisms MAY be different after TLS has been + negotiated (specifically, the EXTERNAL mechanism or the proposed + PLAIN mechanism are likely to only be listed after a TLS negotiation + has been performed). + + If a SASL security layer is negotiated, the client MUST discard all + information about the server fetched prior to SASL. In particular, + if the client is configured to support multiple SASL mechanisms, it + SHOULD fetch supportedSASLMechanisms both before and after the SASL + security layer is negotiated and verify that the value has not + changed after the SASL security layer was negotiated. This detects + active attacks which remove supported SASL mechanisms from the + supportedSASLMechanisms list, and allows the client to ensure that it + is using the best mechanism supported by both client and server + (additionally, this is a SHOULD to allow for environments where the + supported SASL mechanisms list is provided to the client through a + different trusted source, e.g. as part of a digitally signed object). + + + + +Wahl, et al. Standards Track [Page 6] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +5. Anonymous authentication + + Directory operations which modify entries or access protected + attributes or entries generally require client authentication. + Clients which do not intend to perform any of these operations + typically use anonymous authentication. + + LDAP implementations MUST support anonymous authentication, as + defined in section 5.1. + + LDAP implementations MAY support anonymous authentication with TLS, + as defined in section 5.2. + + While there MAY be access control restrictions to prevent access to + directory entries, an LDAP server SHOULD allow an anonymously-bound + client to retrieve the supportedSASLMechanisms attribute of the root + DSE. + + An LDAP server MAY use other information about the client provided by + the lower layers or external means to grant or deny access even to + anonymously authenticated clients. + +5.1. Anonymous authentication procedure + + An LDAP client which has not successfully completed a bind operation + on a connection is anonymously authenticated. + + An LDAP client MAY also specify anonymous authentication in a bind + request by using a zero-length OCTET STRING with the simple + authentication choice. + +5.2. Anonymous authentication and TLS + + An LDAP client MAY use the Start TLS operation [5] to negotiate the + use of TLS security [6]. If the client has not bound beforehand, + then until the client uses the EXTERNAL SASL mechanism to negotiate + the recognition of the client's certificate, the client is + anonymously authenticated. + + Recommendations on TLS ciphersuites are given in section 10. + + An LDAP server which requests that clients provide their certificate + during TLS negotiation MAY use a local security policy to determine + whether to successfully complete TLS negotiation if the client did + not present a certificate which could be validated. + + + + + + +Wahl, et al. Standards Track [Page 7] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +6. Password-based authentication + + LDAP implementations MUST support authentication with a password + using the DIGEST-MD5 SASL mechanism for password protection, as + defined in section 6.1. + + LDAP implementations SHOULD support authentication with the "simple" + password choice when the connection is protected against + eavesdropping using TLS, as defined in section 6.2. + +6.1. Digest authentication + + An LDAP client MAY determine whether the server supports this + mechanism by performing a search request on the root DSE, requesting + the supportedSASLMechanisms attribute, and checking whether the + string "DIGEST-MD5" is present as a value of this attribute. + + In the first stage of authentication, when the client is performing + an "initial authentication" as defined in section 2.1 of [4], the + client sends a bind request in which the version number is 3, the + authentication choice is sasl, the sasl mechanism name is "DIGEST- + MD5", and the credentials are absent. The client then waits for a + response from the server to this request. + + The server will respond with a bind response in which the resultCode + is saslBindInProgress, and the serverSaslCreds field is present. The + contents of this field is a string defined by "digest-challenge" in + section 2.1.1 of [4]. The server SHOULD include a realm indication + and MUST indicate support for UTF-8. + + The client will send a bind request with a distinct message id, in + which the version number is 3, the authentication choice is sasl, the + sasl mechanism name is "DIGEST-MD5", and the credentials contain the + string defined by "digest-response" in section 2.1.2 of [4]. The + serv-type is "ldap". + + The server will respond with a bind response in which the resultCode + is either success, or an error indication. If the authentication is + successful and the server does not support subsequent authentication, + then the credentials field is absent. If the authentication is + successful and the server supports subsequent authentication, then + the credentials field contains the string defined by "response-auth" + in section 2.1.3 of [4]. Support for subsequent authentication is + OPTIONAL in clients and servers. + + + + + + + +Wahl, et al. Standards Track [Page 8] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +6.2. "simple" authentication choice under TLS encryption + + A user who has a directory entry containing a userPassword attribute + MAY authenticate to the directory by performing a simple password + bind sequence following the negotiation of a TLS ciphersuite + providing connection confidentiality [6]. + + The client will use the Start TLS operation [5] to negotiate the use + of TLS security [6] on the connection to the LDAP server. The client + need not have bound to the directory beforehand. + + For this authentication procedure to be successful, the client and + server MUST negotiate a ciphersuite which contains a bulk encryption + algorithm of appropriate strength. Recommendations on cipher suites + are given in section 10. + + Following the successful completion of TLS negotiation, the client + MUST send an LDAP bind request with the version number of 3, the name + field containing the name of the user's entry, and the "simple" + authentication choice, containing a password. + + The server will, for each value of the userPassword attribute in the + named user's entry, compare these for case-sensitive equality with + the client's presented password. If there is a match, then the + server will respond with resultCode success, otherwise the server + will respond with resultCode invalidCredentials. + +6.3. Other authentication choices with TLS + + It is also possible, following the negotiation of TLS, to perform a + SASL authentication which does not involve the exchange of plaintext + reusable passwords. In this case the client and server need not + negotiate a ciphersuite which provides confidentiality if the only + service required is data integrity. + +7. Certificate-based authentication + + LDAP implementations SHOULD support authentication via a client + certificate in TLS, as defined in section 7.1. + +7.1. Certificate-based authentication with TLS + + A user who has a public/private key pair in which the public key has + been signed by a Certification Authority may use this key pair to + authenticate to the directory server if the user's certificate is + requested by the server. The user's certificate subject field SHOULD + be the name of the user's directory entry, and the Certification + Authority must be sufficiently trusted by the directory server to + + + +Wahl, et al. Standards Track [Page 9] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + have issued the certificate in order that the server can process the + certificate. The means by which servers validate certificate paths + is outside the scope of this document. + + A server MAY support mappings for certificates in which the subject + field name is different from the name of the user's directory entry. + A server which supports mappings of names MUST be capable of being + configured to support certificates for which no mapping is required. + + The client will use the Start TLS operation [5] to negotiate the use + of TLS security [6] on the connection to the LDAP server. The client + need not have bound to the directory beforehand. + + In the TLS negotiation, the server MUST request a certificate. The + client will provide its certificate to the server, and MUST perform a + private key-based encryption, proving it has the private key + associated with the certificate. + + As deployments will require protection of sensitive data in transit, + the client and server MUST negotiate a ciphersuite which contains a + bulk encryption algorithm of appropriate strength. Recommendations + of cipher suites are given in section 10. + + The server MUST verify that the client's certificate is valid. The + server will normally check that the certificate is issued by a known + CA, and that none of the certificates on the client's certificate + chain are invalid or revoked. There are several procedures by which + the server can perform these checks. + + Following the successful completion of TLS negotiation, the client + will send an LDAP bind request with the SASL "EXTERNAL" mechanism. + +8. Other mechanisms + + The LDAP "simple" authentication choice is not suitable for + authentication on the Internet where there is no network or transport + layer confidentiality. + + As LDAP includes native anonymous and plaintext authentication + methods, the "ANONYMOUS" and "PLAIN" SASL mechanisms are not used + with LDAP. If an authorization identity of a form different from a + DN is requested by the client, a mechanism that protects the password + in transit SHOULD be used. + + The following SASL-based mechanisms are not considered in this + document: KERBEROS_V4, GSSAPI and SKEY. + + + + + +Wahl, et al. Standards Track [Page 10] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + The "EXTERNAL" SASL mechanism can be used to request the LDAP server + make use of security credentials exchanged by a lower layer. If a TLS + session has not been established between the client and server prior + to making the SASL EXTERNAL Bind request and there is no other + external source of authentication credentials (e.g. IP-level + security [8]), or if, during the process of establishing the TLS + session, the server did not request the client's authentication + credentials, the SASL EXTERNAL bind MUST fail with a result code of + inappropriateAuthentication. Any client authentication and + authorization state of the LDAP association is lost, so the LDAP + association is in an anonymous state after the failure. + +9. Authorization Identity + + The authorization identity is carried as part of the SASL credentials + field in the LDAP Bind request and response. + + When the "EXTERNAL" mechanism is being negotiated, if the credentials + field is present, it contains an authorization identity of the + authzId form described below. + + Other mechanisms define the location of the authorization identity in + the credentials field. + + The authorization identity is a string in the UTF-8 character set, + corresponding to the following ABNF [7]: + + ; Specific predefined authorization (authz) id schemes are + ; defined below -- new schemes may be defined in the future. + + authzId = dnAuthzId / uAuthzId + + ; distinguished-name-based authz id. + dnAuthzId = "dn:" dn + dn = utf8string ; with syntax defined in RFC 2253 + + ; unspecified userid, UTF-8 encoded. + uAuthzId = "u:" userid + userid = utf8string ; syntax unspecified + + A utf8string is defined to be the UTF-8 encoding of one or more ISO + 10646 characters. + + All servers which support the storage of authentication credentials, + such as passwords or certificates, in the directory MUST support the + dnAuthzId choice. + + + + + +Wahl, et al. Standards Track [Page 11] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + The uAuthzId choice allows for compatibility with client applications + which wish to authenticate to a local directory but do not know their + own Distinguished Name or have a directory entry. The format of the + string is defined as only a sequence of UTF-8 encoded ISO 10646 + characters, and further interpretation is subject to prior agreement + between the client and server. + + For example, the userid could identify a user of a specific directory + service, or be a login name or the local-part of an RFC 822 email + address. In general a uAuthzId MUST NOT be assumed to be globally + unique. + + Additional authorization identity schemes MAY be defined in future + versions of this document. + +10. TLS Ciphersuites + + The following ciphersuites defined in [6] MUST NOT be used for + confidentiality protection of passwords or data: + + TLS_NULL_WITH_NULL_NULL + TLS_RSA_WITH_NULL_MD5 + TLS_RSA_WITH_NULL_SHA + + The following ciphersuites defined in [6] can be cracked easily (less + than a week of CPU time on a standard CPU in 1997). The client and + server SHOULD carefully consider the value of the password or data + being protected before using these ciphersuites: + + TLS_RSA_EXPORT_WITH_RC4_40_MD5 + TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 + TLS_RSA_EXPORT_WITH_DES40_CBC_SHA + TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA + TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA + TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA + TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA + TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 + TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA + + The following ciphersuites are vulnerable to man-in-the-middle + attacks, and SHOULD NOT be used to protect passwords or sensitive + data, unless the network configuration is such that the danger of a + man-in-the-middle attack is tolerable: + + + + + + + + +Wahl, et al. Standards Track [Page 12] + +RFC 2829 Authentication Methods for LDAP May 2000 + + + TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 + TLS_DH_anon_WITH_RC4_128_MD5 + TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA + TLS_DH_anon_WITH_DES_CBC_SHA + TLS_DH_anon_WITH_3DES_EDE_CBC_SHA + + A client or server that supports TLS MUST support at least + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA. + +11. SASL service name for LDAP + + For use with SASL [2], a protocol must specify a service name to be + used with various SASL mechanisms, such as GSSAPI. For LDAP, the + service name is "ldap", which has been registered with the IANA as a + GSSAPI service name. + +12. Security Considerations + + Security issues are discussed throughout this memo; the + (unsurprising) conclusion is that mandatory security is important, + and that session encryption is required when snooping is a problem. + + Servers are encouraged to prevent modifications by anonymous users. + Servers may also wish to minimize denial of service attacks by timing + out idle connections, and returning the unwillingToPerform result + code rather than performing computationally expensive operations + requested by unauthorized clients. + + A connection on which the client has not performed the Start TLS + operation or negotiated a suitable SASL mechanism for connection + integrity and encryption services is subject to man-in-the-middle + attacks to view and modify information in transit. + + Additional security considerations relating to the EXTERNAL mechanism + to negotiate TLS can be found in [2], [5] and [6]. + +13. Acknowledgements + + This document is a product of the LDAPEXT Working Group of the IETF. + The contributions of its members is greatly appreciated. + + + + + + + + + + + +Wahl, et al. Standards Track [Page 13] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +14. Bibliography + + [1] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory Access + Protocol (v3)", RFC 2251, December 1997. + + [2] Myers, J., "Simple Authentication and Security Layer (SASL)", RFC + 2222, October 1997. + + [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement + Levels", BCP 14, RFC 2119, March 1997. + + [4] Leach, P. and C. Newman, "Using Digest Authentication as a SASL + Mechanism", RFC 2831, May 2000. + + [5] Hodges, J., Morgan, R. and M. Wahl, "Lightweight Directory Access + Protocol (v3): Extension for Transport Layer Security", RFC 2830, + May 2000. + + [6] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC + 2246, January 1999. + + [7] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", RFC 2234, November 1997. + + [8] Kent, S. and R. Atkinson, "Security Architecture for the Internet + Protocol", RFC 2401, November 1998. + + + + + + + + + + + + + + + + + + + + + + + + + +Wahl, et al. Standards Track [Page 14] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +15. Authors' Addresses + + Mark Wahl + Sun Microsystems, Inc. + 8911 Capital of Texas Hwy #4140 + Austin TX 78759 + USA + + EMail: M.Wahl@innosoft.com + + + Harald Tveit Alvestrand + EDB Maxware + Pirsenteret + N-7462 Trondheim, Norway + + Phone: +47 73 54 57 97 + EMail: Harald@Alvestrand.no + + + Jeff Hodges + Oblix, Inc. + 18922 Forge Drive + Cupertino, CA 95014 + USA + + Phone: +1-408-861-6656 + EMail: JHodges@oblix.com + + + RL "Bob" Morgan + Computing and Communications + University of Washington + Seattle, WA 98105 + USA + + Phone: +1-206-221-3307 + EMail: rlmorgan@washington.edu + + + + + + + + + + + + + +Wahl, et al. Standards Track [Page 15] + +RFC 2829 Authentication Methods for LDAP May 2000 + + +16. Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Wahl, et al. Standards Track [Page 16] + diff --git a/doc/rfc/rfc2830.txt b/doc/rfc/rfc2830.txt new file mode 100644 index 0000000000..7801c7d5b9 --- /dev/null +++ b/doc/rfc/rfc2830.txt @@ -0,0 +1,675 @@ + + + + + + +Network Working Group J. Hodges +Request for Comments: 2830 Oblix Inc. +Category: Standards Track R. Morgan + Univ of Washington + M. Wahl + Sun Microsystems, Inc. + May 2000 + + + Lightweight Directory Access Protocol (v3): + Extension for Transport Layer Security + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + This document defines the "Start Transport Layer Security (TLS) + Operation" for LDAP [LDAPv3, TLS]. This operation provides for TLS + establishment in an LDAP association and is defined in terms of an + LDAP extended request. + +1. Conventions Used in this Document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [ReqsKeywords]. + +2. The Start TLS Request + + This section describes the Start TLS extended request and extended + response themselves: how to form the request, the form of the + response, and enumerates the various result codes the client MUST be + prepared to handle. + + The section following this one then describes how to sequence an + overall Start TLS Operation. + + + + + +Hodges, et al. Standards Track [Page 1] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +2.1. Requesting TLS Establishment + + A client may perform a Start TLS operation by transmitting an LDAP + PDU containing an ExtendedRequest [LDAPv3] specifying the OID for the + Start TLS operation: + + 1.3.6.1.4.1.1466.20037 + + An LDAP ExtendedRequest is defined as follows: + + ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + requestName [0] LDAPOID, + requestValue [1] OCTET STRING OPTIONAL } + + A Start TLS extended request is formed by setting the requestName + field to the OID string given above. The requestValue field is + absent. The client MUST NOT send any PDUs on this connection + following this request until it receives a Start TLS extended + response. + + When a Start TLS extended request is made, the server MUST return an + LDAP PDU containing a Start TLS extended response. An LDAP + ExtendedResponse is defined as follows: + + ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + COMPONENTS OF LDAPResult, + responseName [10] LDAPOID OPTIONAL, + response [11] OCTET STRING OPTIONAL } + + A Start TLS extended response MUST contain a responseName field which + MUST be set to the same string as that in the responseName field + present in the Start TLS extended request. The response field is + absent. The server MUST set the resultCode field to either success or + one of the other values outlined in section 2.3. + +2.2. "Success" Response + + If the ExtendedResponse contains a resultCode of success, this + indicates that the server is willing and able to negotiate TLS. Refer + to section 3, below, for details. + +2.3. Response other than "success" + + If the ExtendedResponse contains a resultCode other than success, + this indicates that the server is unwilling or unable to negotiate + TLS. + + + + + +Hodges, et al. Standards Track [Page 2] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + + If the Start TLS extended request was not successful, the resultCode + will be one of: + + operationsError (operations sequencing incorrect; e.g. TLS already + established) + + protocolError (TLS not supported or incorrect PDU structure) + + referral (this server doesn't do TLS, try this one) + + unavailable (e.g. some major problem with TLS, or server is + shutting down) + + The server MUST return operationsError if the client violates any of + the Start TLS extended operation sequencing requirements described in + section 3, below. + + If the server does not support TLS (whether by design or by current + configuration), it MUST set the resultCode to protocolError (see + section 4.1.1 of [LDAPv3]), or to referral. The server MUST include + an actual referral value in the LDAP Result if it returns a + resultCode of referral. The client's current session is unaffected if + the server does not support TLS. The client MAY proceed with any LDAP + operation, or it MAY close the connection. + + The server MUST return unavailable if it supports TLS but cannot + establish a TLS connection for some reason, e.g. the certificate + server not responding, it cannot contact its TLS implementation, or + if the server is in process of shutting down. The client MAY retry + the StartTLS operation, or it MAY proceed with any other LDAP + operation, or it MAY close the connection. + +3. Sequencing of the Start TLS Operation + + This section describes the overall procedures clients and servers + MUST follow for TLS establishment. These procedures take into + consideration various aspects of the overall security of the LDAP + association including discovery of resultant security level and + assertion of the client's authorization identity. + + Note that the precise effects, on a client's authorization identity, + of establishing TLS on an LDAP association are described in detail in + section 5. + + + + + + + + +Hodges, et al. Standards Track [Page 3] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +3.1. Requesting to Start TLS on an LDAP Association + + The client MAY send the Start TLS extended request at any time after + establishing an LDAP association, except that in the following cases + the client MUST NOT send a Start TLS extended request: + + - if TLS is currently established on the connection, or + - during a multi-stage SASL negotiation, or + - if there are any LDAP operations outstanding on the connection. + + The result of violating any of these requirements is a resultCode of + operationsError, as described above in section 2.3. + + The client MAY have already performed a Bind operation when it sends + a Start TLS request, or the client might have not yet bound. + + If the client did not establish a TLS connection before sending any + other requests, and the server requires the client to establish a TLS + connection before performing a particular request, the server MUST + reject that request with a confidentialityRequired or + strongAuthRequired result. The client MAY send a Start TLS extended + request, or it MAY choose to close the connection. + +3.2. Starting TLS + + The server will return an extended response with the resultCode of + success if it is willing and able to negotiate TLS. It will return + other resultCodes, documented above, if it is unable. + + In the successful case, the client, which has ceased to transfer LDAP + requests on the connection, MUST either begin a TLS negotiation or + close the connection. The client will send PDUs in the TLS Record + Protocol directly over the underlying transport connection to the + server to initiate TLS negotiation [TLS]. + +3.3. TLS Version Negotiation + + Negotiating the version of TLS or SSL to be used is a part of the TLS + Handshake Protocol, as documented in [TLS]. Please refer to that + document for details. + +3.4. Discovery of Resultant Security Level + + After a TLS connection is established on an LDAP association, both + parties MUST individually decide whether or not to continue based on + the privacy level achieved. Ascertaining the TLS connection's privacy + level is implementation dependent, and accomplished by communicating + with one's respective local TLS implementation. + + + +Hodges, et al. Standards Track [Page 4] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + + If the client or server decides that the level of authentication or + privacy is not high enough for it to continue, it SHOULD gracefully + close the TLS connection immediately after the TLS negotiation has + completed (see sections 4.1 and 5.2, below). + + The client MAY attempt to Start TLS again, or MAY send an unbind + request, or send any other LDAP request. + +3.5. Assertion of Client's Authorization Identity + + The client MAY, upon receipt of a Start TLS extended response + indicating success, assert that a specific authorization identity be + utilized in determining the client's authorization status. The client + accomplishes this via an LDAP Bind request specifying a SASL + mechanism of "EXTERNAL" [SASL]. See section 5.1.2, below. + +3.6. Server Identity Check + + The client MUST check its understanding of the server's hostname + against the server's identity as presented in the server's + Certificate message, in order to prevent man-in-the-middle attacks. + + Matching is performed according to these rules: + + - The client MUST use the server hostname it used to open the LDAP + connection as the value to compare against the server name as + expressed in the server's certificate. The client MUST NOT use the + server's canonical DNS name or any other derived form of name. + + - If a subjectAltName extension of type dNSName is present in the + certificate, it SHOULD be used as the source of the server's + identity. + + - Matching is case-insensitive. + + - The "*" wildcard character is allowed. If present, it applies only + to the left-most name component. + + E.g. *.bar.com would match a.bar.com, b.bar.com, etc. but not + bar.com. If more than one identity of a given type is present in the + certificate (e.g. more than one dNSName name), a match in any one of + the set is considered acceptable. + + If the hostname does not match the dNSName-based identity in the + certificate per the above check, user-oriented clients SHOULD either + notify the user (clients MAY give the user the opportunity to + + + + + +Hodges, et al. Standards Track [Page 5] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + + continue with the connection in any case) or terminate the connection + and indicate that the server's identity is suspect. Automated clients + SHOULD close the connection, returning and/or logging an error + indicating that the server's identity is suspect. + + Beyond the server identity checks described in this section, clients + SHOULD be prepared to do further checking to ensure that the server + is authorized to provide the service it is observed to provide. The + client MAY need to make use of local policy information. + +3.7. Refresh of Server Capabilities Information + + The client MUST refresh any cached server capabilities information + (e.g. from the server's root DSE; see section 3.4 of [LDAPv3]) upon + TLS session establishment. This is necessary to protect against + active-intermediary attacks which may have altered any server + capabilities information retrieved prior to TLS establishment. The + server MAY advertise different capabilities after TLS establishment. + +4. Closing a TLS Connection + +4.1. Graceful Closure + + Either the client or server MAY terminate the TLS connection on an + LDAP association by sending a TLS closure alert. This will leave the + LDAP association intact. + + Before closing a TLS connection, the client MUST either wait for any + outstanding LDAP operations to complete, or explicitly abandon them + [LDAPv3]. + + After the initiator of a close has sent a closure alert, it MUST + discard any TLS messages until it has received an alert from the + other party. It will cease to send TLS Record Protocol PDUs, and + following the receipt of the alert, MAY send and receive LDAP PDUs. + + The other party, if it receives a closure alert, MUST immediately + transmit a TLS closure alert. It will subsequently cease to send TLS + Record Protocol PDUs, and MAY send and receive LDAP PDUs. + +4.2. Abrupt Closure + + Either the client or server MAY abruptly close the entire LDAP + association and any TLS connection established on it by dropping the + underlying TCP connection. A server MAY beforehand send the client a + Notice of Disconnection [LDAPv3] in this case. + + + + + +Hodges, et al. Standards Track [Page 6] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +5. Effects of TLS on a Client's Authorization Identity + + This section describes the effects on a client's authorization + identity brought about by establishing TLS on an LDAP association. + The default effects are described first, and next the facilities for + client assertion of authorization identity are discussed including + error conditions. Lastly, the effects of closing the TLS connection + are described. + + Authorization identities and related concepts are defined in + [AuthMeth]. + +5.1. TLS Connection Establishment Effects + +5.1.1. Default Effects + + Upon establishment of the TLS connection onto the LDAP association, + any previously established authentication and authorization + identities MUST remain in force, including anonymous state. This + holds even in the case where the server requests client + authentication via TLS -- e.g. requests the client to supply its + certificate during TLS negotiation (see [TLS]). + +5.1.2. Client Assertion of Authorization Identity + + A client MAY either implicitly request that its LDAP authorization + identity be derived from its authenticated TLS credentials or it MAY + explicitly provide an authorization identity and assert that it be + used in combination with its authenticated TLS credentials. The + former is known as an implicit assertion, and the latter as an + explicit assertion. + +5.1.2.1. Implicit Assertion + + An implicit authorization identity assertion is accomplished after + TLS establishment by invoking a Bind request of the SASL form using + the "EXTERNAL" mechanism name [SASL, LDAPv3] that SHALL NOT include + the optional credentials octet string (found within the + SaslCredentials sequence in the Bind Request). The server will derive + the client's authorization identity from the authentication identity + supplied in the client's TLS credentials (typically a public key + certificate) according to local policy. The underlying mechanics of + how this is accomplished are implementation specific. + + + + + + + + +Hodges, et al. Standards Track [Page 7] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +5.1.2.2. Explicit Assertion + + An explicit authorization identity assertion is accomplished after + TLS establishment by invoking a Bind request of the SASL form using + the "EXTERNAL" mechanism name [SASL, LDAPv3] that SHALL include the + credentials octet string. This string MUST be constructed as + documented in section 9 of [AuthMeth]. + +5.1.2.3. Error Conditions + + For either form of assertion, the server MUST verify that the + client's authentication identity as supplied in its TLS credentials + is permitted to be mapped to the asserted authorization identity. The + server MUST reject the Bind operation with an invalidCredentials + resultCode in the Bind response if the client is not so authorized. + + Additionally, with either form of assertion, if a TLS session has not + been established between the client and server prior to making the + SASL EXTERNAL Bind request and there is no other external source of + authentication credentials (e.g. IP-level security [IPSEC]), or if, + during the process of establishing the TLS session, the server did + not request the client's authentication credentials, the SASL + EXTERNAL bind MUST fail with a result code of + inappropriateAuthentication. + + After the above Bind operation failures, any client authentication + and authorization state of the LDAP association is lost, so the LDAP + association is in an anonymous state after the failure. TLS + connection state is unaffected, though a server MAY end the TLS + connection, via a TLS close_notify message, based on the Bind failure + (as it MAY at any time). + +5.2. TLS Connection Closure Effects + + Closure of the TLS connection MUST cause the LDAP association to move + to an anonymous authentication and authorization state regardless of + the state established over TLS and regardless of the authentication + and authorization state prior to TLS connection establishment. + +6. Security Considerations + + The goals of using the TLS protocol with LDAP are to ensure + connection confidentiality and integrity, and to optionally provide + for authentication. TLS expressly provides these capabilities, as + described in [TLS]. + + + + + + +Hodges, et al. Standards Track [Page 8] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + + All security gained via use of the Start TLS operation is gained by + the use of TLS itself. The Start TLS operation, on its own, does not + provide any additional security. + + The use of TLS does not provide or ensure for confidentiality and/or + non-repudiation of the data housed by an LDAP-based directory server. + Nor does it secure the data from inspection by the server + administrators. Once established, TLS only provides for and ensures + confidentiality and integrity of the operations and data in transit + over the LDAP association, and only if the implementations on the + client and server support and negotiate it. + + The level of security provided though the use of TLS depends directly + on both the quality of the TLS implementation used and the style of + usage of that implementation. Additionally, an active-intermediary + attacker can remove the Start TLS extended operation from the + supportedExtension attribute of the root DSE. Therefore, both parties + SHOULD independently ascertain and consent to the security level + achieved once TLS is established and before beginning use of the TLS + connection. For example, the security level of the TLS connection + might have been negotiated down to plaintext. + + Clients SHOULD either warn the user when the security level achieved + does not provide confidentiality and/or integrity protection, or be + configurable to refuse to proceed without an acceptable level of + security. + + Client and server implementors SHOULD take measures to ensure proper + protection of credentials and other confidential data where such + measures are not otherwise provided by the TLS implementation. + + Server implementors SHOULD allow for server administrators to elect + whether and when connection confidentiality and/or integrity is + required, as well as elect whether and when client authentication via + TLS is required. + +7. Acknowledgements + + The authors thank Tim Howes, Paul Hoffman, John Kristian, Shirish + Rai, Jonathan Trostle, Harald Alvestrand, and Marcus Leech for their + contributions to this document. + + + + + + + + + + +Hodges, et al. Standards Track [Page 9] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +8. References + + [AuthMeth] Wahl, M., Alvestrand, H., Hodges, J. and R. Morgan, + "Authentication Methods for LDAP", RFC 2829, May 2000. + + [IPSEC] Kent, S. and R. Atkinson, "Security Architecture for + the Internet Protocol", RFC 2401, November 1998. + + [LDAPv3] Wahl, M., Kille S. and T. Howes, "Lightweight + Directory Access Protocol (v3)", RFC 2251, December + 1997. + + [ReqsKeywords] Bradner, S., "Key Words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [SASL] Myers, J., "Simple Authentication and Security Layer + (SASL)", RFC 2222, October 1997. + + [TLS] Dierks, T. and C. Allen. "The TLS Protocol Version + 1.0", RFC 2246, January 1999. + +9. Authors' Addresses + + Jeff Hodges + Oblix, Inc. + 18922 Forge Drive + Cupertino, CA 95014 + USA + + Phone: +1-408-861-6656 + EMail: JHodges@oblix.com + + RL "Bob" Morgan + Computing and Communications + University of Washington + Seattle, WA + USA + + Phone: +1-206-221-3307 + EMail: rlmorgan@washington.edu + + Mark Wahl + Sun Microsystems, Inc. + 8911 Capital of Texas Hwy #4140 + Austin TX 78759 + USA + + EMail: M.Wahl@innosoft.com + + + +Hodges, et al. Standards Track [Page 10] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +10. Intellectual Property Rights Notices + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. Copies of + claims of rights made available for publication and any assurances of + licenses to be made available, or the result of an attempt made to + obtain a general license or permission for the use of such + proprietary rights by implementors or users of this specification can + be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Hodges, et al. Standards Track [Page 11] + +RFC 2830 LDAPv3: Extension for Transport Layer Security May 2000 + + +11. Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Hodges, et al. Standards Track [Page 12] + diff --git a/doc/rfc/rfc2831.txt b/doc/rfc/rfc2831.txt new file mode 100644 index 0000000000..c1a54c4944 --- /dev/null +++ b/doc/rfc/rfc2831.txt @@ -0,0 +1,1515 @@ + + + + + + +Network Working Group P. Leach +Request for Comments: 2831 Microsoft +Category: Standards Track C. Newman + Innosoft + May 2000 + + + Using Digest Authentication as a SASL Mechanism + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + This specification defines how HTTP Digest Authentication [Digest] + can be used as a SASL [RFC 2222] mechanism for any protocol that has + a SASL profile. It is intended both as an improvement over CRAM-MD5 + [RFC 2195] and as a convenient way to support a single authentication + mechanism for web, mail, LDAP, and other protocols. + +Table of Contents + + 1 INTRODUCTION.....................................................2 + 1.1 CONVENTIONS AND NOTATION......................................2 + 1.2 REQUIREMENTS..................................................3 + 2 AUTHENTICATION...................................................3 + 2.1 INITIAL AUTHENTICATION........................................3 + 2.1.1 Step One...................................................3 + 2.1.2 Step Two...................................................6 + 2.1.3 Step Three................................................12 + 2.2 SUBSEQUENT AUTHENTICATION....................................12 + 2.2.1 Step one..................................................13 + 2.2.2 Step Two..................................................13 + 2.3 INTEGRITY PROTECTION.........................................13 + 2.4 CONFIDENTIALITY PROTECTION...................................14 + 3 SECURITY CONSIDERATIONS.........................................15 + 3.1 AUTHENTICATION OF CLIENTS USING DIGEST AUTHENTICATION........15 + 3.2 COMPARISON OF DIGEST WITH PLAINTEXT PASSWORDS................16 + 3.3 REPLAY ATTACKS...............................................16 + + + +Leach & Newman Standards Track [Page 1] + +RFC 2831 Digest SASL Mechanism May 2000 + + + 3.4 ONLINE DICTIONARY ATTACKS....................................16 + 3.5 OFFLINE DICTIONARY ATTACKS...................................16 + 3.6 MAN IN THE MIDDLE............................................17 + 3.7 CHOSEN PLAINTEXT ATTACKS.....................................17 + 3.8 SPOOFING BY COUNTERFEIT SERVERS..............................17 + 3.9 STORING PASSWORDS............................................17 + 3.10 MULTIPLE REALMS.............................................18 + 3.11 SUMMARY.....................................................18 + 4 EXAMPLE.........................................................18 + 5 REFERENCES......................................................20 + 6 AUTHORS' ADDRESSES..............................................21 + 7 ABNF............................................................21 + 7.1 AUGMENTED BNF................................................21 + 7.2 BASIC RULES..................................................23 + 8 SAMPLE CODE.....................................................25 + 9 FULL COPYRIGHT STATEMENT........................................27 + +1 Introduction + + This specification describes the use of HTTP Digest Access + Authentication as a SASL mechanism. The authentication type + associated with the Digest SASL mechanism is "DIGEST-MD5". + + This specification is intended to be upward compatible with the + "md5-sess" algorithm of HTTP/1.1 Digest Access Authentication + specified in [Digest]. The only difference in the "md5-sess" + algorithm is that some directives not needed in a SASL mechanism have + had their values defaulted. + + There is one new feature for use as a SASL mechanism: integrity + protection on application protocol messages after an authentication + exchange. + + Also, compared to CRAM-MD5, DIGEST-MD5 prevents chosen plaintext + attacks, and permits the use of third party authentication servers, + mutual authentication, and optimized reauthentication if a client has + recently authenticated to a server. + +1.1 Conventions and Notation + + This specification uses the same ABNF notation and lexical + conventions as HTTP/1.1 specification; see appendix A. + + Let { a, b, ... } be the concatenation of the octet strings a, b, ... + + Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. + + + + + +Leach & Newman Standards Track [Page 2] + +RFC 2831 Digest SASL Mechanism May 2000 + + + Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string + k, a colon and the string s. + + Let HEX(n) be the representation of the 16 octet MD5 hash n as a + string of 32 hex digits (with alphabetic characters always in lower + case, since MD5 is case sensitive). + + Let HMAC(k, s) be the 16 octet HMAC-MD5 [RFC 2104] of the octet + string s using the octet string k as a key. + + The value of a quoted string constant as an octet string does not + include any terminating null character. + +1.2 Requirements + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [RFC 2119]. + + An implementation is not compliant if it fails to satisfy one or more + of the MUST level requirements for the protocols it implements. An + implementation that satisfies all the MUST level and all the SHOULD + level requirements for its protocols is said to be "unconditionally + compliant"; one that satisfies all the MUST level requirements but + not all the SHOULD level requirements for its protocols is said to be + "conditionally compliant." + +2 Authentication + + The following sections describe how to use Digest as a SASL + authentication mechanism. + +2.1 Initial Authentication + + If the client has not recently authenticated to the server, then it + must perform "initial authentication", as defined in this section. If + it has recently authenticated, then a more efficient form is + available, defined in the next section. + +2.1.1 Step One + + The server starts by sending a challenge. The data encoded in the + challenge contains a string formatted according to the rules for a + "digest-challenge" defined as follows: + + + + + + + +Leach & Newman Standards Track [Page 3] + +RFC 2831 Digest SASL Mechanism May 2000 + + + digest-challenge = + 1#( realm | nonce | qop-options | stale | maxbuf | charset + algorithm | cipher-opts | auth-param ) + + realm = "realm" "=" <"> realm-value <"> + realm-value = qdstr-val + nonce = "nonce" "=" <"> nonce-value <"> + nonce-value = qdstr-val + qop-options = "qop" "=" <"> qop-list <"> + qop-list = 1#qop-value + qop-value = "auth" | "auth-int" | "auth-conf" | + token + stale = "stale" "=" "true" + maxbuf = "maxbuf" "=" maxbuf-value + maxbuf-value = 1*DIGIT + charset = "charset" "=" "utf-8" + algorithm = "algorithm" "=" "md5-sess" + cipher-opts = "cipher" "=" <"> 1#cipher-value <"> + cipher-value = "3des" | "des" | "rc4-40" | "rc4" | + "rc4-56" | token + auth-param = token "=" ( token | quoted-string ) + + The meanings of the values of the directives used above are as + follows: + + realm + Mechanistically, a string which can enable users to know which + username and password to use, in case they might have different + ones for different servers. Conceptually, it is the name of a + collection of accounts that might include the user's account. This + string should contain at least the name of the host performing the + authentication and might additionally indicate the collection of + users who might have access. An example might be + "registered_users@gotham.news.example.com". This directive is + optional; if not present, the client SHOULD solicit it from the + user or be able to compute a default; a plausible default might be + the realm supplied by the user when they logged in to the client + system. Multiple realm directives are allowed, in which case the + user or client must choose one as the realm for which to supply to + username and password. + + nonce + A server-specified data string which MUST be different each time a + digest-challenge is sent as part of initial authentication. It is + recommended that this string be base64 or hexadecimal data. Note + that since the string is passed as a quoted string, the + double-quote character is not allowed unless escaped (see section + 7.2). The contents of the nonce are implementation dependent. The + + + +Leach & Newman Standards Track [Page 4] + +RFC 2831 Digest SASL Mechanism May 2000 + + + security of the implementation depends on a good choice. It is + RECOMMENDED that it contain at least 64 bits of entropy. The nonce + is opaque to the client. This directive is required and MUST + appear exactly once; if not present, or if multiple instances are + present, the client should abort the authentication exchange. + + qop-options + A quoted string of one or more tokens indicating the "quality of + protection" values supported by the server. The value "auth" + indicates authentication; the value "auth-int" indicates + authentication with integrity protection; the value "auth-conf" + indicates authentication with integrity protection and encryption. + This directive is optional; if not present it defaults to "auth". + The client MUST ignore unrecognized options; if the client + recognizes no option, it should abort the authentication exchange. + + stale + The "stale" directive is not used in initial authentication. See + the next section for its use in subsequent authentications. This + directive may appear at most once; if multiple instances are + present, the client should abort the authentication exchange. + + maxbuf + A number indicating the size of the largest buffer the server is + able to receive when using "auth-int" or "auth-conf". If this + directive is missing, the default value is 65536. This directive + may appear at most once; if multiple instances are present, the + client should abort the authentication exchange. + + charset + This directive, if present, specifies that the server supports + UTF-8 encoding for the username and password. If not present, the + username and password must be encoded in ISO 8859-1 (of which + US-ASCII is a subset). The directive is needed for backwards + compatibility with HTTP Digest, which only supports ISO 8859-1. + This directive may appear at most once; if multiple instances are + present, the client should abort the authentication exchange. + + algorithm + This directive is required for backwards compatibility with HTTP + Digest., which supports other algorithms. . This directive is + required and MUST appear exactly once; if not present, or if + multiple instances are present, the client should abort the + authentication exchange. + + + + + + + +Leach & Newman Standards Track [Page 5] + +RFC 2831 Digest SASL Mechanism May 2000 + + + cipher-opts + A list of ciphers that the server supports. This directive must be + present exactly once if "auth-conf" is offered in the + "qop-options" directive, in which case the "3des" and "des" modes + are mandatory-to-implement. The client MUST ignore unrecognized + options; if the client recognizes no option, it should abort the + authentication exchange. + + des + the Data Encryption Standard (DES) cipher [FIPS] in cipher + block chaining (CBC) mode with a 56 bit key. + + 3des + the "triple DES" cipher in CBC mode with EDE with the same key + for each E stage (aka "two keys mode") for a total key length + of 112 bits. + + rc4, rc4-40, rc4-56 + the RC4 cipher with a 128 bit, 40 bit, and 56 bit key, + respectively. + + auth-param This construct allows for future extensions; it may appear + more than once. The client MUST ignore any unrecognized + directives. + + For use as a SASL mechanism, note that the following changes are made + to "digest-challenge" from HTTP: the following Digest options (called + "directives" in HTTP terminology) are unused (i.e., MUST NOT be sent, + and MUST be ignored if received): + + opaque + domain + + The size of a digest-challenge MUST be less than 2048 bytes. + +2.1.2 Step Two + + The client makes note of the "digest-challenge" and then responds + with a string formatted and computed according to the rules for a + "digest-response" defined as follows: + + + + + + + + + + + +Leach & Newman Standards Track [Page 6] + +RFC 2831 Digest SASL Mechanism May 2000 + + + digest-response = 1#( username | realm | nonce | cnonce | + nonce-count | qop | digest-uri | response | + maxbuf | charset | cipher | authzid | + auth-param ) + + username = "username" "=" <"> username-value <"> + username-value = qdstr-val + cnonce = "cnonce" "=" <"> cnonce-value <"> + cnonce-value = qdstr-val + nonce-count = "nc" "=" nc-value + nc-value = 8LHEX + qop = "qop" "=" qop-value + digest-uri = "digest-uri" "=" <"> digest-uri-value <"> + digest-uri-value = serv-type "/" host [ "/" serv-name ] + serv-type = 1*ALPHA + host = 1*( ALPHA | DIGIT | "-" | "." ) + serv-name = host + response = "response" "=" response-value + response-value = 32LHEX + LHEX = "0" | "1" | "2" | "3" | + "4" | "5" | "6" | "7" | + "8" | "9" | "a" | "b" | + "c" | "d" | "e" | "f" + cipher = "cipher" "=" cipher-value + authzid = "authzid" "=" <"> authzid-value <"> + authzid-value = qdstr-val + + + username + The user's name in the specified realm, encoded according to the + value of the "charset" directive. This directive is required and + MUST be present exactly once; otherwise, authentication fails. + + realm + The realm containing the user's account. This directive is + required if the server provided any realms in the + "digest-challenge", in which case it may appear exactly once and + its value SHOULD be one of those realms. If the directive is + missing, "realm-value" will set to the empty string when computing + A1 (see below for details). + + nonce + The server-specified data string received in the preceding + digest-challenge. This directive is required and MUST be present + exactly once; otherwise, authentication fails. + + + + + + +Leach & Newman Standards Track [Page 7] + +RFC 2831 Digest SASL Mechanism May 2000 + + + cnonce + A client-specified data string which MUST be different each time a + digest-response is sent as part of initial authentication. The + cnonce-value is an opaque quoted string value provided by the + client and used by both client and server to avoid chosen + plaintext attacks, and to provide mutual authentication. The + security of the implementation depends on a good choice. It is + RECOMMENDED that it contain at least 64 bits of entropy. This + directive is required and MUST be present exactly once; otherwise, + authentication fails. + + nonce-count + The nc-value is the hexadecimal count of the number of requests + (including the current request) that the client has sent with the + nonce value in this request. For example, in the first request + sent in response to a given nonce value, the client sends + "nc=00000001". The purpose of this directive is to allow the + server to detect request replays by maintaining its own copy of + this count - if the same nc-value is seen twice, then the request + is a replay. See the description below of the construction of + the response value. This directive may appear at most once; if + multiple instances are present, the client should abort the + authentication exchange. + + qop + Indicates what "quality of protection" the client accepted. If + present, it may appear exactly once and its value MUST be one of + the alternatives in qop-options. If not present, it defaults to + "auth". These values affect the computation of the response. Note + that this is a single token, not a quoted list of alternatives. + + serv-type + Indicates the type of service, such as "www" for web service, + "ftp" for FTP service, "smtp" for mail delivery service, etc. The + service name as defined in the SASL profile for the protocol see + section 4 of [RFC 2222], registered in the IANA registry of + "service" elements for the GSSAPI host-based service name form + [RFC 2078]. + + host + The DNS host name or IP address for the service requested. The + DNS host name must be the fully-qualified canonical name of the + host. The DNS host name is the preferred form; see notes on server + processing of the digest-uri. + + + + + + + +Leach & Newman Standards Track [Page 8] + +RFC 2831 Digest SASL Mechanism May 2000 + + + serv-name + Indicates the name of the service if it is replicated. The service + is considered to be replicated if the client's service-location + process involves resolution using standard DNS lookup operations, + and if these operations involve DNS records (such as SRV, or MX) + which resolve one DNS name into a set of other DNS names. In this + case, the initial name used by the client is the "serv-name", and + the final name is the "host" component. For example, the incoming + mail service for "example.com" may be replicated through the use + of MX records stored in the DNS, one of which points at an SMTP + server called "mail3.example.com"; it's "serv-name" would be + "example.com", it's "host" would be "mail3.example.com". If the + service is not replicated, or the serv-name is identical to the + host, then the serv-name component MUST be omitted. + + digest-uri + Indicates the principal name of the service with which the client + wishes to connect, formed from the serv-type, host, and serv-name. + For example, the FTP service on "ftp.example.com" would have a + "digest-uri" value of "ftp/ftp.example.com"; the SMTP server from + the example above would have a "digest-uri" value of + "smtp/mail3.example.com/example.com". + + Servers SHOULD check that the supplied value is correct. This will + detect accidental connection to the incorrect server. It is also so + that clients will be trained to provide values that will work with + implementations that use a shared back-end authentication service + that can provide server authentication. + + The serv-type component should match the service being offered. The + host component should match one of the host names of the host on + which the service is running, or it's IP address. Servers SHOULD NOT + normally support the IP address form, because server authentication + by IP address is not very useful; they should only do so if the DNS + is unavailable or unreliable. The serv-name component should match + one of the service's configured service names. + + This directive may appear at most once; if multiple instances are + present, the client should abort the authentication exchange. + + Note: In the HTTP use of Digest authentication, the digest-uri is the + URI (usually a URL) of the resource requested -- hence the name of + the directive. + + response + A string of 32 hex digits computed as defined below, which proves + that the user knows a password. This directive is required and + MUST be present exactly once; otherwise, authentication fails. + + + +Leach & Newman Standards Track [Page 9] + +RFC 2831 Digest SASL Mechanism May 2000 + + + maxbuf + A number indicating the size of the largest buffer the client is + able to receive. If this directive is missing, the default value + is 65536. This directive may appear at most once; if multiple + instances are present, the server should abort the authentication + exchange. + + charset + This directive, if present, specifies that the client has used + UTF-8 encoding for the username and password. If not present, the + username and password must be encoded in ISO 8859-1 (of which + US-ASCII is a subset). The client should send this directive only + if the server has indicated it supports UTF-8. The directive is + needed for backwards compatibility with HTTP Digest, which only + supports ISO 8859-1. + + LHEX + 32 hex digits, where the alphabetic characters MUST be lower case, + because MD5 is not case insensitive. + + cipher + The cipher chosen by the client. This directive MUST appear + exactly once if "auth-conf" is negotiated; if required and not + present, authentication fails. + + authzid + The "authorization ID" as per RFC 2222, encoded in UTF-8. This + directive is optional. If present, and the authenticating user has + sufficient privilege, and the server supports it, then after + authentication the server will use this identity for making all + accesses and access checks. If the client specifies it, and the + server does not support it, then the response-value will be + incorrect, and authentication will fail. + + The size of a digest-response MUST be less than 4096 bytes. + +2.1.2.1 Response-value + + The definition of "response-value" above indicates the encoding for + its value -- 32 lower case hex characters. The following definitions + show how the value is computed. + + Although qop-value and components of digest-uri-value may be + case-insensitive, the case which the client supplies in step two is + preserved for the purpose of computing and verifying the + response-value. + + response-value = + + + +Leach & Newman Standards Track [Page 10] + +RFC 2831 Digest SASL Mechanism May 2000 + + + HEX( KD ( HEX(H(A1)), + { nonce-value, ":" nc-value, ":", + cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) + + If authzid is specified, then A1 is + + + A1 = { H( { username-value, ":", realm-value, ":", passwd } ), + ":", nonce-value, ":", cnonce-value, ":", authzid-value } + + If authzid is not specified, then A1 is + + + A1 = { H( { username-value, ":", realm-value, ":", passwd } ), + ":", nonce-value, ":", cnonce-value } + + where + + passwd = *OCTET + + The "username-value", "realm-value" and "passwd" are encoded + according to the value of the "charset" directive. If "charset=UTF-8" + is present, and all the characters of either "username-value" or + "passwd" are in the ISO 8859-1 character set, then it must be + converted to ISO 8859-1 before being hashed. This is so that + authentication databases that store the hashed username, realm and + password (which is common) can be shared compatibly with HTTP, which + specifies ISO 8859-1. A sample implementation of this conversion is + in section 8. + + If the "qop" directive's value is "auth", then A2 is: + + A2 = { "AUTHENTICATE:", digest-uri-value } + + If the "qop" value is "auth-int" or "auth-conf" then A2 is: + + A2 = { "AUTHENTICATE:", digest-uri-value, + ":00000000000000000000000000000000" } + + Note that "AUTHENTICATE:" must be in upper case, and the second + string constant is a string with a colon followed by 32 zeros. + + These apparently strange values of A2 are for compatibility with + HTTP; they were arrived at by setting "Method" to "AUTHENTICATE" and + the hash of the entity body to zero in the HTTP digest calculation of + A2. + + Also, in the HTTP usage of Digest, several directives in the + + + +Leach & Newman Standards Track [Page 11] + +RFC 2831 Digest SASL Mechanism May 2000 + + + "digest-challenge" sent by the server have to be returned by the + client in the "digest-response". These are: + + opaque + algorithm + + These directives are not needed when Digest is used as a SASL + mechanism (i.e., MUST NOT be sent, and MUST be ignored if received). + +2.1.3 Step Three + + The server receives and validates the "digest-response". The server + checks that the nonce-count is "00000001". If it supports subsequent + authentication (see section 2.2), it saves the value of the nonce and + the nonce-count. It sends a message formatted as follows: + + response-auth = "rspauth" "=" response-value + + where response-value is calculated as above, using the values sent in + step two, except that if qop is "auth", then A2 is + + A2 = { ":", digest-uri-value } + + And if qop is "auth-int" or "auth-conf" then A2 is + + A2 = { ":", digest-uri-value, ":00000000000000000000000000000000" } + + Compared to its use in HTTP, the following Digest directives in the + "digest-response" are unused: + + nextnonce + qop + cnonce + nonce-count + +2.2 Subsequent Authentication + + If the client has previously authenticated to the server, and + remembers the values of username, realm, nonce, nonce-count, cnonce, + and qop that it used in that authentication, and the SASL profile for + a protocol permits an initial client response, then it MAY perform + "subsequent authentication", as defined in this section. + + + + + + + + + +Leach & Newman Standards Track [Page 12] + +RFC 2831 Digest SASL Mechanism May 2000 + + +2.2.1 Step one + + The client uses the values from the previous authentication and sends + an initial response with a string formatted and computed according to + the rules for a "digest-response", as defined above, but with a + nonce-count one greater than used in the last "digest-response". + +2.2.2 Step Two + + The server receives the "digest-response". If the server does not + support subsequent authentication, then it sends a + "digest-challenge", and authentication proceeds as in initial + authentication. If the server has no saved nonce and nonce-count from + a previous authentication, then it sends a "digest-challenge", and + authentication proceeds as in initial authentication. Otherwise, the + server validates the "digest-response", checks that the nonce-count + is one greater than that used in the previous authentication using + that nonce, and saves the new value of nonce-count. + + If the response is invalid, then the server sends a + "digest-challenge", and authentication proceeds as in initial + authentication (and should be configurable to log an authentication + failure in some sort of security audit log, since the failure may be + a symptom of an attack). The nonce-count MUST NOT be incremented in + this case: to do so would allow a denial of service attack by sending + an out-of-order nonce-count. + + If the response is valid, the server MAY choose to deem that + authentication has succeeded. However, if it has been too long since + the previous authentication, or for any other reason, the server MAY + send a new "digest-challenge" with a new value for nonce. The + challenge MAY contain a "stale" directive with value "true", which + says that the client may respond to the challenge using the password + it used in the previous response; otherwise, the client must solicit + the password anew from the user. This permits the server to make sure + that the user has presented their password recently. (The directive + name refers to the previous nonce being stale, not to the last use of + the password.) Except for the handling of "stale", after sending the + "digest-challenge" authentication proceeds as in the case of initial + authentication. + +2.3 Integrity Protection + + If the server offered "qop=auth-int" and the client responded + "qop=auth-int", then subsequent messages, up to but not including the + next subsequent authentication, between the client and the server + + + + + +Leach & Newman Standards Track [Page 13] + +RFC 2831 Digest SASL Mechanism May 2000 + + + MUST be integrity protected. Using as a base session key the value of + H(A1) as defined above the client and server calculate a pair of + message integrity keys as follows. + + The key for integrity protecting messages from client to server is: + + Kic = MD5({H(A1), + "Digest session key to client-to-server signing key magic constant"}) + + The key for integrity protecting messages from server to client is: + + Kis = MD5({H(A1), + "Digest session key to server-to-client signing key magic constant"}) + + where MD5 is as specified in [RFC 1321]. If message integrity is + negotiated, a MAC block for each message is appended to the message. + The MAC block is 16 bytes: the first 10 bytes of the HMAC-MD5 [RFC + 2104] of the message, a 2-byte message type number in network byte + order with value 1, and the 4-byte sequence number in network byte + order. The message type is to allow for future extensions such as + rekeying. + + MAC(Ki, SeqNum, msg) = (HMAC(Ki, {SeqNum, msg})[0..9], 0x0001, + SeqNum) + + where Ki is Kic for messages sent by the client and Kis for those + sent by the server. The sequence number is initialized to zero, and + incremented by one for each message sent. + + Upon receipt, MAC(Ki, SeqNum, msg) is computed and compared with the + received value; the message is discarded if they differ. + +2.4 Confidentiality Protection + + If the server sent a "cipher-opts" directive and the client responded + with a "cipher" directive, then subsequent messages between the + client and the server MUST be confidentiality protected. Using as a + base session key the value of H(A1) as defined above the client and + server calculate a pair of message integrity keys as follows. + + The key for confidentiality protecting messages from client to server + is: + + Kcc = MD5({H(A1)[0..n], + "Digest H(A1) to client-to-server sealing key magic constant"}) + + The key for confidentiality protecting messages from server to client + is: + + + +Leach & Newman Standards Track [Page 14] + +RFC 2831 Digest SASL Mechanism May 2000 + + + Kcs = MD5({H(A1)[0..n], + "Digest H(A1) to server-to-client sealing key magic constant"}) + + where MD5 is as specified in [RFC 1321]. For cipher "rc4-40" n is 5; + for "rc4-56" n is 7; for the rest n is 16. The key for the "rc-*" + ciphers is all 16 bytes of Kcc or Kcs; the key for "des" is the first + 7 bytes; the key for "3des" is the first 14 bytes. The IV for "des" + and "3des" is the last 8 bytes of Kcc or Kcs. + + If message confidentiality is negotiated, each message is encrypted + with the chosen cipher and a MAC block is appended to the message. + + The MAC block is a variable length padding prefix followed by 16 + bytes formatted as follows: the first 10 bytes of the HMAC-MD5 [RFC + 2104] of the message, a 2-byte message type number in network byte + order with value 1, and the 4-byte sequence number in network byte + order. If the blocksize of the chosen cipher is not 1 byte, the + padding prefix is one or more octets each containing the number of + padding bytes, such that total length of the encrypted part of the + message is a multiple of the blocksize. The padding and first 10 + bytes of the MAC block are encrypted along with the message. + + SEAL(Ki, Kc, SeqNum, msg) = + {CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg})[0..9])}), 0x0001, + SeqNum} + + where CIPHER is the chosen cipher, Ki and Kc are Kic and Kcc for + messages sent by the client and Kis and Kcs for those sent by the + server. The sequence number is initialized to zero, and incremented + by one for each message sent. + + Upon receipt, the message is decrypted, HMAC(Ki, {SeqNum, msg}) is + computed and compared with the received value; the message is + discarded if they differ. + +3 Security Considerations + +3.1 Authentication of Clients using Digest Authentication + + Digest Authentication does not provide a strong authentication + mechanism, when compared to public key based mechanisms, for example. + However, since it prevents chosen plaintext attacks, it is stronger + than (e.g.) CRAM-MD5, which has been proposed for use with LDAP [10], + POP and IMAP (see RFC 2195 [9]). It is intended to replace the much + weaker and even more dangerous use of plaintext passwords; however, + since it is still a password based mechanism it avoids some of the + potential deployabilty issues with public-key, OTP or similar + mechanisms. + + + +Leach & Newman Standards Track [Page 15] + +RFC 2831 Digest SASL Mechanism May 2000 + + + Digest Authentication offers no confidentiality protection beyond + protecting the actual password. All of the rest of the challenge and + response are available to an eavesdropper, including the user's name + and authentication realm. + +3.2 Comparison of Digest with Plaintext Passwords + + The greatest threat to the type of transactions for which these + protocols are used is network snooping. This kind of transaction + might involve, for example, online access to a mail service whose use + is restricted to paying subscribers. With plaintext password + authentication an eavesdropper can obtain the password of the user. + This not only permits him to access anything in the database, but, + often worse, will permit access to anything else the user protects + with the same password. + +3.3 Replay Attacks + + Replay attacks are defeated if the client or the server chooses a + fresh nonce for each authentication, as this specification requires. + +3.4 Online dictionary attacks + + If the attacker can eavesdrop, then it can test any overheard + nonce/response pairs against a (potentially very large) list of + common words. Such a list is usually much smaller than the total + number of possible passwords. The cost of computing the response for + each password on the list is paid once for each challenge. + + The server can mitigate this attack by not allowing users to select + passwords that are in a dictionary. + +3.5 Offline dictionary attacks + + If the attacker can choose the challenge, then it can precompute the + possible responses to that challenge for a list of common words. Such + a list is usually much smaller than the total number of possible + passwords. The cost of computing the response for each password on + the list is paid just once. + + Offline dictionary attacks are defeated if the client chooses a fresh + nonce for each authentication, as this specification requires. + + + + + + + + + +Leach & Newman Standards Track [Page 16] + +RFC 2831 Digest SASL Mechanism May 2000 + + +3.6 Man in the Middle + + Digest authentication is vulnerable to "man in the middle" (MITM) + attacks. Clearly, a MITM would present all the problems of + eavesdropping. But it also offers some additional opportunities to + the attacker. + + A possible man-in-the-middle attack would be to substitute a weaker + qop scheme for the one(s) sent by the server; the server will not be + able to detect this attack. For this reason, the client should always + use the strongest scheme that it understands from the choices + offered, and should never choose a scheme that does not meet its + minimum requirements. + +3.7 Chosen plaintext attacks + + A chosen plaintext attack is where a MITM or a malicious server can + arbitrarily choose the challenge that the client will use to compute + the response. The ability to choose the challenge is known to make + cryptanalysis much easier [8]. + + However, Digest does not permit the attack to choose the challenge as + long as the client chooses a fresh nonce for each authentication, as + this specification requires. + +3.8 Spoofing by Counterfeit Servers + + If a user can be led to believe that she is connecting to a host + containing information protected by a password she knows, when in + fact she is connecting to a hostile server, then the hostile server + can obtain challenge/response pairs where it was able to partly + choose the challenge. There is no known way that this can be + exploited. + +3.9 Storing passwords + + Digest authentication requires that the authenticating agent (usually + the server) store some data derived from the user's name and password + in a "password file" associated with a given realm. Normally this + might contain pairs consisting of username and H({ username-value, + ":", realm-value, ":", passwd }), which is adequate to compute H(A1) + as described above without directly exposing the user's password. + + The security implications of this are that if this password file is + compromised, then an attacker gains immediate access to documents on + the server using this realm. Unlike, say a standard UNIX password + file, this information need not be decrypted in order to access + documents in the server realm associated with this file. On the other + + + +Leach & Newman Standards Track [Page 17] + +RFC 2831 Digest SASL Mechanism May 2000 + + + hand, decryption, or more likely a brute force attack, would be + necessary to obtain the user's password. This is the reason that the + realm is part of the digested data stored in the password file. It + means that if one Digest authentication password file is compromised, + it does not automatically compromise others with the same username + and password (though it does expose them to brute force attack). + + There are two important security consequences of this. First the + password file must be protected as if it contained plaintext + passwords, because for the purpose of accessing documents in its + realm, it effectively does. + + A second consequence of this is that the realm string should be + unique among all realms that any single user is likely to use. In + particular a realm string should include the name of the host doing + the authentication. + +3.10 Multiple realms + + Use of multiple realms may mean both that compromise of a the + security database for a single realm does not compromise all + security, and that there are more things to protect in order to keep + the whole system secure. + +3.11 Summary + + By modern cryptographic standards Digest Authentication is weak, + compared to (say) public key based mechanisms. But for a large range + of purposes it is valuable as a replacement for plaintext passwords. + Its strength may vary depending on the implementation. + +4 Example + + This example shows the use of the Digest SASL mechanism with the + IMAP4 AUTHENTICATE command [RFC 2060]. + + In this example, "C:" and "S:" represent a line sent by the client or + server respectively including a CRLF at the end. Linebreaks and + indentation within a "C:" or "S:" are editorial and not part of the + protocol. The password in this example was "secret". Note that the + base64 encoding of the challenges and responses is part of the IMAP4 + AUTHENTICATE command, not part of the Digest specification itself. + + S: * OK elwood.innosoft.com PMDF IMAP4rev1 V6.0-9 + C: c CAPABILITY + S: * CAPABILITY IMAP4 IMAP4rev1 ACL LITERAL+ NAMESPACE QUOTA + UIDPLUS AUTH=CRAM-MD5 AUTH=DIGEST-MD5 AUTH=PLAIN + S: c OK Completed + + + +Leach & Newman Standards Track [Page 18] + +RFC 2831 Digest SASL Mechanism May 2000 + + + C: a AUTHENTICATE DIGEST-MD5 + S: + cmVhbG09ImVsd29vZC5pbm5vc29mdC5jb20iLG5vbmNlPSJPQTZNRzl0 + RVFHbTJoaCIscW9wPSJhdXRoIixhbGdvcml0aG09bWQ1LXNlc3MsY2hh + cnNldD11dGYtOA== + C: Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2 + QuaW5ub3NvZnQuY29tIixub25jZT0iT0E2TUc5dEVRR20yaGgiLG5jPTAw + MDAwMDAxLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLGRpZ2VzdC11cmk9Im + ltYXAvZWx3b29kLmlubm9zb2Z0LmNvbSIscmVzcG9uc2U9ZDM4OGRhZDkw + ZDRiYmQ3NjBhMTUyMzIxZjIxNDNhZjcscW9wPWF1dGg= + S: + cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA== + C: + S: a OK User logged in + --- + + The base64-decoded version of the SASL exchange is: + + S: realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth", + algorithm=md5-sess,charset=utf-8 + C: charset=utf-8,username="chris",realm="elwood.innosoft.com", + nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", + digest-uri="imap/elwood.innosoft.com", + response=d388dad90d4bbd760a152321f2143af7,qop=auth + S: rspauth=ea40f60335c427b5527b84dbabcdfffd + + The password in this example was "secret". + + This example shows the use of the Digest SASL mechanism with the + ACAP, using the same notational conventions and password as in the + previous example. Note that ACAP does not base64 encode and uses + fewer round trips that IMAP4. + + S: * ACAP (IMPLEMENTATION "Test ACAP server") (SASL "CRAM-MD5" + "DIGEST-MD5" "PLAIN") + C: a AUTHENTICATE "DIGEST-MD5" + S: + {94} + S: realm="elwood.innosoft.com",nonce="OA9BSXrbuRhWay",qop="auth", + algorithm=md5-sess,charset=utf-8 + C: {206} + C: charset=utf-8,username="chris",realm="elwood.innosoft.com", + nonce="OA9BSXrbuRhWay",nc=00000001,cnonce="OA9BSuZWMSpW8m", + digest-uri="acap/elwood.innosoft.com", + response=6084c6db3fede7352c551284490fd0fc,qop=auth + S: a OK (SASL {40} + S: rspauth=2f0b3d7c3c2e486600ef710726aa2eae) "AUTHENTICATE + Completed" + --- + + + + + +Leach & Newman Standards Track [Page 19] + +RFC 2831 Digest SASL Mechanism May 2000 + + + The server uses the values of all the directives, plus knowledge of + the users password (or the hash of the user's name, server's realm + and the user's password) to verify the computations above. If they + check, then the user has authenticated. + +5 References + + [Digest] Franks, J., et al., "HTTP Authentication: Basic and Digest + Access Authentication", RFC 2617, June 1999. + + [ISO-8859] ISO-8859. International Standard--Information Processing-- + 8-bit Single-Byte Coded Graphic Character Sets -- + Part 1: Latin alphabet No. 1, ISO-8859-1:1987. + Part 2: Latin alphabet No. 2, ISO-8859-2, 1987. + Part 3: Latin alphabet No. 3, ISO-8859-3, 1988. + Part 4: Latin alphabet No. 4, ISO-8859-4, 1988. + Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988. + Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987. + Part 7: Latin/Greek alphabet, ISO-8859-7, 1987. + Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988. + Part 9: Latin alphabet No. 5, ISO-8859-9, 1990. + + [RFC 822] Crocker, D., "Standard for The Format of ARPA Internet + Text Messages," STD 11, RFC 822, August 1982. + + [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, + April 1992. + + [RFC 2047] Moore, K., "MIME (Multipurpose Internet Mail Extensions) + Part Three: Message Header Extensions for Non-ASCII Text", + RFC 2047, November 1996. + + [RFC 2052] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying the + location of services (DNS SRV)", RFC 2052, October 1996. + + [RFC 2060] Crispin, M., "Internet Message Access Protocol - Version + 4rev1", RFC 2060, December 1996. + + [RFC 2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed- + Hashing for Message Authentication", RFC 2104, February + 1997. + + [RFC 2195] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP + AUTHorize Extension for Simple Challenge/Response", RFC + 2195, September 1997. + + + + + + +Leach & Newman Standards Track [Page 20] + +RFC 2831 Digest SASL Mechanism May 2000 + + + [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC 2222] Myers, J., "Simple Authentication and Security Layer + (SASL)", RFC 2222, October 1997. + + [USASCII] US-ASCII. Coded Character Set - 7-Bit American Standard + Code for Information Interchange. Standard ANSI X3.4-1986, + ANSI, 1986. + +6 Authors' Addresses + + Paul Leach + Microsoft + 1 Microsoft Way + Redmond, WA 98052 + + EMail: paulle@microsoft.com + + + Chris Newman + Innosoft International, Inc. + 1050 Lakes Drive + West Covina, CA 91790 USA + + EMail: chris.newman@innosoft.com + +7 ABNF + + What follows is the definition of the notation as is used in the + HTTP/1.1 specification (RFC 2616) and the HTTP authentication + specification (RFC 2617); it is reproduced here for ease of + reference. Since it is intended that a single Digest implementation + can support both HTTP and SASL-based protocols, the same notation is + used in both to facilitate comparison and prevention of unwanted + differences. Since it is cut-and-paste from the HTTP specifications, + not all productions may be used in this specification. It is also not + quite legal ABNF; again, the errors were copied from the HTTP + specifications. + +7.1 Augmented BNF + + All of the mechanisms specified in this document are described in + both prose and an augmented Backus-Naur Form (BNF) similar to that + used by RFC 822 [RFC 822]. Implementers will need to be familiar with + the notation in order to understand this specification. + + + + + +Leach & Newman Standards Track [Page 21] + +RFC 2831 Digest SASL Mechanism May 2000 + + + The augmented BNF includes the following constructs: + + name = definition + The name of a rule is simply the name itself (without any + enclosing "<" and ">") and is separated from its definition by the + equal "=" character. White space is only significant in that + indentation of continuation lines is used to indicate a rule + definition that spans more than one line. Certain basic rules are + in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle + brackets are used within definitions whenever their presence will + facilitate discerning the use of rule names. + + "literal" + Quotation marks surround literal text. Unless stated otherwise, + the text is case-insensitive. + + rule1 | rule2 + Elements separated by a bar ("|") are alternatives, e.g., "yes | + no" will accept yes or no. + + (rule1 rule2) + Elements enclosed in parentheses are treated as a single element. + Thus, "(elem (foo | bar) elem)" allows the token sequences + "elem foo elem" and "elem bar elem". + + *rule + The character "*" preceding an element indicates repetition. The + full form is "*element" indicating at least and at most + occurrences of element. Default values are 0 and infinity so + that "*(element)" allows any number, including zero; "1*element" + requires at least one; and "1*2element" allows one or two. + + [rule] + Square brackets enclose optional elements; "[foo bar]" is + equivalent to "*1(foo bar)". + + N rule + Specific repetition: "(element)" is equivalent to + "*(element)"; that is, exactly occurrences of (element). + Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three + alphabetic characters. + + #rule + A construct "#" is defined, similar to "*", for defining lists of + elements. The full form is "#element" indicating at least + and at most elements, each separated by one or more commas + (",") and OPTIONAL linear white space (LWS). This makes the usual + form of lists very easy; a rule such as + + + +Leach & Newman Standards Track [Page 22] + +RFC 2831 Digest SASL Mechanism May 2000 + + + ( *LWS element *( *LWS "," *LWS element )) + can be shown as + 1#element + Wherever this construct is used, null elements are allowed, but do + not contribute to the count of elements present. That is, + "(element), , (element) " is permitted, but counts as only two + elements. Therefore, where at least one element is required, at + least one non-null element MUST be present. Default values are 0 + and infinity so that "#element" allows any number, including zero; + "1#element" requires at least one; and "1#2element" allows one or + two. + + ; comment + A semi-colon, set off some distance to the right of rule text, + starts a comment that continues to the end of line. This is a + simple way of including useful notes in parallel with the + specifications. + + implied *LWS + The grammar described by this specification is word-based. Except + where noted otherwise, linear white space (LWS) can be included + between any two adjacent words (token or quoted-string), and + between adjacent words and separators, without changing the + interpretation of a field. At least one delimiter (LWS and/or + separators) MUST exist between any two tokens (for the definition + of "token" below), since they would otherwise be interpreted as a + single token. + +7.2 Basic Rules + + The following rules are used throughout this specification to + describe basic parsing constructs. The US-ASCII coded character set + is defined by ANSI X3.4-1986 [USASCII]. + + OCTET = + CHAR = + UPALPHA = + LOALPHA = + ALPHA = UPALPHA | LOALPHA + DIGIT = + CTL = + CR = + LF = + SP = + HT = + <"> = + CRLF = CR LF + + + +Leach & Newman Standards Track [Page 23] + +RFC 2831 Digest SASL Mechanism May 2000 + + + + All linear white space, including folding, has the same semantics as + SP. A recipient MAY replace any linear white space with a single SP + before interpreting the field value or forwarding the message + downstream. + + LWS = [CRLF] 1*( SP | HT ) + + The TEXT rule is only used for descriptive field contents and values + that are not intended to be interpreted by the message parser. Words + of *TEXT MAY contain characters from character sets other than + ISO-8859-1 [ISO 8859] only when encoded according to the rules of RFC + 2047 [RFC 2047]. + + TEXT = + + A CRLF is allowed in the definition of TEXT only as part of a header + field continuation. It is expected that the folding LWS will be + replaced with a single SP before interpretation of the TEXT value. + + Hexadecimal numeric characters are used in several protocol elements. + + HEX = "A" | "B" | "C" | "D" | "E" | "F" + | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT + + Many HTTP/1.1 header field values consist of words separated by LWS + or special characters. These special characters MUST be in a quoted + string to be used within a parameter value. + + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + + A string of text is parsed as a single word if it is quoted using + double-quote marks. + + quoted-string = ( <"> qdstr-val <"> ) + qdstr-val = *( qdtext | quoted-pair ) + qdtext = > + + Note that LWS is NOT implicit between the double-quote marks (<">) + surrounding a qdstr-val and the qdstr-val; any LWS will be considered + part of the qdstr-val. This is also the case for quotation marks + surrounding any other construct. + + + + +Leach & Newman Standards Track [Page 24] + +RFC 2831 Digest SASL Mechanism May 2000 + + + The backslash character ("\") MAY be used as a single-character + quoting mechanism only within qdstr-val and comment constructs. + + quoted-pair = "\" CHAR + + The value of this construct is CHAR. Note that an effect of this rule + is that backslash must be quoted. + +8 Sample Code + + The sample implementation in [Digest] also applies to DIGEST-MD5. + + The following code implements the conversion from UTF-8 to 8859-1 if + necessary. + + /* if the string is entirely in the 8859-1 subset of UTF-8, then + * translate to 8859-1 prior to MD5 + */ + void MD5_UTF8_8859_1(MD5_CTX *ctx, const unsigned char *base, + int len) + { + const unsigned char *scan, *end; + unsigned char cbuf; + + end = base + len; + for (scan = base; scan < end; ++scan) { + if (*scan > 0xC3) break; /* abort if outside 8859-1 */ + if (*scan >= 0xC0 && *scan <= 0xC3) { + if (++scan == end || *scan < 0x80 || *scan > 0xBF) + break; + } + } + /* if we found a character outside 8859-1, don't alter string + */ + if (scan < end) { + MD5Update(ctx, base, len); + return; + } + + /* convert to 8859-1 prior to applying hash + */ + do { + for (scan = base; scan < end && *scan < 0xC0; ++scan) + ; + if (scan != base) MD5Update(ctx, base, scan - base); + if (scan + 1 >= end) break; + cbuf = ((scan[0] & 0x3) << 6) | (scan[1] & 0x3f); + MD5Update(ctx, &cbuf, 1); + + + +Leach & Newman Standards Track [Page 25] + +RFC 2831 Digest SASL Mechanism May 2000 + + + base = scan + 2; + } while (base < end); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Leach & Newman Standards Track [Page 26] + +RFC 2831 Digest SASL Mechanism May 2000 + + +9 Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Leach & Newman Standards Track [Page 27] + diff --git a/include/Makefile.in b/include/Makefile.in index a3342c6a58..fd255d6cda 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, See COPYRIGHT file ## ## include Makefile.in for OpenLDAP @@ -7,15 +7,12 @@ all-local: ldap_config.h FORCE install-local: FORCE - -$(MKDIR) -p $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/lber.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 lber_types.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap_cdefs.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 ldap_features.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldap_schema.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/disptmpl.h $(includedir) - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/srchpref.h $(includedir) + -$(MKDIR) $(DESTDIR)$(includedir) + for header in $(srcdir)/lber.h lber_types.h $(srcdir)/ldap.h \ + $(srcdir)/ldap_cdefs.h ldap_features.h $(srcdir)/ldap_schema.h \ + $(srcdir)/disptmpl.h $(srcdir)/srchpref.h; do \ + $(INSTALL) $(INSTALLFLAGS) -m 644 $$header $(DESTDIR)$(includedir); \ + done clean-local: FORCE $(RM) ldap_config.h diff --git a/include/ac/alloca.h b/include/ac/alloca.h index 3d04de6179..3f143363d7 100644 --- a/include/ac/alloca.h +++ b/include/ac/alloca.h @@ -1,7 +1,7 @@ /* Generic alloca.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/assert.h b/include/ac/assert.h index 6c3a44ed77..986bf78548 100644 --- a/include/ac/assert.h +++ b/include/ac/assert.h @@ -1,7 +1,7 @@ /* Generic assert.h */ /* $OpenLDAP$ */ /* - * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -31,8 +31,8 @@ * create a replacement and hope it works */ -LDAP_F(void) ber_pvt_assert LDAP_P(( - const char *file, int line, const char *test )); +LIBLBER_F (void) ber_pvt_assert LDAP_P(( const char *file, int line, + const char *test )); /* Can't use LDAP_STRING(test), that'd expand to "test" */ #if defined(__STDC__) || defined(__cplusplus) diff --git a/include/ac/bytes.h b/include/ac/bytes.h index 160f0bbc8e..712ed8b929 100644 --- a/include/ac/bytes.h +++ b/include/ac/bytes.h @@ -1,7 +1,7 @@ /* Generic bytes.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -15,32 +15,41 @@ /* cross compilers should define both AC_INT{2,4}_TYPE in CPPFLAGS */ -#if !defined( AC_INT4_TYPE ) || !defined( AC_INT2_TYPE ) +#if !defined( AC_INT4_TYPE ) /* use autoconf defines to provide sized typedefs */ # if SIZEOF_LONG == 4 # define AC_INT4_TYPE long # elif SIZEOF_INT == 4 # define AC_INT4_TYPE int +# elif SIZEOF_SHORT == 4 +# define AC_INT4_TYPE short # else # error "AC_INT4_TYPE?" # endif +#endif + +typedef AC_INT4_TYPE ac_int4; +typedef signed AC_INT4_TYPE ac_sint4; +typedef unsigned AC_INT4_TYPE ac_uint4; +#if !defined( AC_INT2_TYPE ) # if SIZEOF_SHORT == 2 # define AC_INT2_TYPE short # elif SIZEOF_INT == 2 # define AC_INT2_TYPE int +# elif SIZEOF_LONG == 2 +# define AC_INT2_TYPE long # else -# error "AC_INT2_TYPE?" +/* not used, no error */ +/* # error "AC_INT2_TYPE?" */ # endif #endif -typedef AC_INT4_TYPE ac_int4; -typedef signed AC_INT4_TYPE ac_sint4; -typedef unsigned AC_INT4_TYPE ac_uint4; - +#if defined( AC_INT2_TYPE ) typedef AC_INT2_TYPE ac_int2; typedef signed AC_INT2_TYPE ac_sint2; typedef unsigned AC_INT2_TYPE ac_uint2; +#endif #ifndef BYTE_ORDER /* cross compilers should define BYTE_ORDER in CPPFLAGS */ diff --git a/include/ac/crypt.h b/include/ac/crypt.h new file mode 100644 index 0000000000..c87c7bd4b1 --- /dev/null +++ b/include/ac/crypt.h @@ -0,0 +1,25 @@ +/* Generic crypt.h */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +#ifndef _AC_CRYPT_H +#define _AC_CRYPT_H + +#include + +/* crypt() may be defined in a separate include file */ +#if HAVE_CRYPT_H +# include +#else + extern char *(crypt)(); +#endif + +#endif /* _AC_CRYPT_H */ diff --git a/include/ac/ctype.h b/include/ac/ctype.h index cfdcd924d7..dac50552d9 100644 --- a/include/ac/ctype.h +++ b/include/ac/ctype.h @@ -1,7 +1,7 @@ /* Generic ctype.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/dirent.h b/include/ac/dirent.h index 53f189a518..7942375854 100644 --- a/include/ac/dirent.h +++ b/include/ac/dirent.h @@ -1,7 +1,7 @@ /* Generic dirent.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/errno.h b/include/ac/errno.h index 3d26e5e464..e04c228856 100644 --- a/include/ac/errno.h +++ b/include/ac/errno.h @@ -1,7 +1,7 @@ /* Generic errno.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -25,8 +25,8 @@ # define sys_errlist ((char **)0) #elif DECL_SYS_ERRLIST /* have sys_errlist but need declaration */ - extern int sys_nerr; - extern char *sys_errlist[]; + LIBC_F (int) sys_nerr; + LIBC_F (char) *sys_errlist[]; #endif #ifdef HAVE_STRERROR @@ -36,6 +36,4 @@ ((err) > -1 && (err) < sys_nerr ? sys_errlist[(err)] : "unknown") #endif -extern char* strerror_r(); - #endif /* _AC_ERRNO_H */ diff --git a/include/ac/krb.h b/include/ac/krb.h index a5ffa7abd8..2227977182 100644 --- a/include/ac/krb.h +++ b/include/ac/krb.h @@ -1,7 +1,7 @@ /* Generic krb.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -10,10 +10,12 @@ * in file LICENSE in the top-level directory of the distribution. */ +/* Kerberos IV */ + #ifndef _AC_KRB_H #define _AC_KRB_H -#if defined( HAVE_KERBEROS ) +#if defined( HAVE_KRB4 ) #if defined( HAVE_KERBEROSIV_KRB_H ) #include @@ -27,5 +29,5 @@ #include #endif -#endif /* HAVE_KERBEROS */ +#endif /* HAVE_KRB4 */ #endif /* _AC_KRB_H */ diff --git a/include/ac/krb5.h b/include/ac/krb5.h new file mode 100644 index 0000000000..33d9b73b4b --- /dev/null +++ b/include/ac/krb5.h @@ -0,0 +1,22 @@ +/* Generic krb.h */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +/* Kerberos V */ + +#ifndef _AC_KRB5_H +#define _AC_KRB5_H + +#if defined( HAVE_KRB5 ) +#include +#endif /* HAVE_KRB5 */ + +#endif /* _AC_KRB5_H */ diff --git a/include/ac/param.h b/include/ac/param.h new file mode 100644 index 0000000000..ab2970cbf0 --- /dev/null +++ b/include/ac/param.h @@ -0,0 +1,26 @@ +/* Generic param.h */ +/* $OpenLDAP$ */ +/* + * Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +#ifndef _AC_PARAM_H +#define _AC_PARAM_H + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifndef MAXPATHLEN +# ifdef _MAX_PATH +# define MAXPATHLEN _MAX_PATH +# endif +#endif + +#endif /* _AC_PARAM_H */ diff --git a/include/ac/regex.h b/include/ac/regex.h index 897f7f5fd1..a9a25f1809 100644 --- a/include/ac/regex.h +++ b/include/ac/regex.h @@ -1,7 +1,7 @@ /* Generic Regex */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/setproctitle.h b/include/ac/setproctitle.h index 5bf1d2f496..910dc96b15 100644 --- a/include/ac/setproctitle.h +++ b/include/ac/setproctitle.h @@ -1,7 +1,7 @@ /* Generic setproctitle.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -19,10 +19,10 @@ # include #else /* use lutil version */ - LDAP_F(void) (setproctitle) LDAP_P((const char *fmt, ...)) \ + LIBLUTIL_F (void) (setproctitle) LDAP_P((const char *fmt, ...)) \ LDAP_GCCATTR((format(printf, 1, 2))); - LDAP_F(int) Argc; - LDAP_F(char) **Argv; + LIBLUTIL_F (int) Argc; + LIBLUTIL_F (char) **Argv; #endif #endif /* LDAP_PROCTITLE */ diff --git a/include/ac/signal.h b/include/ac/signal.h index 73f5d48092..4b7a9d120e 100644 --- a/include/ac/signal.h +++ b/include/ac/signal.h @@ -1,7 +1,7 @@ /* Generic signal.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -26,7 +26,11 @@ #undef LDAP_SIGUSR1 #undef LDAP_SIGUSR2 -# ifndef HAVE_LINUX_THREADS +# if defined(WINNT) || defined(_WINNT) || defined(_WIN32) +# define LDAP_SIGUSR1 SIGILL +# define LDAP_SIGUSR2 SIGTERM + +# elif !defined(HAVE_LINUX_THREADS) # define LDAP_SIGUSR1 SIGUSR1 # define LDAP_SIGUSR2 SIGUSR2 diff --git a/include/ac/socket.h b/include/ac/socket.h index fc1d533b6f..5a141e0f0c 100644 --- a/include/ac/socket.h +++ b/include/ac/socket.h @@ -1,7 +1,7 @@ /* Generic socket.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -20,6 +20,10 @@ #ifdef HAVE_SYS_SOCKET_H #include +#ifdef HAVE_SYS_UN_H +#include +#endif + #ifdef HAVE_SYS_SELECT_H #include #endif @@ -86,9 +90,9 @@ #undef sock_errno #undef sock_errstr #define sock_errno() WSAGetLastError() -#define sock_errstr(e) WSAGetErrorString(e) +#define sock_errstr(e) ber_pvt_wsa_err2string(e) -extern char* WSAGetErrorString LDAP_P((int)); +LIBLBER_F (char *) ber_pvt_wsa_err2string LDAP_P((int)); #elif MACOS # define tcp_close( s ) tcpclose( s ) @@ -110,6 +114,11 @@ extern char* WSAGetErrorString LDAP_P((int)); #elif HAVE_CLOSESOCKET # define tcp_close( s ) closesocket( s ) +# ifdef __BEOS__ +# define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) +# define tcp_write( s, buf, len ) send( s, buf, len, 0 ) +# endif + #else # define tcp_close( s ) close( s ) # define tcp_read( s, buf, len) read( s, buf, len ) @@ -139,31 +148,19 @@ extern char* WSAGetErrorString LDAP_P((int)); #if !defined( HAVE_INET_ATON ) && !defined( inet_aton ) #define inet_aton ldap_pvt_inet_aton struct in_addr; -int ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * )); +LIBLDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * )); #endif #if defined(__WIN32) && defined(_ALPHA) /* NT on Alpha is hosed. */ -#define AC_HTONL( l ) \ - ((((l)&0xff)<<24) + (((l)&0xff00)<<8) + \ - (((l)&0xff0000)>>8) + (((l)&0xff000000)>>24)) -#define AC_NTOHL(l) AC_HTONL(l) - -#elif defined(__alpha) && !defined(VMS) -/* - * htonl and ntohl on the DEC Alpha under OSF 1 seem to only swap the - * lower-order 32-bits of a (64-bit) long, so we define correct versions - * here. - */ -#define AC_HTONL( l ) (((long)htonl( (l) & 0x00000000FFFFFFFF )) << 32 \ - | htonl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 )) - -#define AC_NTOHL( l ) (((long)ntohl( (l) & 0x00000000FFFFFFFF )) << 32 \ - | ntohl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 )) +# define AC_HTONL( l ) \ + ((((l)&0xffU)<<24) + (((l)&0xff00U)<<8) + \ + (((l)&0xff0000U)>>8) + (((l)&0xff000000U)>>24)) +# define AC_NTOHL(l) AC_HTONL(l) #else -#define AC_HTONL( l ) htonl( l ) -#define AC_NTOHL( l ) ntohl( l ) +# define AC_HTONL( l ) htonl( l ) +# define AC_NTOHL( l ) ntohl( l ) #endif /* htons()/ntohs() may be broken much like htonl()/ntohl() */ diff --git a/include/ac/stdarg.h b/include/ac/stdarg.h index c7b2d46c87..4d4223fd54 100644 --- a/include/ac/stdarg.h +++ b/include/ac/stdarg.h @@ -1,7 +1,7 @@ /* Generic stdarg.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/stdlib.h b/include/ac/stdlib.h index e8037ed496..0537904dd6 100644 --- a/include/ac/stdlib.h +++ b/include/ac/stdlib.h @@ -1,7 +1,7 @@ /* Generic stdlib.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/string.h b/include/ac/string.h index 980511d3d0..bb1c10b836 100644 --- a/include/ac/string.h +++ b/include/ac/string.h @@ -1,7 +1,7 @@ /* Generic string.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -43,27 +43,26 @@ #endif /* use ldap_pvt_strtok instead of strtok or strtok_r! */ -LDAP_F(char *) ldap_pvt_strtok LDAP_P(( - char *str, const char *delim, char **pos )); - -LDAP_F(char *) ldap_pvt_strdup LDAP_P(( - const char * s )); +LIBLDAP_F(char *) ldap_pvt_strtok LDAP_P(( char *str, const char *delim, + char **pos )); #ifndef HAVE_STRDUP /* strdup() is missing, declare our own version */ # undef strdup -# define strdup(s) ldap_pvt_strdup(s) +# define strdup(s) ber_strdup(s) #else /* some systems fail to declare strdup */ - extern char *(strdup)(); + LIBC_F(char *) (strdup)(); #endif /* * some systems fail to declare strcasecmp() and strncasecmp() * we need them declared so we can obtain pointers to them */ -extern int (strcasecmp)(); -extern int (strncasecmp)(); + +/* In Mingw32, strcasecmp is not in the C library, so we don't LIBC_F it */ +int (strcasecmp)(); +int (strncasecmp)(); #ifndef SAFEMEMCPY # if defined( HAVE_MEMMOVE ) diff --git a/include/ac/sysexits.h b/include/ac/sysexits.h index 8d5df5ffdf..ede4da70aa 100644 --- a/include/ac/sysexits.h +++ b/include/ac/sysexits.h @@ -1,7 +1,7 @@ /* Generic sysexits */ /* $OpenLDAP$ */ /* - * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/syslog.h b/include/ac/syslog.h index 4015fd96a8..2602a407cf 100644 --- a/include/ac/syslog.h +++ b/include/ac/syslog.h @@ -1,7 +1,7 @@ /* Generic syslog.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/termios.h b/include/ac/termios.h index 5b548a4994..c1e15494a6 100644 --- a/include/ac/termios.h +++ b/include/ac/termios.h @@ -1,7 +1,7 @@ /* Generic termios.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/time.h b/include/ac/time.h index 9f8d303868..b61b9f374c 100644 --- a/include/ac/time.h +++ b/include/ac/time.h @@ -1,7 +1,7 @@ /* Generic time.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/ac/unistd.h b/include/ac/unistd.h index 7c2fdfc533..b7710dcd75 100644 --- a/include/ac/unistd.h +++ b/include/ac/unistd.h @@ -1,7 +1,7 @@ /* Generic unistd.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -21,17 +21,23 @@ # include #endif -/* crypt() may be defined in a separate include file */ -#if HAVE_CRYPT_H -# include -#else - extern char *(crypt)(); +#if HAVE_PROCESS_H +# include #endif -#ifndef HAVE_GETPASS -LDAP_F(char*)(getpass) LDAP_P((const char *getpass)); +/* note: callers of crypt(3) should include */ + +#if defined(HAVE_GETPASSPHRASE) +LIBC_F(char*)(getpassphrase)(); + +#elif defined(HAVE_GETPASS) +#define getpassphrase(p) getpass(p) +LIBC_F(char*)(getpass)(); + #else -LDAP_F(char*)(getpass)(); +#define NEED_GETPASSPHRASE 1 +#define getpassphrase(p) lutil_getpass(p) +LIBLUTIL_F(char*)(lutil_getpass) LDAP_P((const char *getpass)); #endif /* getopt() defines may be in separate include file */ @@ -44,17 +50,13 @@ LDAP_F(char*)(getpass)(); #else /* assume we need to declare these externs */ - extern char *optarg; - extern int optind, opterr, optopt; + LIBC_F (char *) optarg; + LIBC_F (int) optind, opterr, optopt; #endif #ifndef HAVE_TEMPNAM - LDAP_F(char *)(tempnam) LDAP_P(( - const char *tmpdir, - const char *prefix)); -#endif -#ifndef HAVE_MKTEMP - LDAP_F(char *)(mktemp) LDAP_P((char *)); + LIBLUTIL_F(char *)(tempnam) LDAP_P(( const char *tmpdir, + const char *prefix)); #endif /* use lutil file locking */ diff --git a/include/ac/wait.h b/include/ac/wait.h index 12bb7d4a6a..6ec659b3ac 100644 --- a/include/ac/wait.h +++ b/include/ac/wait.h @@ -1,7 +1,7 @@ /* Generic wait.h */ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/include/avl.h b/include/avl.h index ae3b44ab65..7ecb3affe5 100644 --- a/include/avl.h +++ b/include/avl.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -61,39 +61,39 @@ typedef int (*AVL_CMP) LDAP_P((const void*, const void*)); typedef int (*AVL_DUP) LDAP_P((void*, void*)); typedef void (*AVL_FREE) LDAP_P((void*)); -LDAP_F( int ) +LIBAVL_F( int ) avl_free LDAP_P(( Avlnode *root, AVL_FREE dfree )); -LDAP_F( int ) +LIBAVL_F( int ) avl_insert LDAP_P((Avlnode **, void*, AVL_CMP, AVL_DUP)); -LDAP_F( void* ) +LIBAVL_F( void* ) avl_delete LDAP_P((Avlnode **, void*, AVL_CMP)); -LDAP_F( void* ) +LIBAVL_F( void* ) avl_find LDAP_P((Avlnode *, const void*, AVL_CMP)); -LDAP_F( void* ) +LIBAVL_F( void* ) avl_find_lin LDAP_P((Avlnode *, const void*, AVL_CMP)); #ifdef AVL_NONREENTRANT -LDAP_F( void* ) +LIBAVL_F( void* ) avl_getfirst LDAP_P((Avlnode *)); -LDAP_F( void* ) +LIBAVL_F( void* ) avl_getnext LDAP_P((void)); #endif -LDAP_F( int ) +LIBAVL_F( int ) avl_dup_error LDAP_P((void*, void*)); -LDAP_F( int ) +LIBAVL_F( int ) avl_dup_ok LDAP_P((void*, void*)); -LDAP_F( int ) +LIBAVL_F( int ) avl_apply LDAP_P((Avlnode *, AVL_APPLY, void*, int, int)); -LDAP_F( int ) +LIBAVL_F( int ) avl_prefixapply LDAP_P((Avlnode *, void*, AVL_CMP, void*, AVL_CMP, void*, int)); /* apply traversal types */ diff --git a/include/disptmpl.h b/include/disptmpl.h index ba6f4bd982..c99ddb240b 100644 --- a/include/disptmpl.h +++ b/include/disptmpl.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -225,88 +225,88 @@ struct ldap_disptmpl { typedef int (*ldap_writeptype) LDAP_P(( void *writeparm, char *p, ber_len_t len )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_init_templates LDAP_P(( char *file, struct ldap_disptmpl **tmpllistp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_init_templates_buf LDAP_P(( char *buf, ber_len_t buflen, struct ldap_disptmpl **tmpllistp )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_free_templates LDAP_P(( struct ldap_disptmpl *tmpllist )); -LDAP_F( struct ldap_disptmpl * ) +LIBLDAP_F( struct ldap_disptmpl * ) ldap_first_disptmpl LDAP_P(( struct ldap_disptmpl *tmpllist )); -LDAP_F( struct ldap_disptmpl * ) +LIBLDAP_F( struct ldap_disptmpl * ) ldap_next_disptmpl LDAP_P(( struct ldap_disptmpl *tmpllist, struct ldap_disptmpl *tmpl )); -LDAP_F( struct ldap_disptmpl * ) +LIBLDAP_F( struct ldap_disptmpl * ) ldap_name2template LDAP_P(( char *name, struct ldap_disptmpl *tmpllist )); -LDAP_F( struct ldap_disptmpl * ) +LIBLDAP_F( struct ldap_disptmpl * ) ldap_oc2template LDAP_P(( char **oclist, struct ldap_disptmpl *tmpllist )); -LDAP_F( char ** ) +LIBLDAP_F( char ** ) ldap_tmplattrs LDAP_P(( struct ldap_disptmpl *tmpl, char **includeattrs, int exclude, unsigned long syntaxmask )); -LDAP_F( struct ldap_tmplitem * ) +LIBLDAP_F( struct ldap_tmplitem * ) ldap_first_tmplrow LDAP_P(( struct ldap_disptmpl *tmpl )); -LDAP_F( struct ldap_tmplitem * ) +LIBLDAP_F( struct ldap_tmplitem * ) ldap_next_tmplrow LDAP_P(( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )); -LDAP_F( struct ldap_tmplitem * ) +LIBLDAP_F( struct ldap_tmplitem * ) ldap_first_tmplcol LDAP_P(( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )); -LDAP_F( struct ldap_tmplitem * ) +LIBLDAP_F( struct ldap_tmplitem * ) ldap_next_tmplcol LDAP_P(( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, struct ldap_tmplitem *col )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_entry2text LDAP_P(( LDAP *ld, char *buf, LDAPMessage *entry, struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, ldap_writeptype writeproc, void *writeparm, char *eol, int rdncount, unsigned long opts )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_vals2text LDAP_P(( LDAP *ld, char *buf, char **vals, char *label, int labelwidth, unsigned long syntaxid, ldap_writeptype writeproc, void *writeparm, char *eol, int rdncount )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_entry2text_search LDAP_P(( LDAP *ld, char *dn, char *base, LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, char ***defvals, ldap_writeptype writeproc, void *writeparm, char *eol, int rdncount, unsigned long opts )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_entry2html LDAP_P(( LDAP *ld, char *buf, LDAPMessage *entry, struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, ldap_writeptype writeproc, void *writeparm, char *eol, int rdncount, unsigned long opts, char *urlprefix, char *base )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_vals2html LDAP_P(( LDAP *ld, char *buf, char **vals, char *label, int labelwidth, unsigned long syntaxid, ldap_writeptype writeproc, void *writeparm, char *eol, int rdncount, char *urlprefix )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_entry2html_search LDAP_P(( LDAP *ld, char *dn, char *base, LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, char ***defvals, diff --git a/include/getopt-compat.h b/include/getopt-compat.h index 14b2a2f5b0..ca23e4b776 100644 --- a/include/getopt-compat.h +++ b/include/getopt-compat.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -18,14 +18,17 @@ LDAP_BEGIN_DECL -extern char *optarg; -extern int optind, opterr, optopt; +/* change symbols to avoid clashing */ +#define optarg lutil_optarg +#define optind lutil_optind +#define opterr lutil_opterr +#define optopt lutil_optopt +#define getopt lutil_getopt -LDAP_F( int ) -getopt LDAP_P(( - int, - char * const [], - const char *)); +LIBLUTIL_F (char *) optarg; +LIBLUTIL_F (int) optind, opterr, optopt; + +LIBLUTIL_F (int) getopt LDAP_P(( int, char * const [], const char *)); LDAP_END_DECL diff --git a/include/lber.h b/include/lber.h index 229e97e55c..13551e37a6 100644 --- a/include/lber.h +++ b/include/lber.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -23,31 +23,10 @@ #ifndef _LBER_H #define _LBER_H -#include #include LDAP_BEGIN_DECL -/* boolean, enumerations, and integers */ -typedef LBER_INT_T ber_int_t; - -/* signed and unsigned versions */ -typedef signed LBER_INT_T ber_sint_t; -typedef unsigned LBER_INT_T ber_uint_t; - -/* tags */ -typedef LBER_TAG_T ber_tag_t; - -/* "socket" descriptors */ -typedef LBER_SOCKET_T ber_socket_t; - -/* lengths */ -typedef unsigned LBER_LEN_T ber_len_t; - -/* signed lengths */ -typedef LBER_LEN_T ber_slen_t; - - /* Overview of LBER tag construction * * Bits @@ -66,62 +45,65 @@ typedef LBER_LEN_T ber_slen_t; */ /* BER classes and mask */ -#define LBER_CLASS_UNIVERSAL (ber_tag_t) 0x00U -#define LBER_CLASS_APPLICATION (ber_tag_t) 0x40U -#define LBER_CLASS_CONTEXT (ber_tag_t) 0x80U -#define LBER_CLASS_PRIVATE (ber_tag_t) 0xc0U -#define LBER_CLASS_MASK (ber_tag_t) 0xc0U +#define LBER_CLASS_UNIVERSAL ((ber_tag_t) 0x00U) +#define LBER_CLASS_APPLICATION ((ber_tag_t) 0x40U) +#define LBER_CLASS_CONTEXT ((ber_tag_t) 0x80U) +#define LBER_CLASS_PRIVATE ((ber_tag_t) 0xc0U) +#define LBER_CLASS_MASK ((ber_tag_t) 0xc0U) /* BER encoding type and mask */ -#define LBER_PRIMITIVE (ber_tag_t) 0x00U -#define LBER_CONSTRUCTED (ber_tag_t) 0x20U -#define LBER_ENCODING_MASK (ber_tag_t) 0x20U +#define LBER_PRIMITIVE ((ber_tag_t) 0x00U) +#define LBER_CONSTRUCTED ((ber_tag_t) 0x20U) +#define LBER_ENCODING_MASK ((ber_tag_t) 0x20U) -#define LBER_BIG_TAG_MASK (ber_tag_t) 0x1fU -#define LBER_MORE_TAG_MASK (ber_tag_t) 0x80U +#define LBER_BIG_TAG_MASK ((ber_tag_t) 0x1fU) +#define LBER_MORE_TAG_MASK ((ber_tag_t) 0x80U) /* * Note that LBER_ERROR and LBER_DEFAULT are values that can never appear * as valid BER tags, and so it is safe to use them to report errors. In * fact, any tag for which the following is true is invalid: */ -#define LBER_INVALID(t) (((t) & 0x080) && (((t) & (ber_tag_t) ~ 0x0FF)) -#define LBER_ERROR ((ber_tag_t) ~ 0x0) -#define LBER_DEFAULT ((ber_tag_t) ~ 0x0) +#define LBER_INVALID(t) (((t) & (ber_tag_t) 0x080UL) \ + && (((t) & (ber_tag_t) ~ 0x0FF)) + +#define LBER_ERROR ((ber_tag_t) -1) +#define LBER_DEFAULT ((ber_tag_t) -1) /* general BER types we know about */ -#define LBER_BOOLEAN (ber_tag_t) 0x01UL -#define LBER_INTEGER (ber_tag_t) 0x02UL -#define LBER_BITSTRING (ber_tag_t) 0x03UL -#define LBER_OCTETSTRING (ber_tag_t) 0x04UL -#define LBER_NULL (ber_tag_t) 0x05UL -#define LBER_ENUMERATED (ber_tag_t) 0x0aUL -#define LBER_SEQUENCE (ber_tag_t) 0x30UL /* constructed */ -#define LBER_SET (ber_tag_t) 0x31UL /* constructed */ - -#define OLD_LBER_SEQUENCE (ber_tag_t) 0x10UL /* w/o constructed bit - broken */ -#define OLD_LBER_SET (ber_tag_t) 0x11UL /* w/o constructed bit - broken */ - -typedef int (*BERTranslateProc) LDAP_P(( - char **bufp, - ber_len_t *buflenp, - int free_input )); +#define LBER_BOOLEAN ((ber_tag_t) 0x01UL) +#define LBER_INTEGER ((ber_tag_t) 0x02UL) +#define LBER_BITSTRING ((ber_tag_t) 0x03UL) +#define LBER_OCTETSTRING ((ber_tag_t) 0x04UL) +#define LBER_NULL ((ber_tag_t) 0x05UL) +#define LBER_ENUMERATED ((ber_tag_t) 0x0aUL) +#define LBER_SEQUENCE ((ber_tag_t) 0x30UL) /* constructed */ +#define LBER_SET ((ber_tag_t) 0x31UL) /* constructed */ /* LBER BerElement options */ #define LBER_USE_DER 0x01 #define LBER_USE_INDEFINITE_LEN 0x02 -#define LBER_TRANSLATE_STRINGS 0x04 /* get/set options for BerElement */ -#define LBER_OPT_BER_OPTIONS 0x01 -#define LBER_OPT_BER_DEBUG 0x02 +#define LBER_OPT_BER_OPTIONS 0x01 +#define LBER_OPT_BER_DEBUG 0x02 +#define LBER_OPT_BER_REMAINING_BYTES 0x03 +#define LBER_OPT_BER_TOTAL_BYTES 0x04 +#define LBER_OPT_BER_BYTES_TO_WRITE 0x05 #define LBER_OPT_DEBUG_LEVEL LBER_OPT_BER_DEBUG +#define LBER_OPT_REMAINING_BYTES LBER_OPT_BER_REMAINING_BYTES +#define LBER_OPT_TOTAL_BYTES LBER_OPT_BER_TOTAL_BYTES +#define LBER_OPT_BYTES_TO_WRITE LBER_OPT_BER_BYTES_TO_WRITE #define LBER_OPT_LOG_PRINT_FN 0x8001 #define LBER_OPT_MEMORY_FNS 0x8002 +#define LBER_OPT_ERROR_FN 0x8003 +#define LBER_OPT_LOG_PRINT_FILE 0x8004 + +typedef int* (*BER_ERRNO_FN) LDAP_P(( void )); -typedef void (*BER_LOG_PRINT_FN) LDAP_P(( char *buf )); +typedef void (*BER_LOG_PRINT_FN) LDAP_P(( LDAP_CONST char *buf )); typedef void* (*BER_MEMALLOC_FN) LDAP_P(( ber_len_t size )); typedef void* (*BER_MEMCALLOC_FN) LDAP_P(( ber_len_t n, ber_len_t size )); @@ -135,11 +117,26 @@ typedef struct lber_memory_fns { BER_MEMFREE_FN bmf_free; } BerMemoryFunctions; -/* LBER Sockbuf options */ -#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */ -#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */ -#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */ -#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */ +/* LBER Sockbuf_IO options */ +#define LBER_SB_OPT_GET_FD 1 +#define LBER_SB_OPT_SET_FD 2 +#define LBER_SB_OPT_HAS_IO 3 +#define LBER_SB_OPT_SET_NONBLOCK 4 +#define LBER_SB_OPT_UDP_GET_SRC 5 +#define LBER_SB_OPT_UDP_SET_DST 6 +#define LBER_SB_OPT_GET_SSL 7 +#define LBER_SB_OPT_DATA_READY 8 +#define LBER_SB_OPT_SET_READAHEAD 9 +#define LBER_SB_OPT_DRAIN 10 +#define LBER_SB_OPT_NEEDS_READ 11 +#define LBER_SB_OPT_NEEDS_WRITE 12 +/* Largest option used by the library */ +#define LBER_SB_OPT_OPT_MAX 12 + +/* LBER IO operations stacking levels */ +#define LBER_SBIOD_LEVEL_PROVIDER 10 +#define LBER_SBIOD_LEVEL_TRANSPORT 20 +#define LBER_SBIOD_LEVEL_APPLICATION 30 /* get/set options for Sockbuf */ #define LBER_OPT_SOCKBUF_DESC 0x1000 @@ -150,37 +147,76 @@ typedef struct lber_memory_fns { #define LBER_OPT_ON ((void *) 1) #define LBER_OPT_OFF ((void *) 0) -#define LBER_OPT_SUCCESS 0 +#define LBER_OPT_SUCCESS (0) #define LBER_OPT_ERROR (-1) typedef struct berelement BerElement; typedef struct sockbuf Sockbuf; typedef struct seqorset Seqorset; +typedef struct sockbuf_io Sockbuf_IO; + +/* Structure for LBER IO operarion descriptor */ +typedef struct sockbuf_io_desc { + int sbiod_level; + Sockbuf *sbiod_sb; + Sockbuf_IO *sbiod_io; + void *sbiod_pvt; + struct sockbuf_io_desc *sbiod_next; +} Sockbuf_IO_Desc; + +/* Structure for LBER IO operation functions */ +struct sockbuf_io { + int (*sbi_setup)( Sockbuf_IO_Desc *sbiod, void *arg ); + int (*sbi_remove)( Sockbuf_IO_Desc *sbiod ); + int (*sbi_ctrl)( Sockbuf_IO_Desc *sbiod, int opt, void *arg); + + ber_slen_t (*sbi_read)( Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len ); + ber_slen_t (*sbi_write)( Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len ); + + int (*sbi_close)( Sockbuf_IO_Desc *sbiod ); +}; + +/* Helper macros for LBER IO functions */ +#define LBER_SBIOD_READ_NEXT( sbiod, buf, len ) \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_read( (sbiod)->sbiod_next, \ + buf, len ) ) +#define LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ) \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_write( (sbiod)->sbiod_next, \ + buf, len ) ) +#define LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ) \ + ( (sbiod)->sbiod_next ? \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_ctrl( \ + (sbiod)->sbiod_next, opt, arg ) ) : 0 ) + /* structure for returning a sequence of octet strings + length */ typedef struct berval { ber_len_t bv_len; char *bv_val; } BerValue; +/* this should be moved to lber-int.h */ + /* * in bprint.c: */ -LDAP_F( void ) -ber_print_error LDAP_P(( +LIBLBER_F( void ) +ber_error_print LDAP_P(( LDAP_CONST char *data )); -LDAP_F( void ) +LIBLBER_F( void ) ber_bprint LDAP_P(( LDAP_CONST char *data, ber_len_t len )); -LDAP_F( void ) +LIBLBER_F( void ) ber_dump LDAP_P(( - LDAP_CONST BerElement *ber, int inout )); + BerElement *ber, int inout )); -LDAP_F( void ) +LIBLBER_F( void ) ber_sos_dump LDAP_P(( - LDAP_CONST Seqorset *sos )); + Seqorset *sos )); /* @@ -191,80 +227,79 @@ typedef int (*BERDecodeCallback) LDAP_P(( void *data, int mode )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_tag LDAP_P(( BerElement *ber )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_skip_tag LDAP_P(( BerElement *ber, ber_len_t *len )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_peek_tag LDAP_P(( - LDAP_CONST BerElement *ber, + BerElement *ber, ber_len_t *len )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_int LDAP_P(( BerElement *ber, ber_int_t *num )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) +ber_get_enum LDAP_P(( + BerElement *ber, + ber_int_t *num )); + +LIBLBER_F( ber_tag_t ) ber_get_stringb LDAP_P(( BerElement *ber, char *buf, ber_len_t *len )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_stringa LDAP_P(( BerElement *ber, char **buf )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_stringal LDAP_P(( BerElement *ber, struct berval **bv )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_bitstringa LDAP_P(( BerElement *ber, char **buf, ber_len_t *len )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_null LDAP_P(( BerElement *ber )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_boolean LDAP_P(( BerElement *ber, ber_int_t *boolval )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_first_element LDAP_P(( BerElement *ber, ber_len_t *len, char **last )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_next_element LDAP_P(( BerElement *ber, ber_len_t *len, - char *last )); + LDAP_CONST char *last )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_scanf LDAP_P(( BerElement *ber, LDAP_CONST char *fmt, ... )); -LDAP_F( void ) -ber_set_string_translators LDAP_P(( - BerElement *ber, - BERTranslateProc encode_proc, - BERTranslateProc decode_proc )); - /* * in encode.c */ @@ -272,74 +307,74 @@ typedef int (*BEREncodeCallback) LDAP_P(( BerElement *ber, void *data )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_enum LDAP_P(( BerElement *ber, ber_int_t num, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_int LDAP_P(( BerElement *ber, ber_int_t num, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_ostring LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_len_t len, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_berval LDAP_P(( BerElement *ber, LDAP_CONST struct berval *bv, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_string LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_bitstring LDAP_P(( BerElement *ber, LDAP_CONST char *str, ber_len_t bitlen, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_null LDAP_P(( BerElement *ber, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_boolean LDAP_P(( BerElement *ber, ber_int_t boolval, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_start_seq LDAP_P(( BerElement *ber, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_start_set LDAP_P(( BerElement *ber, ber_tag_t tag )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_seq LDAP_P(( BerElement *ber )); -LDAP_F( int ) +LIBLBER_F( int ) ber_put_set LDAP_P(( BerElement *ber )); -LDAP_F( int ) +LIBLBER_F( int ) ber_printf LDAP_P(( BerElement *ber, LDAP_CONST char *fmt, @@ -350,80 +385,80 @@ ber_printf LDAP_P(( * in io.c: */ -LDAP_F( ber_slen_t ) +LIBLBER_F( ber_slen_t ) ber_read LDAP_P(( BerElement *ber, char *buf, ber_len_t len )); -LDAP_F( ber_slen_t ) +LIBLBER_F( ber_slen_t ) ber_write LDAP_P(( BerElement *ber, LDAP_CONST char *buf, ber_len_t len, int nosos )); -LDAP_F( void ) +LIBLBER_F( void ) ber_free LDAP_P(( BerElement *ber, int freebuf )); -LDAP_F( int ) +LIBLBER_F( int ) ber_flush LDAP_P(( Sockbuf *sb, BerElement *ber, int freeit )); -LDAP_F( BerElement * ) +LIBLBER_F( BerElement * ) ber_alloc LDAP_P(( void )); /* DEPRECATED */ -LDAP_F( BerElement * ) +LIBLBER_F( BerElement * ) der_alloc LDAP_P(( void )); /* DEPRECATED */ -LDAP_F( BerElement * ) +LIBLBER_F( BerElement * ) ber_alloc_t LDAP_P(( int beroptions )); -LDAP_F( BerElement * ) +LIBLBER_F( BerElement * ) ber_dup LDAP_P(( - LDAP_CONST BerElement *ber )); + BerElement *ber )); -LDAP_F( ber_tag_t ) +LIBLBER_F( ber_tag_t ) ber_get_next LDAP_P(( Sockbuf *sb, ber_len_t *len, BerElement *ber )); -LDAP_F( void ) +LIBLBER_F( void ) ber_init_w_nullc LDAP_P(( BerElement *ber, int options )); -LDAP_F( void ) +LIBLBER_F( void ) ber_reset LDAP_P(( BerElement *ber, int was_writing )); -LDAP_F( BerElement * ) +LIBLBER_F( BerElement * ) ber_init LDAP_P(( struct berval *bv )); -LDAP_F( int ) +LIBLBER_F( int ) ber_flatten LDAP_P(( - LDAP_CONST BerElement *ber, + BerElement *ber, struct berval **bvPtr )); /* * LBER ber accessor functions */ -LDAP_F( int ) +LIBLBER_F( int ) ber_get_option LDAP_P(( - LDAP_CONST void *item, + void *item, int option, void *outvalue)); -LDAP_F( int ) +LIBLBER_F( int ) ber_set_option LDAP_P(( void *item, int option, @@ -433,58 +468,103 @@ ber_set_option LDAP_P(( * LBER sockbuf.c */ -LDAP_F( Sockbuf * ) -ber_sockbuf_alloc( void ); +LIBLBER_F( Sockbuf * ) +ber_sockbuf_alloc LDAP_P(( + void )); -LDAP_F( Sockbuf * ) -ber_sockbuf_alloc_fd( - ber_socket_t fd ); +LIBLBER_F( void ) +ber_sockbuf_free LDAP_P(( + Sockbuf *sb )); -LDAP_F( void ) -ber_sockbuf_free( - Sockbuf *sb ); +LIBLBER_F( int ) +ber_sockbuf_add_io LDAP_P(( + Sockbuf *sb, + Sockbuf_IO *sbio, + int layer, + void *arg )); + +LIBLBER_F( int ) +ber_sockbuf_remove_io LDAP_P(( + Sockbuf *sb, + Sockbuf_IO *sbio, + int layer )); + +LIBLBER_F( int ) +ber_sockbuf_ctrl LDAP_P(( + Sockbuf *sb, + int opt, + void *arg )); + +LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_tcp; +LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_udp; +LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_readahead; +LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_fd; +LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_debug; /* * LBER memory.c */ -LDAP_F( void * ) +LIBLBER_F( void * ) ber_memalloc LDAP_P(( ber_len_t s )); -LDAP_F( void * ) +LIBLBER_F( void * ) ber_memrealloc LDAP_P(( void* p, ber_len_t s )); -LDAP_F( void * ) +LIBLBER_F( void * ) ber_memcalloc LDAP_P(( ber_len_t n, ber_len_t s )); -LDAP_F( void ) +LIBLBER_F( void ) ber_memfree LDAP_P(( void* p )); -LDAP_F( void ) +LIBLBER_F( void ) ber_memvfree LDAP_P(( void** vector )); -LDAP_F( void ) +LIBLBER_F( void ) ber_bvfree LDAP_P(( struct berval *bv )); -LDAP_F( void ) +LIBLBER_F( void ) ber_bvecfree LDAP_P(( struct berval **bv )); -LDAP_F( struct berval * ) +LIBLBER_F( int ) +ber_bvecadd LDAP_P(( + struct berval ***bvec, + struct berval *bv )); + +LIBLBER_F( struct berval * ) ber_bvdup LDAP_P(( LDAP_CONST struct berval *bv )); -LDAP_F( char * ) +LIBLBER_F( struct berval * ) +ber_bvstr LDAP_P(( + LDAP_CONST char * )); + +LIBLBER_F( struct berval * ) +ber_bvstrdup LDAP_P(( + LDAP_CONST char * )); + +LIBLBER_F( char * ) ber_strdup LDAP_P(( LDAP_CONST char * )); +/* + * error.c + */ +LIBLBER_F( int * ) ber_errno_addr LDAP_P((void)); +#define ber_errno (*(ber_errno_addr)()) + +#define LBER_ERROR_NONE 0 +#define LBER_ERROR_PARAM 0x1 +#define LBER_ERROR_MEMORY 0x2 + LDAP_END_DECL #endif /* _LBER_H */ diff --git a/include/lber_pvt.h b/include/lber_pvt.h index 7e26591cea..e314205f47 100644 --- a/include/lber_pvt.h +++ b/include/lber_pvt.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -20,18 +20,46 @@ LDAP_BEGIN_DECL +typedef struct sockbuf_buf { + ber_len_t buf_size; + ber_len_t buf_ptr; + ber_len_t buf_end; + char *buf_base; +} Sockbuf_Buf; + /* * bprint.c */ -LDAP_F( BER_LOG_PRINT_FN ) ber_pvt_log_print; +LIBLBER_F( BER_LOG_PRINT_FN ) ber_pvt_log_print; -LDAP_F( int ) +LIBLBER_F( int ) ber_pvt_log_printf LDAP_P(( int errlvl, int loglvl, const char *fmt, ... )) LDAP_GCCATTR((format(printf, 3, 4))); +/* + * sockbuf.c + */ +LIBLBER_F( ber_slen_t ) +ber_pvt_sb_do_write LDAP_P(( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )); + +LIBLBER_F( void ) +ber_pvt_sb_buf_init LDAP_P(( Sockbuf_Buf *buf )); + +LIBLBER_F( void ) +ber_pvt_sb_buf_destroy LDAP_P(( Sockbuf_Buf *buf )); + +LIBLBER_F( int ) +ber_pvt_sb_grow_buffer LDAP_P(( Sockbuf_Buf *buf, ber_len_t minsize )); + +LIBLBER_F( ber_len_t ) +ber_pvt_sb_copy_out LDAP_P(( Sockbuf_Buf *sbb, char *buf, ber_len_t len )); + +LIBLBER_F( int ) +ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb )); + LDAP_END_DECL #endif diff --git a/include/lber_types.h.in b/include/lber_types.h.in index 6abba8f722..46adad9e5c 100644 --- a/include/lber_types.h.in +++ b/include/lber_types.h.in @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -16,16 +16,43 @@ #ifndef _LBER_TYPES_H #define _LBER_TYPES_H -/* LBER boolean, enum, integers - 32 bits or larger*/ +#include + +LDAP_BEGIN_DECL + +/* LBER boolean, enum, integers (32 bits or larger) */ #undef LBER_INT_T -/* LBER tags - 32 bits or larger */ +/* LBER tags (32 bits or larger) */ #undef LBER_TAG_T /* LBER socket descriptor */ #undef LBER_SOCKET_T -/* LBER lengths - 32 bits or larger*/ +/* LBER lengths (32 bits or larger) */ #undef LBER_LEN_T +/* ------------------------------------------------------------ */ + +/* booleans, enumerations, and integers */ +typedef LBER_INT_T ber_int_t; + +/* signed and unsigned versions */ +typedef signed LBER_INT_T ber_sint_t; +typedef unsigned LBER_INT_T ber_uint_t; + +/* tags */ +typedef unsigned LBER_TAG_T ber_tag_t; + +/* "socket" descriptors */ +typedef LBER_SOCKET_T ber_socket_t; + +/* lengths */ +typedef unsigned LBER_LEN_T ber_len_t; + +/* signed lengths */ +typedef signed LBER_LEN_T ber_slen_t; + +LDAP_END_DECL + #endif /* _LBER_TYPES_H */ diff --git a/include/lber_types.nt b/include/lber_types.nt index 884188edcf..9b04d5c76e 100644 --- a/include/lber_types.nt +++ b/include/lber_types.nt @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -10,18 +10,23 @@ */ /* - * LBER types for Windows NT + * LBER types for Windows NT (and Win32) + * copied by setup.mak to lber_types.h (when confingure is not used). */ -#ifndef _LBER_TYPES_H_NT -#define _LBER_TYPES_H_NT +#ifndef _LBER_TYPES_H +#define _LBER_TYPES_H + +#include + +LDAP_BEGIN_DECL /* * NT types: * * bitsof(short) == 2 * bitsof(int) == 4 - * bitsof(long) == 4 + * bitsof(long) == 4 (or larger) * * typedef unsigned int size_t; * typedef unsigned int SOCKET; @@ -39,6 +44,29 @@ #define LBER_SOCKET_T unsigned int /* LBER lengths - 32 bits or larger*/ -#define LBER_LEN_T int +#define LBER_LEN_T long + +/* ------------------------------------------------------------ */ + +/* booleans, enumerations, and integers */ +typedef LBER_INT_T ber_int_t; + +/* signed and unsigned versions */ +typedef signed LBER_INT_T ber_sint_t; +typedef unsigned LBER_INT_T ber_uint_t; + +/* tags */ +typedef unsigned LBER_TAG_T ber_tag_t; + +/* "socket" descriptors */ +typedef LBER_SOCKET_T ber_socket_t; + +/* lengths */ +typedef unsigned LBER_LEN_T ber_len_t; + +/* signed lengths */ +typedef signed LBER_LEN_T ber_slen_t; + +LDAP_END_DECL -#endif /* _LBER_TYPES_H_NT */ +#endif /* _LBER_TYPES_H */ diff --git a/include/ldap.h b/include/ldap.h index 8dbbd1b1ef..460d381177 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -23,9 +23,7 @@ #ifndef _LDAP_H #define _LDAP_H -#include - -/* draft spec requires ldap.h include lber declarations */ +/* pull in lber */ #include LDAP_BEGIN_DECL @@ -43,10 +41,10 @@ LDAP_BEGIN_DECL * As such, the number will be above the old RFC but below * whatever number does finally get assigned */ -#define LDAP_API_VERSION 2003 +#define LDAP_API_VERSION 2004 #define LDAP_VENDOR_NAME "OpenLDAP" /* We'll eventually release as 200 */ -#define LDAP_VENDOR_VERSION 192 +#define LDAP_VENDOR_VERSION 19905 /* OpenLDAP API Features */ #define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION @@ -73,7 +71,7 @@ LDAP_BEGIN_DECL #define LDAP_ROOT_DSE "" #define LDAP_NO_ATTRS "1.1" #define LDAP_ALL_USER_ATTRIBUTES "*" -#define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+" +#define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+" /* OpenLDAP extension */ /* * LDAP_OPTions defined by draft-ldapext-ldap-c-api-02 @@ -82,7 +80,7 @@ LDAP_BEGIN_DECL * 0x4000 - 0x7fff reserved for private and experimental options */ #define LDAP_OPT_API_INFO 0x0000 -#define LDAP_OPT_DESC 0x0001 +#define LDAP_OPT_DESC 0x0001 /* deprecated */ #define LDAP_OPT_DEREF 0x0002 #define LDAP_OPT_SIZELIMIT 0x0003 #define LDAP_OPT_TIMELIMIT 0x0004 @@ -100,22 +98,21 @@ LDAP_BEGIN_DECL #define LDAP_OPT_HOST_NAME 0x0030 #define LDAP_OPT_ERROR_NUMBER 0x0031 #define LDAP_OPT_ERROR_STRING 0x0032 +#define LDAP_OPT_MATCHED_DN 0x0033 -/* 0x33 - 0x0fff not defined by current draft */ +/* 0x34 - 0x0fff not defined by current draft */ -/* extended options - none */ +#define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x4000 /* to 0x7FFF inclusive */ /* private and experimental options */ -#define LDAP_OPT_DNS 0x4001 /* use DN & DNS */ - /* OpenLDAP specific options */ #define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */ #define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */ #define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */ -#define LDAP_OPT_MATCHED_DN 0x5004 /* should have been in draft */ #define LDAP_OPT_NETWORK_TIMEOUT 0x5005 /* socket level timeout */ +#define LDAP_OPT_URI 0x5006 -/* TLS options */ +/* OpenLDAP TLS options */ #define LDAP_OPT_X_TLS_CACERTFILE 0x6001 #define LDAP_OPT_X_TLS_CACERTDIR 0x6002 #define LDAP_OPT_X_TLS_CERT 0x6003 @@ -132,6 +129,11 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_ALLOW 3 #define LDAP_OPT_X_TLS_TRY 4 +/* OpenLDAP SASL options */ +#define LDAP_OPT_X_SASL_MINSSF 0x6100 +#define LDAP_OPT_X_SASL_MAXSSF 0x6101 +#define LDAP_OPT_X_SASL_ACTSSF 0x6102 + /* on/off values */ #define LDAP_OPT_ON ((void *) 1) #define LDAP_OPT_OFF ((void *) 0) @@ -165,16 +167,30 @@ typedef struct ldapcontrol { /* LDAP Controls */ /* chase referrals controls */ #define LDAP_CONTROL_REFERRALS "1.2.840.113666.1.4.616" -#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x0020 -#define LDAP_CHASE_EXTERNAL_REFERRALS 0x0040 +#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x0020U +#define LDAP_CHASE_EXTERNAL_REFERRALS 0x0040U + +#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2" -#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.2.6" +/* Experimental Controls */ + +#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473" +#define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474" +#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" +#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" /* LDAP Unsolicited Notifications */ -#define LDAP_NOTICE_DISCONNECT "1.3.6.1.4.1.1466.20036" +#define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" +#define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION /* LDAP Extended Operations */ +#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" +#define LDAP_EXOP_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.666.6.1" +#define LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) +#define LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U) +#define LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) +#define LDAP_TAG_EXOP_X_MODIFY_PASSWD_GEN ((ber_tag_t) 0x80U) /* * specific LDAP instantiations of BER types we know about @@ -198,115 +214,100 @@ typedef struct ldapcontrol { */ /* general stuff */ -#define LDAP_TAG_MESSAGE (ber_tag_t) 0x30U /* constructed + 16 */ -#define LDAP_TAG_MSGID (ber_tag_t) 0x02U /* integer */ -#define LDAP_TAG_LDAPDN (ber_tag_t) 0x04U /* octect string */ -#define LDAP_TAG_LDAPCRED (ber_tag_t) 0x04U /* octect string */ -#define LDAP_TAG_CONTROLS (ber_tag_t) 0xa0U /* context specific + constructed + 0 */ -#define LDAP_TAG_REFERRAL (ber_tag_t) 0xa3U /* context specific + constructed + 3 */ - -#define LDAP_TAG_NEWSUPERIOR (ber_tag_t) 0x80U /* context-specific + primitive + 0 */ - -#define LDAP_TAG_EXOP_REQ_OID (ber_tag_t) 0x80U /* context specific + primitive */ -#define LDAP_TAG_EXOP_REQ_VALUE (ber_tag_t) 0x81U /* context specific + primitive */ -#define LDAP_TAG_EXOP_RES_OID (ber_tag_t) 0x8aU /* context specific + primitive */ -#define LDAP_TAG_EXOP_RES_VALUE (ber_tag_t) 0x8bU /* context specific + primitive */ +#define LDAP_TAG_MESSAGE ((ber_tag_t) 0x30U) /* constructed + 16 */ +#define LDAP_TAG_MSGID ((ber_tag_t) 0x02U) /* integer */ +#define LDAP_TAG_LDAPDN ((ber_tag_t) 0x04U) /* octect string */ +#define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octect string */ +#define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */ +#define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */ -#define LDAP_TAG_SASL_RES_CREDS (ber_tag_t) 0x87U /* context specific + primitive */ +#define LDAP_TAG_NEWSUPERIOR ((ber_tag_t) 0x80U) /* context-specific + primitive + 0 */ +#define LDAP_TAG_EXOP_REQ_OID ((ber_tag_t) 0x80U) /* context specific + primitive */ +#define LDAP_TAG_EXOP_REQ_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */ +#define LDAP_TAG_EXOP_RES_OID ((ber_tag_t) 0x8aU) /* context specific + primitive */ +#define LDAP_TAG_EXOP_RES_VALUE ((ber_tag_t) 0x8bU) /* context specific + primitive */ +#define LDAP_TAG_SASL_RES_CREDS ((ber_tag_t) 0x87U) /* context specific + primitive */ /* possible operations a client can invoke */ -#define LDAP_REQ_BIND (ber_tag_t) 0x60U /* application + constructed */ -#define LDAP_REQ_UNBIND (ber_tag_t) 0x42U /* application + primitive */ -#define LDAP_REQ_SEARCH (ber_tag_t) 0x63U /* application + constructed */ -#define LDAP_REQ_MODIFY (ber_tag_t) 0x66U /* application + constructed */ -#define LDAP_REQ_ADD (ber_tag_t) 0x68U /* application + constructed */ -#define LDAP_REQ_DELETE (ber_tag_t) 0x4aU /* application + primitive */ -#define LDAP_REQ_MODRDN (ber_tag_t) 0x6cU /* application + constructed */ +#define LDAP_REQ_BIND ((ber_tag_t) 0x60U) /* application + constructed */ +#define LDAP_REQ_UNBIND ((ber_tag_t) 0x42U) /* application + primitive */ +#define LDAP_REQ_SEARCH ((ber_tag_t) 0x63U) /* application + constructed */ +#define LDAP_REQ_MODIFY ((ber_tag_t) 0x66U) /* application + constructed */ +#define LDAP_REQ_ADD ((ber_tag_t) 0x68U) /* application + constructed */ +#define LDAP_REQ_DELETE ((ber_tag_t) 0x4aU) /* application + primitive */ +#define LDAP_REQ_MODRDN ((ber_tag_t) 0x6cU) /* application + constructed */ #define LDAP_REQ_MODDN LDAP_REQ_MODRDN #define LDAP_REQ_RENAME LDAP_REQ_MODRDN -#define LDAP_REQ_COMPARE (ber_tag_t) 0x6eU /* application + constructed */ -#define LDAP_REQ_ABANDON (ber_tag_t) 0x50U /* application + primitive */ -#define LDAP_REQ_EXTENDED (ber_tag_t) 0x77U /* application + constructed */ +#define LDAP_REQ_COMPARE ((ber_tag_t) 0x6eU) /* application + constructed */ +#define LDAP_REQ_ABANDON ((ber_tag_t) 0x50U) /* application + primitive */ +#define LDAP_REQ_EXTENDED ((ber_tag_t) 0x77U) /* application + constructed */ /* possible result types a server can return */ -#define LDAP_RES_BIND (ber_tag_t) 0x61U /* application + constructed */ -#define LDAP_RES_SEARCH_ENTRY (ber_tag_t) 0x64U /* application + constructed */ -#define LDAP_RES_SEARCH_REFERENCE (ber_tag_t) 0x73U /* V3: application + constructed */ -#define LDAP_RES_SEARCH_RESULT (ber_tag_t) 0x65U /* application + constructed */ -#define LDAP_RES_MODIFY (ber_tag_t) 0x67U /* application + constructed */ -#define LDAP_RES_ADD (ber_tag_t) 0x69U /* application + constructed */ -#define LDAP_RES_DELETE (ber_tag_t) 0x6bU /* application + constructed */ -#define LDAP_RES_MODRDN (ber_tag_t) 0x6dU /* application + constructed */ +#define LDAP_RES_BIND ((ber_tag_t) 0x61U) /* application + constructed */ +#define LDAP_RES_SEARCH_ENTRY ((ber_tag_t) 0x64U) /* application + constructed */ +#define LDAP_RES_SEARCH_REFERENCE ((ber_tag_t) 0x73U) /* V3: application + constructed */ +#define LDAP_RES_SEARCH_RESULT ((ber_tag_t) 0x65U) /* application + constructed */ +#define LDAP_RES_MODIFY ((ber_tag_t) 0x67U) /* application + constructed */ +#define LDAP_RES_ADD ((ber_tag_t) 0x69U) /* application + constructed */ +#define LDAP_RES_DELETE ((ber_tag_t) 0x6bU) /* application + constructed */ +#define LDAP_RES_MODRDN ((ber_tag_t) 0x6dU) /* application + constructed */ #define LDAP_RES_MODDN LDAP_RES_MODRDN /* application + constructed */ #define LDAP_RES_RENAME LDAP_RES_MODRDN /* application + constructed */ -#define LDAP_RES_COMPARE (ber_tag_t) 0x6fU /* application + constructed */ -#define LDAP_RES_EXTENDED (ber_tag_t) 0x78U /* V3: application + constructed */ -#define LDAP_RES_ANY ((ber_tag_t)(~0)) +#define LDAP_RES_COMPARE ((ber_tag_t) 0x6fU) /* application + constructed */ +#define LDAP_RES_EXTENDED ((ber_tag_t) 0x78U) /* V3: application + constructed */ +#define LDAP_RES_EXTENDED_PARTIAL ((ber_tag_t) 0x79U) /* V3+: application + constructed */ + +#define LDAP_RES_ANY ((ber_tag_t)(-1)) +#define LDAP_RES_UNSOLICITED ((ber_tag_t)(0)) /* sasl methods */ #define LDAP_SASL_SIMPLE NULL /* authentication methods available */ -#define LDAP_AUTH_NONE (ber_tag_t) 0x00U /* no authentication */ -#define LDAP_AUTH_SIMPLE (ber_tag_t) 0x80U /* context specific + primitive */ -#define LDAP_AUTH_SASL (ber_tag_t) 0xa3U /* context specific + primitive */ -#define LDAP_AUTH_KRBV4 (ber_tag_t) 0xffU /* means do both of the following */ -#define LDAP_AUTH_KRBV41 (ber_tag_t) 0x81U /* context specific + primitive */ -#define LDAP_AUTH_KRBV42 (ber_tag_t) 0x82U /* context specific + primitive */ +#define LDAP_AUTH_NONE ((ber_tag_t) 0x00U) /* no authentication */ +#define LDAP_AUTH_SIMPLE ((ber_tag_t) 0x80U) /* context specific + primitive */ +#define LDAP_AUTH_SASL ((ber_tag_t) 0xa3U) /* context specific + primitive */ +#define LDAP_AUTH_KRBV4 ((ber_tag_t) 0xffU) /* means do both of the following */ +#define LDAP_AUTH_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */ +#define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* context specific + primitive */ /* filter types */ -#define LDAP_FILTER_AND (ber_tag_t) 0xa0U /* context specific + constructed */ -#define LDAP_FILTER_OR (ber_tag_t) 0xa1U /* context specific + constructed */ -#define LDAP_FILTER_NOT (ber_tag_t) 0xa2U /* context specific + constructed */ -#define LDAP_FILTER_EQUALITY (ber_tag_t) 0xa3U /* context specific + constructed */ -#define LDAP_FILTER_SUBSTRINGS (ber_tag_t) 0xa4U /* context specific + constructed */ -#define LDAP_FILTER_GE (ber_tag_t) 0xa5U /* context specific + constructed */ -#define LDAP_FILTER_LE (ber_tag_t) 0xa6U /* context specific + constructed */ -#define LDAP_FILTER_PRESENT (ber_tag_t) 0x87U /* context specific + primitive */ -#define LDAP_FILTER_APPROX (ber_tag_t) 0xa8U /* context specific + constructed */ -#define LDAP_FILTER_EXT (ber_tag_t) 0xa9U /* context specific + constructed */ +#define LDAP_FILTER_AND ((ber_tag_t) 0xa0U) /* context specific + constructed */ +#define LDAP_FILTER_OR ((ber_tag_t) 0xa1U) /* context specific + constructed */ +#define LDAP_FILTER_NOT ((ber_tag_t) 0xa2U) /* context specific + constructed */ +#define LDAP_FILTER_EQUALITY ((ber_tag_t) 0xa3U) /* context specific + constructed */ +#define LDAP_FILTER_SUBSTRINGS ((ber_tag_t) 0xa4U) /* context specific + constructed */ +#define LDAP_FILTER_GE ((ber_tag_t) 0xa5U) /* context specific + constructed */ +#define LDAP_FILTER_LE ((ber_tag_t) 0xa6U) /* context specific + constructed */ +#define LDAP_FILTER_PRESENT ((ber_tag_t) 0x87U) /* context specific + primitive */ +#define LDAP_FILTER_APPROX ((ber_tag_t) 0xa8U) /* context specific + constructed */ +#define LDAP_FILTER_EXT ((ber_tag_t) 0xa9U) /* context specific + constructed */ /* extended filter component types */ -#define LDAP_FILTER_EXT_OID (ber_tag_t) 0x81U /* context specific */ -#define LDAP_FILTER_EXT_TYPE (ber_tag_t) 0x82U /* context specific */ -#define LDAP_FILTER_EXT_VALUE (ber_tag_t) 0x83U /* context specific */ -#define LDAP_FILTER_EXT_DNATTRS (ber_tag_t) 0x84U /* context specific */ +#define LDAP_FILTER_EXT_OID ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_FILTER_EXT_TYPE ((ber_tag_t) 0x82U) /* context specific */ +#define LDAP_FILTER_EXT_VALUE ((ber_tag_t) 0x83U) /* context specific */ +#define LDAP_FILTER_EXT_DNATTRS ((ber_tag_t) 0x84U) /* context specific */ /* substring filter component types */ -#define LDAP_SUBSTRING_INITIAL (ber_tag_t) 0x80U /* context specific */ -#define LDAP_SUBSTRING_ANY (ber_tag_t) 0x81U /* context specific */ -#define LDAP_SUBSTRING_FINAL (ber_tag_t) 0x82U /* context specific */ +#define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ +#define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ /* search scopes */ -#define LDAP_SCOPE_BASE (ber_int_t) 0x0000 -#define LDAP_SCOPE_ONELEVEL (ber_int_t) 0x0001 -#define LDAP_SCOPE_SUBTREE (ber_int_t) 0x0002 +#define LDAP_SCOPE_BASE ((ber_int_t) 0x0000) +#define LDAP_SCOPE_ONELEVEL ((ber_int_t) 0x0001) +#define LDAP_SCOPE_SUBTREE ((ber_int_t) 0x0002) -/* for modifications */ -typedef struct ldapmod { - int mod_op; -#define LDAP_MOD_ADD (ber_int_t) 0x0000 -#define LDAP_MOD_DELETE (ber_int_t) 0x0001 -#define LDAP_MOD_REPLACE (ber_int_t) 0x0002 -#define LDAP_MOD_BVALUES (ber_int_t) 0x0080 -/* IMPORTANT: do not use code 0x1000 (or above), - * it is used internally by the backends! - * (see ldap/servers/slapd/slap.h) - * JCG 05/1999 (gomez@engr.sgi.com) - */ - char *mod_type; - union mod_vals_u { - char **modv_strvals; - struct berval **modv_bvals; - } mod_vals; -#define mod_values mod_vals.modv_strvals -#define mod_bvalues mod_vals.modv_bvals -} LDAPMod; +/* substring filter component types */ +#define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ +#define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ /* * possible error codes we can return @@ -404,6 +405,28 @@ typedef struct ldapmod { typedef struct ldapmsg LDAPMessage; +/* for modifications */ +typedef struct ldapmod { + int mod_op; + +#define LDAP_MOD_ADD ((ber_int_t) 0x0000) +#define LDAP_MOD_DELETE ((ber_int_t) 0x0001) +#define LDAP_MOD_REPLACE ((ber_int_t) 0x0002) +#define LDAP_MOD_BVALUES ((ber_int_t) 0x0080) +/* IMPORTANT: do not use code 0x1000 (or above), + * it is used internally by the backends! + * (see ldap/servers/slapd/slap.h) + */ + + char *mod_type; + union mod_vals_u { + char **modv_strvals; + struct berval **modv_bvals; + } mod_vals; +#define mod_values mod_vals.modv_strvals +#define mod_bvalues mod_vals.modv_bvals +} LDAPMod; + /* * structures for ldap getfilter routines */ @@ -411,8 +434,8 @@ typedef struct ldapmsg LDAPMessage; typedef struct ldap_filt_info { char *lfi_filter; char *lfi_desc; - int lfi_scope; /* LDAP_SCOPE_BASE, etc */ - int lfi_isexact; /* exact match filter? */ + int lfi_scope; + int lfi_isexact; struct ldap_filt_info *lfi_next; } LDAPFiltInfo; @@ -441,9 +464,10 @@ typedef struct ldap_filt_desc { /* - * structure representing an ldap connection + * structure representing an ldap session which can + * encompass connections to multiple servers (in the + * face of referrals). */ - typedef struct ldap LDAP; #define LDAP_DEREF_NEVER 0x00 @@ -471,21 +495,22 @@ typedef struct ldap_friendly { * types for ldap URL handling */ typedef struct ldap_url_desc { - int lud_ldaps; + struct ldap_url_desc *lud_next; + char *lud_scheme; char *lud_host; int lud_port; char *lud_dn; char **lud_attrs; int lud_scope; char *lud_filter; - char **lud_exts; + char **lud_exts; } LDAPURLDesc; #define LDAP_URL_SUCCESS 0x00 /* Success */ #define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ #define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ -#define LDAP_URL_ERR_NOTLDAP 0x03 /* URL doesn't begin with "ldap[s]://" */ +#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ #define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ #define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ #define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ @@ -496,42 +521,67 @@ typedef struct ldap_url_desc { /* * The API draft spec says we should declare (or cause to be declared) - * 'struct timeval'. We don't. See LDAPext discussions. + * 'struct timeval'. We don't. See IETF LDAPext discussions. */ struct timeval; /* * in options.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_get_option LDAP_P(( - LDAP_CONST LDAP *ld, + LDAP *ld, int option, void *outvalue)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_set_option LDAP_P(( LDAP *ld, int option, LDAP_CONST void *invalue)); +/* V3 REBIND Function Callback Prototype */ +typedef int (LDAP_REBIND_PROC) LDAP_P(( + LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid )); + +LIBLDAP_F( int ) +ldap_set_rebind_proc LDAP_P(( + LDAP *ld, + LDAP_REBIND_PROC *ldap_proc)); /* * in controls.c: */ -LDAP_F( void ) +LIBLDAP_F( void ) ldap_control_free LDAP_P(( LDAPControl *ctrl )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_controls_free LDAP_P(( LDAPControl **ctrls )); - +/* + * in dnssrv.c: + */ +LIBLDAP_F( int ) +ldap_domain2dn LDAP_P(( + LDAP_CONST char* domain, + char** dn )); + +LIBLDAP_F( int ) +ldap_dn2domain LDAP_P(( + LDAP_CONST char* dn, + char** domain )); + +LIBLDAP_F( int ) +ldap_domain2hostlist LDAP_P(( + LDAP_CONST char *domain, + char** hostlist )); + /* * in extended.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_extended_operation LDAP_P(( LDAP *ld, LDAP_CONST char *reqoid, @@ -540,7 +590,7 @@ ldap_extended_operation LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_extended_operation_s LDAP_P(( LDAP *ld, LDAP_CONST char *reqoid, @@ -550,7 +600,7 @@ ldap_extended_operation_s LDAP_P(( char **retoidp, struct berval **retdatap )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_parse_extended_result LDAP_P(( LDAP *ld, LDAPMessage *res, @@ -561,12 +611,12 @@ ldap_parse_extended_result LDAP_P(( /* * in abandon.c: */ -LDAP_F( int ) -ldap_abandon LDAP_P(( +LIBLDAP_F( int ) +ldap_abandon LDAP_P(( /* deprecated */ LDAP *ld, int msgid )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_abandon_ext LDAP_P(( LDAP *ld, int msgid, @@ -577,7 +627,7 @@ ldap_abandon_ext LDAP_P(( /* * in add.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_add_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -586,7 +636,7 @@ ldap_add_ext LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_add_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -594,14 +644,14 @@ ldap_add_ext_s LDAP_P(( LDAPControl **serverctrls, LDAPControl **clientctrls )); -LDAP_F( int ) -ldap_add LDAP_P(( +LIBLDAP_F( int ) +ldap_add LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )); -LDAP_F( int ) -ldap_add_s LDAP_P(( +LIBLDAP_F( int ) +ldap_add_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )); @@ -610,7 +660,7 @@ ldap_add_s LDAP_P(( /* * in sasl.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_sasl_bind LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -620,7 +670,18 @@ ldap_sasl_bind LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) +ldap_negotiated_sasl_bind_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *authenticationId, + LDAP_CONST char *authorizationId, /* usually NULL */ + LDAP_CONST char *saslMechanism, + struct berval *passPhrase, + LDAPControl **serverControls, + LDAPControl **clientControls )); + +LIBLDAP_F( int ) ldap_sasl_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -630,7 +691,7 @@ ldap_sasl_bind_s LDAP_P(( LDAPControl **clientctrls, struct berval **servercredp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_parse_sasl_bind_result LDAP_P(( LDAP *ld, LDAPMessage *res, @@ -641,41 +702,30 @@ ldap_parse_sasl_bind_result LDAP_P(( * in bind.c: * (deprecated) */ -LDAP_F( int ) -ldap_bind LDAP_P(( +LIBLDAP_F( int ) +ldap_bind LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *passwd, int authmethod )); -LDAP_F( int ) -ldap_bind_s LDAP_P(( +LIBLDAP_F( int ) +ldap_bind_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *cred, int authmethod )); -LDAP_F( void ) -ldap_set_rebind_proc LDAP_P(( - LDAP *ld, - int (*rebindproc) LDAP_P(( - LDAP *ld, - char **dnp, - char **passwdp, - int *authmethodp, - int freeit )))); - - /* * in sbind.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_simple_bind LDAP_P(( LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *passwd )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_simple_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *who, @@ -686,28 +736,28 @@ ldap_simple_bind_s LDAP_P(( * in kbind.c: * (deprecated) */ -LDAP_F( int ) -ldap_kerberos_bind_s LDAP_P(( +LIBLDAP_F( int ) +ldap_kerberos_bind_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who )); -LDAP_F( int ) -ldap_kerberos_bind1 LDAP_P(( +LIBLDAP_F( int ) +ldap_kerberos_bind1 LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who )); -LDAP_F( int ) -ldap_kerberos_bind1_s LDAP_P(( +LIBLDAP_F( int ) +ldap_kerberos_bind1_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who )); -LDAP_F( int ) -ldap_kerberos_bind2 LDAP_P(( +LIBLDAP_F( int ) +ldap_kerberos_bind2 LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who )); -LDAP_F( int ) -ldap_kerberos_bind2_s LDAP_P(( +LIBLDAP_F( int ) +ldap_kerberos_bind2_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *who )); @@ -715,32 +765,32 @@ ldap_kerberos_bind2_s LDAP_P(( * in cache.c * (deprecated) */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_enable_cache LDAP_P(( LDAP *ld, long timeout, ber_len_t maxmem )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_disable_cache LDAP_P(( LDAP *ld )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_set_cache_options LDAP_P(( LDAP *ld, unsigned long opts )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_destroy_cache LDAP_P(( LDAP *ld )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_flush_cache LDAP_P(( LDAP *ld )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_uncache_entry LDAP_P(( LDAP *ld, LDAP_CONST char *dn )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_uncache_request LDAP_P(( LDAP *ld, int msgid )); /* * in compare.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_compare_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -750,7 +800,7 @@ ldap_compare_ext LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_compare_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -759,15 +809,15 @@ ldap_compare_ext_s LDAP_P(( LDAPControl **serverctrls, LDAPControl **clientctrls )); -LDAP_F( int ) -ldap_compare LDAP_P(( +LIBLDAP_F( int ) +ldap_compare LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, LDAP_CONST char *value )); -LDAP_F( int ) -ldap_compare_s LDAP_P(( +LIBLDAP_F( int ) +ldap_compare_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, @@ -777,7 +827,7 @@ ldap_compare_s LDAP_P(( /* * in delete.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_delete_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -785,20 +835,20 @@ ldap_delete_ext LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_delete_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAPControl **serverctrls, LDAPControl **clientctrls )); -LDAP_F( int ) -ldap_delete LDAP_P(( +LIBLDAP_F( int ) +ldap_delete LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn )); -LDAP_F( int ) -ldap_delete_s LDAP_P(( +LIBLDAP_F( int ) +ldap_delete_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn )); @@ -806,7 +856,7 @@ ldap_delete_s LDAP_P(( /* * in error.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_parse_result LDAP_P(( LDAP *ld, LDAPMessage *res, @@ -817,17 +867,17 @@ ldap_parse_result LDAP_P(( LDAPControl ***serverctrls, int freeit )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_err2string LDAP_P(( int err )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_result2error LDAP_P(( /* deprecated */ LDAP *ld, LDAPMessage *r, int freeit )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_perror LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *s )); @@ -836,7 +886,7 @@ ldap_perror LDAP_P(( /* deprecated */ /* * in modify.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_modify_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -845,7 +895,7 @@ ldap_modify_ext LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_modify_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -853,14 +903,14 @@ ldap_modify_ext_s LDAP_P(( LDAPControl **serverctrls, LDAPControl **clientctrls )); -LDAP_F( int ) -ldap_modify LDAP_P(( +LIBLDAP_F( int ) +ldap_modify LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )); -LDAP_F( int ) -ldap_modify_s LDAP_P(( +LIBLDAP_F( int ) +ldap_modify_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )); @@ -869,28 +919,28 @@ ldap_modify_s LDAP_P(( /* * in modrdn.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_rename LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, LDAP_CONST char *newSuperior, + int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_rename_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, LDAP_CONST char *newSuperior, + int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_rename_ext LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -901,7 +951,7 @@ ldap_rename_ext LDAP_P(( LDAPControl **clientctrls, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_rename_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, @@ -911,43 +961,43 @@ ldap_rename_ext_s LDAP_P(( LDAPControl **serverctrls, LDAPControl **clientctrls )); -LDAP_F( int ) -ldap_rename2 LDAP_P(( +LIBLDAP_F( int ) +ldap_rename2 LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, - LDAP_CONST char *newSuperior )); + LDAP_CONST char *newSuperior, + int deleteoldrdn )); -LDAP_F( int ) -ldap_rename2_s LDAP_P(( +LIBLDAP_F( int ) +ldap_rename2_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, - LDAP_CONST char *newSuperior)); + LDAP_CONST char *newSuperior, + int deleteoldrdn )); -LDAP_F( int ) -ldap_modrdn LDAP_P(( +LIBLDAP_F( int ) +ldap_modrdn LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )); -LDAP_F( int ) -ldap_modrdn_s LDAP_P(( +LIBLDAP_F( int ) +ldap_modrdn_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )); -LDAP_F( int ) -ldap_modrdn2 LDAP_P(( +LIBLDAP_F( int ) +ldap_modrdn2 LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn )); -LDAP_F( int ) -ldap_modrdn2_s LDAP_P(( +LIBLDAP_F( int ) +ldap_modrdn2_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, @@ -957,31 +1007,45 @@ ldap_modrdn2_s LDAP_P(( /* * in open.c: */ -LDAP_F( LDAP *) -ldap_open LDAP_P(( +LIBLDAP_F( LDAP *) +ldap_open LDAP_P(( /* deprecated */ LDAP_CONST char *host, int port )); -LDAP_F( LDAP *) +LIBLDAP_F( LDAP *) ldap_init LDAP_P(( LDAP_CONST char *host, int port )); +LIBLDAP_F( int ) +ldap_create LDAP_P(( + LDAP **ldp )); + +LIBLDAP_F( int ) +ldap_initialize LDAP_P(( + LDAP **ldp, + LDAP_CONST char *url )); + +LIBLDAP_F( int ) +ldap_start_tls LDAP_P(( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); /* * in messages.c: */ -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_first_message LDAP_P(( LDAP *ld, LDAPMessage *chain )); -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_next_message LDAP_P(( LDAP *ld, LDAPMessage *msg )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_count_messages LDAP_P(( LDAP *ld, LDAPMessage *chain )); @@ -990,22 +1054,22 @@ ldap_count_messages LDAP_P(( /* * in references.c: */ -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_first_reference LDAP_P(( LDAP *ld, LDAPMessage *chain )); -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_next_reference LDAP_P(( LDAP *ld, LDAPMessage *ref )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_count_references LDAP_P(( LDAP *ld, LDAPMessage *chain )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_parse_reference LDAP_P(( LDAP *ld, LDAPMessage *ref, @@ -1017,22 +1081,22 @@ ldap_parse_reference LDAP_P(( /* * in getentry.c: */ -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_first_entry LDAP_P(( LDAP *ld, LDAPMessage *chain )); -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_next_entry LDAP_P(( LDAP *ld, LDAPMessage *entry )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_count_entries LDAP_P(( LDAP *ld, LDAPMessage *chain )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_get_entry_controls LDAP_P(( LDAP *ld, LDAPMessage *entry, @@ -1042,12 +1106,12 @@ ldap_get_entry_controls LDAP_P(( /* * in addentry.c */ -LDAP_F( LDAPMessage *) +LIBLDAP_F( LDAPMessage *) ldap_delete_result_entry LDAP_P(( LDAPMessage **list, LDAPMessage *e )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_add_result_entry LDAP_P(( LDAPMessage **list, LDAPMessage *e )); @@ -1056,56 +1120,53 @@ ldap_add_result_entry LDAP_P(( /* * in getdn.c */ -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_get_dn LDAP_P(( LDAP *ld, LDAPMessage *entry )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_dn2ufn LDAP_P(( LDAP_CONST char *dn )); -LDAP_F( char ** ) +LIBLDAP_F( char ** ) ldap_explode_dn LDAP_P(( LDAP_CONST char *dn, int notypes )); -LDAP_F( char ** ) +LIBLDAP_F( char ** ) ldap_explode_rdn LDAP_P(( LDAP_CONST char *rdn, int notypes )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_parent_dn LDAP_P(( LDAP_CONST char *dn )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_relative_dn LDAP_P(( LDAP_CONST char *dn )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_normalize_dn LDAP_P(( LDAP_CONST char *dn )); -LDAP_F( char ** ) -ldap_explode_dns LDAP_P(( /* deprecated */ - LDAP_CONST char *dn )); - -LDAP_F( int ) -ldap_is_dns_dn LDAP_P(( /* deprecated */ - LDAP_CONST char *dn )); +LIBLDAP_F( char * ) +ldap_dn2dcedn LDAP_P(( LDAP_CONST char *dn )); /* deprecated */ +LIBLDAP_F( char * ) +ldap_dcedn2dn LDAP_P(( LDAP_CONST char *dce )); /* deprecated */ /* * in getattr.c */ -LDAP_F( char *) +LIBLDAP_F( char *) ldap_first_attribute LDAP_P(( LDAP *ld, LDAPMessage *entry, BerElement **ber )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_next_attribute LDAP_P(( LDAP *ld, LDAPMessage *entry, @@ -1115,38 +1176,38 @@ ldap_next_attribute LDAP_P(( /* * in getvalues.c */ -LDAP_F( char **) +LIBLDAP_F( char **) ldap_get_values LDAP_P(( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target )); -LDAP_F( struct berval **) +LIBLDAP_F( struct berval **) ldap_get_values_len LDAP_P(( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_count_values LDAP_P(( char **vals )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_count_values_len LDAP_P(( struct berval **vals )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_value_free LDAP_P(( char **vals )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_value_free_len LDAP_P(( struct berval **vals )); /* * in result.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_result LDAP_P(( LDAP *ld, int msgid, @@ -1154,19 +1215,19 @@ ldap_result LDAP_P(( struct timeval *timeout, LDAPMessage **result )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_msgtype LDAP_P(( LDAPMessage *lm )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_msgid LDAP_P(( LDAPMessage *lm )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_msgfree LDAP_P(( LDAPMessage *lm )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_msgdelete LDAP_P(( LDAP *ld, int msgid )); @@ -1175,7 +1236,7 @@ ldap_msgdelete LDAP_P(( /* * in search.c: */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_search_ext LDAP_P(( LDAP *ld, LDAP_CONST char *base, @@ -1189,7 +1250,7 @@ ldap_search_ext LDAP_P(( int sizelimit, int *msgidp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_search_ext_s LDAP_P(( LDAP *ld, LDAP_CONST char *base, @@ -1203,8 +1264,8 @@ ldap_search_ext_s LDAP_P(( int sizelimit, LDAPMessage **res )); -LDAP_F( int ) -ldap_search LDAP_P(( +LIBLDAP_F( int ) +ldap_search LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *base, int scope, @@ -1212,8 +1273,8 @@ ldap_search LDAP_P(( char **attrs, int attrsonly )); -LDAP_F( int ) -ldap_search_s LDAP_P(( +LIBLDAP_F( int ) +ldap_search_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *base, int scope, @@ -1222,8 +1283,8 @@ ldap_search_s LDAP_P(( int attrsonly, LDAPMessage **res )); -LDAP_F( int ) -ldap_search_st LDAP_P(( +LIBLDAP_F( int ) +ldap_search_st LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *base, int scope, @@ -1235,10 +1296,11 @@ ldap_search_st LDAP_P(( /* - * in ufn.c + * in ufn.c + * (deprecated) */ -LDAP_F( int ) -ldap_ufn_search_c LDAP_P(( +LIBLDAP_F( int ) +ldap_ufn_search_c LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *ufn, char **attrs, @@ -1247,8 +1309,8 @@ ldap_ufn_search_c LDAP_P(( int (*cancelproc)( void *cl ), void *cancelparm )); -LDAP_F( int ) -ldap_ufn_search_ct LDAP_P(( +LIBLDAP_F( int ) +ldap_ufn_search_ct LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *ufn, char **attrs, @@ -1260,47 +1322,47 @@ ldap_ufn_search_ct LDAP_P(( char *tag2, char *tag3 )); -LDAP_F( int ) -ldap_ufn_search_s LDAP_P(( +LIBLDAP_F( int ) +ldap_ufn_search_s LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *ufn, char **attrs, int attrsonly, LDAPMessage **res )); -LDAP_F( LDAPFiltDesc *) -ldap_ufn_setfilter LDAP_P(( +LIBLDAP_F( LDAPFiltDesc *) +ldap_ufn_setfilter LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *fname )); -LDAP_F( void ) -ldap_ufn_setprefix LDAP_P(( +LIBLDAP_F( void ) +ldap_ufn_setprefix LDAP_P(( /* deprecated */ LDAP *ld, LDAP_CONST char *prefix )); -LDAP_F( int ) -ldap_ufn_timeout LDAP_P(( +LIBLDAP_F( int ) +ldap_ufn_timeout LDAP_P(( /* deprecated */ void *tvparam )); /* * in unbind.c */ -LDAP_F( int ) -ldap_unbind LDAP_P(( +LIBLDAP_F( int ) +ldap_unbind LDAP_P(( /* deprecated */ LDAP *ld )); -LDAP_F( int ) -ldap_unbind_s LDAP_P(( +LIBLDAP_F( int ) +ldap_unbind_s LDAP_P(( /* deprecated */ LDAP *ld )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_unbind_ext LDAP_P(( LDAP *ld, LDAPControl **serverctrls, LDAPControl **clientctrls)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_unbind_ext_s LDAP_P(( LDAP *ld, LDAPControl **serverctrls, @@ -1308,34 +1370,35 @@ ldap_unbind_ext_s LDAP_P(( /* * in getfilter.c + * (deprecated) */ -LDAP_F( LDAPFiltDesc *) -ldap_init_getfilter LDAP_P(( +LIBLDAP_F( LDAPFiltDesc *) +ldap_init_getfilter LDAP_P(( /* deprecated */ LDAP_CONST char *fname )); -LDAP_F( LDAPFiltDesc *) -ldap_init_getfilter_buf LDAP_P(( +LIBLDAP_F( LDAPFiltDesc *) +ldap_init_getfilter_buf LDAP_P(( /* deprecated */ /* LDAP_CONST */ char *buf, ber_len_t buflen )); -LDAP_F( LDAPFiltInfo *) -ldap_getfirstfilter LDAP_P(( +LIBLDAP_F( LDAPFiltInfo *) +ldap_getfirstfilter LDAP_P(( /* deprecated */ LDAPFiltDesc *lfdp, /* LDAP_CONST */ char *tagpat, /* LDAP_CONST */ char *value )); -LDAP_F( LDAPFiltInfo *) -ldap_getnextfilter LDAP_P(( +LIBLDAP_F( LDAPFiltInfo *) +ldap_getnextfilter LDAP_P(( /* deprecated */ LDAPFiltDesc *lfdp )); -LDAP_F( void ) -ldap_setfilteraffixes LDAP_P(( +LIBLDAP_F( void ) +ldap_setfilteraffixes LDAP_P(( /* deprecated */ LDAPFiltDesc *lfdp, LDAP_CONST char *prefix, LDAP_CONST char *suffix )); -LDAP_F( void ) -ldap_build_filter LDAP_P(( +LIBLDAP_F( void ) +ldap_build_filter LDAP_P(( /* deprecated */ char *buf, ber_len_t buflen, LDAP_CONST char *pattern, @@ -1350,37 +1413,37 @@ ldap_build_filter LDAP_P(( * in free.c */ -LDAP_F( void * ) +LIBLDAP_F( void * ) ldap_memalloc LDAP_P(( ber_len_t s )); -LDAP_F( void * ) +LIBLDAP_F( void * ) ldap_memrealloc LDAP_P(( void* p, ber_len_t s )); -LDAP_F( void * ) +LIBLDAP_F( void * ) ldap_memcalloc LDAP_P(( ber_len_t n, ber_len_t s )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_memfree LDAP_P(( void* p )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_memvfree LDAP_P(( void** v )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_strdup LDAP_P(( LDAP_CONST char * )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_getfilter_free LDAP_P(( LDAPFiltDesc *lfdp )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_mods_free LDAP_P(( LDAPMod **mods, int freemods )); @@ -1388,32 +1451,35 @@ ldap_mods_free LDAP_P(( /* * in friendly.c + * (deprecated) */ -LDAP_F( char * ) -ldap_friendly_name LDAP_P(( +LIBLDAP_F( char * ) +ldap_friendly_name LDAP_P(( /* deprecated */ LDAP_CONST char *filename, /* LDAP_CONST */ char *uname, LDAPFriendlyMap **map )); -LDAP_F( void ) -ldap_free_friendlymap LDAP_P(( +LIBLDAP_F( void ) +ldap_free_friendlymap LDAP_P(( /* deprecated */ LDAPFriendlyMap **map )); /* * in cldap.c + * (deprecated) */ -LDAP_F( LDAP * ) -cldap_open LDAP_P(( +LIBLDAP_F( LDAP * ) +cldap_open LDAP_P(( /* deprecated */ LDAP_CONST char *host, int port )); -LDAP_F( void ) -cldap_close LDAP_P(( +LIBLDAP_F( void ) +cldap_close LDAP_P(( /* deprecated */ LDAP *ld )); -LDAP_F( int ) -cldap_search_s LDAP_P(( LDAP *ld, +LIBLDAP_F( int ) +cldap_search_s LDAP_P(( /* deprecated */ + LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, @@ -1422,8 +1488,8 @@ cldap_search_s LDAP_P(( LDAP *ld, LDAPMessage **res, char *logdn )); -LDAP_F( void ) -cldap_setretryinfo LDAP_P(( +LIBLDAP_F( void ) +cldap_setretryinfo LDAP_P(( /* deprecated */ LDAP *ld, int tries, int timeout )); @@ -1432,19 +1498,27 @@ cldap_setretryinfo LDAP_P(( /* * in sort.c */ -LDAP_F( int ) +typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( + LDAP_CONST char *left, + LDAP_CONST char *right )); + +typedef int (LDAP_SORT_AV_CMP_PROC) LDAP_P(( + LDAP_CONST void *left, + LDAP_CONST void *right )); + +LIBLDAP_F( int ) ldap_sort_entries LDAP_P(( LDAP *ld, LDAPMessage **chain, LDAP_CONST char *attr, - int (*cmp) (LDAP_CONST char *, LDAP_CONST char *) )); + LDAP_SORT_AD_CMP_PROC *cmp )); -LDAP_F( int ) +LIBLDAP_F( int ) /* deprecated */ ldap_sort_values LDAP_P(( LDAP *ld, char **vals, - int (*cmp) (LDAP_CONST void *, LDAP_CONST void *) )); + LDAP_SORT_AV_CMP_PROC *cmp )); -LDAP_F( int ) +LIBLDAP_F( int ) /* deprecated */ ldap_sort_strcasecmp LDAP_P(( LDAP_CONST void *a, LDAP_CONST void *b )); @@ -1455,37 +1529,41 @@ ldap_sort_strcasecmp LDAP_P(( * * need _ext varients */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_is_ldap_url LDAP_P(( LDAP_CONST char *url )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_is_ldaps_url LDAP_P(( LDAP_CONST char *url )); -LDAP_F( int ) +LIBLDAP_F( int ) +ldap_is_ldapi_url LDAP_P(( + LDAP_CONST char *url )); + +LIBLDAP_F( int ) ldap_url_parse LDAP_P(( LDAP_CONST char *url, LDAPURLDesc **ludpp )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_free_urldesc LDAP_P(( LDAPURLDesc *ludp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_url_search LDAP_P(( LDAP *ld, LDAP_CONST char *url, int attrsonly )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_url_search_s LDAP_P(( LDAP *ld, LDAP_CONST char *url, int attrsonly, LDAPMessage **res )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_url_search_st LDAP_P(( LDAP *ld, LDAP_CONST char *url, @@ -1493,49 +1571,75 @@ ldap_url_search_st LDAP_P(( struct timeval *timeout, LDAPMessage **res )); - +/* + * in sortctrl.c + */ /* - * in charset.c - * DEPRECATED + * structure for a sort-key */ -LDAP_F( void ) -ldap_set_string_translators LDAP_P(( - LDAP *ld, - BERTranslateProc encode_proc, - BERTranslateProc decode_proc )); - -LDAP_F( int ) -ldap_translate_from_t61 LDAP_P(( - LDAP *ld, - char **bufp, - ber_len_t *lenp, - int free_input )); +typedef struct ldapsortkey { + char * attributeType; + char * orderingRule; + int reverseOrder; +} LDAPSortKey; + +LIBLDAP_F( int ) +ldap_create_sort_keylist LDAP_P(( + LDAPSortKey ***sortKeyList, + char *keyString )); + +LIBLDAP_F( void ) +ldap_free_sort_keylist LDAP_P(( + LDAPSortKey **sortkeylist )); + +LIBLDAP_F( int ) +ldap_create_sort_control LDAP_P(( + LDAP *ld, + LDAPSortKey **keyList, + int ctl_iscritical, + LDAPControl **ctrlp )); + +LIBLDAP_F( int ) +ldap_parse_sort_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp, + unsigned long *result, + char **attribute )); -LDAP_F( int ) -ldap_translate_to_t61 LDAP_P(( - LDAP *ld, - char **bufp, - ber_len_t *lenp, - int free_input )); -LDAP_F( void ) -ldap_enable_translation LDAP_P(( - LDAP *ld, - LDAPMessage *entry, - int enable )); +/* + * in vlvctrl.c + */ -LDAP_F( int ) -ldap_t61_to_8859 LDAP_P(( - char **bufp, - ber_len_t *buflenp, - int free_input )); +/* + * structure for virtul list. + */ +typedef struct ldapvlvinfo { + int ldvlv_version; + unsigned long ldvlv_before_count; + unsigned long ldvlv_after_count; + unsigned long ldvlv_offset; + unsigned long ldvlv_count; + struct berval *ldvlv_attrvalue; + struct berval *ldvlv_context; + void *ldvlv_extradata; +} LDAPVLVInfo; + +LIBLDAP_F( int ) +ldap_create_vlv_control LDAP_P(( + LDAP *ld, + LDAPVLVInfo *ldvlistp, + LDAPControl **ctrlp )); + +LIBLDAP_F( int ) +ldap_parse_vlv_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrls, + unsigned long *target_posp, + unsigned long *list_countp, + struct berval **contextp, + int *errcodep )); -LDAP_F( int ) -ldap_8859_to_t61 LDAP_P(( - char **bufp, - ber_len_t *buflenp, - int free_input )); LDAP_END_DECL - #endif /* _LDAP_H */ diff --git a/include/ldap_cdefs.h b/include/ldap_cdefs.h index dc5722d82e..c4e78b4cc2 100644 --- a/include/ldap_cdefs.h +++ b/include/ldap_cdefs.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -48,14 +48,6 @@ #endif /* no prototypes */ -#if _WIN32 && _DLL -# define LDAP_F_IMPORT extern __declspec( dllimport ) -# define LDAP_F_EXPORT extern __declspec( dllexport ) -#else -# define LDAP_F_IMPORT extern -# define LDAP_F_EXPORT extern -#endif - #if (__GNUC__) * 1000 + (__GNUC_MINOR__) >= 2006 # define LDAP_GCCATTR(attrs) __attribute__(attrs) #else @@ -63,16 +55,67 @@ #endif -#endif /* _LDAP_CDEFS_H */ +/* Support for NT dynamic libraries. */ + +/* + * C library. Mingw32 links with the C run-time library by default, + * so the explicit definition of CSTATIC will keep dllimport from + * being defined. + */ +#if (defined(__MINGW32__) && !defined(CSTATIC) || \ + defined(_WIN32) && defined(_DLL)) +# define LIBC_F(type) extern __declspec(dllimport) type +#else +# define LIBC_F(type) extern type +#endif -/* purposely allow these to be redefined */ -#ifndef LDAP_F_PRE -# define LDAP_F_PRE LDAP_F_IMPORT +/* AVL library */ +#if defined(LIBAVL_DECL) && defined(_WIN32) +# define LIBAVL_F(type) extern __declspec(LIBAVL_DECL) type +#else +# define LIBAVL_F(type) extern type #endif -#ifndef LDAP_F_POST -# define LDAP_F_POST /* no post */ + +/* LBER library */ +#if defined(LIBLBER_DECL) && defined(_WIN32) +# define LIBLBER_F(type) extern __declspec(LIBLBER_DECL) type +#else +# define LIBLBER_F(type) extern type #endif -#ifndef LDAP_F -#define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST + +/* LDAP library */ +#if defined(LIBLDAP_DECL) && defined(_WIN32) +# define LIBLDAP_F(type) extern __declspec(LIBLDAP_DECL) type +#else +# define LIBLDAP_F(type) extern type #endif +/* LDBM library */ +#if defined(LIBLDBM_DECL) && defined(_WIN32) +# define LIBLDBM_F(type) extern __declspec(LIBLDBM_DECL) type +#else +# define LIBLDBM_F(type) extern type +#endif + +/* LDIF library */ +#if defined(LIBLDIF_DECL) && defined(_WIN32) +# define LIBLDIF_F(type) extern __declspec(LIBLDIF_DECL) type +#else +# define LIBLDIF_F(type) extern type +#endif + +/* LUTIL library */ +#if defined(LIBLUTIL_DECL) && defined(_WIN32) +# define LIBLUTIL_F(type) extern __declspec(LIBLUTIL_DECL) type +#else +# define LIBLUTIL_F(type) extern type +#endif + +/* SLAPD (as a module exporting symbols) */ +#if defined(LIBSLAPD_DECL) && defined(_WIN32) +# define LIBSLAPD_F(type) extern __declspec(LIBSLAPD_DECL) type +#else +# define LIBSLAPD_F(type) extern type +#endif + +#endif /* _LDAP_CDEFS_H */ diff --git a/include/ldap_config.h.in b/include/ldap_config.h.in index a7d0f01cb9..63b604f6ea 100644 --- a/include/ldap_config.h.in +++ b/include/ldap_config.h.in @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -19,7 +19,11 @@ /* directory separator */ #ifndef LDAP_DIRSEP +#ifndef _WIN32 #define LDAP_DIRSEP "/" +#else +#define LDAP_DIRSEP "\\" +#endif #endif /* directories */ diff --git a/include/ldap_config.nt b/include/ldap_config.nt index ce3597a76b..cee39be0b4 100644 --- a/include/ldap_config.nt +++ b/include/ldap_config.nt @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -10,7 +10,7 @@ */ /* - * This file works in confunction with OpenLDAP configure system. + * This file works in confunction with OpenLDAP setup.mak system. * If you do no like the values below, adjust your configure options. */ diff --git a/include/ldap_defaults.h b/include/ldap_defaults.h index 0b27fff34e..14ee2137d1 100644 --- a/include/ldap_defaults.h +++ b/include/ldap_defaults.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -22,7 +22,7 @@ /* * This file controls defaults for OpenLDAP package. - * You should not change any of these settings. + * You probably do not need to edit the defaults provided by this file. */ #ifndef _LDAP_DEFAULTS_H @@ -36,12 +36,6 @@ #define LDAP_ENV_PREFIX "LDAP" -/********************************************************************* - * * - * You probably do not need to edit anything below this point * - * * - *********************************************************************/ - /* * SHARED DEFINITIONS - other things you can change */ @@ -208,14 +202,16 @@ Please try again later.\r\n" /* default timelimit to spend on a search */ #define SLAPD_DEFAULT_TIMELIMIT 3600 /* minimum max ids that a single index entry can map to in ldbm */ -#define SLAPD_LDBM_MIN_MAXIDS 4000 +#define SLAPD_LDBM_MIN_MAXIDS (8192-4) -/* the following DNs must be normalized and in uppercase! */ +/* the following DNs must be normalized! */ + /* dn of the special "schema" entry */ +#define SLAPD_SCHEMA_DN "cn=Schema" +#if 0 /* dn of the special "monitor" entry */ -#define SLAPD_MONITOR_DN "CN=MONITOR" +#define SLAPD_MONITOR_DN "cn=Monitor" /* dn of the special "config" entry */ -#define SLAPD_CONFIG_DN "CN=CONFIG" - /* dn of the special "schema" entry */ -#define SLAPD_SCHEMA_DN "CN=SCHEMA" +#define SLAPD_CONFIG_DN "cn=Config" +#endif #endif /* _LDAP_CONFIG_H */ diff --git a/include/ldap_features.h.in b/include/ldap_features.h.in index 62c3b5a167..1722986246 100644 --- a/include/ldap_features.h.in +++ b/include/ldap_features.h.in @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -47,10 +47,16 @@ /* is threadsafe version of -lldap (ie: -lldap_r) *available* or not */ #undef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE -/* LDAP v2 DNS */ -#undef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS +/* LDAP v2 Kerberos Bind */ +#undef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND /* LDAP v2 Referrals */ #undef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS +/* LDAP Server Side Sort. */ +#define LDAP_API_FEATURE_SERVER_SIDE_SORT 1000 + +/* LDAP Virtual List View. */ +#define LDAP_API_FEATURE_VIRTUAL_LIST_VIEW 1000 + #endif /* LDAP_FEATURES */ diff --git a/include/ldap_features.nt b/include/ldap_features.nt index 29cd0a5314..746e7d9f3e 100644 --- a/include/ldap_features.nt +++ b/include/ldap_features.nt @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -47,10 +47,15 @@ /* is threadsafe version of -lldap (ie: -lldap_r) *available* or not */ #define LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE LDAP_VENDOR_VERSION -/* LDAP v2 DNS */ -/* #undef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ - /* LDAP v2 Referrals */ #define LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS LDAP_VENDOR_VERSION +/* LDAP Server Side Sort. */ +#define LDAP_API_FEATURE_SERVER_SIDE_SORT 1000 + +/* LDAP Virtual List View. Version = 1000 + draft revision. + * VLV requires Server Side Sort control. + */ +#define LDAP_API_FEATURE_VIRTUAL_LIST_VIEW 1000 + #endif /* LDAP_FEATURES */ diff --git a/include/ldap_int_thread.h b/include/ldap_int_thread.h new file mode 100644 index 0000000000..f89afb55a4 --- /dev/null +++ b/include/ldap_int_thread.h @@ -0,0 +1,201 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ +/* ldap_int_thread.h - ldap internal thread wrappers header file */ + +#ifndef _LDAP_INT_THREAD_H +#define _LDAP_INT_THREAD_H + +#if defined( HAVE_PTHREADS ) +/********************************** + * * + * definitions for POSIX Threads * + * * + **********************************/ + +#include +#ifdef HAVE_SCHED_H +#include +#endif + +LDAP_BEGIN_DECL + +typedef pthread_t ldap_int_thread_t; +typedef pthread_mutex_t ldap_int_thread_mutex_t; +typedef pthread_cond_t ldap_int_thread_cond_t; + +#if defined( _POSIX_REENTRANT_FUNCTIONS ) || \ + defined( _POSIX_THREAD_SAFE_FUNCTIONS ) || \ + defined( _POSIX_THREADSAFE_FUNCTIONS ) +#define HAVE_REENTRANT_FUNCTIONS 1 +#endif + +#if defined( HAVE_PTHREAD_GETCONCURRENCY ) || \ + defined( HAVE_THR_GETCONCURRENCY ) +#define LDAP_THREAD_HAVE_GETCONCURRENCY 1 +#endif + +#if defined( HAVE_PTHREAD_SETCONCURRENCY ) || \ + defined( HAVE_THR_SETCONCURRENCY ) +#define LDAP_THREAD_HAVE_SETCONCURRENCY 1 +#endif + +#if 0 && defined( HAVE_PTHREAD_RWLOCK_DESTROY ) +#define LDAP_THREAD_HAVE_RDWR 1 +typedef pthread_rwlock_t ldap_pvt_thread_rdwr_t; +#endif + +LDAP_END_DECL + +#elif defined ( HAVE_MACH_CTHREADS ) +/********************************** + * * + * definitions for Mach CThreads * + * * + **********************************/ + +#include + +LDAP_BEGIN_DECL + +typedef cthread_t ldap_int_thread_t; +typedef struct mutex ldap_int_thread_mutex_t; +typedef struct condition ldap_int_thread_cond_t; + +LDAP_END_DECL + +#elif defined( HAVE_GNU_PTH ) +/*********************************** + * * + * thread definitions for GNU Pth * + * * + ***********************************/ + +#define PTH_SYSCALL_SOFT 1 +#include + +LDAP_BEGIN_DECL + +typedef pth_t ldap_int_thread_t; +typedef pth_mutex_t ldap_int_thread_mutex_t; +typedef pth_cond_t ldap_int_thread_cond_t; + +#if 0 +#define LDAP_THREAD_HAVE_RDWR 1 +typedef pth_rwlock_t ldap_pvt_thread_rdwr_t; +#endif + +LDAP_END_DECL + +#elif defined( HAVE_THR ) +/******************************************** + * * + * thread definitions for Solaris LWP (THR) * + * * + ********************************************/ + +#include +#include + +LDAP_BEGIN_DECL + +typedef thread_t ldap_int_thread_t; +typedef mutex_t ldap_int_thread_mutex_t; +typedef cond_t ldap_int_thread_cond_t; + +#define HAVE_REENTRANT_FUNCTIONS 1 + +#ifdef HAVE_THR_GETCONCURRENCY +#define LDAP_THREAD_HAVE_GETCONCURRENCY 1 +#endif +#ifdef HAVE_THR_SETCONCURRENCY +#define LDAP_THREAD_HAVE_SETCONCURRENCY 1 +#endif + +LDAP_END_DECL + +#elif defined( HAVE_LWP ) +/************************************* + * * + * thread definitions for SunOS LWP * + * * + *************************************/ + +#include +#include +#define LDAP_THREAD_HAVE_SLEEP 1 + +LDAP_BEGIN_DECL + +typedef thread_t ldap_int_thread_t; +typedef mon_t ldap_int_thread_mutex_t; +struct ldap_int_thread_lwp_cv { + int lcv_created; + cv_t lcv_cv; +}; +typedef struct ldap_int_thread_lwp_cv ldap_int_thread_cond_t; + +#define HAVE_REENTRANT_FUNCTIONS 1 + +LDAP_END_DECL + +#elif defined(HAVE_NT_THREADS) + +#include +#include + +LDAP_BEGIN_DECL + +typedef unsigned long ldap_int_thread_t; +typedef HANDLE ldap_int_thread_mutex_t; +typedef HANDLE ldap_int_thread_cond_t; + +LDAP_END_DECL + +#else + +/*********************************** + * * + * thread definitions for no * + * underlying library support * + * * + ***********************************/ + +#ifndef NO_THREADS +#define NO_THREADS 1 +#endif + +LDAP_BEGIN_DECL + +typedef int ldap_int_thread_t; +typedef int ldap_int_thread_mutex_t; +typedef int ldap_int_thread_cond_t; + +#define LDAP_THREAD_HAVE_TPOOL 1 +typedef int ldap_int_thread_pool_t; + +LDAP_END_DECL + +#endif /* no threads support */ + +LDAP_BEGIN_DECL + +LIBLDAP_F(int) ldap_int_thread_initialize LDAP_P(( void )); +LIBLDAP_F(int) ldap_int_thread_destroy LDAP_P(( void )); +LIBLDAP_F(int) ldap_int_thread_pool_startup ( void ); +LIBLDAP_F(int) ldap_int_thread_pool_shutdown ( void ); + +#ifndef LDAP_THREAD_HAVE_TPOOL +typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t; +#endif + +LDAP_END_DECL + +#endif /* _LDAP_INT_THREAD_H */ diff --git a/include/ldap_log.h b/include/ldap_log.h index dfb2e7a9cd..1ba0b42d68 100644 --- a/include/ldap_log.h +++ b/include/ldap_log.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -47,6 +47,10 @@ LDAP_BEGIN_DECL /* debugging stuff */ #ifdef LDAP_DEBUG +/* + * This is a bogus extern declaration for the compiler. No need to ensure + * a 'proper' dllimport. + */ #ifndef ldap_debug extern int ldap_debug; #endif /* !ldap_debug */ @@ -74,7 +78,7 @@ extern int ldap_syslog_level; #define Debug( level, fmt, arg1, arg2, arg3 ) #endif /* LDAP_DEBUG */ -LDAP_F(void) lutil_debug LDAP_P(( +LIBLUTIL_F(void) lutil_debug LDAP_P(( int debug, int level, const char* fmt, ... )) LDAP_GCCATTR((format(printf, 3, 4))); diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 2b20ed4929..7107c9b8ec 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -21,14 +21,31 @@ LDAP_BEGIN_DECL +#define LDAP_PROTO_TCP 1 +#define LDAP_PROTO_UDP 2 +#define LDAP_PROTO_IPC 3 + +LIBLDAP_F ( int ) +ldap_pvt_url_scheme2proto LDAP_P(( + const char * )); +LIBLDAP_F ( int ) +ldap_pvt_url_scheme2tls LDAP_P(( + const char * )); + + +LIBLDAP_F ( int ) +ldap_pvt_domain2dn LDAP_P(( + LDAP_CONST char *domain, + char **dn )); + struct hostent; /* avoid pulling in */ -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_pvt_ctime LDAP_P(( const time_t *tp, char *buf )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_gethostbyname_a LDAP_P(( const char *name, struct hostent *resbuf, @@ -36,7 +53,7 @@ ldap_pvt_gethostbyname_a LDAP_P(( struct hostent **result, int *herrno_ptr )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_gethostbyaddr_a LDAP_P(( const char *addr, int len, @@ -49,35 +66,35 @@ ldap_pvt_gethostbyaddr_a LDAP_P(( /* charray.c */ -LDAP_F( int ) +LIBLDAP_F( int ) ldap_charray_add LDAP_P(( char ***a, char *s )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_charray_merge LDAP_P(( char ***a, char **s )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_charray_free LDAP_P(( char **a )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_charray_inlist LDAP_P(( char **a, char *s )); -LDAP_F( char ** ) +LIBLDAP_F( char ** ) ldap_charray_dup LDAP_P(( char **a )); -LDAP_F( char ** ) +LIBLDAP_F( char ** ) ldap_str2charray LDAP_P(( - char *str, - char *brkstr )); + const char *str, + const char *brkstr )); /* url.c */ -void ldap_pvt_hex_unescape LDAP_P(( char *s )); -int ldap_pvt_unhex( int c ); +LIBLDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s )); +LIBLDAP_F (int) ldap_pvt_unhex( int c ); /* these macros assume 'x' is an ASCII x */ #define LDAP_DNSEPARATOR(c) ((c) == ',' || (c) == ';') @@ -100,20 +117,114 @@ int ldap_pvt_unhex( int c ); #define LDAP_NEEDSESCAPE(c) ((c) == '\\' || (c) == '"') +#ifdef HAVE_CYRUS_SASL +/* sasl.c */ + +#include +#include + +LIBLDAP_F (int) ldap_pvt_sasl_init LDAP_P(( void )); /* clientside init */ +LIBLDAP_F (int) ldap_pvt_sasl_install LDAP_P(( Sockbuf *, void * )); +LIBLDAP_F (int) ldap_pvt_sasl_bind LDAP_P(( LDAP *, LDAP_CONST char *, + LDAP_CONST char *, LDAP_CONST sasl_callback_t *, LDAPControl **, + LDAPControl ** )); +LIBLDAP_F (int) ldap_pvt_sasl_get_option LDAP_P(( LDAP *ld, int option, + void *arg )); +LIBLDAP_F (int) ldap_pvt_sasl_set_option LDAP_P(( LDAP *ld, int option, + void *arg )); +#endif /* HAVE_CYRUS_SASL */ + /* search.c */ -LDAP_F( char * ) -ldap_pvt_find_wildcard LDAP_P(( char *s )); +LIBLDAP_F( char * ) +ldap_pvt_find_wildcard LDAP_P(( const char *s )); -LDAP_F( ber_slen_t ) +LIBLDAP_F( ber_slen_t ) ldap_pvt_filter_value_unescape LDAP_P(( char *filter )); /* string.c */ -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_pvt_str2upper LDAP_P(( char *str )); -LDAP_F( char * ) +LIBLDAP_F( char * ) ldap_pvt_str2lower LDAP_P(( char *str )); +/* tls.c */ +struct ldapoptions; +struct ldap; + +LIBLDAP_F (int) ldap_pvt_tls_init LDAP_P(( void )); +LIBLDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); +LIBLDAP_F (int) ldap_pvt_tls_connect LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg )); +LIBLDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg )); +LIBLDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); +LIBLDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); +LIBLDAP_F (void *) ldap_pvt_tls_sb_handle LDAP_P(( Sockbuf *sb )); +LIBLDAP_F (void *) ldap_pvt_tls_get_handle LDAP_P(( struct ldap *ld )); +LIBLDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb )); +LIBLDAP_F (int) ldap_pvt_tls_start LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg )); + +/* + * UTF-8 (in utf-8.c) + */ + +typedef ber_int_t ldap_ucs4_t; +typedef short ldap_ucs2_t; +typedef ldap_ucs2_t ldap_unicode_t; + +/* returns the number of bytes in the UTF-8 string */ +LIBLDAP_F (ber_len_t) ldap_utf8_bytes( const char * ); +/* returns the number of UTF-8 characters in the string */ +LIBLDAP_F (ber_len_t) ldap_utf8_chars( const char * ); +/* returns the length (in bytes) of the UTF-8 character */ +LIBLDAP_F (int) ldap_utf8_offset( const char * ); +/* returns the length (in bytes) indicated by the UTF-8 character */ +LIBLDAP_F (int) ldap_utf8_charlen( const char * ); +/* copies a UTF-8 character and returning number of bytes copied */ +LIBLDAP_F (int) ldap_utf8_copy( char *, const char *); + +/* returns pointer of next UTF-8 character in string */ +LIBLDAP_F (char*) ldap_utf8_next( const char * ); +/* returns pointer of previous UTF-8 character in string */ +LIBLDAP_F (char*) ldap_utf8_prev( const char * ); + +/* primitive ctype routines -- not aware of non-ascii characters */ +LIBLDAP_F (int) ldap_utf8_isascii( const char * ); +LIBLDAP_F (int) ldap_utf8_isalpha( const char * ); +LIBLDAP_F (int) ldap_utf8_isalnum( const char * ); +LIBLDAP_F (int) ldap_utf8_isdigit( const char * ); +LIBLDAP_F (int) ldap_utf8_isxdigit( const char * ); +LIBLDAP_F (int) ldap_utf8_isspace( const char * ); + +/* span characters not in set, return bytes spanned */ +LIBLDAP_F (ber_len_t) ldap_utf8_strcspn( const char* str, const char *set); +/* span characters in set, return bytes spanned */ +LIBLDAP_F (ber_len_t) ldap_utf8_strspn( const char* str, const char *set); +/* return first occurance of character in string */ +LIBLDAP_F (char *) ldap_utf8_strchr( const char* str, const char *chr); +/* return first character of set in string */ +LIBLDAP_F (char *) ldap_utf8_strpbrk( const char* str, const char *set); +/* reentrant tokenizer */ +LIBLDAP_F (char*) ldap_utf8_strtok( char* sp, const char* sep, char **last); + +/* Optimizations */ +#define LDAP_UTF8_ISASCII(p) ( * (const unsigned char *) (p) < 0x100 ) +#define LDAP_UTF8_CHARLEN(p) ( LDAP_UTF8_ISASCII(p) \ + ? 1 : ldap_utf8_charlen((p)) ) +#define LDAP_UTF8_OFFSET(p) ( LDAP_UTF8_ISASCII(p) \ + ? 1 : ldap_utf8_offset((p)) ) + +#define LDAP_UTF8_COPY(d,s) ( LDAP_UTF8_ISASCII(s) \ + ? (*(d) = *(s), 1) : ldap_utf8_copy((d),(s)) ) + +#define LDAP_UTF8_NEXT(p) ( LDAP_UTF8_ISASCII(p) \ + ? (char *)(p)+1 : ldap_utf8_next((p)) ) + +#define LDAP_UTF8_INCR(p) ((p) = LDAP_UTF8_NEXT(p)) + +/* For symmetry */ +#define LDAP_UTF8_PREV(p) (ldap_utf8_prev((p))) +#define LDAP_UTF8_DECR(p) ((p)=LDAP_UTF8_PREV((p))) + LDAP_END_DECL #endif diff --git a/include/ldap_pvt_thread.h b/include/ldap_pvt_thread.h index a006a2ef66..23df121b1e 100644 --- a/include/ldap_pvt_thread.h +++ b/include/ldap_pvt_thread.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -14,295 +14,149 @@ #define _LDAP_PVT_THREAD_H #include "ldap_cdefs.h" - -#if defined( HAVE_PTHREADS ) -/********************************** - * * - * definitions for POSIX Threads * - * * - **********************************/ - -#include -#ifdef HAVE_SCHED_H -#include -#endif - -LDAP_BEGIN_DECL - -typedef pthread_t ldap_pvt_thread_t; -typedef pthread_mutex_t ldap_pvt_thread_mutex_t; -typedef pthread_cond_t ldap_pvt_thread_cond_t; - -#if defined( _POSIX_REENTRANT_FUNCTIONS ) || \ - defined( _POSIX_THREAD_SAFE_FUNCTIONS ) || \ - defined( _POSIX_THREADSAFE_FUNCTIONS ) -#define HAVE_REENTRANT_FUNCTIONS 1 -#endif - -#if defined( HAVE_PTHREAD_GETCONCURRENCY ) || \ - defined( HAVE_THR_GETCONCURRENCY ) -#define HAVE_GETCONCURRENCY 1 -#endif - -#if defined( HAVE_PTHREAD_SETCONCURRENCY ) || \ - defined( HAVE_THR_SETCONCURRENCY ) -#define HAVE_SETCONCURRENCY 1 -#endif - -LDAP_END_DECL - -#elif defined ( HAVE_MACH_CTHREADS ) -/********************************** - * * - * definitions for Mach CThreads * - * * - **********************************/ - -#include - -LDAP_BEGIN_DECL - -typedef cthread_t ldap_pvt_thread_t; -typedef struct mutex ldap_pvt_thread_mutex_t; -typedef struct condition ldap_pvt_thread_cond_t; - -LDAP_END_DECL - -#elif defined( HAVE_GNU_PTH ) -/*********************************** - * * - * thread definitions for GNU Pth * - * * - ***********************************/ - -#include - -LDAP_BEGIN_DECL - -typedef pth_t ldap_pvt_thread_t; -typedef pth_mutex_t ldap_pvt_thread_mutex_t; -typedef pth_cond_t ldap_pvt_thread_cond_t; - -LDAP_END_DECL - - -#elif defined( HAVE_THR ) -/******************************************** - * * - * thread definitions for Solaris LWP (THR) * - * * - ********************************************/ - -#include -#include - -LDAP_BEGIN_DECL - -typedef thread_t ldap_pvt_thread_t; -typedef mutex_t ldap_pvt_thread_mutex_t; -typedef cond_t ldap_pvt_thread_cond_t; - -#define HAVE_REENTRANT_FUNCTIONS 1 - -#ifdef HAVE_THR_GETCONCURRENCY -#define HAVE_GETCONCURRENCY 1 -#endif -#ifdef HAVE_THR_SETCONCURRENCY -#define HAVE_SETCONCURRENCY 1 -#endif - -LDAP_END_DECL - -#elif defined( HAVE_LWP ) -/************************************* - * * - * thread definitions for SunOS LWP * - * * - *************************************/ - -#include -#include +#include "ldap_int_thread.h" LDAP_BEGIN_DECL -typedef thread_t ldap_pvt_thread_t; -typedef mon_t ldap_pvt_thread_mutex_t; -struct ldap_pvt_thread_lwp_cv { - int lcv_created; - cv_t lcv_cv; -}; -typedef struct ldap_pvt_thread_lwp_cv ldap_pvt_thread_cond_t; - -#define HAVE_REENTRANT_FUNCTIONS 1 - -LDAP_END_DECL - -#elif HAVE_NT_THREADS - -LDAP_BEGIN_DECL - -#define WIN32_LEAN_AND_MEAN -#include -#include - -typedef unsigned long ldap_pvt_thread_t; -typedef HANDLE ldap_pvt_thread_mutex_t; -typedef HANDLE ldap_pvt_thread_cond_t; - -LDAP_END_DECL - -#else - -/*********************************** - * * - * thread definitions for no * - * underlying library support * - * * - ***********************************/ - -LDAP_BEGIN_DECL +typedef ldap_int_thread_t ldap_pvt_thread_t; +typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t; +typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t; -#ifndef NO_THREADS -#define NO_THREADS 1 -#endif - -typedef int ldap_pvt_thread_t; -typedef int ldap_pvt_thread_mutex_t; -typedef int ldap_pvt_thread_cond_t; - -LDAP_END_DECL - -#endif /* no threads support */ - -LDAP_BEGIN_DECL - -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_initialize LDAP_P(( void )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_destroy LDAP_P(( void )); -LDAP_F( unsigned int ) +LIBLDAP_F( unsigned int ) ldap_pvt_thread_sleep LDAP_P(( unsigned int s )); -#ifdef HAVE_GETCONCURRENCY -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_get_concurrency LDAP_P(( void )); -#endif -#ifdef HAVE_SETCONCURRENCY -# ifndef LDAP_THREAD_CONCURRENCY - /* three concurrent threads should be enough */ -# define LDAP_THREAD_CONCURRENCY 3 -# endif -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_set_concurrency LDAP_P(( int )); -#endif #define LDAP_PVT_THREAD_CREATE_JOINABLE 0 #define LDAP_PVT_THREAD_CREATE_DETACHED 1 -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_create LDAP_P(( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void * ), void *arg)); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_pvt_thread_exit LDAP_P(( void *retval )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_join LDAP_P(( ldap_pvt_thread_t thread, void **status )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_kill LDAP_P(( ldap_pvt_thread_t thread, int signo )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_yield LDAP_P(( void )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_cond_init LDAP_P(( ldap_pvt_thread_cond_t *cond )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_cond_destroy LDAP_P(( ldap_pvt_thread_cond_t *cond )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_cond_signal LDAP_P(( ldap_pvt_thread_cond_t *cond )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_cond_broadcast LDAP_P(( ldap_pvt_thread_cond_t *cond )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_cond_wait LDAP_P(( ldap_pvt_thread_cond_t *cond, ldap_pvt_thread_mutex_t *mutex )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_mutex_init LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_mutex_destroy LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_mutex_lock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_mutex_trylock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); -typedef struct ldap_pvt_thread_rdwr_var { - ldap_pvt_thread_mutex_t ltrw_mutex; - ldap_pvt_thread_cond_t ltrw_read; /* wait for read */ - ldap_pvt_thread_cond_t ltrw_write; /* wait for write */ - int ltrw_valid; -#define LDAP_PVT_THREAD_RDWR_VALID 0x0bad - int ltrw_r_active; - int ltrw_w_active; - int ltrw_r_wait; - int ltrw_w_wait; -} ldap_pvt_thread_rdwr_t; - -LDAP_F( int ) +#ifndef LDAP_THREAD_HAVE_RDWR +typedef struct ldap_int_thread_rdwr_s * ldap_pvt_thread_rdwr_t; +#endif + +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_destroy LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_rlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_rtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_runlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_wlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_wtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); #ifdef LDAP_DEBUG -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_readers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_writers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_pvt_thread_rdwr_active LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); #endif /* LDAP_DEBUG */ #define LDAP_PVT_THREAD_EINVAL EINVAL #define LDAP_PVT_THREAD_EBUSY EINVAL +typedef ldap_int_thread_pool_t ldap_pvt_thread_pool_t; + +LIBLDAP_F( int ) +ldap_pvt_thread_pool_init LDAP_P(( + ldap_pvt_thread_pool_t *pool_out, + int max_concurrency, + int max_pending )); + +LIBLDAP_F( int ) +ldap_pvt_thread_pool_submit LDAP_P(( + ldap_pvt_thread_pool_t *pool, + void *(*start_routine)( void * ), + void *arg )); + +LIBLDAP_F( int ) +ldap_pvt_thread_pool_backload LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LIBLDAP_F( int ) +ldap_pvt_thread_pool_destroy LDAP_P(( + ldap_pvt_thread_pool_t *pool, + int run_pending )); + + LDAP_END_DECL #endif /* _LDAP_THREAD_H */ diff --git a/include/ldap_schema.h b/include/ldap_schema.h index c0c21bc88d..ec29616445 100644 --- a/include/ldap_schema.h +++ b/include/ldap_schema.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -33,9 +33,16 @@ LDAP_BEGIN_DECL #define LDAP_SCHERR_DUPOPT 9 #define LDAP_SCHERR_EMPTY 10 +typedef struct ldap_schema_extension_item { + char *lsei_name; + char **lsei_values; +} LDAP_SCHEMA_EXTENSION_ITEM; + typedef struct ldap_syntax { char *syn_oid; /* REQUIRED */ + char **syn_names; /* OPTIONAL */ char *syn_desc; /* OPTIONAL */ + LDAP_SCHEMA_EXTENSION_ITEM **syn_extensions; /* OPTIONAL */ } LDAP_SYNTAX; typedef struct ldap_matchingrule { @@ -44,6 +51,7 @@ typedef struct ldap_matchingrule { char *mr_desc; /* OPTIONAL */ int mr_obsolete; /* OPTIONAL */ char *mr_syntax_oid; /* REQUIRED */ + LDAP_SCHEMA_EXTENSION_ITEM **mr_extensions; /* OPTIONAL */ } LDAP_MATCHING_RULE; typedef struct ldap_attributetype { @@ -62,6 +70,7 @@ typedef struct ldap_attributetype { int at_no_user_mod; /* 0=no, 1=yes */ int at_usage; /* 0=userApplications, 1=directoryOperation, 2=distributedOperation, 3=dSAOperation */ + LDAP_SCHEMA_EXTENSION_ITEM **at_extensions; /* OPTIONAL */ } LDAP_ATTRIBUTE_TYPE; typedef struct ldap_objectclass { @@ -73,6 +82,7 @@ typedef struct ldap_objectclass { int oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ char **oc_at_oids_must; /* OPTIONAL */ char **oc_at_oids_may; /* OPTIONAL */ + LDAP_SCHEMA_EXTENSION_ITEM **oc_extensions; /* OPTIONAL */ } LDAP_OBJECT_CLASS; #define LDAP_SCHEMA_NO 0 @@ -87,79 +97,93 @@ typedef struct ldap_objectclass { #define LDAP_SCHEMA_STRUCTURAL 1 #define LDAP_SCHEMA_AUXILIARY 2 -LDAP_F( LDAP_CONST char * ) +/* + * Flags that control how liberal the parsing routines are. + */ +#define LDAP_SCHEMA_ALLOW_NONE 0x00 /* Strict parsing */ +#define LDAP_SCHEMA_ALLOW_NO_OID 0x01 /* Allow missing oid */ +#define LDAP_SCHEMA_ALLOW_QUOTED 0x02 /* Allow bogus extra quotes */ +#define LDAP_SCHEMA_ALLOW_DESCR 0x04 /* Allow descr instead of OID */ +#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08 /* Allow descr as OID prefix */ +#define LDAP_SCHEMA_ALLOW_ALL 0x0f /* Be very liberal in parsing */ + +LIBLDAP_F( LDAP_CONST char * ) ldap_syntax2name LDAP_P(( LDAP_SYNTAX * syn )); -LDAP_F( LDAP_CONST char * ) +LIBLDAP_F( LDAP_CONST char * ) ldap_matchingrule2name LDAP_P(( LDAP_MATCHING_RULE * mr )); -LDAP_F( LDAP_CONST char * ) +LIBLDAP_F( LDAP_CONST char * ) ldap_attributetype2name LDAP_P(( LDAP_ATTRIBUTE_TYPE * at )); -LDAP_F( LDAP_CONST char * ) +LIBLDAP_F( LDAP_CONST char * ) ldap_objectclass2name LDAP_P(( LDAP_OBJECT_CLASS * oc )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_syntax_free LDAP_P(( LDAP_SYNTAX * syn )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_matchingrule_free LDAP_P(( LDAP_MATCHING_RULE * mr )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_attributetype_free LDAP_P(( LDAP_ATTRIBUTE_TYPE * at )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_objectclass_free LDAP_P(( LDAP_OBJECT_CLASS * oc )); -LDAP_F( LDAP_OBJECT_CLASS * ) +LIBLDAP_F( LDAP_OBJECT_CLASS * ) ldap_str2objectclass LDAP_P(( LDAP_CONST char * s, int * code, - LDAP_CONST char ** errp )); + LDAP_CONST char ** errp, + LDAP_CONST int flags )); -LDAP_F( LDAP_ATTRIBUTE_TYPE * ) +LIBLDAP_F( LDAP_ATTRIBUTE_TYPE * ) ldap_str2attributetype LDAP_P(( LDAP_CONST char * s, int * code, - LDAP_CONST char ** errp )); + LDAP_CONST char ** errp, + LDAP_CONST int flags )); -LDAP_F( LDAP_SYNTAX * ) +LIBLDAP_F( LDAP_SYNTAX * ) ldap_str2syntax LDAP_P(( LDAP_CONST char * s, int * code, - LDAP_CONST char ** errp )); + LDAP_CONST char ** errp, + LDAP_CONST int flags )); -LDAP_F( LDAP_MATCHING_RULE * ) +LIBLDAP_F( LDAP_MATCHING_RULE * ) ldap_str2matchingrule LDAP_P(( LDAP_CONST char * s, int * code, - LDAP_CONST char ** errp )); + LDAP_CONST char ** errp, + LDAP_CONST int flags )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_objectclass2str LDAP_P(( LDAP_CONST LDAP_OBJECT_CLASS * oc )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_attributetype2str LDAP_P(( LDAP_CONST LDAP_ATTRIBUTE_TYPE * at )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_syntax2str LDAP_P(( LDAP_CONST LDAP_SYNTAX * syn )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_matchingrule2str LDAP_P(( LDAP_CONST LDAP_MATCHING_RULE * mr )); -LDAP_F( char *) +LIBLDAP_F( char *) ldap_scherr2str LDAP_P(( int code )) LDAP_GCCATTR((const)); diff --git a/include/ldbm.h b/include/ldbm.h index 9fd65730e3..3da50df682 100644 --- a/include/ldbm.h +++ b/include/ldbm.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -15,14 +15,13 @@ #include -#ifdef LDBM_USE_DBBTREE +#if defined( LDBM_USE_DBBTREE ) || defined( LDBM_USE_DBHASH ) /***************************************************************** * * - * use berkeley db btree package * + * use berkeley db btree or hash package * * * *****************************************************************/ - #include #include #include @@ -35,77 +34,23 @@ # else # include # endif -# ifdef HAVE_BERKELEY_DB2 -# define R_NOOVERWRITE DB_NOOVERWRITE -# define DEFAULT_DB_PAGE_SIZE 1024 -# endif #endif - -LDAP_BEGIN_DECL - -typedef DBT Datum; -#define dsize size -#define dptr data - -typedef DB *LDBM; - - -#define DB_TYPE DB_BTREE - -/* for ldbm_open */ -#ifdef HAVE_BERKELEY_DB2 -typedef DBC LDBMCursor; -# define LDBM_READER DB_RDONLY -# define LDBM_WRITER 0x00000 /* hopefully */ -# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE|DB_THREAD) -# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE|DB_THREAD) -#else -typedef int LDBMCursor; -# define LDBM_READER O_RDONLY -# define LDBM_WRITER O_RDWR -# define LDBM_WRCREAT (O_RDWR|O_CREAT) -# define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT) +#ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +#endif +#ifndef DB_VERSION_MINOR +# define DB_VERSION_MINOR 85 #endif -LDAP_END_DECL - -# define LDBM_FAST 0 - -#define LDBM_SUFFIX ".dbb" -#define LDBM_ORDERED 1 - -/* for ldbm_insert */ -#define LDBM_INSERT R_NOOVERWRITE -#define LDBM_REPLACE 0 -#define LDBM_SYNC 0x80000000 - -#elif defined( LDBM_USE_DBHASH ) - -/***************************************************************** - * * - * use berkeley db hash package * - * * - *****************************************************************/ - -#include -#include -#include - -#ifdef HAVE_DB_185_H -# include -#else -# ifdef HAVE_DB1_DB_H -# include -# else -# include -# endif -# ifdef LDBM_USE_DB2 -# define R_NOOVERWRITE DB_NOOVERWRITE -# define DEFAULT_DB_PAGE_SIZE 1024 +#if DB_VERSION_MAJOR >= 2 +# define R_NOOVERWRITE DB_NOOVERWRITE +# ifndef DEFAULT_DB_PAGE_SIZE +# define DEFAULT_DB_PAGE_SIZE 4096 # endif #endif + LDAP_BEGIN_DECL typedef DBT Datum; @@ -114,32 +59,49 @@ typedef DBT Datum; typedef DB *LDBM; -#define DB_TYPE DB_HASH /* for ldbm_open */ -#ifdef LDBM_USE_DB2 +#if DB_VERSION_MAJOR >= 2 typedef DBC LDBMCursor; + # define LDBM_READER DB_RDONLY # define LDBM_WRITER 0x00000 /* hopefully */ +# if defined( HAVE_BERKELEY_DB_THREAD ) # define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE|DB_THREAD) # define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE|DB_THREAD) +# else +# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE) +# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE) +# endif + #else -typedef int LDBMCursor; +typedef void LDBMCursor; # define LDBM_READER O_RDONLY # define LDBM_WRITER O_RDWR # define LDBM_WRCREAT (O_RDWR|O_CREAT) # define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT) -# define LDBM_FAST 0 #endif LDAP_END_DECL -#define LDBM_SUFFIX ".dbh" +/* for ldbm_open */ +#define LDBM_NOSYNC 0 +#define LDBM_SYNC 0 +#define LDBM_LOCKING 0 +#define LDBM_NOLOCKING 0 /* for ldbm_insert */ #define LDBM_INSERT R_NOOVERWRITE #define LDBM_REPLACE 0 -#define LDBM_SYNC 0x80000000 + +#ifdef LDBM_USE_DBBTREE +# define LDBM_ORDERED 1 +# define LDBM_SUFFIX ".dbb" +# define DB_TYPE DB_BTREE +#else +# define LDBM_SUFFIX ".dbh" +# define DB_TYPE DB_HASH +#endif #elif defined( HAVE_GDBM ) @@ -154,7 +116,7 @@ LDAP_END_DECL LDAP_BEGIN_DECL typedef datum Datum; -typedef int LDBMCursor; +typedef Datum LDBMCursor; typedef GDBM_FILE LDBM; extern gdbm_error gdbm_errno; @@ -166,14 +128,31 @@ LDAP_END_DECL #define LDBM_WRITER GDBM_WRITER #define LDBM_WRCREAT GDBM_WRCREAT #define LDBM_NEWDB GDBM_NEWDB -#define LDBM_FAST GDBM_FAST + +#ifdef GDBM_FAST +#define LDBM_NOSYNC GDBM_FAST +#else +#define LDBM_NOSYNC 0 +#endif + +#ifdef GDBM_SYNC +#define LDBM_SYNC GDBM_SYNC +#else +#define LDBM_SYNC 0 +#endif + +#define LDBM_LOCKING 0 +#ifdef GDBM_NOLOCK +#define LDBM_NOLOCKING GDBM_NOLOCK +#else +#define LDBM_NOLOCKING 0 +#endif #define LDBM_SUFFIX ".gdbm" /* for ldbm_insert */ #define LDBM_INSERT GDBM_INSERT #define LDBM_REPLACE GDBM_REPLACE -#define LDBM_SYNC 0x80000000 #elif defined( HAVE_MDBM ) @@ -202,15 +181,17 @@ LDAP_END_DECL #define LDBM_WRITER O_RDWR #define LDBM_WRCREAT (O_RDWR|O_CREAT) #define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT) -#define LDBM_FAST 0 + +#define LDBM_SYNC 0 +#define LDBM_NOSYNC 0 +#define LDBM_LOCKING 0 +#define LDBM_NOLOCKING 0 #define LDBM_SUFFIX ".mdbm" /* for ldbm_insert */ #define LDBM_INSERT MDBM_INSERT #define LDBM_REPLACE MDBM_REPLACE -#define LDBM_SYNC 0x80000000 - #elif defined( HAVE_NDBM ) @@ -239,42 +220,45 @@ LDAP_END_DECL #define LDBM_WRITER O_WRONLY #define LDBM_WRCREAT (O_RDWR|O_CREAT) #define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT) -#define LDBM_FAST 0 + +#define LDBM_NOSYNC 0 +#define LDBM_SYNC 0 +#define LDBM_NOLOCK 0 +#define LDBM_SYNC 0 #define LDBM_SUFFIX ".ndbm" /* for ldbm_insert */ #define LDBM_INSERT DBM_INSERT #define LDBM_REPLACE DBM_REPLACE -#define LDBM_SYNC 0 #endif LDAP_BEGIN_DECL -int ldbm_initialize( void ); -int ldbm_shutdown( void ); +LIBLDBM_F (int) ldbm_initialize( void ); +LIBLDBM_F (int) ldbm_shutdown( void ); -int ldbm_errno( LDBM ldbm ); -LDBM ldbm_open( char *name, int rw, int mode, int dbcachesize ); -void ldbm_close( LDBM ldbm ); -void ldbm_sync( LDBM ldbm ); -void ldbm_datum_free( LDBM ldbm, Datum data ); -Datum ldbm_datum_dup( LDBM ldbm, Datum data ); -Datum ldbm_fetch( LDBM ldbm, Datum key ); -int ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ); -int ldbm_delete( LDBM ldbm, Datum key ); +LIBLDBM_F (int) ldbm_errno( LDBM ldbm ); +LIBLDBM_F (LDBM) ldbm_open( char *name, int rw, int mode, int dbcachesize ); +LIBLDBM_F (void) ldbm_close( LDBM ldbm ); +LIBLDBM_F (void) ldbm_sync( LDBM ldbm ); +LIBLDBM_F (void) ldbm_datum_free( LDBM ldbm, Datum data ); +LIBLDBM_F (Datum) ldbm_datum_dup( LDBM ldbm, Datum data ); +LIBLDBM_F (Datum) ldbm_fetch( LDBM ldbm, Datum key ); +LIBLDBM_F (int) ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ); +LIBLDBM_F (int) ldbm_delete( LDBM ldbm, Datum key ); -Datum ldbm_firstkey( LDBM ldbm, LDBMCursor **cursor ); -Datum ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *cursor ); +LIBLDBM_F (Datum) ldbm_firstkey( LDBM ldbm, LDBMCursor **cursor ); +LIBLDBM_F (Datum) ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *cursor ); /* initialization of Datum structures */ -#ifdef HAVE_BERKELEY_DB2 - void *ldbm_malloc( size_t size ); -# define ldbm_datum_init(d) ((void)memset(&(d), 0, sizeof(Datum))) +#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2) + LIBLDBM_F (void *) ldbm_malloc( size_t size ); +# define ldbm_datum_init(d) ((void)memset(&(d), '\0', sizeof(Datum))) #else # define ldbm_datum_init(d) ((void)0) -#endif /* HAVE_BERKELEY_DB2 */ +#endif /* HAVE_BERKELEY_DB */ LDAP_END_DECL diff --git a/include/ldif.h b/include/ldif.h index a50bbf0634..2d0ee1de9d 100644 --- a/include/ldif.h +++ b/include/ldif.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -27,7 +27,8 @@ LDAP_BEGIN_DECL -extern int ldif_debug; +/* This is NOT a bogus extern declaration (unlike ldap_debug) */ +LIBLDIF_F (int) ldif_debug; #define LDIF_LINE_WIDTH 76 /* maximum length of LDIF lines */ @@ -48,23 +49,23 @@ extern int ldif_debug; ((nlen) + 4 + LDIF_BASE64_LEN(vlen) \ + ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / LDIF_LINE_WIDTH * 2 )) -LDAP_F( int ) +LIBLDIF_F( int ) ldif_parse_line LDAP_P(( LDAP_CONST char *line, char **name, char **value, ber_len_t *vlen )); -LDAP_F( int ) +LIBLDIF_F( int ) ldif_fetch_url LDAP_P(( LDAP_CONST char *line, char **value, ber_len_t *vlen )); -LDAP_F( char * ) +LIBLDIF_F( char * ) ldif_getline LDAP_P(( char **next )); -LDAP_F( int ) +LIBLDIF_F( int ) ldif_read_record LDAP_P(( FILE *fp, int *lineno, @@ -82,7 +83,7 @@ ldif_read_record LDAP_P(( #define LDIF_PUT_URL 0x0020 /* url */ #define LDIF_PUT_SEP 0x0040 /* separator */ -LDAP_F( void ) +LIBLDIF_F( void ) ldif_sput LDAP_P(( char **out, int type, @@ -90,14 +91,14 @@ ldif_sput LDAP_P(( LDAP_CONST char *val, ber_len_t vlen )); -LDAP_F( char * ) +LIBLDIF_F( char * ) ldif_put LDAP_P(( int type, LDAP_CONST char *name, LDAP_CONST char *val, ber_len_t vlen )); -LDAP_F( int ) +LIBLDIF_F( int ) ldif_is_not_printable LDAP_P(( LDAP_CONST char *val, ber_len_t vlen )); diff --git a/include/lutil.h b/include/lutil.h index 05d6279f94..398f50f2a8 100644 --- a/include/lutil.h +++ b/include/lutil.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -21,44 +21,88 @@ LDAP_BEGIN_DECL +/* n octets encode into ceiling(n/3) * 4 bytes */ +/* Avoid floating point math by through extra padding */ + +#define LUTIL_BASE64_ENCODE_LEN(n) ((n)/3 * 4 + 4) +#define LUTIL_BASE64_DECODE_LEN(n) ((n)/4 * 3) + /* ISC Base64 Routines */ /* base64.c */ -LDAP_F( int ) +LIBLUTIL_F( int ) lutil_b64_ntop LDAP_P(( unsigned char const *, size_t, char *, size_t)); -LDAP_F( int ) +LIBLUTIL_F( int ) lutil_b64_pton LDAP_P(( char const *, unsigned char *, size_t)); /* detach.c */ -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_detach LDAP_P(( int debug, int do_close)); +/* entropy.c */ +LIBLUTIL_F( int ) +lutil_entropy LDAP_P(( + char *buf, + ber_len_t nbytes )); + /* passwd.c */ -LDAP_F( int ) +struct berval; /* avoid pulling in lber.h */ + +LIBLUTIL_F( int ) +lutil_authpasswd LDAP_P(( + const struct berval *passwd, /* stored password */ + const struct berval *cred, /* user supplied value */ + const char **methods )); + +LIBLUTIL_F( int ) +lutil_authpasswd_hash LDAP_P(( + const struct berval *cred, + struct berval **passwd, /* password to store */ + struct berval **salt, /* salt to store */ + const char *method )); + +#if defined( SLAPD_SPASSWD ) && defined( HAVE_CYRUS_SASL ) + /* cheat to avoid pulling in */ +LIBLUTIL_F( struct sasl_conn * ) lutil_passwd_sasl_conn; +#endif + +LIBLUTIL_F( int ) lutil_passwd LDAP_P(( - const char *cred, - const char *passwd, + const struct berval *passwd, /* stored password */ + const struct berval *cred, /* user supplied value */ const char **methods )); +LIBLUTIL_F( struct berval * ) +lutil_passwd_generate LDAP_P(( ber_len_t )); + +LIBLUTIL_F( struct berval * ) +lutil_passwd_hash LDAP_P(( + const struct berval *passwd, + const char *method )); + +LIBLUTIL_F( int ) +lutil_passwd_scheme LDAP_P(( + const char *scheme )); + /* utils.c */ -LDAP_F( char* ) +LIBLUTIL_F( char* ) lutil_progname LDAP_P(( const char* name, int argc, char *argv[] )); /* sockpair.c */ -LDAP_F( int ) +LIBLUTIL_F( int ) lutil_pair( LBER_SOCKET_T sd[2] ); LDAP_END_DECL diff --git a/include/lutil_lockf.h b/include/lutil_lockf.h index 728b445cbf..3afb7bd335 100644 --- a/include/lutil_lockf.h +++ b/include/lutil_lockf.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -19,10 +19,10 @@ LDAP_BEGIN_DECL -LDAP_F( int ) +LIBLUTIL_F( int ) lutil_lockf LDAP_P(( int fd )); -LDAP_F( int ) +LIBLUTIL_F( int ) lutil_unlockf LDAP_P(( int fd )); LDAP_END_DECL diff --git a/include/lutil_md5.h b/include/lutil_md5.h index 6a140c9753..7148abc0ab 100644 --- a/include/lutil_md5.h +++ b/include/lutil_md5.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -14,46 +14,42 @@ #ifndef _LUTIL_MD5_H_ #define _LUTIL_MD5_H_ -#include -#include +#include LDAP_BEGIN_DECL -/* Unlike previous versions of this code, uint32 need not be exactly +/* Unlike previous versions of this code, ber_int_t need not be exactly 32 bits, merely 32 bits or more. Choosing a data type which is 32 bits instead of 64 is not important; speed is considerably more important. ANSI guarantees that "unsigned long" will be big enough, and always using it seems to have few disadvantages. */ -#ifndef LDAP_UINT32 -#define LDAP_UINT32 1 -typedef ac_uint4 uint32; -#endif +#define LUTIL_MD5_BYTES 16 struct lutil_MD5Context { - uint32 buf[4]; - uint32 bits[2]; + ber_uint_t buf[4]; + ber_uint_t bits[2]; unsigned char in[64]; }; -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_MD5Init LDAP_P(( struct lutil_MD5Context *context)); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_MD5Update LDAP_P(( struct lutil_MD5Context *context, unsigned char const *buf, - unsigned len)); + ber_len_t len)); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_MD5Final LDAP_P(( unsigned char digest[16], struct lutil_MD5Context *context)); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_MD5Transform LDAP_P(( - uint32 buf[4], + ber_uint_t buf[4], const unsigned char in[64])); /* diff --git a/include/lutil_sha1.h b/include/lutil_sha1.h index 07f82fb8eb..cb3e67c2b1 100644 --- a/include/lutil_sha1.h +++ b/include/lutil_sha1.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -24,11 +24,10 @@ LDAP_BEGIN_DECL * SHA-1 in C * By Steve Reid */ +#define LUTIL_SHA1_BYTES 20 -#ifndef LDAP_UINT32 -#define LDAP_UINT32 1 +/* This code assumes char are 8-bits and uint32 are 32-bits */ typedef ac_uint4 uint32; -#endif typedef struct { uint32 state[5]; @@ -36,31 +35,31 @@ typedef struct { unsigned char buffer[64]; } lutil_SHA1_CTX; -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_SHA1Transform LDAP_P((uint32 state[5], const unsigned char buffer[64])); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_SHA1Init LDAP_P((lutil_SHA1_CTX *context)); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_SHA1Update LDAP_P((lutil_SHA1_CTX *context, const unsigned char *data, uint32 len)); -LDAP_F( void ) +LIBLUTIL_F( void ) lutil_SHA1Final LDAP_P((unsigned char digest[20], lutil_SHA1_CTX *context)); -LDAP_F( char * ) +LIBLUTIL_F( char * ) lutil_SHA1End LDAP_P((lutil_SHA1_CTX *, char *)); -LDAP_F( char * ) +LIBLUTIL_F( char * ) lutil_SHA1File LDAP_P((char *, char *)); -LDAP_F( char * ) +LIBLUTIL_F( char * ) lutil_SHA1Data LDAP_P((const unsigned char *, size_t, char *)); diff --git a/include/portable.h.in b/include/portable.h.in index 3464300ce2..55786a172a 100644 --- a/include/portable.h.in +++ b/include/portable.h.in @@ -1,6 +1,6 @@ /* include/portable.h.in. Generated automatically from configure.in by autoheader. */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -14,6 +14,12 @@ /* end of preamble */ +#if !defined(SLAPD_SCHEMA_COMPAT) && !defined(SLAPD_SCHEMA_NOT_COMPAT) + /* define SLAPD_SCHEMA_COMPAT if you want old schema codes */ +#define SLAPD_SCHEMA_NOT_COMPAT 1 +#endif + + /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ @@ -24,10 +30,6 @@ /* Define to empty if the keyword does not work. */ #undef const -/* Define to the type of elements in the array set by `getgroups'. - Usually this is either `int' or `gid_t'. */ -#undef GETGROUPS_T - /* Define to `int' if doesn't define. */ #undef gid_t @@ -49,15 +51,6 @@ /* Define if on MINIX. */ #undef _MINIX -/* Define to `int' if doesn't define. */ -#undef mode_t - -/* Define to `long' if doesn't define. */ -#undef off_t - -/* Define to `int' if doesn't define. */ -#undef pid_t - /* Define if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE @@ -77,9 +70,6 @@ /* Define to the type of arg5 for select(). */ #undef SELECT_TYPE_ARG5 -/* Define to `unsigned' if doesn't define. */ -#undef size_t - /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS @@ -126,7 +116,7 @@ /* LDAP_API_FEATURE_X_OPENLDAP_REENTRANT LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE - LDAP_API_FEATURE_X_OPENLDAP_V2_DNS + LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ @@ -138,18 +128,12 @@ LBER_TAG_T */ -/* The number of bytes in a int. */ -#undef SIZEOF_INT - -/* The number of bytes in a long. */ -#undef SIZEOF_LONG - -/* The number of bytes in a short. */ -#undef SIZEOF_SHORT - /* Define if you have the bcopy function. */ #undef HAVE_BCOPY +/* Define if you have the chroot function. */ +#undef HAVE_CHROOT + /* Define if you have the closesocket function. */ #undef HAVE_CLOSESOCKET @@ -165,6 +149,9 @@ /* Define if you have the flock function. */ #undef HAVE_FLOCK +/* Define if you have the getaddrinfo function. */ +#undef HAVE_GETADDRINFO + /* Define if you have the getdtablesize function. */ #undef HAVE_GETDTABLESIZE @@ -186,6 +173,9 @@ /* Define if you have the getpass function. */ #undef HAVE_GETPASS +/* Define if you have the getpassphrase function. */ +#undef HAVE_GETPASSPHRASE + /* Define if you have the getpwnam function. */ #undef HAVE_GETPWNAM @@ -222,6 +212,9 @@ /* Define if you have the pthread_kill function. */ #undef HAVE_PTHREAD_KILL +/* Define if you have the pthread_rwlock_destroy function. */ +#undef HAVE_PTHREAD_RWLOCK_DESTROY + /* Define if you have the pthread_setconcurrency function. */ #undef HAVE_PTHREAD_SETCONCURRENCY @@ -342,27 +335,27 @@ /* Define if you have the header file. */ #undef HAVE_ASSERT_H +/* Define if you have the header file. */ +#undef HAVE_CONIO_H + /* Define if you have the header file. */ #undef HAVE_CRYPT_H /* Define if you have the header file. */ #undef HAVE_DB_H -/* Define if you have the header file. */ -#undef HAVE_DB1_DB_H - /* Define if you have the header file. */ #undef HAVE_DB_185_H /* Define if you have the header file. */ #undef HAVE_DES_H +/* Define if you have the header file. */ +#undef HAVE_DIRECT_H + /* Define if you have the header file. */ #undef HAVE_DIRENT_H -/* Define if you have the header file. */ -#undef HAVE_DMALLOC_H - /* Define if you have the header file. */ #undef HAVE_ERRNO_H @@ -381,15 +374,27 @@ /* Define if you have the header file. */ #undef HAVE_GRP_H +/* Define if you have the header file. */ +#undef HAVE_HEIM_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + /* Define if you have the header file. */ #undef HAVE_KERBEROSIV_DES_H /* Define if you have the header file. */ #undef HAVE_KERBEROSIV_KRB_H +/* Define if you have the header file. */ +#undef HAVE_KRB_ARCHAEOLOGY_H + /* Define if you have the header file. */ #undef HAVE_KRB_H +/* Define if you have the header file. */ +#undef HAVE_KRB5_H + /* Define if you have the header file. */ #undef HAVE_LIBUTIL_H @@ -417,6 +422,9 @@ /* Define if you have the header file. */ #undef HAVE_MEMORY_H +/* Define if you have the header file. */ +#undef HAVE_MINIX_CONFIG_H + /* Define if you have the header file. */ #undef HAVE_NCURSES_H @@ -432,6 +440,9 @@ /* Define if you have the header file. */ #undef HAVE_OPENSSL_SSL_H +/* Define if you have the header file. */ +#undef HAVE_PROCESS_H + /* Define if you have the header file. */ #undef HAVE_PSAP_H @@ -459,6 +470,9 @@ /* Define if you have the header file. */ #undef HAVE_RESOLV_H +/* Define if you have the header file. */ +#undef HAVE_SASL_H + /* Define if you have the header file. */ #undef HAVE_SCHED_H @@ -522,15 +536,15 @@ /* Define if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define if you have the header file. */ +#undef HAVE_SYS_UN_H + /* Define if you have the header file. */ #undef HAVE_SYSEXITS_H /* Define if you have the header file. */ #undef HAVE_SYSLOG_H -/* Define if you have the header file. */ -#undef HAVE_TCL_H - /* Define if you have the header file. */ #undef HAVE_TCPD_H @@ -546,24 +560,21 @@ /* Define if you have the header file. */ #undef HAVE_UNISTD_H +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + /* Define if you have the V3 library (-lV3). */ #undef HAVE_LIBV3 /* Define if you have the bind library (-lbind). */ #undef HAVE_LIBBIND -/* Define if you have the dmalloc library (-ldmalloc). */ -#undef HAVE_LIBDMALLOC - /* Define if you have the gen library (-lgen). */ #undef HAVE_LIBGEN /* Define if you have the inet library (-linet). */ #undef HAVE_LIBINET -/* Define if you have the ltdl library (-lltdl). */ -#undef HAVE_LIBLTDL - /* Define if you have the net library (-lnet). */ #undef HAVE_LIBNET @@ -591,6 +602,12 @@ /* defined to be the EXE extension */ #undef EXEEXT +/* define if you have AIX security lib */ +#undef HAVE_AIX_SECURITY + +/* define if you have libtool -ltdl */ +#undef HAVE_LIBLTDL + /* define if system uses EBCDIC instead of ASCII */ #undef HAVE_EBCDIC @@ -600,12 +617,33 @@ /* define if you have POSIX termios */ #undef HAVE_POSIX_TERMIOS -/* define if you have res_search() */ -#undef HAVE_RES_SEARCH +/* define if you have winsock */ +#undef HAVE_WINSOCK + +/* define if you have res_query() */ +#undef HAVE_RES_QUERY + +/* define if you have HEIMDAL Kerberos */ +#undef HAVE_HEIMDAL_KERBEROS + +/* define if you have Kerberos V */ +#undef HAVE_KRB5 + +/* define if you have Kerberos V with IV support */ +#undef HAVE_KRB425 + +/* define if you have Kerberos IV */ +#undef HAVE_KRB4 /* define if you have Kerberos des_debug */ #undef HAVE_DES_DEBUG +/* define if you have Kerberos IV */ +#undef HAVE_KRB4 + +/* define if you have Kth Kerberos */ +#undef HAVE_KTH_KERBEROS + /* define if you have Kerberos */ #undef HAVE_KERBEROS @@ -627,6 +665,15 @@ /* set to the number of arguments gethostbyaddr_r() expects */ #undef GETHOSTBYADDR_R_NARGS +/* if you have NT Threads */ +#undef HAVE_NT_THREADS + +/* if you have NT Service Manager */ +#undef HAVE_NT_SERVICE_MANAGER + +/* if you have NT Event Log */ +#undef HAVE_NT_EVENT_LOG + /* define if pthreads API compatible with final spec */ #undef HAVE_PTHREADS_FINAL @@ -666,16 +713,10 @@ /* define if you have (or want) no threads */ #undef NO_THREADS -/* define if Berkeley DBv2 is available */ -#undef HAVE_BERKELEY_DB2 +/* define if Berkeley DB has DB_THREAD support */ +#undef HAVE_BERKELEY_DB_THREAD -/* define this to use DBHASH w/ LDBM backend */ -#undef LDBM_USE_DBHASH - -/* define this to use DBBTREE w/ LDBM backend */ -#undef LDBM_USE_DBBTREE - -/* define if Berkeley DB is available */ +/* define this if Berkeley DB is available */ #undef HAVE_BERKELEY_DB /* define this to use DBHASH w/ LDBM backend */ @@ -708,6 +749,9 @@ /* define if you have Cyrus SASL */ #undef HAVE_CYRUS_SASL +/* set to urandom device */ +#undef URANDOM_DEVICE + /* define if you actually have FreeBSD fetch(3) */ #undef HAVE_FETCH @@ -720,15 +764,33 @@ /* define if setproctitle(3) is available */ #undef HAVE_SETPROCTITLE +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + /* Define if system has ptrdiff_t type */ #undef HAVE_PTRDIFF_T -/* define to atomic type if sig_atomic_t is not available */ -#undef sig_atomic_t +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define to `signed int' if does not define. */ +#undef ssize_t + +/* Define to `char *' if does not define. */ +#undef caddr_t /* define to int if socklen_t is not available */ #undef socklen_t +/* define to atomic type if sig_atomic_t is not available */ +#undef sig_atomic_t + /* define if struct passwd has pw_gecos */ #undef HAVE_PW_GECOS @@ -744,9 +806,27 @@ /* define if cross compiling */ #undef CROSS_COMPILING +/* The number of bytes in type short */ +#undef SIZEOF_SHORT + +/* The number of bytes in type int */ +#undef SIZEOF_INT + +/* The number of bytes in type long */ +#undef SIZEOF_LONG + /* define to you inet_aton(3) is available */ #undef HAVE_INET_ATON +/* if you have spawnlp() */ +#undef HAVE_SPAWNLP + +/* define to snprintf routine */ +#undef snprintf + +/* define to vsnprintf routine */ +#undef vsnprintf + /* define if sys_errlist is not declared in stdio.h or errno.h */ #undef DECL_SYS_ERRLIST @@ -771,12 +851,24 @@ /* define to support CLDAP */ #undef LDAP_CONNECTIONLESS -/* define to support crypt(3) passwords */ -#undef SLAPD_CRYPT +/* define to support PF_UNIX */ +#undef LDAP_PF_UNIX + +/* define to support PF_INET6 */ +#undef LDAP_PF_INET6 /* define to support cleartext passwords */ #undef SLAPD_CLEARTEXT +/* define to support crypt(3) passwords */ +#undef SLAPD_CRYPT + +/* define to support Kerberos passwords */ +#undef SLAPD_KPASSWD + +/* define to support SASL passwords */ +#undef SLAPD_SPASSWD + /* define to support multimaster replication */ #undef SLAPD_MULTIMASTER @@ -789,17 +881,14 @@ /* define to support per-object ACIs */ #undef SLAPD_ACI_ENABLED -/* define to support discrete rights in ACIs */ -#undef SLAPD_ACI_DISCRETE_RIGHTS - /* define to support modules */ #undef SLAPD_MODULES -/* define to support BDB2 backend */ -#undef SLAPD_BDB2 +/* define to support DNS SRV backend */ +#undef SLAPD_DNSSRV -/* define to support dynamic BDB2 backend */ -#undef SLAPD_BDB2_DYNAMIC +/* define to support dynamic DNS SRV backend */ +#undef SLAPD_DNSSRV_DYNAMIC /* define to support LDAP backend */ #undef SLAPD_LDAP @@ -819,26 +908,20 @@ /* define to support dynamic PASSWD backend */ #undef SLAPD_PASSWD_DYNAMIC -/* define to support PERL backend */ -#undef SLAPD_PERL - -/* define to support dynamic PERL backend */ -#undef SLAPD_PERL_DYNAMIC - /* define to support SHELL backend */ #undef SLAPD_SHELL /* define to support dynamic SHELL backend */ #undef SLAPD_SHELL_DYNAMIC -/* define to support TCL backend */ -#undef SLAPD_TCL - -/* define to support dynamic TCL backend */ -#undef SLAPD_TCL_DYNAMIC /* begin of postamble */ +#ifdef _WIN32 + /* don't suck in all of the win32 api */ +# define WIN32_LEAN_AND_MEAN 1 +#endif + #ifndef __NEED_PROTOTYPES /* force LDAP_P to always include prototypes */ #define __NEED_PROTOTYPES 1 diff --git a/include/portable.nt b/include/portable.nt index af077ef6f2..080089649f 100644 --- a/include/portable.nt +++ b/include/portable.nt @@ -2,7 +2,7 @@ /* include/portable.h.nt -- manually updated of MS NT (MS VC5) */ /* synced with portable.h.in 1.24 */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -16,24 +16,33 @@ /* end of preamble */ +/* comment this out if you don't have Cyrus SASL */ +#define HAVE_CYRUS_SASL 1 + /* --------------------------------------------------- */ /* begin of MSVC5 specific entries */ #define OPENLDAP_PACKAGE "OpenLDAP" #define OPENLDAP_VERSION "-devel" #define EXEEXT ".exe" -#define LDAP_DIRSEP "\\" /* don't suck in all of the win32 api */ #define WIN32_LEAN_AND_MEAN -#ifdef _WINNT -/* WindowsNT specific features */ +#if defined(_WIN32) && !defined(_WINNT) && !defined(_WIN95) +#define _WINNT +#endif + +#if defined( _MT ) && defined( _WINNT ) +#define HAVE_NT_THREADS 1 +#else +#define NO_THREADS 1 +#endif + +#ifdef HAVE_NT_THREADS +/* enable WINNT specific features only if we have NT THREADS */ #define HAVE_NT_SERVICE_MANAGER 1 #define HAVE_NT_EVENT_LOG 1 - -#elif _WIN95 -/* Windows95 specific features */ #endif #if defined( _DEBUG ) && !defined( LDAP_DEBUG ) @@ -49,7 +58,6 @@ #define strcasecmp stricmp #define strncasecmp strnicmp -#define strdup _strdup #define snprintf _snprintf #define vsnprintf _vsnprintf @@ -58,20 +66,8 @@ /* define type for caddr_t */ typedef char * caddr_t; -#define ssize_t signed int - -#define LOG_DEBUG 0 -#define openlog( a, b ) -#define closelog() - -#define FD_SETSIZE 1024 - -/* we have NT threads */ -#ifdef _MT -#define HAVE_NT_THREADS 1 -#else -#define NO_THREADS 1 -#endif +/* define type for ssize_t */ +typedef signed int ssize_t; /* we have spawnlp instead of fork/execlp */ #define HAVE_SPAWNLP 1 @@ -94,8 +90,8 @@ typedef char * caddr_t; /* we have */ #define HAVE_PROCESS_H 1 -#define LDAP_SIGUSR1 SIGILL -#define LDAP_SIGUSR2 SIGTERM +/* we have */ +#define HAVE_WINCRYPT_H 1 #define MAXPATHLEN _MAX_PATH @@ -210,10 +206,7 @@ typedef char * caddr_t; #define HAVE_SYS_ERRLIST 1 /* define if you have berkeley db */ -/* #undef HAVE_BERKELEY_DB */ - -/* define if you have berkeley db2 */ -#define HAVE_BERKELEY_DB2 1 +#define HAVE_BERKELEY_DB 1 /* define if you have crypt */ /* #undef HAVE_CRYPT */ @@ -266,9 +259,6 @@ typedef char * caddr_t; /* define this for ACL Group support */ #define SLAPD_ACLGROUPS 1 -/* define this to use SLAPD Berkeley DB2 backend */ -/* #define SLAPD_BDB2 1 */ - /* define this for ClearText password support */ #define SLAPD_CLEARTEXT 1 @@ -281,6 +271,9 @@ typedef char * caddr_t; /* define this to use SLAPD LDBM backend */ #define SLAPD_LDBM 1 +/* define this to use SLAPD SQL backend */ +/* #undef SLAPD_SQL */ + /* define this to use SLAPD passwd backend */ /* #undef SLAPD_PASSWD */ @@ -296,9 +289,6 @@ typedef char * caddr_t; /* define this for per-object ACIs */ /* #undef SLAPD_ACI_ENABLED */ -/* define this for discrete rights in ACIs */ -/* #undef SLAPD_ACI_DISCRETE_RIGHTS */ - /* define this to use SLAPD shell backend */ /* #undef SLAPD_SHELL */ @@ -403,12 +393,12 @@ typedef char * caddr_t; /* Define if you have the sigset function. */ /* #undef HAVE_SIGSET */ -/* Define if you have the snprintf function. */ -/* #undef HAVE_SNPRINTF */ - /* Define if you have the socket function. */ #define HAVE_SOCKET 1 +/* Define if you have the snprintf function. */ +#define HAVE_SNPRINTF 1 + /* Define if you have the strdup function. */ #define HAVE_STRDUP 1 @@ -446,7 +436,7 @@ typedef char * caddr_t; /* #undef HAVE_SYSCONF */ /* Define if you have the tempnam function. */ -/* #undef HAVE_TEMPNAM */ +#define HAVE_TEMPNAM 1 /* Define if you have the thr_getconcurrency function. */ /* #undef HAVE_THR_GETCONCURRENCY */ @@ -527,7 +517,7 @@ typedef char * caddr_t; #define HAVE_MALLOC_H 1 /* Define if you have the header file. */ -/* #define HAVE_MEMORY_H */ +#define HAVE_MEMORY_H 1 /* Define if you have the header file. */ /* #undef HAVE_NCURSES_H */ diff --git a/include/setup.dsp b/include/setup.dsp index 2114f7205e..299f29cdeb 100644 --- a/include/setup.dsp +++ b/include/setup.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) External Target" 0x0106 -CFG=setup - Win32 Debug +CFG=setup - Win32 DLL Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,17 @@ CFG=setup - Win32 Debug !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "setup.mak" CFG="setup - Win32 Debug" +!MESSAGE NMAKE /f "setup.mak" CFG="setup - Win32 DLL Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "setup - Win32 Release" (based on "Win32 (x86) External Target") !MESSAGE "setup - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE "setup - Win32 Single Debug" (based on "Win32 (x86) External Target") +!MESSAGE "setup - Win32 Single Release" (based on\ + "Win32 (x86) External Target") +!MESSAGE "setup - Win32 DLL Debug" (based on "Win32 (x86) External Target") +!MESSAGE "setup - Win32 DLL Release" (based on "Win32 (x86) External Target") !MESSAGE # Begin Project @@ -63,17 +68,105 @@ CFG=setup - Win32 Debug # PROP Bsc_Name "setup.bsc" # PROP Target_Dir "" +!ELSEIF "$(CFG)" == "setup - Win32 Single Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "setup___" +# PROP BASE Intermediate_Dir "setup___" +# PROP BASE Cmd_Line "NMAKE /f setup.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "setup.txt" +# PROP BASE Bsc_Name "setup.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "setup___" +# PROP Intermediate_Dir "setup___" +# PROP Cmd_Line "NMAKE /f setup.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "setup.txt" +# PROP Bsc_Name "setup.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "setup - Win32 Single Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "setup__0" +# PROP BASE Intermediate_Dir "setup__0" +# PROP BASE Cmd_Line "NMAKE /f setup.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "setup.txt" +# PROP BASE Bsc_Name "setup.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "setup__0" +# PROP Intermediate_Dir "setup__0" +# PROP Cmd_Line "NMAKE /f setup.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "setup.txt" +# PROP Bsc_Name "setup.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "setup - Win32 DLL Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "setup__1" +# PROP BASE Intermediate_Dir "setup__1" +# PROP BASE Cmd_Line "NMAKE /f setup.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "setup.txt" +# PROP BASE Bsc_Name "setup.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "setup__1" +# PROP Intermediate_Dir "setup__1" +# PROP Cmd_Line "NMAKE /f setup.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "setup.txt" +# PROP Bsc_Name "setup.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "setup - Win32 DLL Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "setup__2" +# PROP BASE Intermediate_Dir "setup__2" +# PROP BASE Cmd_Line "NMAKE /f setup.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "setup.txt" +# PROP BASE Bsc_Name "setup.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "setup__2" +# PROP Intermediate_Dir "setup__2" +# PROP Cmd_Line "NMAKE /f setup.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "setup.txt" +# PROP Bsc_Name "setup.bsc" +# PROP Target_Dir "" + !ENDIF # Begin Target # Name "setup - Win32 Release" # Name "setup - Win32 Debug" +# Name "setup - Win32 Single Debug" +# Name "setup - Win32 Single Release" +# Name "setup - Win32 DLL Debug" +# Name "setup - Win32 DLL Release" !IF "$(CFG)" == "setup - Win32 Release" !ELSEIF "$(CFG)" == "setup - Win32 Debug" +!ELSEIF "$(CFG)" == "setup - Win32 Single Debug" + +!ELSEIF "$(CFG)" == "setup - Win32 Single Release" + +!ELSEIF "$(CFG)" == "setup - Win32 DLL Debug" + +!ELSEIF "$(CFG)" == "setup - Win32 DLL Release" + !ENDIF # Begin Source File diff --git a/include/setup.mak b/include/setup.mak index 9e3b1c3a53..a24056e9ed 100644 --- a/include/setup.mak +++ b/include/setup.mak @@ -1,6 +1,6 @@ # $OpenLDAP$ # -# Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +# Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. # COPYING RESTRICTIONS APPLY, see COPYRIGHT file # diff --git a/include/srchpref.h b/include/srchpref.h index e3523b0051..4731597f05 100644 --- a/include/srchpref.h +++ b/include/srchpref.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -78,22 +78,22 @@ struct ldap_searchobj { #define LDAP_SEARCHPREF_ERR_FILE 4 -LDAP_F( int ) +LIBLDAP_F( int ) ldap_init_searchprefs LDAP_P(( char *file, struct ldap_searchobj **solistp )); -LDAP_F( int ) +LIBLDAP_F( int ) ldap_init_searchprefs_buf LDAP_P(( char *buf, ber_len_t buflen, struct ldap_searchobj **solistp )); -LDAP_F( void ) +LIBLDAP_F( void ) ldap_free_searchprefs LDAP_P(( struct ldap_searchobj *solist )); -LDAP_F( struct ldap_searchobj * ) +LIBLDAP_F( struct ldap_searchobj * ) ldap_first_searchobj LDAP_P(( struct ldap_searchobj *solist )); -LDAP_F( struct ldap_searchobj * ) +LIBLDAP_F( struct ldap_searchobj * ) ldap_next_searchobj LDAP_P(( struct ldap_searchobj *sollist, struct ldap_searchobj *so )); diff --git a/include/sysexits-compat.h b/include/sysexits-compat.h index 4855154980..578415657e 100644 --- a/include/sysexits-compat.h +++ b/include/sysexits-compat.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/libraries/Makefile.in b/libraries/Makefile.in index d911128bea..46d260a0f5 100644 --- a/libraries/Makefile.in +++ b/libraries/Makefile.in @@ -1,8 +1,10 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## Libraries Makefile for OpenLDAP -SUBDIRS= liblutil libldif liblber libldap libavl libldbm libldap_r +SUBDIRS= liblutil libldif \ + liblber libldap libldap_r \ + libavl libldbm liblunicode diff --git a/libraries/libavl/Makefile.in b/libraries/libavl/Makefile.in index 92af71fa0d..e641c50c31 100644 --- a/libraries/libavl/Makefile.in +++ b/libraries/libavl/Makefile.in @@ -1,4 +1,6 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## LIBAVL ## diff --git a/libraries/libavl/avl.c b/libraries/libavl/avl.c index eb30049ef4..63a543f8e4 100644 --- a/libraries/libavl/avl.c +++ b/libraries/libavl/avl.c @@ -1,7 +1,7 @@ /* avl.c - routines to implement an avl tree */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* diff --git a/libraries/libavl/libavl.dsp b/libraries/libavl/libavl.dsp new file mode 100644 index 0000000000..c1077b59db --- /dev/null +++ b/libraries/libavl/libavl.dsp @@ -0,0 +1,137 @@ +# Microsoft Developer Studio Project File - Name="libavl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libavl - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libavl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libavl.mak" CFG="libavl - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libavl - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libavl - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libavl - Win32 Single Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libavl - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "libavl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\libavl" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libavl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\libavl" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libavl - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libavl__" +# PROP BASE Intermediate_Dir "libavl__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\libavl" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libavl - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libavl_0" +# PROP BASE Intermediate_Dir "libavl_0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\libavl" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libavl - Win32 Release" +# Name "libavl - Win32 Debug" +# Name "libavl - Win32 Single Debug" +# Name "libavl - Win32 Single Release" +# Begin Source File + +SOURCE=.\avl.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\avl.h +# End Source File +# End Target +# End Project diff --git a/libraries/libavl/testavl.c b/libraries/libavl/testavl.c index 94540c304d..de948d8bcd 100644 --- a/libraries/libavl/testavl.c +++ b/libraries/libavl/testavl.c @@ -1,5 +1,9 @@ /* testavl.c - Test Tim Howes AVL code */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/libraries/libavl/testavl.dsp b/libraries/libavl/testavl.dsp new file mode 100644 index 0000000000..ecc7045029 --- /dev/null +++ b/libraries/libavl/testavl.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="testavl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testavl - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testavl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testavl.mak" CFG="testavl - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testavl - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testavl - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "testavl - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "testavl - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testavl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\testavl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "testavl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testavl_" +# PROP BASE Intermediate_Dir "testavl_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\testavl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "testavl - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testavl_" +# PROP BASE Intermediate_Dir "testavl_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\testavl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "testavl - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "testavl0" +# PROP BASE Intermediate_Dir "testavl0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\testavl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "testavl - Win32 Release" +# Name "testavl - Win32 Debug" +# Name "testavl - Win32 Single Debug" +# Name "testavl - Win32 Single Release" +# Begin Source File + +SOURCE=.\testavl.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblber/Makefile.in b/libraries/liblber/Makefile.in index 4808224b22..0c687d843d 100644 --- a/libraries/liblber/Makefile.in +++ b/libraries/liblber/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## LIBLBER @@ -8,10 +8,13 @@ LIBRARY = liblber.la XLIBRARY = ../liblber.a +NT_SRCS = nt_err.c +NT_OBJS = nt_err.lo + SRCS= assert.c decode.c encode.c io.c bprint.c \ - memory.c options.c sockbuf.c + memory.c options.c sockbuf.c $(@PLAT@_SRCS) OBJS= assert.lo decode.lo encode.lo io.lo bprint.lo \ - memory.lo options.lo sockbuf.lo + memory.lo options.lo sockbuf.lo $(@PLAT@_OBJS) XSRCS= version.c PROGRAMS= dtest etest idtest @@ -22,6 +25,17 @@ LDAP_LIBDIR= ../../libraries XLIBS = -llber XXLIBS = +LINKAGE = @LT_LIB_LINKAGE@ + +NT_DYN_TEST_DEFS = -DLIBLBER_DECL=dllimport + +# Extras for building the library +EXTRA_DEFS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) +EXTRA_LIBS = + +# Only the test programs will pick up these defs. +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_TEST_DEFS) + dtest: $(LIBRARY) dtest.o $(LTLINK) $(LDFLAGS) -o $@ dtest.o $(LIBS) etest: $(LIBRARY) etest.o @@ -30,6 +44,6 @@ idtest: $(LIBRARY) idtest.o $(LTLINK) $(LDFLAGS) -o $@ idtest.o $(LIBS) install-local: FORCE - -$(MKDIR) $(libdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(libdir) + -$(MKDIR) $(DESTDIR)$(libdir) + $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) diff --git a/libraries/liblber/assert.c b/libraries/liblber/assert.c index 50b70dd53b..c0530ad6ee 100644 --- a/libraries/liblber/assert.c +++ b/libraries/liblber/assert.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1999-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only diff --git a/libraries/liblber/bprint.c b/libraries/liblber/bprint.c index eb8808563c..e7569dc377 100644 --- a/libraries/liblber/bprint.c +++ b/libraries/liblber/bprint.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -12,21 +12,51 @@ #include #include -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" +/* + * We don't just set ber_pvt_err_file to stderr here, because in NT, + * stderr is a symbol imported from a DLL. As such, the compiler + * doesn't recognize the symbol as having a constant address. Thus + * we set ber_pvt_err_file to stderr later, when it first gets + * referenced. + */ +FILE *ber_pvt_err_file; + +/* + * ber errno + */ +BER_ERRNO_FN ber_int_errno_fn; + +int * ber_errno_addr(void) +{ + static int ber_int_errno = LBER_ERROR_NONE; + + if( ber_int_errno_fn ) { + return (*ber_int_errno_fn)(); + } + + return &ber_int_errno; +} + /* * Print stuff */ -static void -ber_error_print( char *data ) +void ber_error_print( LDAP_CONST char *data ) { assert( data != NULL ); - fputs( data, stderr ); - fflush( stderr ); + if (!ber_pvt_err_file) ber_pvt_err_file = stderr; + + fputs( data, ber_pvt_err_file ); + + /* Print to both streams */ + if (ber_pvt_err_file != stderr) { + fputs( data, stderr ); + fflush( stderr ); + } + + fflush( ber_pvt_err_file ); } BER_LOG_PRINT_FN ber_pvt_log_print = ber_error_print; @@ -114,7 +144,7 @@ ber_bprint( assert( data != NULL ); - memset( out, 0, BPLEN ); + memset( out, '\0', BPLEN ); for ( ;; ) { if ( len < 1 ) { sprintf( buf, "\t%s\n", ( i == 0 ) ? "(end)" : out ); @@ -141,7 +171,7 @@ ber_bprint( char data[128 + BPLEN]; sprintf( data, "\t%s\n", out ); (*ber_pvt_log_print)(data); - memset( out, 0, BPLEN ); + memset( out, '\0', BPLEN ); i = 0; continue; } @@ -153,7 +183,7 @@ int ber_log_dump( int errlvl, int loglvl, - const BerElement *ber, + BerElement *ber, int inout ) { assert( ber != NULL ); @@ -169,7 +199,7 @@ ber_log_dump( void ber_dump( - LDAP_CONST BerElement *ber, + BerElement *ber, int inout ) { char buf[132]; @@ -201,7 +231,7 @@ int ber_log_sos_dump( int errlvl, int loglvl, - const Seqorset *sos ) + Seqorset *sos ) { assert( sos != NULL ); @@ -215,7 +245,7 @@ ber_log_sos_dump( void ber_sos_dump( - LDAP_CONST Seqorset *sos ) + Seqorset *sos ) { char buf[132]; diff --git a/libraries/liblber/decode.c b/libraries/liblber/decode.c index e2c204d793..99ff60b908 100644 --- a/libraries/liblber/decode.c +++ b/libraries/liblber/decode.c @@ -1,7 +1,7 @@ /* decode.c - ber input decoding routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -26,9 +26,6 @@ #include #include -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" static ber_len_t ber_getnint LDAP_P(( @@ -42,7 +39,6 @@ ber_get_tag( BerElement *ber ) { unsigned char xbyte; ber_tag_t tag; - char *tagp; unsigned int i; assert( ber != NULL ); @@ -51,16 +47,17 @@ ber_get_tag( BerElement *ber ) if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); + tag = xbyte; + if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) - return( (ber_tag_t) xbyte ); + return tag; - tagp = (char *) &tag; - tagp[0] = xbyte; for ( i = 1; i < sizeof(ber_tag_t); i++ ) { if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); - tagp[i] = xbyte; + tag <<= 8; + tag |= 0x00ffUL & (ber_tag_t) xbyte; if ( ! (xbyte & LBER_MORE_TAG_MASK) ) break; @@ -70,8 +67,7 @@ ber_get_tag( BerElement *ber ) if ( i == sizeof(ber_tag_t) ) return( LBER_DEFAULT ); - /* want leading, not trailing 0's */ - return( tag >> (sizeof(ber_tag_t) - i - 1) ); + return tag; } ber_tag_t @@ -79,9 +75,8 @@ ber_skip_tag( BerElement *ber, ber_len_t *len ) { ber_tag_t tag; unsigned char lc; - ber_len_t noctets; - int diff; - ber_len_t netlen; + ber_len_t i, noctets; + unsigned char netlen[sizeof(ber_len_t)]; assert( ber != NULL ); assert( len != NULL ); @@ -97,6 +92,8 @@ ber_skip_tag( BerElement *ber, ber_len_t *len ) * 2) primitive encodings used whenever possible */ + *len = 0; + /* * First, we read the tag. */ @@ -111,18 +108,25 @@ ber_skip_tag( BerElement *ber, ber_len_t *len ) * greater than what we can hold in a ber_len_t. */ - *len = netlen = 0; if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) return( LBER_DEFAULT ); + if ( lc & 0x80U ) { noctets = (lc & 0x7fU); - if ( noctets > sizeof(ber_len_t) ) + + if ( noctets > sizeof(ber_len_t) ) { return( LBER_DEFAULT ); - diff = sizeof(ber_len_t) - noctets; - if ( (unsigned) ber_read( ber, (char *) &netlen + diff, noctets ) - != noctets ) + } + + if( (unsigned) ber_read( ber, netlen, noctets ) != noctets ) { return( LBER_DEFAULT ); - *len = LBER_LEN_NTOH( netlen ); + } + + for( i = 0; i < noctets; i++ ) { + *len <<= 8; + *len |= netlen[i]; + } + } else { *len = lc; } @@ -132,7 +136,7 @@ ber_skip_tag( BerElement *ber, ber_len_t *len ) ber_tag_t ber_peek_tag( - LDAP_CONST BerElement *ber_in, + BerElement *ber_in, ber_len_t *len ) { ber_tag_t tag; @@ -141,6 +145,8 @@ ber_peek_tag( assert( ber_in != NULL ); assert( BER_VALID( ber_in ) ); + *len = 0; + ber = ber_dup( ber_in ); if( ber == NULL ) { @@ -222,6 +228,14 @@ ber_get_int( return( tag ); } +ber_tag_t +ber_get_enum( + BerElement *ber, + ber_int_t *num ) +{ + return ber_get_int( ber, num ); +} + ber_tag_t ber_get_stringb( BerElement *ber, @@ -231,10 +245,6 @@ ber_get_stringb( ber_len_t datalen; ber_tag_t tag; -#ifdef STR_TRANSLATION - char *transbuf; -#endif /* STR_TRANSLATION */ - assert( ber != NULL ); assert( BER_VALID( ber ) ); @@ -248,25 +258,6 @@ ber_get_stringb( buf[datalen] = '\0'; -#ifdef STR_TRANSLATION - if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 - && ber->ber_decode_translate_proc ) { - transbuf = buf; - ++datalen; - if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen, - 0 ) != 0 ) { - return( LBER_DEFAULT ); - } - if ( datalen > *len ) { - LBER_FREE( transbuf ); - return( LBER_DEFAULT ); - } - SAFEMEMCPY( buf, transbuf, datalen ); - LBER_FREE( transbuf ); - --datalen; - } -#endif /* STR_TRANSLATION */ - *len = datalen; return( tag ); } @@ -297,19 +288,6 @@ ber_get_stringa( BerElement *ber, char **buf ) } (*buf)[datalen] = '\0'; -#ifdef STR_TRANSLATION - if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 - && ber->ber_decode_translate_proc ) { - ++datalen; - if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 ) - != 0 ) { - LBER_FREE( *buf ); - *buf = NULL; - return( LBER_DEFAULT ); - } - } -#endif /* STR_TRANSLATION */ - return( tag ); } @@ -346,20 +324,6 @@ ber_get_stringal( BerElement *ber, struct berval **bv ) ((*bv)->bv_val)[len] = '\0'; (*bv)->bv_len = len; -#ifdef STR_TRANSLATION - if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 - && ber->ber_decode_translate_proc ) { - ++len; - if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val), - &len, 1 ) != 0 ) { - ber_bvfree( *bv ); - *bv = NULL; - return( LBER_DEFAULT ); - } - (*bv)->bv_len = len - 1; - } -#endif /* STR_TRANSLATION */ - return( tag ); } @@ -470,7 +434,7 @@ ber_tag_t ber_next_element( BerElement *ber, ber_len_t *len, - char *last ) + LDAP_CONST char *last ) { assert( ber != NULL ); assert( len != NULL ); @@ -764,17 +728,3 @@ ber_scanf ( BerElement *ber, return( rc ); } - - -#ifdef STR_TRANSLATION -void -ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc, - BERTranslateProc decode_proc ) -{ - assert( ber != NULL ); - assert( BER_VALID( ber ) ); - - ber->ber_encode_translate_proc = encode_proc; - ber->ber_decode_translate_proc = decode_proc; -} -#endif /* STR_TRANSLATION */ diff --git a/libraries/liblber/dtest.c b/libraries/liblber/dtest.c index 749958b1ee..633d42ed7e 100644 --- a/libraries/liblber/dtest.c +++ b/libraries/liblber/dtest.c @@ -1,7 +1,7 @@ /* dtest.c - lber decoding test program */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -47,6 +47,7 @@ main( int argc, char **argv ) BerElement *ber; Sockbuf *sb; + int fd; /* enable debugging */ int ival = -1; @@ -62,7 +63,10 @@ main( int argc, char **argv ) cshow( stdout ); #endif - sb = ber_sockbuf_alloc_fd( fileno(stdin) ); + sb = ber_sockbuf_alloc(); + fd = fileno( stdin ); + ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, + (void *)&fd ); if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) { perror( "ber_alloc_t" ); diff --git a/libraries/liblber/dtest.dsp b/libraries/liblber/dtest.dsp new file mode 100644 index 0000000000..ad00d2c10c --- /dev/null +++ b/libraries/liblber/dtest.dsp @@ -0,0 +1,200 @@ +# Microsoft Developer Studio Project File - Name="dtest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dtest - Win32 DLL Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dtest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dtest.mak" CFG="dtest - Win32 DLL Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dtest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dtest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "dtest - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "dtest - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "dtest - Win32 DLL Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "dtest - Win32 DLL Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dtest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\dtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "dtest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dtest___" +# PROP BASE Intermediate_Dir "dtest___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\dtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "dtest - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dtest___" +# PROP BASE Intermediate_Dir "dtest___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\dtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "dtest - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "dtest__0" +# PROP BASE Intermediate_Dir "dtest__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\dtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "dtest - Win32 DLL Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dtest___" +# PROP BASE Intermediate_Dir "dtest___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\DLLDebug" +# PROP Intermediate_Dir "..\..\DLLDebug\dtest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "dtest - Win32 DLL Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "dtest__0" +# PROP BASE Intermediate_Dir "dtest__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "dtest__0" +# PROP Intermediate_Dir "dtest__0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ENDIF + +# Begin Target + +# Name "dtest - Win32 Release" +# Name "dtest - Win32 Debug" +# Name "dtest - Win32 Single Debug" +# Name "dtest - Win32 Single Release" +# Name "dtest - Win32 DLL Debug" +# Name "dtest - Win32 DLL Release" +# Begin Source File + +SOURCE=.\dtest.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblber/encode.c b/libraries/liblber/encode.c index ef515a3369..68f321d8be 100644 --- a/libraries/liblber/encode.c +++ b/libraries/liblber/encode.c @@ -1,7 +1,7 @@ /* encode.c - ber output encoding routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -26,9 +26,6 @@ #include #include -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" static int ber_put_len LDAP_P(( @@ -73,17 +70,21 @@ ber_put_tag( { int rc; ber_len_t taglen; - ber_tag_t ntag; + ber_len_t i; + unsigned char nettag[sizeof(ber_tag_t)]; assert( ber != NULL ); assert( BER_VALID( ber ) ); taglen = ber_calc_taglen( tag ); - ntag = LBER_TAG_HTON( tag ); + for( i=0; i>= 8; + } rc = ber_write( ber, - ((char *) &ntag) + sizeof(ber_tag_t) - taglen, + &nettag[sizeof(ber_tag_t) - taglen], taglen, nosos ); return rc; @@ -118,10 +119,11 @@ ber_calc_lenlen( ber_len_t len ) static int ber_put_len( BerElement *ber, ber_len_t len, int nosos ) { - int i; + int rc; + int i,j; char lenlen; ber_len_t mask; - ber_len_t netlen; + unsigned char netlen[sizeof(ber_len_t)]; assert( ber != NULL ); assert( BER_VALID( ber ) ); @@ -151,19 +153,24 @@ ber_put_len( BerElement *ber, ber_len_t len, int nosos ) lenlen = (unsigned char) ++i; if ( lenlen > 4 ) return( -1 ); + lenlen |= 0x80UL; /* write the length of the length */ if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) return( -1 ); + for( j=0; j>= 8; + } + /* write the length itself */ - netlen = LBER_LEN_HTON( len ); - if ( ber_write( ber, (char *) &netlen + (sizeof(ber_len_t) - i), i, nosos ) - != i ) - return( -1 ); + rc = ber_write( ber, + &netlen[sizeof(ber_len_t)-i], + i, nosos ); - return( i + 1 ); + return rc == i ? i+1 : -1; } static int @@ -172,9 +179,11 @@ ber_put_int_or_enum( ber_int_t num, ber_tag_t tag ) { - int i, sign; + int rc; + int i, j, sign; ber_len_t len, lenlen, taglen; - ber_uint_t unum, netnum, mask; + ber_uint_t unum, mask; + unsigned char netnum[sizeof(ber_uint_t)]; assert( ber != NULL ); assert( BER_VALID( ber ) ); @@ -216,13 +225,18 @@ ber_put_int_or_enum( if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) return( -1 ); i++; - netnum = LBER_INT_HTON( unum ); - if ( ber_write( ber, (char *) &netnum + (sizeof(ber_int_t) - i), i, 0 ) - != i ) - return( -1 ); + + for( j=0; j>= 8; + } + + rc = ber_write( ber, + &netnum[sizeof(ber_int_t) - i], + i, 0 ); /* length of tag + length + contents */ - return( taglen + lenlen + i ); + return rc == i ? taglen + lenlen + i : -1; } int @@ -264,9 +278,6 @@ ber_put_ostring( { ber_len_t taglen, lenlen; int rc; -#ifdef STR_TRANSLATION - int free_str; -#endif /* STR_TRANSLATION */ assert( ber != NULL ); assert( str != NULL ); @@ -279,19 +290,6 @@ ber_put_ostring( if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) return( -1 ); -#ifdef STR_TRANSLATION - if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 && - ber->ber_encode_translate_proc ) { - if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 ) - != 0 ) { - return( -1 ); - } - free_str = 1; - } else { - free_str = 0; - } -#endif /* STR_TRANSLATION */ - if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 || (ber_len_t) ber_write( ber, str, len, 0 ) != len ) { rc = -1; @@ -300,12 +298,6 @@ ber_put_ostring( rc = taglen + lenlen + len; } -#ifdef STR_TRANSLATION - if ( free_str ) { - LBER_FREE( str ); - } -#endif /* STR_TRANSLATION */ - return( rc ); } @@ -402,8 +394,8 @@ ber_put_boolean( ber_tag_t tag ) { ber_len_t taglen; - unsigned char trueval = 0xFFU; - unsigned char falseval = 0x00U; + unsigned char trueval = (unsigned char) -1; + unsigned char falseval = 0; assert( ber != NULL ); assert( BER_VALID( ber ) ); @@ -484,7 +476,9 @@ ber_start_set( BerElement *ber, ber_tag_t tag ) static int ber_put_seqorset( BerElement *ber ) { - ber_len_t len, netlen; + int rc; + ber_len_t len; + unsigned char netlen[sizeof(ber_len_t)]; ber_len_t taglen, lenlen; unsigned char ltag = 0x80U + FOUR_BYTE_LEN - 1; Seqorset *next; @@ -502,16 +496,27 @@ ber_put_seqorset( BerElement *ber ) */ len = (*sos)->sos_clen; - netlen = LBER_LEN_HTON( len ); + if ( sizeof(ber_len_t) > 4 && len > 0xffffffffUL ) return( -1 ); if ( ber->ber_options & LBER_USE_DER ) { lenlen = ber_calc_lenlen( len ); + } else { lenlen = FOUR_BYTE_LEN; } + if( lenlen > 1 ) { + ber_len_t i; + for( i=0; i < lenlen-1; i++ ) { + netlen[(sizeof(ber_len_t)-1) - i] = + (unsigned char)((len >> i*8) & 0xffU); + } + } else { + netlen[sizeof(ber_len_t)-1] = (unsigned char)(len & 0x7fU); + } + if ( (next = (*sos)->sos_next) == NULL ) { /* write the tag */ if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 ) @@ -539,21 +544,48 @@ ber_put_seqorset( BerElement *ber ) return( -1 ); /* the length itself */ - if ( ber_write( ber, (char *) (&netlen + 1) - - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 ) - != FOUR_BYTE_LEN - 1 ) + rc = ber_write( ber, + &netlen[sizeof(ber_len_t) - (FOUR_BYTE_LEN-1)], + FOUR_BYTE_LEN-1, 1 ); + + if( rc != FOUR_BYTE_LEN - 1 ) { return( -1 ); + } } /* The ber_ptr is at the set/seq start - move it to the end */ (*sos)->sos_ber->ber_ptr += len; + } else { - ber_tag_t ntag; + ber_len_t i; + unsigned char nettag[sizeof(ber_tag_t)]; + ber_tag_t tmptag = (*sos)->sos_tag; + + if( ber->ber_sos->sos_ptr > ber->ber_end ) { + /* The sos_ptr exceeds the end of the BerElement + * this can happen, for example, when the sos_ptr + * is near the end and no data was written for the + * 'V'. We must realloc the BerElement to ensure + * we don't overwrite the buffer when writing + * the tag and length fields. + */ + ber_len_t ext = ber->ber_sos->sos_ptr - ber->ber_end; + + if( ber_realloc( ber, ext ) != 0 ) { + return -1; + } + } /* the tag */ - taglen = ber_calc_taglen( (*sos)->sos_tag ); - ntag = LBER_TAG_HTON( (*sos)->sos_tag ); - SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag + - sizeof(ber_tag_t) - taglen, taglen ); + taglen = ber_calc_taglen( tmptag ); + + for( i = 0; i < taglen; i++ ) { + nettag[(sizeof(ber_tag_t)-1) - i] = (unsigned char)(tmptag & 0xffU); + tmptag >>= 8; + } + + SAFEMEMCPY( (*sos)->sos_first, + &nettag[sizeof(ber_tag_t) - taglen], + taglen ); if ( ber->ber_options & LBER_USE_DER ) { ltag = (lenlen == 1) @@ -568,9 +600,8 @@ ber_put_seqorset( BerElement *ber ) if (lenlen > 1) { /* Write the length itself */ SAFEMEMCPY( (*sos)->sos_first + 2, - (char *)&netlen + sizeof(ber_len_t) - - (lenlen - 1), - lenlen - 1 ); + &netlen[sizeof(ber_len_t) - (lenlen - 1)], + lenlen - 1 ); } if (lenlen != FOUR_BYTE_LEN) { /* @@ -585,8 +616,8 @@ ber_put_seqorset( BerElement *ber ) } else { /* the length itself */ SAFEMEMCPY( (*sos)->sos_first + taglen + 1, - (char *) &netlen + sizeof(ber_len_t) - - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 ); + &netlen[sizeof(ber_len_t) - (FOUR_BYTE_LEN - 1)], + FOUR_BYTE_LEN - 1 ); } next->sos_clen += (taglen + lenlen + len); @@ -685,6 +716,7 @@ ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... ) break; case 'B': /* bit string */ + case 'X': /* bit string (deprecated) */ s = va_arg( ap, char * ); len = va_arg( ap, int ); /* in bits */ rc = ber_put_bitstring( ber, s, len, ber->ber_tag ); diff --git a/libraries/liblber/etest.c b/libraries/liblber/etest.c index 9d235b8554..01c10e9907 100644 --- a/libraries/liblber/etest.c +++ b/libraries/liblber/etest.c @@ -1,7 +1,7 @@ /* test.c - lber encoding test program */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -75,7 +75,9 @@ main( int argc, char **argv ) fd = fileno(stdout); #endif - sb = ber_sockbuf_alloc_fd( fd ); + sb = ber_sockbuf_alloc(); + ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, + (void *)&fd ); if( sb == NULL ) { perror( "ber_sockbuf_alloc_fd" ); diff --git a/libraries/liblber/etest.dsp b/libraries/liblber/etest.dsp new file mode 100644 index 0000000000..69e94a2261 --- /dev/null +++ b/libraries/liblber/etest.dsp @@ -0,0 +1,145 @@ +# Microsoft Developer Studio Project File - Name="etest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=etest - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "etest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "etest.mak" CFG="etest - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "etest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "etest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "etest - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "etest - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "etest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\etest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "etest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "etest___" +# PROP BASE Intermediate_Dir "etest___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\etest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "etest - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "etest___" +# PROP BASE Intermediate_Dir "etest___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\etest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "etest - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "etest__0" +# PROP BASE Intermediate_Dir "etest__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\etest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "etest - Win32 Release" +# Name "etest - Win32 Debug" +# Name "etest - Win32 Single Debug" +# Name "etest - Win32 Single Release" +# Begin Source File + +SOURCE=.\etest.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblber/idtest.c b/libraries/liblber/idtest.c index 2bc6822971..51863c2d30 100644 --- a/libraries/liblber/idtest.c +++ b/libraries/liblber/idtest.c @@ -1,7 +1,7 @@ /* idtest.c - ber decoding test program using isode libraries */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index 830c16e5f0..859b70c137 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -1,7 +1,7 @@ /* io.c - ber general i/o routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -32,9 +32,6 @@ #include #endif -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" static ber_slen_t BerRead LDAP_P(( @@ -42,10 +39,6 @@ static ber_slen_t BerRead LDAP_P(( char *buf, ber_len_t len )); -static int ber_realloc LDAP_P(( - BerElement *ber, - ber_len_t len )); - #define EXBUFSIZ 1024 /* probably far too large... */ @@ -71,7 +64,7 @@ BerRead( assert( SOCKBUF_VALID( sb ) ); while ( len > 0 ) { - if ( (c = ber_pvt_sb_read( sb, buf, len )) <= 0 ) { + if ( (c = ber_int_sb_read( sb, buf, len )) <= 0 ) { if ( nread > 0 ) break; return( c ); @@ -140,7 +133,7 @@ ber_write( } } -static int +int ber_realloc( BerElement *ber, ber_len_t len ) { ber_len_t need, have, total; @@ -202,10 +195,18 @@ ber_free( BerElement *ber, int freebuf ) assert( BER_VALID( ber ) ); - if ( freebuf && ber->ber_buf != NULL ) + if ( freebuf ) { + Seqorset *s, *next; LBER_FREE( ber->ber_buf ); + for( s = ber->ber_sos ; s != NULL ; s = next ) { + next = s->sos_next; + LBER_FREE( s ); + } + } + ber->ber_buf = NULL; + ber->ber_sos = NULL; ber->ber_valid = LBER_UNINITIALIZED; LBER_FREE( (char *) ber ); @@ -220,7 +221,7 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) assert( sb != NULL ); assert( ber != NULL ); - assert( SOCKBUF_VALID( ber ) ); + assert( SOCKBUF_VALID( sb ) ); assert( BER_VALID( ber ) ); if ( ber->ber_rwptr == NULL ) { @@ -231,26 +232,15 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) if ( sb->sb_debug ) { ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, "ber_flush: %ld bytes to sd %ld%s\n", towrite, - (long) sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" - : "" ); + (long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ? + " (re-flush)" : "" ); ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug, ber->ber_rwptr, towrite ); } -#if HAVE_WRITE - if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) { - rc = write( sb->sb_fd, ber->ber_rwptr, towrite ); - if ( sb->sb_options & LBER_TO_FILE_ONLY ) { - if ( freeit ) - ber_free( ber, 1 ); - return( (int)rc ); - } - } -#endif - nwritten = 0; do { - rc = ber_pvt_sb_write( sb, ber->ber_rwptr, towrite ); + rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite ); if (rc<=0) { return -1; } @@ -299,7 +289,7 @@ der_alloc( void ) /* deprecated */ } BerElement * -ber_dup( LDAP_CONST BerElement *ber ) +ber_dup( BerElement *ber ) { BerElement *new; @@ -376,7 +366,7 @@ ber_init( struct berval *bv ) ** the returned berval. */ int ber_flatten( - LDAP_CONST BerElement *ber, + BerElement *ber, struct berval **bvPtr) { struct berval *bv; @@ -445,7 +435,7 @@ get_tag( Sockbuf *sb ) assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); - if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) + if ( ber_int_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) @@ -454,7 +444,7 @@ get_tag( Sockbuf *sb ) tagp = (char *) &tag; tagp[0] = xbyte; for ( i = 1; i < sizeof(ber_tag_t); i++ ) { - if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) + if ( ber_int_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); tagp[i] = xbyte; @@ -474,7 +464,7 @@ get_tag( Sockbuf *sb ) /* * A rewrite of ber_get_next that can safely be called multiple times - * for the same packet. It will simply continue were it stopped until + * for the same packet. It will simply continue where it stopped until * a full packet is read. */ @@ -515,12 +505,13 @@ ber_get_next( ber->ber_tag = 0; } -#define PTR_IN_VAR( ptr, var )\ -(((ptr)>=(char *) &(var)) && ((ptr)< (char *) &(var)+sizeof(var))) +#undef PTR_IN_VAR +#define PTR_IN_VAR( ptr, var ) \ + (((ptr)>=(char *) &(var)) && ((ptr)< (char *) &(var)+sizeof(var))) if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag)) { if (ber->ber_rwptr == (char *) &ber->ber_tag) { - if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0) + if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0) return LBER_DEFAULT; if ((ber->ber_rwptr[0] & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK) { @@ -532,7 +523,7 @@ ber_get_next( } do { /* reading the tag... */ - if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0) + if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0) return LBER_DEFAULT; if (! (ber->ber_rwptr[0] & LBER_MORE_TAG_MASK) ) { ber->ber_tag>>=sizeof(ber->ber_tag) - @@ -540,14 +531,15 @@ ber_get_next( ber->ber_rwptr = (char *) &ber->ber_usertag; goto get_lenbyte; } - } while (PTR_IN_VAR(ber->ber_rwptr,ber->ber_tag)); + } while( PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag )); errno = ERANGE; /* this is a serious error. */ return LBER_DEFAULT; } + get_lenbyte: if (ber->ber_rwptr==(char *) &ber->ber_usertag) { unsigned char c; - if (ber_pvt_sb_read( sb, (char *) &c, 1)<=0) + if (ber_int_sb_read( sb, (char *) &c, 1)<=0) return LBER_DEFAULT; if (c & 0x80U) { int len = c & 0x7fU; @@ -563,29 +555,29 @@ get_lenbyte: goto fill_buffer; } } + if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len)) { + unsigned char netlen[sizeof(ber_len_t)]; + ber_slen_t res; ber_slen_t to_go; to_go = (char *) &ber->ber_len + sizeof( ber->ber_len ) - ber->ber_rwptr; assert( to_go > 0 ); - res = ber_pvt_sb_read( sb, ber->ber_rwptr, to_go ); - if (res <=0) + res = BerRead( sb, netlen, to_go ); + if (res <= 0) { return LBER_DEFAULT; + } ber->ber_rwptr += res; - if (res==to_go) { - /* convert length. */ - ber->ber_len = LBER_LEN_NTOH( ber->ber_len ); - goto fill_buffer; - } else { -#if defined( EWOULDBLOCK ) - errno = EWOULDBLOCK; -#elif defined( EAGAIN ) - errno = EAGAIN; -#endif - return LBER_DEFAULT; + + /* convert length. */ + ber->ber_len = 0; + for( to_go = 0; to_go < res ; to_go++ ) { + ber->ber_len <<= 8; + ber->ber_len |= netlen[to_go]; } } + fill_buffer: /* now fill the buffer. */ if (ber->ber_buf==NULL) { @@ -600,6 +592,7 @@ fill_buffer: ber->ber_ptr = ber->ber_buf; ber->ber_end = ber->ber_buf + ber->ber_len; } + if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptrber_end)) { ber_slen_t res; ber_slen_t to_go; @@ -607,7 +600,7 @@ fill_buffer: to_go = ber->ber_end - ber->ber_rwptr; assert( to_go > 0 ); - res = ber_pvt_sb_read( sb, ber->ber_rwptr, to_go ); + res = ber_int_sb_read( sb, ber->ber_rwptr, to_go ); if (res<=0) return LBER_DEFAULT; ber->ber_rwptr+=res; diff --git a/libraries/liblber/lber-int.h b/libraries/liblber/lber-int.h index 7d080349f5..136ea0c024 100644 --- a/libraries/liblber/lber-int.h +++ b/libraries/liblber/lber-int.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -24,27 +24,20 @@ LDAP_BEGIN_DECL -/* these have to match lber types settings */ -#define LBER_INT_HTON(i) AC_HTONL(i) -#define LBER_INT_NTOH(i) AC_NTOHL(i) -#define LBER_LEN_HTON(l) AC_HTONL(l) -#define LBER_LEN_NTOH(l) AC_NTOHL(l) -#define LBER_TAG_HTON(t) AC_HTONL(t) -#define LBER_TAG_NTOH(t) AC_NTOHL(t) - +LIBLBER_F (BER_ERRNO_FN) ber_int_errno_fn; struct lber_options { short lbo_valid; + unsigned short lbo_options; + int lbo_debug; +}; + #define LBER_UNINITIALIZED 0x0 #define LBER_INITIALIZED 0x1 #define LBER_VALID_BERELEMENT 0x2 #define LBER_VALID_SOCKBUF 0x3 - unsigned short lbo_options; - int lbo_debug; -}; - -extern struct lber_options ber_int_options; +LIBLBER_F (struct lber_options) ber_int_options; #define ber_int_debug ber_int_options.lbo_debug struct berelement { @@ -64,111 +57,24 @@ struct berelement { struct seqorset *ber_sos; char *ber_rwptr; - BERTranslateProc ber_encode_translate_proc; - BERTranslateProc ber_decode_translate_proc; }; #define BER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT) - #define ber_pvt_ber_bytes(ber) ((ber)->ber_ptr - (ber)->ber_buf) #define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr) -struct sockbuf; - -struct sockbuf_io { - int (*sbi_setup)( struct sockbuf * sb, void *arg ); - int (*sbi_remove)( struct sockbuf *sb ); - - ber_slen_t (*sbi_read)( struct sockbuf *sb, void *buf, ber_len_t len ); - ber_slen_t (*sbi_write)( struct sockbuf *sb, void *buf, ber_len_t len ); - int (*sbi_close)( struct sockbuf *sb ); -}; - -struct sockbuf_sec { - int (*sbs_setup)( struct sockbuf * sb, void *arg ); - int (*sbs_remove)( struct sockbuf *sb ); - - long (*sbs_protect)( struct sockbuf *sb, char *in, long *ilen, - char *out, long olen ); - long (*sbs_release)( struct sockbuf *sb, char *in, long ilen, - char *out0, long olen0, char *out1, long olen1 ); -}; - -struct sockbuf_buf { - ber_len_t buf_size; - ber_len_t buf_ptr; - ber_len_t buf_end; - char *buf_base; -}; - -typedef struct sockbuf_io Sockbuf_IO; -typedef struct sockbuf_sec Sockbuf_Sec; -typedef struct sockbuf_buf Sockbuf_Buf; - -extern Sockbuf_IO ber_pvt_sb_io_tcp; -extern Sockbuf_IO ber_pvt_sb_io_udp; - - struct sockbuf { struct lber_options sb_opts; + Sockbuf_IO_Desc *sb_iod; /* I/O functions */ #define sb_valid sb_opts.lbo_valid #define sb_options sb_opts.lbo_options #define sb_debug sb_opts.lbo_debug - - int sb_non_block:1; - int sb_read_ahead:1; - - int sb_buf_ready:1; - int sb_trans_ready:1; - int sb_sec_ready:1; - - /* these bits indicate if the transport layer - * needs to read or write - */ + ber_socket_t sb_fd; int sb_trans_needs_read:1; int sb_trans_needs_write:1; - - int sb_fd; - - void *sb_iodata; /* transport-layer data pointer */ - Sockbuf_IO *sb_io; /* I/O functions */ - -#ifdef LDAP_SASL - void *sb_sdata; /* security-layer data pointer */ - Sockbuf_Sec *sb_sec; -#endif - - ber_socket_t sb_sd; - -#ifdef DEADWOOD - long sb_max_incoming; -#endif - Sockbuf_Buf sb_buf; -#ifdef LDAP_SASL - Sockbuf_Buf sb_sec_buf_in; - Sockbuf_Buf sb_sec_buf_out; - ber_len_t sb_sec_prev_len; -#endif }; -#define SOCKBUF_VALID(ber) ((sb)->sb_valid==LBER_VALID_SOCKBUF) - -/* these should be internal ie: ber_int_* */ -#define ber_pvt_sb_get_desc( sb ) ((sb)->sb_sd) -#define ber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val)) - -#define ber_pvt_sb_in_use( sb ) ((sb)->sb_sd != AC_SOCKET_INVALID) -#ifdef USE_SASL -#define ber_pvt_sb_data_ready( sb ) \ -(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready)) -#else -#define ber_pvt_sb_data_ready( sb ) \ -(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready)) -#endif -#define ber_pvt_sb_needs_read( sb ) \ -((sb)->sb_trans_needs_read) -#define ber_pvt_sb_needs_write( sb ) \ -((sb)->sb_trans_needs_write) +#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF ) #define READBUFSIZ 8192 @@ -182,35 +88,42 @@ struct seqorset { }; +/* + * io.c + */ +int ber_realloc LDAP_P(( + BerElement *ber, + ber_len_t len )); + /* * bprint.c */ #define ber_log_printf ber_pvt_log_printf -LDAP_F( int ) +LIBLBER_F( int ) ber_log_bprint LDAP_P(( int errlvl, int loglvl, const char *data, ber_len_t len )); -LDAP_F( int ) +LIBLBER_F( int ) ber_log_dump LDAP_P(( int errlvl, int loglvl, - const BerElement *ber, + BerElement *ber, int inout )); -LDAP_F( int ) +LIBLBER_F( int ) ber_log_sos_dump LDAP_P(( int errlvl, int loglvl, - const Seqorset *sos )); + Seqorset *sos )); /* memory.c */ /* simple macros to realloc for now */ -extern BerMemoryFunctions* ber_int_memory_fns; +LIBLBER_F (BerMemoryFunctions *) ber_int_memory_fns; #ifdef CSRIMALLOC #define LBER_INT_MALLOC malloc @@ -245,50 +158,21 @@ extern BerMemoryFunctions* ber_int_memory_fns; /* sockbuf.c */ -/* these should be ber_int*() functions */ - -LDAP_F( int ) -ber_pvt_sb_init LDAP_P(( Sockbuf *sb )); - -LDAP_F( int ) -ber_pvt_sb_destroy LDAP_P(( Sockbuf *sb )); - -#ifdef USE_SASL -LDAP_F( int ) -ber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg )); - -LDAP_F( int ) -ber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb )); -#endif - -LDAP_F( int ) -ber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg )); - -LDAP_F( int ) -ber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb )); - -LDAP_F( int ) -ber_pvt_sb_close LDAP_P((Sockbuf *sb )); - -LDAP_F( int ) -ber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb )); - -LDAP_F( int ) -ber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh )); +LIBLBER_F( int ) +ber_int_sb_init LDAP_P(( Sockbuf *sb )); -LDAP_F( ber_slen_t ) -ber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); +LIBLBER_F( int ) +ber_int_sb_close LDAP_P(( Sockbuf *sb )); -LDAP_F( ber_slen_t ) -ber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); +LIBLBER_F( int ) +ber_int_sb_destroy LDAP_P(( Sockbuf *sb )); -LDAP_F( int ) -ber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr )); +LIBLBER_F( ber_slen_t ) +ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); -LDAP_F( void * ) -ber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb )); +LIBLBER_F( ber_slen_t ) +ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); -LDAP_F( int ) -ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb )); +LDAP_END_DECL #endif /* _LBER_INT_H */ diff --git a/libraries/liblber/liblber.dsp b/libraries/liblber/liblber.dsp new file mode 100644 index 0000000000..e02e1f3f76 --- /dev/null +++ b/libraries/liblber/liblber.dsp @@ -0,0 +1,225 @@ +# Microsoft Developer Studio Project File - Name="liblber" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=liblber - Win32 DLL Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "liblber.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "liblber.mak" CFG="liblber - Win32 DLL Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "liblber - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Single Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 DLL Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "liblber - Win32 DLL Release" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "liblber - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Debug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "liblber_" +# PROP BASE Intermediate_Dir "liblber_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Sdebug" +# PROP Intermediate_Dir "..\..\SDebug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "liblber0" +# PROP BASE Intermediate_Dir "liblber0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 DLL Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "liblber_" +# PROP BASE Intermediate_Dir "liblber_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\DLLDebug" +# PROP Intermediate_Dir "..\..\DLLDebug\liblber" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\..\Debug\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\DLLDebug\olber32.lib" + +!ELSEIF "$(CFG)" == "liblber - Win32 DLL Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "liblber0" +# PROP BASE Intermediate_Dir "liblber0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "liblber0" +# PROP Intermediate_Dir "liblber0" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\..\Release\olber32.lib" +# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib" + +!ENDIF + +# Begin Target + +# Name "liblber - Win32 Release" +# Name "liblber - Win32 Debug" +# Name "liblber - Win32 Single Debug" +# Name "liblber - Win32 Single Release" +# Name "liblber - Win32 DLL Debug" +# Name "liblber - Win32 DLL Release" +# Begin Source File + +SOURCE=.\bprint.c +# End Source File +# Begin Source File + +SOURCE=.\decode.c +# End Source File +# Begin Source File + +SOURCE=.\encode.c +# End Source File +# Begin Source File + +SOURCE=.\io.c +# End Source File +# Begin Source File + +SOURCE=".\lber-int.h" +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber_pvt.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\lber_types.h +# End Source File +# Begin Source File + +SOURCE=.\memory.c +# End Source File +# Begin Source File + +SOURCE=.\nt_err.c +# End Source File +# Begin Source File + +SOURCE=.\options.c +# End Source File +# Begin Source File + +SOURCE=.\sockbuf.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblber/memory.c b/libraries/liblber/memory.c index 604e8ccc94..3b4be421ba 100644 --- a/libraries/liblber/memory.c +++ b/libraries/liblber/memory.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ #include "portable.h" @@ -8,12 +8,20 @@ #include #include -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" #if LDAP_MEMORY_DEBUG +/* + * LDAP_MEMORY_DEBUG should only be enabled for the purposes of + * debugging memory management within OpenLDAP libraries and slapd. + * It should only be enabled by an experienced developer as it + * causes the inclusion of numerous assert()'s, many of which may + * be triggered by a prefectly valid program. + * + * The code behind this macro is subject to change as needed to + * support this testing. + */ + struct ber_mem_hdr { union bmu_align_u { ber_len_t bmu_len_t; @@ -30,13 +38,14 @@ struct ber_mem_hdr { #define bm_junk ber_align.bmu_len_t #define bm_data ber_align.bmu_char[1] }; -#define BER_MEM_JUNK 0xddeeddeeU +#define BER_MEM_JUNK 0xdeaddadaU static const struct ber_mem_hdr ber_int_mem_hdr = { BER_MEM_JUNK }; #define BER_MEM_BADADDR ((void *) &ber_int_mem_hdr.bm_data) #define BER_MEM_VALID(p) do { \ assert( (p) != BER_MEM_BADADDR ); \ assert( (p) != (void *) &ber_int_mem_hdr ); \ } while(0) + #else #define BER_MEM_VALID(p) /* no-op */ #endif @@ -83,7 +92,6 @@ ber_memfree( void *p ) assert( ber_int_memory_fns->bmf_free ); - (*ber_int_memory_fns->bmf_free)( p ); } @@ -112,6 +120,7 @@ ber_memvfree( void **vec ) void * ber_memalloc( ber_len_t s ) { + void *new; ber_int_options.lbo_valid = LBER_INITIALIZED; #ifdef LDAP_MEMORY_DEBUG @@ -131,21 +140,26 @@ ber_memalloc( ber_len_t s ) mh->bm_junk = BER_MEM_JUNK; BER_MEM_VALID( &mh[1] ); - return &mh[1]; + new = &mh[1]; #else - return malloc( s ); + new = malloc( s ); #endif + } else { + new = (*ber_int_memory_fns->bmf_malloc)( s ); } - assert( ber_int_memory_fns->bmf_malloc ); + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } - return (*ber_int_memory_fns->bmf_malloc)( s ); + return new; } void * ber_memcalloc( ber_len_t n, ber_len_t s ) { + void *new; ber_int_options.lbo_valid = LBER_INITIALIZED; #ifdef LDAP_MEMORY_DEBUG @@ -164,21 +178,27 @@ ber_memcalloc( ber_len_t n, ber_len_t s ) mh->bm_junk = BER_MEM_JUNK; BER_MEM_VALID( &mh[1] ); - return &mh[1]; + new = &mh[1]; #else - return calloc( n, s ); + new = calloc( n, s ); #endif + + } else { + new = (*ber_int_memory_fns->bmf_calloc)( n, s ); } - assert( ber_int_memory_fns->bmf_calloc ); + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } - return (*ber_int_memory_fns->bmf_calloc)( n, s ); + return new; } void * ber_memrealloc( void* p, ber_len_t s ) { + void *new = NULL; ber_int_options.lbo_valid = LBER_INITIALIZED; /* realloc(NULL,s) -> malloc(s) */ @@ -202,22 +222,26 @@ ber_memrealloc( void* p, ber_len_t s ) p = realloc( mh, s + sizeof(struct ber_mem_hdr) ); - if( p == NULL ) return NULL; + if( p != NULL ) { + mh = p; - mh = p; - - assert( mh->bm_junk == BER_MEM_JUNK ); + assert( mh->bm_junk == BER_MEM_JUNK ); - BER_MEM_VALID( &mh[1] ); - return &mh[1]; + BER_MEM_VALID( &mh[1] ); + new = &mh[1]; + } #else - return realloc( p, s ); + new = realloc( p, s ); #endif + } else { + new = (*ber_int_memory_fns->bmf_realloc)( p, s ); } - assert( ber_int_memory_fns->bmf_realloc ); + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } - return (*ber_int_memory_fns->bmf_realloc)( p, s ); + return new; } @@ -258,6 +282,57 @@ ber_bvecfree( struct berval **bv ) LBER_FREE( (char *) bv ); } +int +ber_bvecadd( struct berval ***bvec, struct berval *bv ) +{ + ber_len_t i; + struct berval **new; + + ber_int_options.lbo_valid = LBER_INITIALIZED; + + if( bvec == NULL ) { + if( bv == NULL ) { + /* nothing to add */ + return 0; + } + + *bvec = ber_memalloc( 2 * sizeof(struct berval *) ); + + if( *bvec == NULL ) { + return -1; + } + + (*bvec)[0] = bv; + (*bvec)[1] = NULL; + + return 1; + } + + BER_MEM_VALID( bvec ); + + /* count entries */ + for ( i = 0; bvec[i] != NULL; i++ ) { + /* EMPTY */; + } + + if( bv == NULL ) { + return i; + } + + new = ber_memrealloc( *bvec, (i+2) * sizeof(struct berval *)); + + if( new == NULL ) { + return -1; + } + + *bvec = new; + + (*bvec)[i++] = bv; + (*bvec)[i] = NULL; + + return i; +} + struct berval * ber_bvdup( @@ -268,10 +343,12 @@ ber_bvdup( ber_int_options.lbo_valid = LBER_INITIALIZED; if( bv == NULL ) { + ber_errno = LBER_ERROR_PARAM; return NULL; } if(( new = LBER_MALLOC( sizeof(struct berval) )) == NULL ) { + ber_errno = LBER_ERROR_MEMORY; return NULL; } @@ -282,6 +359,7 @@ ber_bvdup( } if(( new->bv_val = LBER_MALLOC( bv->bv_len + 1 )) == NULL ) { + ber_errno = LBER_ERROR_MEMORY; LBER_FREE( new ); return NULL; } @@ -293,6 +371,66 @@ ber_bvdup( return( new ); } +struct berval * +ber_bvstr( + LDAP_CONST char *s ) +{ + struct berval *new; + + ber_int_options.lbo_valid = LBER_INITIALIZED; + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + if(( new = LBER_MALLOC( sizeof(struct berval) )) == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + return NULL; + } + + if ( *s == '\0' ) { + new->bv_val = NULL; + new->bv_len = 0; + return new; + } + + new->bv_val = (char *) s; + new->bv_len = strlen( s ); + + return( new ); +} + +struct berval * +ber_bvstrdup( + LDAP_CONST char *s ) +{ + struct berval *new; + char *p; + + ber_int_options.lbo_valid = LBER_INITIALIZED; + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + p = LBER_STRDUP( s ); + + if( p == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + return NULL; + } + + new = ber_bvstr( p ); + + if( new == NULL || *p == '\0' ) { + LBER_FREE( p ); + } + + return( new ); +} + char * ber_strdup( LDAP_CONST char *s ) { @@ -306,12 +444,14 @@ ber_strdup( LDAP_CONST char *s ) #endif if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; return( NULL ); } len = strlen( s ) + 1; if ( (p = LBER_MALLOC( len )) == NULL ) { + ber_errno = LBER_ERROR_MEMORY; return( NULL ); } diff --git a/libraries/liblutil/nt_err.c b/libraries/liblber/nt_err.c similarity index 80% rename from libraries/liblutil/nt_err.c rename to libraries/liblber/nt_err.c index 6d119d2b3d..45de02c8be 100644 --- a/libraries/liblutil/nt_err.c +++ b/libraries/liblber/nt_err.c @@ -1,12 +1,20 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" #ifdef HAVE_WINSOCK2 #include +#elif HAVE_WINSOCK +#include +#endif /* HAVE_WINSOCK(2) */ +#undef __RETSTR #define __RETSTR( x ) case x: return #x; -char *WSAGetErrorString( int err ) +char *ber_pvt_wsa_err2string( int err ) { switch( err ) { @@ -57,6 +65,8 @@ char *WSAGetErrorString( int err ) __RETSTR( WSAVERNOTSUPPORTED ) __RETSTR( WSANOTINITIALISED ) __RETSTR( WSAEDISCON ) + +#ifdef HAVE_WINSOCK2 __RETSTR( WSAENOMORE ) __RETSTR( WSAECANCELLED ) __RETSTR( WSAEINVALIDPROCTABLE ) @@ -67,42 +77,12 @@ char *WSAGetErrorString( int err ) __RETSTR( WSA_E_NO_MORE ) __RETSTR( WSA_E_CANCELLED ) __RETSTR( WSAEREFUSED ) +#endif // HAVE_WINSOCK2 __RETSTR( WSAHOST_NOT_FOUND ) __RETSTR( WSATRY_AGAIN ) __RETSTR( WSANO_RECOVERY ) __RETSTR( WSANO_DATA ) } - return "unknown"; -} - -char *WSAGetLastErrorString( void ) -{ - return WSAGetErrorString( WSAGetLastError() ); -} - -#undef __RETSTR - -#endif /* HAVE_WINSOCK2 */ - - -char *GetErrorString( int err ) -{ - static char msgBuf[1024]; - - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - msgBuf, 1024, NULL ); - - return msgBuf; -} - -char *GetLastErrorString( void ) -{ - return GetErrorString( GetLastError() ); -} - - - + return "unknown WSA error"; +} \ No newline at end of file diff --git a/libraries/liblber/options.c b/libraries/liblber/options.c index 4ffea28b1d..dc61707dfd 100644 --- a/libraries/liblber/options.c +++ b/libraries/liblber/options.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ #include "portable.h" @@ -8,17 +8,16 @@ #include #include -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" +extern void * ber_pvt_err_file; /* bprint.c */ + struct lber_options ber_int_options = { LBER_UNINITIALIZED, 0, 0 }; int ber_get_option( - LDAP_CONST void *item, + void *item, int option, void *outvalue) { @@ -29,6 +28,7 @@ ber_get_option( if(outvalue == NULL) { /* no place to get to */ + ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } @@ -38,6 +38,7 @@ ber_get_option( return LBER_OPT_SUCCESS; } + ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } @@ -55,8 +56,21 @@ ber_get_option( * (int *) outvalue = ber->ber_debug; return LBER_OPT_SUCCESS; + case LBER_OPT_BER_REMAINING_BYTES: + *((ber_len_t *) outvalue) = ber->ber_end - ber->ber_ptr; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_TOTAL_BYTES: + *((ber_len_t *) outvalue) = ber->ber_end - ber->ber_buf; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_BYTES_TO_WRITE: + *((ber_len_t *) outvalue) = ber->ber_ptr - ber->ber_buf; + return LBER_OPT_SUCCESS; + default: /* bad param */ + ber_errno = LBER_ERROR_PARAM; break; } @@ -84,6 +98,7 @@ ber_set_option( if(!( f->bmf_malloc && f->bmf_calloc && f->bmf_realloc && f->bmf_free )) { + ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } @@ -91,6 +106,7 @@ ber_set_option( (*(f->bmf_malloc))(sizeof(BerMemoryFunctions)); if ( ber_int_memory_fns == NULL ) { + ber_errno = LBER_ERROR_MEMORY; return LBER_OPT_ERROR; } @@ -104,6 +120,7 @@ ber_set_option( if(invalue == NULL) { /* no place to set from */ + ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } @@ -115,8 +132,12 @@ ber_set_option( } else if(option == LBER_OPT_LOG_PRINT_FN) { ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue; return LBER_OPT_SUCCESS; + } else if(option == LBER_OPT_LOG_PRINT_FILE) { + ber_pvt_err_file = (void *) invalue; + return LBER_OPT_SUCCESS; } + ber_errno = LBER_ERROR_PARAM; return LBER_OPT_ERROR; } @@ -134,8 +155,21 @@ ber_set_option( ber->ber_debug = * (const int *) invalue; return LBER_OPT_SUCCESS; + case LBER_OPT_BER_REMAINING_BYTES: + ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_TOTAL_BYTES: + ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_BYTES_TO_WRITE: + ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + default: /* bad param */ + ber_errno = LBER_ERROR_PARAM; break; } diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c index 30bceb6bed..e3ddbcd44a 100644 --- a/libraries/liblber/sockbuf.c +++ b/libraries/liblber/sockbuf.c @@ -1,7 +1,7 @@ /* sockbuf.c - i/o routines with support for adding i/o layers. */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -27,635 +27,268 @@ #include #endif -#undef LDAP_F_PRE -#define LDAP_F_PRE LDAP_F_EXPORT - #include "lber-int.h" -#ifdef LDAP_TEST -#undef TEST_PARTIAL_READ -#undef TEST_PARTIAL_WRITE -#endif - -#define MAX_BUF_SIZE 65535 -#define MIN_BUF_SIZE 4096 +#define MIN_BUFF_SIZE 4096 +#define MAX_BUFF_SIZE 65536 +#define DEFAULT_READAHEAD 16384 -#define sockbuf_io_write( sb, buf, len ) \ -((sb)->sb_io->sbi_write( (sb), (buf), (len) )) - -#define sockbuf_io_read( sb, buf, len ) \ -((sb)->sb_io->sbi_read( (sb), (buf), (len) )) +Sockbuf * +ber_sockbuf_alloc( void ) +{ + Sockbuf *sb; -static ber_slen_t have_no_read( Sockbuf *sb, void *buf, ber_len_t len ); -static ber_slen_t have_no_write( Sockbuf *sb, void *buf, ber_len_t len ); -static int have_no_close( Sockbuf *sb ); + ber_int_options.lbo_valid = LBER_INITIALIZED; -static Sockbuf_IO sb_IO_None= -{ - NULL, /* sbi_setup */ - NULL, /* sbi_release */ - have_no_read, /* sbi_read */ - have_no_write, /* sbi_write */ - have_no_close /* sbi_close */ -}; + sb = LBER_CALLOC( 1, sizeof( Sockbuf ) ); -static void -update_status( Sockbuf *sb ) -{ - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + if( sb == NULL ) + return NULL; - sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end); -#ifdef USE_SASL - sb->sb_sec_ready = ((sb->sb_sec_buf_in.buf_end!=0) && - (sb->sb_sec_buf_in.buf_ptr >= - sb->sb_sec_buf_in.buf_end)); -#endif + ber_int_sb_init( sb ); + return sb; } -#ifdef LDAP_DEBUG -static int -status_is_ok( Sockbuf *sb ) +void +ber_sockbuf_free( Sockbuf *sb ) { - int obr; -#ifdef USE_SASL - int osr; -#endif - assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); - obr = sb->sb_buf_ready; -#ifdef USE_SASL - osr = sb->sb_sec_ready; -#endif - - update_status(sb); - if (obr!=sb->sb_buf_ready) - return 0; - -#ifdef USE_SASL - if (osr!=sb->sb_sec_ready) - return 0; -#endif - - return 1; + ber_int_sb_close( sb ); + ber_int_sb_destroy( sb ); + LBER_FREE( sb ); } -#endif -#ifdef USE_SASL -static ber_len_t -packet_length( Sockbuf *sb, const char *buf ) +/* Return values: -1: error, 0: no operation performed or the answer is false, + * 1: successful operation or the answer is true + */ +int +ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg ) { - ber_len_t size; + Sockbuf_IO_Desc *p; + int ret = 0; + char buf[4096]; - assert( buf != NULL ); + assert( sb != NULL ); - size = (((ber_len_t)buf[0])<<24)| - (((ber_len_t)buf[1])<<16)| - (((ber_len_t)buf[2])<<8)| - (((ber_len_t)buf[3])); - - if ( size > MAX_BUF_SIZE ) { - /* somebody is trying to mess me up. */ - ber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug, - "SASL: received packet length of %lu bytes\n", - (unsigned long) size ); - size = 16; /* this should lead to an error. */ + switch ( opt ) { + case LBER_SB_OPT_HAS_IO: + p = sb->sb_iod; + + while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) + p = p->sbiod_next; + + if ( p ) + ret = 1; + break; + case LBER_SB_OPT_GET_FD: + if ( arg != NULL ) + *((int *)arg) = sb->sb_fd; + ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1); + break; + case LBER_SB_OPT_SET_FD: + sb->sb_fd = *((int *)arg); + ret = 1; + break; + case LBER_SB_OPT_SET_NONBLOCK: + ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL) + ? -1 : 1; + break; + case LBER_SB_OPT_DRAIN: + /* Drain the data source to enable possible errors (e.g. + * TLS) to be propagated to the upper layers + */ + do { + ret = ber_int_sb_read( sb, buf, sizeof( buf ) ); + } while ( ret == sizeof( buf ) ); + + ret = 1; + break; + case LBER_SB_OPT_NEEDS_READ: + ret = ( sb->sb_trans_needs_read ? 1 : 0 ); + break; + case LBER_SB_OPT_NEEDS_WRITE: + ret = ( sb->sb_trans_needs_write ? 1 : 0 ); + break; + default: + ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, + opt, arg ); + break; } - - return size + 4; /* include the size !!! */ -} -#endif - -static int -grow_buffer( Sockbuf_Buf * buf, ber_len_t minsize ) -{ - ber_len_t pw;; - - assert( buf != NULL ); - for( pw=MIN_BUF_SIZE; pw MAX_BUF_SIZE) { - /* this could mean that somebody is trying to crash us. */ - return -1; - } - } - minsize = pw; - - if (buf->buf_sizebuf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) { - /* empty buffer */ - if (buf->buf_base!=NULL) - LBER_FREE( buf->buf_base ); - assert( buf->buf_ptr==0 ); - assert( buf->buf_end==0 ); - buf->buf_base = LBER_MALLOC( minsize ); - if (buf->buf_base==NULL) - return -1; - } else { - char *nb; - nb = LBER_REALLOC( buf->buf_base, minsize ); - if (nb==NULL) - return -1; - buf->buf_base = nb; - } - buf->buf_size = minsize; - } - return 0; + return ret; } -#ifdef USE_SASL -static ber_slen_t -sockbuf_sec_release( Sockbuf *sb, char *buf, ber_len_t len ) +int +ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg ) { - /* when this is called: - * sb->sb_sec_buf_in.buf_base points to a packet. - * sb->sb_sec_buf_in.buf_ptr contains the total bytes read. - * sb->sb_sec_end.buf_end contains the packet length. - * - * sb->sb_buf.buf_ptr == sb->sb_buf.buf_end == 0; - */ - long rlen; - long total; - char *ptr; - char *end; - long size; + Sockbuf_IO_Desc *d, *p, **q; - assert( buf != NULL ); assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); - - assert( sb->sb_sec ); - assert( sb->sb_sec->sbs_release ); - assert( sb->sb_sec_buf_in.sb_ptr >= sb->sb_sec_buf_in.sb_end ); - - assert( sb->sb_buf.sb_ptr == 0 ); - assert( sb->sb_buf.sb_end == 0 ); - - assert( status_is_ok(sb) ); - total = 0; + if ( sbio == NULL ) + return -1; - ptr = sb->sb_sec_buf_in.buf_base; - end = ptr+ sb->sb_sec_buf_in.buf_ptr; - size = sb->sb_sec_buf_in.buf_end; + q = &sb->sb_iod; + p = *q; + while ( p && p->sbiod_level > layer ) { + q = &p->sbiod_next; + p = *q; + } - sb->sb_sec_ready = 1; + d = LBER_MALLOC( sizeof( *d ) ); + if ( d == NULL ) + return -1; - for(;(ptr+size<=end);) { - for(;;) { - rlen = sb->sb_sec->sbs_release( sb, ptr, size, - buf, len, - sb->sb_buf.buf_base, - sb->sb_buf.buf_size ); - if (rlen==0) { - /* this means a security violation. */ - return total; /* total ? total : 0 */ - } - if (rlen<0) { - /* this means that the buffer isn't big enough. */ - if (grow_buffer( &(sb->sb_buf), -rlen )<0) - /* memory violation. */ - return total; /* total ? total : 0 */ - continue; - } - /* if (rlen>0) */ - break; - } - total+=rlen; - - /* move to the next packet... */ - ptr+=size; + d->sbiod_level = layer; + d->sbiod_sb = sb; + d->sbiod_io = sbio; + memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) ); + d->sbiod_next = p; + *q = d; - if (ptr+4<=end) - size = packet_length( sb, ptr ); - /* size is always at least 4, so the loop condition is always OK !!*/ - assert( size>=4 ); + if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) + return -1; - if (rlensb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0; - break; - } + return 0; } - if (ptr+size>end) - sb->sb_sec_ready = 0; - /* clean up the mess. */ - if (ptrsb_sec_buf_in.buf_base, ptr, end-ptr ); - sb->sb_sec_buf_in.buf_ptr = 0; - sb->sb_sec_buf_in.buf_end -= (ptr - sb->sb_sec_buf_in.buf_base); - } - assert( status_is_ok(sb) ); - return total; -} - -static long -sockbuf_sec_protect( Sockbuf *sb, char *buf, long len ) +int +ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer ) { - long ret; - long blen; - long total; - - assert( buf != NULL ); + Sockbuf_IO_Desc *p, **q; assert( sb != NULL ); assert( SOCKBUF_VALID( sb ) ); - - assert( sb->sb_sec_out.buf_end == 0 ); - assert( sb->sb_sec_out.buf_ptr == 0 ); - - assert( sb->sb_sec ); - assert( sb->sb_sec->sbs_protect ); - assert( status_is_ok(sb) ); - - total = 0; - for(;(len);) { - for(;;) { - blen = len; - ret = sb->sb_sec->sbs_protect( sb, buf, &blen, - sb->sb_sec_out.buf_base+ - sb->sb_sec_out.buf_end, - sb->sb_sec_out.buf_size - - sb->sb_sec_out.buf_end ); - if (ret==0) - /* protection error ? */ - return total; - if (ret<0) { - if (grow_buffer( &(sb->sb_sec_out),-ret-sb->sb_sec_out.buf_end )<0) - /* memory error */ - return total; - continue; - } - /* else if (ret>0) */ + if ( sb->sb_iod == NULL ) + return -1; + + q = &sb->sb_iod; + while ( *q != NULL ) { + p = *q; + if ( layer == p->sbiod_level && p->sbiod_io == sbio ) { + if ( p->sbiod_io->sbi_remove != NULL && + p->sbiod_io->sbi_remove( p ) < 0 ) + return -1; + *q = p->sbiod_next; + LBER_FREE( p ); break; - } - sb->sb_sec_out.buf_end += ret; - len -= blen; - total += blen; } - assert( status_is_ok(sb) ); - return total; + q = &p->sbiod_next; } -#endif - -static ber_len_t -sockbuf_copy_out( Sockbuf *sb, char **buf, ber_len_t len ) -{ - ber_len_t blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr ); - assert( buf != NULL ); - - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( status_is_ok(sb) ); - - if (blen) { - ber_len_t rlen = (blensb_buf.buf_base + sb->sb_buf.buf_ptr, rlen ); - sb->sb_buf.buf_ptr+=rlen; - *buf+=rlen; - len -= rlen; - if (sb->sb_buf.buf_ptr >= sb->sb_buf.buf_end) { - sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0; - sb->sb_buf_ready = 0; - } else { - sb->sb_buf_ready = 1; - } - } - assert( status_is_ok(sb) ); - return len; + return 0; } -Sockbuf *ber_sockbuf_alloc( void ) +void +ber_pvt_sb_buf_init( Sockbuf_Buf *buf ) { - Sockbuf *sb; - - ber_int_options.lbo_valid = LBER_INITIALIZED; - - sb = LBER_CALLOC(1, sizeof(Sockbuf)); - - if( sb == NULL ) return NULL; - - ber_pvt_sb_init( sb ); - return sb; + buf->buf_base = NULL; + buf->buf_ptr = 0; + buf->buf_end = 0; + buf->buf_size = 0; } -Sockbuf *ber_sockbuf_alloc_fd( ber_socket_t fd ) +void +ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf ) { - Sockbuf *sb = ber_sockbuf_alloc(); - - if( sb == NULL ) return NULL; - - ber_pvt_sb_set_desc( sb, fd ); - ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL ); - return sb; -} + assert( buf != NULL); -void ber_sockbuf_free( Sockbuf *sb ) -{ - assert(sb != NULL); - assert( SOCKBUF_VALID( sb ) ); - ber_pvt_sb_destroy( sb ); - LBER_FREE(sb); + if (buf->buf_base) + LBER_FREE( buf->buf_base ); + ber_pvt_sb_buf_init( buf ); } -ber_slen_t -ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, ber_len_t len ) +int +ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize ) { - char *buf; - ber_slen_t ret; + ber_len_t pw; + char *p; - assert( buf_arg != NULL ); - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( status_is_ok(sb) ); - - /* slapd might have problems with this */ - assert( ber_pvt_sb_in_use( sb ) ); + assert( buf != NULL ); -#ifdef TEST_PARTIAL_READ - if ((rand() & 3)==1) { /* 1 out of 4 */ - errno = EWOULDBLOCK; + for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) { + if (pw > MAX_BUFF_SIZE) return -1; } - if( len > 0 ) - len = (rand() % len)+1; -#endif - - buf = (char *) buf_arg; - - if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) { - len = sockbuf_copy_out( sb, &buf, len ); - if (len==0) { - return (buf - (char *) buf_arg); - } + if ( buf->buf_size < pw ) { + p = LBER_REALLOC( buf->buf_base, pw ); + if ( p == NULL ) + return -1; + buf->buf_base = p; + buf->buf_size = pw; } - -#ifdef USE_SASL - if (sb->sb_sec) { - ber_slen_t max; - assert( sb->sb_sec->sbs_release ); - assert( sb->sb_sec_buf_in.buf_base ); - if (sb->sb_read_ahead) { - max = sb->sb_sec_buf_in.buf_size - sb->sb_sec_buf_in.buf_ptr; - } else { - max = sb->sb_sec_buf_in.buf_end - sb->sb_sec_buf_in.buf_ptr; - if (max<=0) { - /* special situation. This means that we need to read the first - * four bytes for the packet length. - */ - max += 4; - } - } - for(;;) { - /* read from stream into sb_sec_buf_in */ - for(;;) { - ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base + - sb->sb_sec_buf_in.buf_ptr, max ); -#ifdef EINTR - if ((ret<0) && (errno==EINTR)) - continue; -#endif - break; - } - if (ret<=0) { - /* read error. return */ - goto do_return; - } - sb->sb_sec_buf_in.buf_ptr += ret; - - if (sb->sb_sec_buf_in.buf_ptr < sb->sb_sec_buf_in.buf_end) { - /* did not finish a packet. give up. */ - goto do_return; - } - - if (sb->sb_sec_buf_in.buf_end == 0) { - /* Were trying to read the first four bytes... */ - if (sb->sb_sec_buf_in.buf_ptr < 4) { - /* did not read enough for packet length. give up. */ - goto do_return; - } - /* calculate the packet length. */ - sb->sb_sec_buf_in.buf_end = - packet_length(sb, sb->sb_sec_buf_in.buf_base ); - if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) && - (grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) { - /* buffer has to be to big. exit with error. */ - ret = -1; - goto do_return; - } - if (sb->sb_sec_buf_in.buf_ptr >= sb->sb_sec_buf_in.buf_end) { - /* finished packet. decode it. */ - goto decode_packet; - } - /* did not finish packet yet. try again ? */ - if (sb->sb_read_ahead) { - /* we were trying to read the max anyway. forget it */ - goto do_return; - } - } -decode_packet: - /* we read enough for at least 1 packet */ - ret = sockbuf_sec_release( sb, buf, len ); - if (ret<=0) { - /* something went wrong... */ - goto do_return; - } - buf+=ret; - len-=ret; - /* we are finished !!! */ - if ((len==0) || (ret!=max)) - goto do_return; - } - } else { -#endif - if (sb->sb_read_ahead) { - ber_slen_t max; - max = sb->sb_buf.buf_size - sb->sb_buf.buf_end; - if (max> (ber_slen_t) len) { - for(;;) { - ret = sockbuf_io_read( sb, - sb->sb_buf.buf_base + - sb->sb_buf.buf_end, - max ); -#ifdef EINTR - if ((ret<0) && (errno==EINTR)) - continue; -#endif - break; - } - if (ret<=0) { - /* some error occured */ - goto do_return; - } - sb->sb_buf.buf_end += ret; - /* move out the data... */ - len = sockbuf_copy_out( sb, &buf, len ); - goto do_return; - } - } - /* no read_ahead, just try to put the data in the buf. */ - for(;;) { - ret = sockbuf_io_read( sb, buf, len ); -#ifdef EINTR - if ((ret<0) && (errno==EINTR)) - continue; -#endif - break; - } - if (ret>0) { - buf+=ret; - len-=ret; - } - /* we might as well return, since there is nothing to do... */ -#ifdef USE_SASL - } -#endif -do_return: - assert( status_is_ok(sb) ); - if ((ret<=0) && (buf==buf_arg)) { - /* there was an error. */ - return ret; - } - return (buf - ((char *) buf_arg)); + return 0; } -#ifdef USE_SASL -long sockbuf_do_write( Sockbuf *sb ) +ber_len_t +ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len ) { - long to_go; - ber_slen_t ret; + ber_len_t max; - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - - to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr; - assert( to_go > 0 ); - /* there is something left of the last time... */ - for(;;) { - ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+ - sb->sb_sec_out.buf_ptr, to_go ); -#ifdef EINTR - if ((ret<0) && (errno==EINTR)) - continue; -#endif - break; + assert( buf != NULL ); + assert( sbb != NULL ); + assert( sbb->buf_size > 0 ); + + max = sbb->buf_end - sbb->buf_ptr; + max = ( max < len) ? max : len; + if ( max ) { + memcpy( buf, sbb->buf_base + sbb->buf_ptr, max ); + sbb->buf_ptr += max; + if ( sbb->buf_ptr >= sbb->buf_end ) + sbb->buf_ptr = sbb->buf_end = 0; } - if (ret<=0) /* error */ - return ret; - sb->sb_sec_out.buf_ptr += ret; - if (retsbiod_sb ) ); - len_arg = (rand() % len_arg)+1; - len = len_arg; -#endif + to_go = buf_out->buf_end - buf_out->buf_ptr; + assert( to_go > 0 ); -#ifdef USE_SASL - if (sb->sb_sec) { - assert( sb->sb_sec_prev_len <= len ); - if (sb->sb_sec_prev_len) { - ret = sockbuf_do_write( sb ); - if (ret<=0) - return ret; - /* finished. */ - len -= sb->sb_sec_prev_len; - sb->sb_sec_prev_len = 0; - sb->sb_sec_out.buf_end = sb->sb_sec_out.buf_ptr = 0; - } - /* now protect the next packet. */ - ret = sockbuf_sec_protect( sb, buf, len ); - if (ret<=0) - return ret; - ret = sockbuf_do_write( sb ); - if (ret<=0) { - sb->sb_sec_prev_len = len; - return ret; - } - return len_arg; - } else { -#endif for(;;) { - ret = sockbuf_io_write( sb, buf, len ); + ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base + + buf_out->buf_ptr, to_go ); #ifdef EINTR if ((ret<0) && (errno==EINTR)) continue; #endif break; } -#ifdef USE_SASL - } -#endif + if ( ret <= 0 ) return ret; -} - -int ber_pvt_sb_close( Sockbuf *sb ) -{ - int ret; - - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( sb->sb_io ); - assert( sb->sb_io->sbi_close ); - assert( status_is_ok(sb) ); - assert( ber_pvt_sb_in_use( sb ) ); - ret = sb->sb_io->sbi_close( sb ); - ber_pvt_sb_set_desc( sb, -1 ); - + buf_out->buf_ptr += ret; + if (buf_out->buf_ptr == buf_out->buf_end) + buf_out->buf_end = buf_out->buf_ptr = 0; + if ( (ber_len_t)ret < to_go ) + /* not enough data, so pretend no data was sent. */ + return -1; return ret; } -int ber_pvt_sb_set_readahead( Sockbuf *sb, int rh ) -{ - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( status_is_ok(sb) ); - sb->sb_read_ahead = (rh!=0); - return 0; -} - -int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) +int +ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) { #if HAVE_FCNTL - int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL); - if( nb ) { + int flags = fcntl( sd, F_GETFL); + if( nb ) flags |= O_NONBLOCK; - } else { + else flags &= ~O_NONBLOCK; - } - return fcntl( ber_pvt_sb_get_desc(sb), F_SETFL, flags ); + return fcntl( sd, F_SETFL, flags ); #elif defined( FIONBIO ) ioctl_t status = nb ? 1 : 0; @@ -663,201 +296,100 @@ int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) #endif } -#define USE_NONBLOCK -#ifdef USE_NONBLOCK -int ber_pvt_sb_set_nonblock( Sockbuf *sb, int nb ) -{ - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( status_is_ok(sb) ); - if (nb) { - sb->sb_non_block = 1; -#if 0 - sb->sb_read_ahead = 1; -#endif - } else { - sb->sb_non_block = 0; -#if 0 - sb->sb_read_ahead = 0; -#endif - } - if (ber_pvt_sb_in_use(sb)) { - return ber_pvt_socket_set_nonblock( - ber_pvt_sb_get_desc(sb), nb ); - } - return 0; -} -#endif - -#define sockbuf_buf_init( bb ) do { \ - Sockbuf_Buf *sbb = (bb); \ - sbb->buf_base = NULL; \ - sbb->buf_ptr = 0; \ - sbb->buf_end = 0; \ - sbb->buf_size = 0; \ - } while(0) - -static int -sockbuf_buf_destroy( Sockbuf_Buf *buf ) -{ - assert( buf != NULL); - - if (buf->buf_base) - LBER_FREE( buf->buf_base ); - sockbuf_buf_init( buf ); - return 0; -} - -int ber_pvt_sb_init( Sockbuf *sb ) +int +ber_int_sb_init( Sockbuf *sb ) { assert( sb != NULL); - ber_int_options.lbo_valid = LBER_INITIALIZED; - sb->sb_valid=LBER_VALID_SOCKBUF; sb->sb_options = 0; - sb->sb_debug = 0; - sb->sb_trans_ready = 0; - sb->sb_buf_ready = 0; -#ifdef USE_SASL - sb->sb_sec_ready = 0; -#endif - sb->sb_read_ahead = 1; /* test */ - sb->sb_non_block = 0; + sb->sb_debug = ber_int_debug; + sb->sb_fd = AC_SOCKET_INVALID; + sb->sb_iod = NULL; sb->sb_trans_needs_read = 0; sb->sb_trans_needs_write = 0; - sb->sb_fd = -1; - sb->sb_iodata = NULL; - sb->sb_io = &sb_IO_None; - sb->sb_sd = -1; -#ifdef DEADWOOD - sb->sb_max_incoming = 0; -#endif - sockbuf_buf_init( &(sb->sb_buf) ); -#ifdef USE_SASL - sockbuf_buf_init( &(sb->sb_sec_buf_in) ); - sockbuf_buf_init( &(sb->sb_sec_buf_out) ); - sb->sb_sdata = NULL; - sb->sb_sec = NULL; - sb->sb_sec_prev_len = 0; -#endif assert( SOCKBUF_VALID( sb ) ); return 0; } -int ber_pvt_sb_destroy( Sockbuf *sb ) +int +ber_int_sb_close( Sockbuf *sb ) { - assert( sb != NULL); - assert( SOCKBUF_VALID(sb) ); -#ifdef USE_SASL - ber_pvt_sb_clear_sec(sb); - sockbuf_buf_destroy( &(sb->sb_sec_buf_in) ); - sockbuf_buf_destroy( &(sb->sb_sec_buf_out) ); -#endif - ber_pvt_sb_clear_io(sb); - sockbuf_buf_destroy( &(sb->sb_buf) ); - return ber_pvt_sb_init( sb ); -} + Sockbuf_IO_Desc *p; -#ifdef USE_SASL -int ber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg ) -{ - int len; assert( sb != NULL); - assert( SOCKBUF_VALID( *sb ) ); - if ((sb->sb_sec) || (sec==NULL)) - return -1; - - sb->sb_sec = sec; - if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) { + p = sb->sb_iod; + while ( p ) { + if ( p->sbiod_io->sbi_close && + p->sbiod_io->sbi_close( p ) < 0 ) return -1; + p = p->sbiod_next; } - len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr; + sb->sb_fd = AC_SOCKET_INVALID; - if (len>0) { - /* move this to the security layer. */ - if (grow_buffer( &(sb->sb_sec_buf_in), len )<0) - return -1; - memcpy( sb->sb_sec_buf_in.buf_base, - sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len ); - sb->sb_sec_buf_in.buf_ptr = len; - sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb, sb->sb_sec_buf_in ) : 0; - sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0; - } - update_status( sb ); return 0; } -int ber_pvt_sb_clear_sec( Sockbuf *sb ) +int +ber_int_sb_destroy( Sockbuf *sb ) { + Sockbuf_IO_Desc *p; + assert( sb != NULL); assert( SOCKBUF_VALID( sb ) ); - - if (sb->sb_buf.buf_ptr!=0) - return -1; - if (sb->sb_sec==NULL) - return -1; - if ((sb->sb_sec->sbs_remove) && (sb->sb_sec->sbs_remove(sb)<0)) - return -1; - sb->sb_sec = NULL; - if (sb->sb_sec_buf_in.buf_ptr!=0) { - if (grow_buffer( &(sb->sb_buf), - sb->sb_buf.buf_end + sb->sb_sec_buf_in.buf_ptr)<0) - return -1; - memcpy( sb->sb_buf.buf_base + sb->sb_buf.buf_end, - sb->sb_sec_buf_in.buf_base, sb->sb_sec_buf_in.buf_ptr ); - sb->sb_buf.buf_end += sb->sb_sec_buf_in.buf_ptr; - sb->sb_buf_ready = 1; - } - sockbuf_buf_destroy( &(sb->sb_sec_buf_in) ); - assert( sb->sb_sec_buf.buf_end==0 ); - sockbuf_buf_destroy( &(sb->sb_sec_buf_out) ); - - sb->sb_sec_ready = 0; - - return 0; + while ( sb->sb_iod ) { + p = sb->sb_iod->sbiod_next; + ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io, + sb->sb_iod->sbiod_level ); + sb->sb_iod = p; +} + return ber_int_sb_init( sb ); } -#endif -int ber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg ) +ber_slen_t +ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len ) { + ber_slen_t ret; + + assert( buf != NULL ); assert( sb != NULL); + assert( sb->sb_iod != NULL ); assert( SOCKBUF_VALID( sb ) ); - assert( sb->sb_io == &sb_IO_None ); - if (trans==NULL) - return -1; - - sb->sb_io = trans; - - if ((trans->sbi_setup) && (trans->sbi_setup( sb, arg)<0)) - return -1; - - return 0; + for (;;) { + ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + break; +} + return ret; } -int ber_pvt_sb_clear_io( Sockbuf *sb ) +ber_slen_t +ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len ) { + ber_slen_t ret; + + assert( buf != NULL ); assert( sb != NULL); + assert( sb->sb_iod != NULL ); assert( SOCKBUF_VALID( sb ) ); - if (sb->sb_io==&sb_IO_None) - return -1; - - if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0)) - return -1; - - sb->sb_io = &sb_IO_None; - - sb->sb_trans_ready = 0; - sb->sb_trans_needs_read = 0; - sb->sb_trans_needs_write = 0; - - return 0; + for (;;) { + ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + break; +} + return ret; } /* @@ -865,16 +397,16 @@ int ber_pvt_sb_clear_io( Sockbuf *sb ) */ static ber_slen_t -stream_read( Sockbuf *sb, void *buf, ber_len_t len ) +sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { - assert( sb != NULL); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); #if defined(MACOS) /* * MacTCP/OpenTransport */ - return tcpread( ber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf, + return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf, len, NULL ); #elif defined( HAVE_PCNFS ) || \ @@ -890,36 +422,44 @@ stream_read( Sockbuf *sb, void *buf, ber_len_t len ) */ { int rc; - rc = recv( ber_pvt_sb_get_desc(sb), buf, len, 0 ); + + rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); + #ifdef HAVE_WINSOCK - if ( rc < 0 ) errno = WSAGetLastError(); + if ( rc < 0 ) + { + int err; + + err = WSAGetLastError(); + errno = err; + } #endif + return rc; } #elif defined( HAVE_NCSA ) /* * NCSA Telnet TCP/IP stack (under DOS) */ - return nread( ber_pvt_sb_get_desc(sb), buf, len ); + return nread( sbiod->sbiod_sb->sb_fd, buf, len ); #else - return read( ber_pvt_sb_get_desc(sb), buf, len ); + return read( sbiod->sbiod_sb->sb_fd, buf, len ); #endif } static ber_slen_t -stream_write( Sockbuf *sb, void *buf, ber_len_t len ) +sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { - assert( sb != NULL); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); #if defined(MACOS) /* * MacTCP/OpenTransport */ #define MAX_WRITE 65535 - return tcpwrite( ber_pvt_sb_get_desc(sb), - (unsigned char *)(buf), + return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf, (lensbiod_sb->sb_fd, buf, len, 0 ); #ifdef HAVE_WINSOCK - if ( rc < 0 ) errno = WSAGetLastError(); + if ( rc < 0 ) + { + int err; + + err = WSAGetLastError(); + errno = err; + } #endif return rc; } #elif defined(HAVE_NCSA) - return netwrite( ber_pvt_sb_get_desc(sb), buf, len ); + return netwrite( sbiod->sbiod_sb->sb_fd, buf, len ); #elif defined(VMS) /* * VMS -- each write must be 64K or smaller */ #define MAX_WRITE 65535 - return write( ber_pvt_sb_get_desc(sb), buf, + return write( sbiod->sbiod_sb->sb_fd, buf, (lensbiod_sb->sb_fd, buf, len ); #endif } static int -stream_close( Sockbuf *sb ) +sb_stream_close( Sockbuf_IO_Desc *sbiod ) { - assert( sb != NULL); - assert( SOCKBUF_VALID( sb ) ); - tcp_close( ber_pvt_sb_get_desc( sb ) ); + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + tcp_close( sbiod->sbiod_sb->sb_fd ); return 0; } -Sockbuf_IO ber_pvt_sb_io_tcp= +/* The argument is a pointer to the socket descriptor */ +static int +sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { + assert( sbiod != NULL ); + + if ( arg != NULL ) + sbiod->sbiod_sb->sb_fd = *((int *)arg); + return 0; +} + +static int +sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { + /* This is an end IO descriptor */ + return 0; +} + +Sockbuf_IO ber_sockbuf_io_tcp = { - NULL, /* sbi_setup */ - NULL, /* sbi_release */ - stream_read, /* sbi_read */ - stream_write, /* sbi_write */ - stream_close, /* sbi_close */ + sb_stream_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + sb_stream_ctrl, /* sbi_ctrl */ + sb_stream_read, /* sbi_read */ + sb_stream_write, /* sbi_write */ + sb_stream_close /* sbi_close */ }; /* @@ -987,53 +551,52 @@ struct dgram_data }; static int -dgram_setup( Sockbuf *sb, void *arg ) +sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { - assert( sb != NULL); - assert( SOCKBUF_VALID( sb ) ); + struct dgram_data *p; + + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - sb->sb_iodata = LBER_MALLOC( sizeof( struct dgram_data ) ); - if (sb->sb_iodata==NULL) + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) return -1; - sb->sb_read_ahead = 1; /* important since udp is packet based. */ + memset( p, '\0', sizeof( *p ) ); + sbiod->sbiod_pvt = (void *)p; + if ( arg != NULL ) + sbiod->sbiod_sb->sb_fd = *((int *)arg); return 0; } static int -dgram_release( Sockbuf *sb ) +sb_dgram_release( Sockbuf_IO_Desc *sbiod ) { - assert( sb != NULL); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - LBER_FREE( sb->sb_iodata ); + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; return 0; } static ber_slen_t -dgram_read( Sockbuf *sb, void *buf, ber_len_t len ) +sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { #ifdef LDAP_CONNECTIONLESS ber_slen_t rc; socklen_t addrlen; - struct dgram_data *dd; + struct dgram_data *p; - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); assert( buf != NULL ); - dd = (struct dgram_data *)(sb->sb_iodata); + p = (struct dgram_data *)sbiod->sbiod_pvt; addrlen = sizeof( struct sockaddr ); - rc=recvfrom( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen ); + rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->src, + &addrlen ); - if ( sb->sb_debug ) { - ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, - "dgram_read udp_read %ld bytes\n", - (long) rc ); - if ( rc > 0 ) - ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug, - buf, rc ); - } return rc; # else /* LDAP_CONNECTIONLESS */ return -1; @@ -1041,30 +604,30 @@ dgram_read( Sockbuf *sb, void *buf, ber_len_t len ) } static ber_slen_t -dgram_write( Sockbuf *sb, void *buf, ber_len_t len ) +sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { #ifdef LDAP_CONNECTIONLESS ber_slen_t rc; - struct dgram_data *dd; + struct dgram_data *p; - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); assert( buf != NULL ); - dd = (struct dgram_data *)(sb->sb_iodata); + p = (struct dgram_data *)sbiod->sbiod_pvt; - rc=sendto( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst), + rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->dst, sizeof( struct sockaddr ) ); if ( rc <= 0 ) - return( -1 ); + return -1; /* fake error if write was not atomic */ if (rc < len) { # ifdef EMSGSIZE errno = EMSGSIZE; # endif - return( -1 ); + return -1; } return rc; #else @@ -1073,84 +636,325 @@ dgram_write( Sockbuf *sb, void *buf, ber_len_t len ) } static int -dgram_close( Sockbuf *sb ) +sb_dgram_close( Sockbuf_IO_Desc *sbiod ) { - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + tcp_close( sbiod->sbiod_sb->sb_fd ); + return 0; +} + +static int +sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct dgram_data *p; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct dgram_data *)sbiod->sbiod_pvt; - tcp_close( ber_pvt_sb_get_desc(sb) ); + if ( opt == LBER_SB_OPT_UDP_SET_DST ) { + memcpy( &p->dst, arg, sizeof( struct sockaddr ) ); + return 1; + } + else if ( opt == LBER_SB_OPT_UDP_GET_SRC ) { + *(( struct sockaddr **)arg) = &p->src; + return 1; + } + /* This is an end IO descriptor */ return 0; } -Sockbuf_IO ber_pvt_sb_io_udp= +Sockbuf_IO ber_sockbuf_io_udp = { - dgram_setup, /* sbi_setup */ - dgram_release, /* sbi_release */ - dgram_read, /* sbi_read */ - dgram_write, /* sbi_write */ - dgram_close, /* sbi_close */ + sb_dgram_setup, /* sbi_setup */ + sb_dgram_release, /* sbi_release */ + sb_dgram_ctrl, /* sbi_ctrl */ + sb_dgram_read, /* sbi_read */ + sb_dgram_write, /* sbi_write */ + sb_dgram_close /* sbi_close */ }; -int ber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr ) +/* + * Support for readahead (UDP needs it) + */ + +static int +sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { - struct dgram_data *dd; - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( sb->sb_io == &ber_pvt_sb_io_udp ); - dd = (struct dgram_data *) (sb->sb_iodata); - memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) ); + Sockbuf_Buf *p; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) + return -1; + ber_pvt_sb_buf_init( p ); + if ( arg == NULL ) + ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD ); + else + ber_pvt_sb_grow_buffer( p, *((int *)arg) ); + sbiod->sbiod_pvt = p; return 0; } -void *ber_pvt_sb_udp_get_src( Sockbuf *sb ) +static int +sb_rdahead_remove( Sockbuf_IO_Desc *sbiod ) { - struct dgram_data *dd; + Sockbuf_Buf *p; - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); - assert( sb->sb_io == &ber_pvt_sb_io_udp ); - dd = (struct dgram_data *) (sb->sb_iodata); - return &(dd->src); + assert( sbiod != NULL ); + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + if ( p->buf_ptr != p->buf_end ) + return -1; + + ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) ); + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + + return 0; } +static ber_slen_t +sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + Sockbuf_Buf *p; + ber_slen_t bufptr = 0, ret, max; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + assert( sbiod->sbiod_next != NULL ); + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + assert( p->buf_size > 0 ); + + /* Are there anything left in the buffer? */ + ret = ber_pvt_sb_copy_out( p, buf, len ); + bufptr += ret; + len -= ret; + + if ( len == 0 ) + return bufptr; + + max = p->buf_size - p->buf_end; + ret = 0; + while ( max > 0 ) { + ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end, + max ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + break; +} + + if ( ret < 0 ) + return ( bufptr ? bufptr : ret ); + + p->buf_end += ret; + bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len ); + return bufptr; +} + +static ber_slen_t +sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL ); + assert( sbiod->sbiod_next != NULL ); + + return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); +} + +static int +sb_rdahead_close( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + + /* Just erase the buffer */ + ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt); + return 0; +} + +static int +sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + Sockbuf_Buf *p; + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( p->buf_ptr != p->buf_end ) + return 1; + } + else if ( opt == LBER_SB_OPT_SET_READAHEAD ) { + if ( p->buf_size >= *((ber_len_t *)arg) ) + return 0; + return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ? + -1 : 1 ); + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +Sockbuf_IO ber_sockbuf_io_readahead = +{ + sb_rdahead_setup, /* sbi_setup */ + sb_rdahead_remove, /* sbi_remove */ + sb_rdahead_ctrl, /* sbi_ctrl */ + sb_rdahead_read, /* sbi_read */ + sb_rdahead_write, /* sbi_write */ + sb_rdahead_close /* sbi_close */ +}; + /* - * debug routines. - * - * BUGS: - * These routines should really call abort, but at the moment that would - * break the servers. + * Support for simple file IO */ static ber_slen_t -have_no_read( Sockbuf *sb, void *buf, ber_len_t len ) +sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug, - "warning: reading from uninitialized sockbuf\n"); - errno = EBADF; - return -1; + return read( sbiod->sbiod_sb->sb_fd, buf, len ); } static ber_slen_t -have_no_write( Sockbuf *sb, void *buf, ber_len_t len ) +sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug, - "warning: writing to uninitialized sockbuf\n"); - errno = EBADF; - return -1; + return write( sbiod->sbiod_sb->sb_fd, buf, len ); } static int -have_no_close( Sockbuf *sb ) +sb_fd_close( Sockbuf_IO_Desc *sbiod ) { - assert( sb != NULL ); - assert( SOCKBUF_VALID( sb ) ); + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + close( sbiod->sbiod_sb->sb_fd ); + return 0; +} + +/* The argument is a pointer to the file descriptor */ +static int +sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { + assert( sbiod != NULL ); + + if ( arg != NULL ) + sbiod->sbiod_sb->sb_fd = *((int *)arg); + return 0; +} + +static int +sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { + /* This is an end IO descriptor */ + return 0; +} + +Sockbuf_IO ber_sockbuf_io_fd = +{ + sb_fd_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + sb_fd_ctrl, /* sbi_ctrl */ + sb_fd_read, /* sbi_read */ + sb_fd_write, /* sbi_write */ + sb_fd_close /* sbi_close */ +}; + +/* + * Debugging layer + */ - assert( 0 ); +static int +sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + assert( sbiod != NULL ); + + if ( arg == NULL ) + arg = "sockbuf_"; + + sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 ); + if ( sbiod->sbiod_pvt == NULL ) return -1; + strcpy( (char *)sbiod->sbiod_pvt, (char *)arg ); + return 0; +} + +static int +sb_debug_remove( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static int +sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +static ber_slen_t +sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + + ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len ); + if ( ret < 0 ) { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, + (long)len, strerror( errno ) ); + } + else { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt, + (long)len, (long)ret ); + ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + (const char *)buf, ret ); + } + return ret; } + +static ber_slen_t +sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + + ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); + if ( ret < 0 ) { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%swrite: want=%ld error=%s\n", + (char *)sbiod->sbiod_pvt, (long)len, + strerror( errno ) ); + } + else { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%swrite: want=%ld, written=%ld\n", + (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); + ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + (const char *)buf, ret ); + } + return ret; +} + +Sockbuf_IO ber_sockbuf_io_debug = +{ + sb_debug_setup, /* sbi_setup */ + sb_debug_remove, /* sbi_remove */ + sb_debug_ctrl, /* sbi_ctrl */ + sb_debug_read, /* sbi_read */ + sb_debug_write, /* sbi_write */ + NULL /* sbi_close */ +}; + diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index 1ee85ec934..0ae884ddb1 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## Makefile.in for LDAP -lldap @@ -15,25 +15,45 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ - request.c getdxbyname.c os-ip.c url.c charset.c \ + request.c os-ip.c url.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ - charray.c digest.c tls.c dn.c + charray.c tls.c dn.c os-local.c dnssrv.c \ + utf-8.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ - request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \ + request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ - charray.lo digest.lo tls.lo dn.lo + charray.lo tls.lo dn.lo os-local.lo dnssrv.lo \ + utf-8.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries -XLIBS = -lldap -llber +XLIBS = -lldap -llber -llutil XXLIBS = $(SECURITY_LIBS) $(TLS_LIBS) +LINKAGE = @LT_LIB_LINKAGE@ + +NT_DYN_LIB_LIBS = -llber -llutil $(AC_LIBS) +NT_DYN_LIB_DEFS = -DLIBLBER_DECL=dllimport +NT_DYN_TEST_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport + +NT_XXLIBS = $(SECURITY_LIBS) + +UNIX_DYN_LIB_LIBS = -llber $(AC_LIBS) +UNIX_XXLIBS = $(SECURITY_LIBS) + +# Extras for building the library +EXTRA_DEFS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) +EXTRA_LIBS = $(@PLAT@_@LIB_LINKAGE@_LIB_LIBS) $(@PLAT@_XXLIBS) + +# Only the test programs will pick up these defs. +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_TEST_DEFS) + apitest: $(LIBRARY) apitest.o $(LDAP_LIBLBER_DEPEND) $(LTLINK) $(LDFLAGS) -o $@ apitest.o $(LIBS) ltest: $(LIBRARY) test.o $(LDAP_LIBLBER_DEPEND) @@ -44,20 +64,20 @@ ttest: $(LIBRARY) tmpltest.o $(LDAP_LIBLBER_DEPEND) CFFILES=ldap.conf ldapfilter.conf ldaptemplates.conf ldapsearchprefs.conf install-local: $(CFFILES) FORCE - -$(MKDIR) $(libdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(libdir) - -$(MKDIR) $(sysconfdir) + -$(MKDIR) $(DESTDIR)$(libdir) + $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) + -$(MKDIR) $(DESTDIR)$(sysconfdir) @for i in $(CFFILES); do \ - if test ! -f $(sysconfdir)/$$i; then \ + if test ! -f $(DESTDIR)$(sysconfdir)/$$i; then \ echo "installing $$i in $(sysconfdir)"; \ - echo "$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i"; \ - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i; \ + echo "$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i"; \ + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i; \ else \ echo "PRESERVING EXISTING CONFIGURATION FILE $(sysconfdir)/$$i" ; \ fi; \ - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(sysconfdir)/$$i.default; \ + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/$$i $(DESTDIR)$(sysconfdir)/$$i.default; \ done - -$(MKDIR) $(datadir) - -$(MV) $(datadir)/ldapfriendly $(datadir)/ldapfriendly- - $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldapfriendly $(datadir)/ldapfriendly + -$(MKDIR) $(DESTDIR)$(datadir) + -$(MV) $(DESTDIR)$(datadir)/ldapfriendly $(DESTDIR)$(datadir)/ldapfriendly- + $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/ldapfriendly $(DESTDIR)$(datadir)/ldapfriendly diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index 0541dd93cc..3ce621f7aa 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -180,7 +180,7 @@ do_abandon( if ( lr != NULL ) { sb = lr->lr_conn->lconn_sb; } else { - sb = &ld->ld_sb; + sb = ld->ld_sb; } if ( ber_flush( sb, ber, 1 ) != 0 ) { diff --git a/libraries/libldap/add.c b/libraries/libldap/add.c index aa69653572..34f61e8c8f 100644 --- a/libraries/libldap/add.c +++ b/libraries/libldap/add.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/addentry.c b/libraries/libldap/addentry.c index 1249157f0d..4ee6870222 100644 --- a/libraries/libldap/addentry.c +++ b/libraries/libldap/addentry.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/apitest.c b/libraries/libldap/apitest.c index b14f563d4b..0fe1de5ee5 100644 --- a/libraries/libldap/apitest.c +++ b/libraries/libldap/apitest.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* diff --git a/libraries/libldap/apitest.dsp b/libraries/libldap/apitest.dsp new file mode 100644 index 0000000000..b191770b53 --- /dev/null +++ b/libraries/libldap/apitest.dsp @@ -0,0 +1,145 @@ +# Microsoft Developer Studio Project File - Name="apitest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=apitest - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "apitest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "apitest.mak" CFG="apitest - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "apitest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "apitest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "apitest - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "apitest - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "apitest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\apitest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 oldap32.lib olber32.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "apitest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "apitest_" +# PROP BASE Intermediate_Dir "apitest_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\apitest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 oldap32.lib olber32.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "apitest - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "apitest_" +# PROP BASE Intermediate_Dir "apitest_" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\apitest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 oldap32.lib olber32.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "apitest - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "apitest0" +# PROP BASE Intermediate_Dir "apitest0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\apitest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 oldap32.lib olber32.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "apitest - Win32 Release" +# Name "apitest - Win32 Debug" +# Name "apitest - Win32 Single Debug" +# Name "apitest - Win32 Single Release" +# Begin Source File + +SOURCE=.\apitest.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap/bind.c b/libraries/libldap/bind.c index b9579f2b4a..f985b3b0d9 100644 --- a/libraries/libldap/bind.c +++ b/libraries/libldap/bind.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -16,7 +16,7 @@ * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND * krbv42ldap [1] OCTET STRING * krbv42dsa [2] OCTET STRING #endif @@ -66,7 +66,7 @@ ldap_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmetho case LDAP_AUTH_SIMPLE: return( ldap_simple_bind( ld, dn, passwd ) ); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND case LDAP_AUTH_KRBV41: return( ldap_kerberos_bind1( ld, dn ) ); @@ -111,7 +111,7 @@ ldap_bind_s( case LDAP_AUTH_SIMPLE: return( ldap_simple_bind_s( ld, dn, passwd ) ); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND case LDAP_AUTH_KRBV4: return( ldap_kerberos_bind_s( ld, dn ) ); @@ -130,14 +130,3 @@ ldap_bind_s( return( ld->ld_errno = LDAP_AUTH_UNKNOWN ); } } - - -void -ldap_set_rebind_proc( LDAP *ld, int (*rebindproc)( LDAP *ld, char **dnp, - char **passwdp, int *authmethodp, int freeit )) -{ - assert( ld != NULL ); - assert( LDAP_VALID( ld ) ); - - ld->ld_rebindproc = rebindproc; -} diff --git a/libraries/libldap/cache.c b/libraries/libldap/cache.c index 0e01394a90..93e0e31083 100644 --- a/libraries/libldap/cache.c +++ b/libraries/libldap/cache.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -44,7 +44,7 @@ ldap_enable_cache( LDAP *ld, long timeout, ber_len_t maxmem ) ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } - (void) memset( ld->ld_cache, 0, sizeof( LDAPCache )); + (void) memset( ld->ld_cache, '\0', sizeof( LDAPCache )); ld->ld_cache->lc_memused = sizeof( LDAPCache ); } @@ -387,6 +387,7 @@ ldap_check_cache( LDAP *ld, ber_tag_t msgtype, BerElement *request ) return( -1 ); } + reqber.ber_valid = LBER_VALID_BERELEMENT; reqber.ber_buf = reqber.ber_ptr = request->ber_buf; reqber.ber_end = request->ber_ptr; diff --git a/libraries/libldap/charray.c b/libraries/libldap/charray.c index 6be3152427..744ab07b73 100644 --- a/libraries/libldap/charray.c +++ b/libraries/libldap/charray.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* charray.c - routines for dealing with char * arrays */ @@ -165,22 +165,22 @@ ldap_charray_dup( char **a ) } char ** -ldap_str2charray( char *str, char *brkstr ) +ldap_str2charray( const char *str_in, const char *brkstr ) { char **res; - char *s; + char *str, *s; char *lasts; int i; /* protect the input string from strtok */ - str = LDAP_STRDUP( str ); + str = LDAP_STRDUP( str_in ); if( str == NULL ) { return NULL; } i = 1; for ( s = str; *s; s++ ) { - if ( strchr( brkstr, *s ) != NULL ) { + if ( ldap_utf8_strchr( brkstr, s ) != NULL ) { i++; } } @@ -194,9 +194,9 @@ ldap_str2charray( char *str, char *brkstr ) i = 0; - for ( s = ldap_pvt_strtok( str, brkstr, &lasts ); + for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); s != NULL; - s = ldap_pvt_strtok( NULL, brkstr, &lasts ) ) + s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) { res[i] = LDAP_STRDUP( s ); diff --git a/libraries/libldap/charset.c b/libraries/libldap/charset.c deleted file mode 100644 index 7d85f5ad79..0000000000 --- a/libraries/libldap/charset.c +++ /dev/null @@ -1,1806 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ -/* Portions - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - * - * charset.c - */ - -#include "portable.h" - -#ifdef STR_TRANSLATION - -#include - -#include - -#include -#include -#include - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#include "ldap-int.h" - - -void -ldap_set_string_translators( LDAP *ld, BERTranslateProc encode_proc, - BERTranslateProc decode_proc ) -{ - ld->ld_lber_encode_translate_proc = encode_proc; - ld->ld_lber_decode_translate_proc = decode_proc; -} - - -void -ldap_enable_translation( LDAP *ld, LDAPMessage *entry, int enable ) -{ - unsigned short *optionsp; - - optionsp = ( entry == NULL ) ? &ld->ld_lberoptions : - &entry->lm_ber->ber_options; - - if ( enable ) { - *optionsp |= LBER_TRANSLATE_STRINGS; - } else { - *optionsp &= ~LBER_TRANSLATE_STRINGS; - } -} - - -int -ldap_translate_from_t61( LDAP *ld, char **bufp, ber_len_t *lenp, - int free_input ) -{ - if ( ld->ld_lber_decode_translate_proc == 0 ) { - return( LDAP_SUCCESS ); - } - - return( (*ld->ld_lber_decode_translate_proc)( bufp, lenp, free_input )); -} - - -int -ldap_translate_to_t61( LDAP *ld, char **bufp, ber_len_t *lenp, - int free_input ) -{ - if ( ld->ld_lber_encode_translate_proc == 0 ) { - return( LDAP_SUCCESS ); - } - - return( (*ld->ld_lber_encode_translate_proc)( bufp, lenp, free_input )); -} - - -/* - ** Character translation routine notes: - * - * On entry: bufp points to a "string" to be converted (not necessarily - * zero-terminated) and buflenp points to the length of the buffer. - * - * On exit: bufp should point to a malloc'd result. If free_input is - * non-zero then the original bufp will be freed. *buflenp should be - * set to the new length. Zero bytes in the input buffer must be left - * as zero bytes. - * - * Return values: any ldap error code (LDAP_SUCCESS if all goes well). - */ - - -#ifdef LDAP_CHARSET_8859 - -#if LDAP_CHARSET_8859 == 88591 -#define ISO_8859 1 -#elif LDAP_CHARSET_8859 == 88592 -#define ISO_8859 2 -#elif LDAP_CHARSET_8859 == 88593 -#define ISO_8859 3 -#elif LDAP_CHARSET_8859 == 88594 -#define ISO_8859 4 -#elif LDAP_CHARSET_8859 == 88595 -#define ISO_8859 5 -#elif LDAP_CHARSET_8859 == 88596 -#define ISO_8859 6 -#elif LDAP_CHARSET_8859 == 88597 -#define ISO_8859 7 -#elif LDAP_CHARSET_8859 == 88598 -#define ISO_8859 8 -#elif LDAP_CHARSET_8859 == 88599 -#define ISO_8859 9 -#elif LDAP_CHARSET_8859 == 885910 -#define ISO_8859 10 -#else -#define ISO_8859 0 -#endif - -/* - * the following ISO_8859 to/afrom T.61 character set translation code is - * based on the code found in Enrique Silvestre Mora's iso-t61.c, found - * as part of this package: - * ftp://pereiii.uji.es/pub/uji-ftp/unix/ldap/iso-t61.translation.tar.Z - * Enrique is now (10/95) at this address: enrique.silvestre@uv.es - * - * changes made by mcs@umich.edu 12 October 1995: - * Change calling conventions of iso8859_t61() and t61_iso8859() to - * match libldap conventions; rename to ldap_8859_to_t61() and - * ldap_t61_to_8859(). - * Change conversion routines to deal with non-zero terminated strings. - * ANSI-ize functions and include prototypes. - */ - -/* iso-t61.c - ISO-T61 translation routines (version: 0.2.1, July-1994) */ -/* - * Copyright (c) 1994 Enrique Silvestre Mora, Universitat Jaume I, Spain. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and that due credit is given - * to the Universitat Jaume I. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. This software - * is provided ``as is'' without express or implied warranty. -*/ - - -#include -#include -#include - -/* Character set used: ISO 8859-1, ISO 8859-2, ISO 8859-3, ... */ -/* #define ISO_8859 1 */ - -#ifndef ISO_8859 -# define ISO_8859 0 -#endif - -typedef unsigned char Byte; -typedef struct { Byte a, b; } Couple; - -/* Prototypes without LDAP_P(): - * 'Byte' in definition incompatible with unprototyped declaration. */ -static Byte *c_to_hh ( Byte *o, Byte c ); -static Byte *c_to_cc ( Byte *o, const Couple *cc, Byte c ); -static int hh_to_c ( const Byte *h ); -static Byte *cc_to_t61 ( Byte *o, const Byte *s ); - -/* - Character choosed as base in diacritics alone: NO-BREAK SPACE. - (The standard say it must be a blank space, 0x20.) -*/ -#define ALONE 0xA0 - -static const Couple diacritic[16] = { -#if (ISO_8859 == 1) || (ISO_8859 == 9) - {0,0}, {'`',0}, {0xb4,0}, {'^',0}, - {'~',0}, {0xaf,0}, {'(',ALONE}, {'.',ALONE}, - {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0}, - {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE}, -#elif (ISO_8859 == 2) - {0,0}, {'`',0}, {0xb4,0}, {'^',0}, - {'~',0}, {'-',ALONE}, {0xa2,0}, {0xff,0}, - {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0}, - {0,0}, {0xbd,0}, {0xb2,0}, {0xb7,0} -#elif (ISO_8859 == 3) - {0,0}, {'`',0}, {0xb4,0}, {'^',0}, - {'~',0}, {'-',ALONE}, {0xa2,0}, {0xff,0}, - {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0}, - {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE} -#elif (ISO_8859 == 4) - {0,0}, {'`',0}, {0xb4,0}, {'^',0}, - {'~',0}, {0xaf,0}, {'(',ALONE}, {0xff,0}, - {0xa8,0}, {0,0}, {'0',ALONE}, {0xb8,0}, - {0,0}, {'"',ALONE}, {0xb2,0}, {0xb7,0} -#else - {0,0}, {'`',0}, {'\'',ALONE}, {'^',0}, - {'~',0}, {'-',ALONE}, {'(',ALONE}, {'.',ALONE}, - {':',ALONE}, {0,0}, {'0',ALONE}, {',',ALONE}, - {0,0}, {'"',ALONE}, {';',ALONE}, {'<',ALONE} -#endif -}; - -/* - --- T.61 (T.51) letters with diacritics: conversion to ISO 8859-n ----- - A, C, D, E, G, H, I, J, K, - L, N, O, R, S, T, U, W, Y, Z. - ----------------------------------------------------------------------- -*/ -static const int letter_w_diacritic[16][38] = { -#if (ISO_8859 == 1) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0, - 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0, - 0xe0,0, 0, 0xe8,0, 0, 0xec,0, 0, - 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0, - 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0, - -1, -1, 0xd3,-1, -1, 0, 0xda,0, 0xdd,-1, - 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0, - -1, -1, 0xf3,-1, -1, 0, 0xfa,0, 0xfd,-1, - 0xc2,-1, 0, 0xca,-1, -1, 0xce,-1, 0, - 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0, - 0xe2,-1, 0, 0xea,-1, -1, 0xee,-1, 0, - 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0, - 0xc3,0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xd1,0xd5,0, 0, 0, -1, 0, 0, 0, - 0xe3,0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xf1,0xf5,0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, -1, -1, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0, -1, 0, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, 0xff,0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xe5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, 0xc7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, - 0, 0xe7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1 -#elif (ISO_8859 == 2) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xc1,0xc6,0, 0xc9,0, 0, 0xcd,0, 0, - 0xc5,0xd1,0xd3,0xc0,0xa6,0, 0xda,0, 0xdd,0xac, - 0xe1,0xe6,0, 0xe9,0, 0, 0xed,0, 0, - 0xe5,0xf1,0xf3,0xe0,0xb6,0, 0xfa,0, 0xfd,0xbc, - 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0, - 0, 0, 0xd4,0, -1, 0, -1, -1, -1, 0, - 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0, - 0, 0, 0xf4,0, -1, 0, -1, -1, -1, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xc3,0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xe3,0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, -1, -1, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xaf, - 0, -1, 0, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbf, - 0xc4,0, 0, 0xcb,0, 0, -1, 0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0, - 0, 0xc7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xaa,0xde,0, 0, 0, 0, - 0, 0xe7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xba,0xfe,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xd5,0, 0, 0, 0xdb,0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xf5,0, 0, 0, 0xfb,0, 0, 0, - 0xa1,0, 0, 0xca,0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xb1,0, 0, 0xea,0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, 0xc8,0xcf,0xcc,0, 0, 0, 0, 0, - 0xa5,0xd2,0, 0xd8,0xa9,0xab,0, 0, 0, 0xae, - 0, 0xe8,0xef,0xec,0, 0, 0, 0, 0, - 0xb5,0xf2,0, 0xf8,0xb9,0xbb,0, 0, 0, 0xbe -#elif (ISO_8859 == 3) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0, - 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0, - 0xe0,0, 0, 0xe8,0, 0, 0xec,0, 0, - 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0, - 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0, - -1, -1, 0xd3,-1, -1, 0, 0xda,0, -1, -1, - 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0, - -1, -1, 0xf3,-1, -1, 0, 0xfa,0, -1, -1, - 0xc2,0xc6,0, 0xca,0xd8,0xa6,0xce,0xac,0, - 0, 0, 0xd4,0, 0xde,0, 0xdb,-1, -1, 0, - 0xe2,0xe6,0, 0xea,0xf8,0xb6,0xee,0xbc,0, - 0, 0, 0xf4,0, 0xfe,0, 0xfb,-1, -1, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xd1,-1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xf1,-1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0xab,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xdd,0, 0, 0, - -1, 0, 0, 0, 0xbb,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xfd,0, 0, 0, - 0, 0xc5,0, -1, 0xd5,0, 0xa9,0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xaf, - 0, 0xe5,0, -1, 0xf5,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbf, - 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, 0xc7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xaa,-1, 0, 0, 0, 0, - 0, 0xe7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xba,-1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1 -#elif (ISO_8859 == 4) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0, - -1, -1, -1, -1, -1, 0, 0xda,0, -1, -1, - 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0, - -1, -1, -1, -1, -1, 0, 0xfa,0, -1, -1, - 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0, - 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0, - 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0, - 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0, - 0xc3,0, 0, 0, 0, 0, 0xa5,0, 0, - 0, -1, 0xd5,0, 0, 0, 0xdd,0, 0, 0, - 0xe3,0, 0, 0, 0, 0, 0xb5,0, 0, - 0, -1, 0xf5,0, 0, 0, 0xfd,0, 0, 0, - 0xc0,0, 0, 0xaa,0, 0, 0xcf,0, 0, - 0, 0, 0xd2,0, 0, 0, 0xde,0, 0, 0, - 0xe0,0, 0, 0xba,0, 0, 0xef,0, 0, - 0, 0, 0xf2,0, 0, 0, 0xfe,0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, 0xcc,-1, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0, -1, 0, 0xec,-1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0xc4,0, 0, 0xcb,0, 0, -1, 0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xe5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, 0, 0xab,0, 0, 0, 0xd3, - 0xa6,0xd1,0, 0xa3,-1, -1, 0, 0, 0, 0, - 0, -1, 0, 0, 0xbb,0, 0, 0, 0xf3, - 0xb6,0xf1,0, 0xb3,-1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xa1,0, 0, 0xca,0, 0, 0xc7,0, 0, - 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0, - 0xb1,0, 0, 0xea,0, 0, 0xe7,0, 0, - 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0, - 0, 0xc8,-1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, 0xa9,-1, 0, 0, 0, 0xae, - 0, 0xe8,-1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, 0xb9,-1, 0, 0, 0, 0xbe -#elif (ISO_8859 == 9) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc0,0, 0, 0xc8,0, 0, 0xcc,0, 0, - 0, 0, 0xd2,0, 0, 0, 0xd9,0, 0, 0, - 0xe0,0, 0, 0xe8,0, 0, -1, 0, 0, - 0, 0, 0xf2,0, 0, 0, 0xf9,0, 0, 0, - 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0, - -1, -1, 0xd3,-1, -1, 0, 0xda,0, -1, -1, - 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0, - -1, -1, 0xf3,-1, -1, 0, 0xfa,0, -1, -1, - 0xc2,-1, 0, 0xca,-1, -1, 0xce,-1, 0, - 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0, - 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0, - 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0, - 0xc3,0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xd1,0xd5,0, 0, 0, -1, 0, 0, 0, - 0xe3,0, 0, 0, 0, 0, -1, 0, 0, - 0, 0xf1,0xf5,0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, 0xef,0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0xd0,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0xf0,0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, -1, -1, 0, 0xdd,0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0, -1, 0, 0xec,-1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, -1, 0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, 0xff,0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xe5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, 0xc7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xde,-1, 0, 0, 0, 0, - 0, 0xe7,0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, 0xfe,-1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0xea,0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1 -#elif (ISO_8859 == 10) - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xc1,-1, 0, 0xc9,0, 0, 0xcd,0, 0, - -1, -1, 0xd3,-1, -1, 0, 0xda,0, 0xdd,-1, - 0xe1,-1, 0, 0xe9,0, 0, 0xed,0, 0, - -1, -1, 0xf3,-1, -1, 0, 0xfa,0, 0xfd,-1, - 0xc2,-1, 0, -1, -1, -1, 0xce,-1, 0, - 0, 0, 0xd4,0, -1, 0, 0xdb,-1, -1, 0, - 0xe2,-1, 0, -1, -1, -1, 0xee,-1, 0, - 0, 0, 0xf4,0, -1, 0, 0xfb,-1, -1, 0, - 0xc3,0, 0, 0, 0, 0, 0xa5,0, 0, - 0, -1, 0xd5,0, 0, 0, 0xd7,0, 0, 0, - 0xe3,0, 0, 0, 0, 0, 0xb5,0, 0, - 0, -1, 0xf5,0, 0, 0, 0xf7,0, 0, 0, - 0xc0,0, 0, 0xa2,0, 0, 0xa4,0, 0, - 0, 0, 0xd2,0, 0, 0, 0xae,0, 0, 0, - 0xe0,0, 0, 0xb2,0, 0, 0xb4,0, 0, - 0, 0, 0xf2,0, 0, 0, 0xbe,0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, 0xcc,-1, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0, -1, 0, 0xec,-1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0xc4,0, 0, 0xcb,0, 0, 0xcf,0, 0, - 0, 0, 0xd6,0, 0, 0, 0xdc,0, -1, 0, - 0xe4,0, 0, 0xeb,0, 0, 0xef,0, 0, - 0, 0, 0xf6,0, 0, 0, 0xfc,0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xc5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0xe5,0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, 0, 0xa3,0, 0, 0, 0xa6, - 0xa8,0xd1,0, -1, -1, -1, 0, 0, 0, 0, - 0, -1, 0, 0, 0xb3,0, 0, 0, 0xb6, - 0xb8,0xf1,0, -1, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0xa1,0, 0, 0xca,0, 0, 0xc7,0, 0, - 0, 0, 0, 0, 0, 0, 0xd9,0, 0, 0, - 0xb1,0, 0, 0xea,0, 0, 0xe7,0, 0, - 0, 0, 0, 0, 0, 0, 0xf9,0, 0, 0, - 0, 0xc8,-1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, 0xaa,-1, 0, 0, 0, 0xac, - 0, 0xe8,-1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, 0xba,-1, 0, 0, 0, 0xbc -#else - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, -1, 0, -1, 0, 0, -1, 0, 0, - -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, - -1, -1, 0, -1, 0, 0, -1, 0, 0, - -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, - -1, -1, 0, -1, -1, -1, -1, -1, 0, - 0, 0, -1, 0, -1, 0, -1, -1, -1, 0, - -1, -1, 0, -1, -1, -1, -1, -1, 0, - 0, 0, -1, 0, -1, 0, -1, -1, -1, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0, 0, -1, 0, 0, - 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, -1, -1, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 0, -1, 0, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, -1, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, 0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, - 0, -1, 0, 0, -1, 0, 0, 0, -1, - -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - -1, 0, 0, -1, 0, 0, -1, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1, - 0, -1, -1, -1, 0, 0, 0, 0, 0, - -1, -1, 0, -1, -1, -1, 0, 0, 0, -1 -#endif -}; - -/* ---- T.61 characters [0xA0 .. 0xBF] ----------------- -*/ -static const Couple trans_t61a_iso8859[32] = { -#if (ISO_8859 == 1) || (ISO_8859 == 9) - {'N','S'}, {0xa1,0}, {0xa2,0}, {0xa3,0}, - {'D','O'}, {0xa5,0}, {'C','u'}, {0xa7,0}, - {0xa4,0}, {'\'','6'},{'"','6'}, {0xab,0}, - {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'}, - {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0}, - {0xd7,0}, {0xb5,0}, {0xb6,0}, {0xb7,0}, - {0xf7,0}, {'\'','9'},{'"','9'}, {0xbb,0}, - {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0} -#elif (ISO_8859 == 2) || (ISO_8859 == 4) - {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'}, - {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0}, - {0xa4,0}, {'\'','6'},{'"','6'}, {'<','<'}, - {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'}, - {0xb0,0}, {'+','-'}, {'2','S'}, {'3','S'}, - {0xd7,0}, {'M','y'}, {'P','I'}, {'.','M'}, - {0xf7,0}, {'\'','9'},{'"','9'}, {'>','>'}, - {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'}, -#elif (ISO_8859 == 3) - {'N','S'}, {'!','I'}, {'C','t'}, {0xa3,0}, - {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0}, - {0xa4,0}, {'\'','6'},{'"','6'}, {'<','<'}, - {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'}, - {0xb0,0}, {'+','-'}, {0xb2,0}, {0xb3,0}, - {0xd7,0}, {0xb5,0}, {'P','I'}, {0xb7,0}, - {0xf7,0}, {'\'','9'},{'"','9'}, {'>','>'}, - {'1','4'}, {0xbd,0}, {'3','4'}, {'?','I'} -#elif (ISO_8859 == 10) - {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'}, - {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0}, - {'C','u'}, {'\'','6'},{'"','6'}, {'<','<'}, - {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'}, - {0xb0,0}, {'+','-'}, {'2','S'}, {'3','S'}, - {'*','X'}, {'M','y'}, {'P','I'}, {0xb7,0}, - {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'}, - {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'} -#else - {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'}, - {'D','O'}, {'Y','e'}, {'C','u'}, {'S','E'}, - {'X','O'}, {'\'','6'},{'"','6'}, {'<','<'}, - {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'}, - {'D','G'}, {'+','-'}, {'2','S'}, {'3','S'}, - {'*','X'}, {'M','y'}, {'P','I'}, {'.','M'}, - {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'}, - {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'} -#endif -}; - -/* ---- T.61 characters [0xE0 .. 0xFF] ----------------- -*/ -static const Couple trans_t61b_iso8859[48] = { -#if (ISO_8859 == 1) - {'-','M'}, {0xb9,0}, {0xae,0}, {0xa9,0}, - {'T','M'}, {'M','8'}, {0xac,0}, {0xa6,0}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {0xc6,0}, {0xd0,0}, {0xaa,0}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {0xd8,0}, {'O','E'}, {0xba,0}, - {0xde,0}, {'T','/'}, {'N','G'}, {'\'','n'}, - {'k','k'}, {0xe6,0}, {'d','/'}, {0xf0,0}, - {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'}, - {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0}, - {0xfe,0}, {'t','/'}, {'n','g'}, {'-','-'} -#elif (ISO_8859 == 2) - {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'}, - {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {'A','E'}, {0xd0,0}, {'-','a'}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {0xa3,0}, {'O','/'}, {'O','E'}, {'-','o'}, - {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'}, - {'k','k'}, {'a','e'}, {0xf0,0}, {'d','-'}, - {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'}, - {0xb3,0}, {'o','/'}, {'o','e'}, {0xdf,0}, - {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'} -#elif (ISO_8859 == 3) - {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'}, - {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'}, - {0xa1,0}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'}, - {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'}, - {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'}, - {0xb1,0}, {0xb9,0}, {'i','j'}, {'l','.'}, - {'l','/'}, {'o','/'}, {'o','e'}, {0xdf,0}, - {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'} -#elif (ISO_8859 == 4) - {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'}, - {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {0xc6,0}, {0xd0,0}, {'-','a'}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {0xd8,0}, {'O','E'}, {'-','o'}, - {'T','H'}, {0xac,0}, {0xbd,0}, {'\'','n'}, - {0xa2,0}, {0xe6,0}, {0xf0,0}, {'d','-'}, - {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'}, - {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0}, - {'t','h'}, {0xbc,0}, {0xbf,0}, {'-','-'} -#elif (ISO_8859 == 9) - {'-','M'}, {0xb9,0}, {0xae,0}, {0xa9,0}, - {'T','M'}, {'M','8'}, {0xac,0}, {0xa6,0}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {0xc6,0}, {'D','/'}, {0xaa,0}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {0xd8,0}, {'O','E'}, {0xba,0}, - {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'}, - {'k','k'}, {0xe6,0}, {'d','/'}, {'d','-'}, - {'h','/'}, {0xfd,0}, {'i','j'}, {'l','.'}, - {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0}, - {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'} -#elif (ISO_8859 == 10) - {0xbd,0}, {'1','S'}, {'R','g'}, {'C','o'}, - {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {0xc6,0}, {0xa9,0}, {'-','a'}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {0xd8,0}, {'O','E'}, {'-','o'}, - {0xde,0}, {0xab,0}, {0xaf,0}, {'\'','n'}, - {0xff,0}, {0xe6,0}, {0xb9,0}, {0xf0,0}, - {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'}, - {'l','/'}, {0xf8,0}, {'o','e'}, {0xdf,0}, - {0xfe,0}, {0xbb,0}, {0xbf,0}, {'-','-'} -#else - {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'}, - {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'}, - {0,0}, {0,0}, {0,0}, {0,0}, - {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'}, - {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'}, - {'H','/'}, {0,0}, {'I','J'}, {'L','.'}, - {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'}, - {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'}, - {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'}, - {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'}, - {'l','/'}, {'o','/'}, {'o','e'}, {'s','s'}, - {'t','h'}, {'t','-'}, {'n','g'}, {'-','-'} -#endif -}; - -/* ---- ISO 8859-n characters <0xA0 .. 0xFF> ------------------- -*/ -#if (ISO_8859 == 1) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xa1,0}, {0xa2,0}, {0xa3,0}, - {0xa8,0}, {0xa5,0}, {0xd7,0}, {0xa7,0}, - {0xc8,ALONE}, {0xd3,0}, {0xe3,0}, {0xab,0}, - {0xd6,0}, {0xff,0}, {0xd2,0}, {0xc5,ALONE}, - {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0}, - {0xc2,ALONE}, {0xb5,0}, {0xb6,0}, {0xb7,0}, - {0xcb,ALONE}, {0xd1,0}, {0xeb,0}, {0xbb,0}, - {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0}, - {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'}, - {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xcb,'C'}, - {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'}, - {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'}, - {0xe2,0}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'}, - {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0}, - {0xe9,0}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'}, - {0xc8,'U'}, {0xc2,'Y'}, {0xec,0}, {0xfb,0}, - {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'}, - {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xcb,'c'}, - {0xc1,'e'}, {0xc2,'e'}, {0xc3,'e'}, {0xc8,'e'}, - {0xc1,'i'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'}, - {0xf3,0}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'}, - {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0}, - {0xf9,0}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'}, - {0xc8,'u'}, {0xc2,'y'}, {0xfc,0}, {0xc8,'y'} -}; -#elif (ISO_8859 == 2) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xce,'A'}, {0xc6,ALONE}, {0xe8,0}, - {0xa8,0}, {0xcf,'L'}, {0xc2,'S'}, {0xa7,0}, - {0xc8,ALONE}, {0xcf,'S'}, {0xcb,'S'}, {0xcf,'T'}, - {0xc2,'Z'}, {0xff,0}, {0xcf,'Z'}, {0xc7,'Z'}, - {0xb0,0}, {0xce,'a'}, {0xce,ALONE}, {0xf8,0}, - {0xc2,ALONE}, {0xcf,'l'}, {0xc2,'s'}, {0xcf,ALONE}, - {0xcb,ALONE}, {0xcf,'s'}, {0xcb,'s'}, {0xcf,'t'}, - {0xc2,'z'}, {0xcd,ALONE}, {0xcf,'z'}, {0xc7,'z'}, - {0xc2,'R'}, {0xc2,'A'}, {0xc3,'A'}, {0xc6,'A'}, - {0xc8,'A'}, {0xc2,'L'}, {0xc2,'C'}, {0xcb,'C'}, - {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'}, - {0xcf,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xcf,'D'}, - {0xe2,0}, {0xc2,'N'}, {0xcf,'N'}, {0xc2,'O'}, - {0xc3,'O'}, {0xcd,'O'}, {0xc8,'O'}, {0xb4,0}, - {0xcf,'R'}, {0xca,'U'}, {0xc2,'U'}, {0xcd,'U'}, - {0xc8,'U'}, {0xc2,'Y'}, {0xcb,'T'}, {0xfb,0}, - {0xc2,'r'}, {0xc2,'a'}, {0xc3,'a'}, {0xc6,'a'}, - {0xc8,'a'}, {0xc2,'l'}, {0xc2,'c'}, {0xcb,'c'}, - {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'}, - {0xcf,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xcf,'d'}, - {0xf2,0}, {0xc2,'n'}, {0xcf,'n'}, {0xc2,'o'}, - {0xc3,'o'}, {0xcd,'o'}, {0xc8,'o'}, {0xb8,0}, - {0xcf,'r'}, {0xca,'u'}, {0xc2,'u'}, {0xcd,'u'}, - {0xc8,'u'}, {0xc2,'y'}, {0xcb,'t'}, {0xc7,ALONE} -}; -#elif (ISO_8859 == 3) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xe4,0}, {0xc6,ALONE}, {0xa3,0}, - {0xa8,0}, {0,0}, {0xc3,'H'}, {0xa7,0}, - {0xc8,ALONE}, {0xc7,'I'}, {0xcb,'S'}, {0xc6,'G'}, - {0xc3,'J'}, {0xff,0}, {0,0}, {0xc7,'Z'}, - {0xb0,0}, {0xf4,0}, {0xb2,0}, {0xb3,0}, - {0xc2,ALONE}, {0xb5,0}, {0xc3,'h'}, {0xb7,0}, - {0xcb,ALONE}, {0xf5,0}, {0xcb,'s'}, {0xc6,'g'}, - {0xc3,'j'}, {0xbd,0}, {0,0}, {0xc7,'z'}, - {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0,0}, - {0xc8,'A'}, {0xc7,'C'}, {0xc3,'C'}, {0xcb,'C'}, - {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'}, - {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'}, - {0,0}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'}, - {0xc3,'O'}, {0xc7,'G'}, {0xc8,'O'}, {0xb4,0}, - {0xc3,'G'}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'}, - {0xc8,'U'}, {0xc6,'U'}, {0xc3,'S'}, {0xfb,0}, - {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0,0}, - {0xc8,'a'}, {0xc7,'c'}, {0xc3,'c'}, {0xcb,'c'}, - {0xc1,'e'}, {0xc2,'e'}, {0xc3,'e'}, {0xc8,'e'}, - {0xc1,'i'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'}, - {0,0}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'}, - {0xc3,'o'}, {0xc7,'g'}, {0xc8,'o'}, {0xb8,0}, - {0xc3,'g'}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'}, - {0xc8,'u'}, {0xc6,'u'}, {0xc3,'s'}, {0xc7,ALONE} -}; -#elif (ISO_8859 == 4) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xce,'A'}, {0xf0,0}, {0xcb,'R'}, - {0xa8,0}, {0xc4,'I'}, {0xcb,'L'}, {0xa7,0}, - {0xc8,ALONE}, {0xcf,'S'}, {0xc5,'E'}, {0xcb,'G'}, - {0xed,0}, {0xff,0}, {0xcf,'Z'}, {0xc5,ALONE}, - {0xb0,0}, {0xce,'a'}, {0xce,ALONE}, {0xcb,'r'}, - {0xc2,ALONE}, {0xc4,'i'}, {0xcb,'l'}, {0xcf,ALONE}, - {0xcb,ALONE}, {0xcf,'s'}, {0xc5,'e'}, {0xcb,'g'}, - {0xfd,0}, {0xee,0}, {0xcf,'z'}, {0xfe,0}, - {0xc5,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'}, - {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xce,'I'}, - {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'}, - {0xc7,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xc5,'I'}, - {0xe2,0}, {0xcb,'N'}, {0xc5,'O'}, {0xcb,'K'}, - {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0}, - {0xe9,0}, {0xce,'U'}, {0xc2,'U'}, {0xc3,'U'}, - {0xc8,'U'}, {0xc4,'U'}, {0xc5,'U'}, {0xfb,0}, - {0xc5,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'}, - {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xce,'i'}, - {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'}, - {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc5,'i'}, - {0xf2,0}, {0xcb,'n'}, {0xc5,'o'}, {0xcb,'k'}, - {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0}, - {0xf9,0}, {0xce,'u'}, {0xc2,'u'}, {0xc3,'u'}, - {0xc8,'u'}, {0xc4,'u'}, {0xc5,'u'}, {0xc7,ALONE} -}; -#elif (ISO_8859 == 9) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xa1,0}, {0xa2,0}, {0xa3,0}, - {0xa8,0}, {0xa5,0}, {0xd7,0}, {0xa7,0}, - {0xc8,ALONE}, {0xd3,0}, {0xe3,0}, {0xab,0}, - {0xd6,0}, {0xff,0}, {0xd2,0}, {0xc5,ALONE}, - {0xb0,0}, {0xb1,0}, {0xb2,0}, {0xb3,0}, - {0xc2,ALONE}, {0xb5,0}, {0xb6,0}, {0xb7,0}, - {0xcb,ALONE}, {0xd1,0}, {0xeb,0}, {0xbb,0}, - {0xbc,0}, {0xbd,0}, {0xbe,0}, {0xbf,0}, - {0xc1,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'}, - {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xcb,'C'}, - {0xc1,'E'}, {0xc2,'E'}, {0xc3,'E'}, {0xc8,'E'}, - {0xc1,'I'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'}, - {0xc6,'G'}, {0xc4,'N'}, {0xc1,'O'}, {0xc2,'O'}, - {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xb4,0}, - {0xe9,0}, {0xc1,'U'}, {0xc2,'U'}, {0xc3,'U'}, - {0xc8,'U'}, {0xc7,'I'}, {0xcb,'S'}, {0xfb,0}, - {0xc1,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'}, - {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xcb,'c'}, - {0xc1,'e'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'}, - {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc5,'i'}, - {0xc6,'g'}, {0xc4,'n'}, {0xc1,'o'}, {0xc2,'o'}, - {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xb8,0}, - {0xf9,0}, {0xc1,'u'}, {0xc2,'u'}, {0xc3,'u'}, - {0xc8,'u'}, {0xf5,0}, {0xcb,'s'}, {0xc8,'y'} -}; -#elif (ISO_8859 == 10) -static const Couple trans_iso8859_t61[96] = { - {0xa0,0}, {0xce,'A'}, {0xc5,'E'}, {0xcb,'G'}, - {0xc5,'I'}, {0xc4,'I'}, {0xcb,'K'}, {0xa7,0}, - {0xcb,'L'}, {0xe2,0}, {0xcf,'S'}, {0xed,0}, - {0xcf,'Z'}, {0xff,0}, {0xc5,'U'}, {0xee,0}, - {0xb0,0}, {0xce,'a'}, {0xc5,'e'}, {0xcb,'g'}, - {0xc5,'i'}, {0xc4,'i'}, {0xcb,'k'}, {0xb7,0}, - {0xcb,'l'}, {0xf2,0}, {0xcf,'s'}, {0xfd,0}, - {0xcf,'z'}, {0xd0,0}, {0xc5,'u'}, {0xfe,0}, - {0xc5,'A'}, {0xc2,'A'}, {0xc3,'A'}, {0xc4,'A'}, - {0xc8,'A'}, {0xca,'A'}, {0xe1,0}, {0xce,'I'}, - {0xcf,'C'}, {0xc2,'E'}, {0xce,'E'}, {0xc8,'E'}, - {0xc7,'E'}, {0xc2,'I'}, {0xc3,'I'}, {0xc8,'I'}, - {0,0}, {0xcb,'N'}, {0xc5,'O'}, {0xc2,'O'}, - {0xc3,'O'}, {0xc4,'O'}, {0xc8,'O'}, {0xc4,'U'}, - {0xe9,0}, {0xce,'U'}, {0xc2,'U'}, {0xc3,'U'}, - {0xc8,'U'}, {0xc2,'Y'}, {0xec,0}, {0xfb,0}, - {0xc5,'a'}, {0xc2,'a'}, {0xc3,'a'}, {0xc4,'a'}, - {0xc8,'a'}, {0xca,'a'}, {0xf1,0}, {0xce,'i'}, - {0xcf,'c'}, {0xc2,'e'}, {0xce,'e'}, {0xc8,'e'}, - {0xc7,'e'}, {0xc2,'i'}, {0xc3,'i'}, {0xc8,'i'}, - {0xf3,0}, {0xcb,'n'}, {0xc5,'o'}, {0xc2,'o'}, - {0xc3,'o'}, {0xc4,'o'}, {0xc8,'o'}, {0xc4,'u'}, - {0xf9,0}, {0xce,'u'}, {0xc2,'u'}, {0xc3,'u'}, - {0xc8,'u'}, {0xc2,'y'}, {0xfc,0}, {0xf0,0} -}; -#endif - - -static Byte * -c_to_hh( Byte *o, Byte c ) -{ - Byte n; - - *o++ = '{'; *o++ = 'x'; - n = c >> 4; - *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n; - n = c & 0x0F; - *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n; - *o++ = '}'; - return o; -} - - -static Byte * -c_to_cc( Byte *o, const Couple *cc, Byte c ) -{ - if ( (*cc).a != 0 ) { - if ( (*cc).b == 0 ) - *o++ = (*cc).a; - else { - *o++ = '{'; - *o++ = (*cc).a; - *o++ = (*cc).b; - *o++ = '}'; - } - return o; - } - else - return c_to_hh( o, c ); -} - -/* --- routine to convert from T.61 to ISO 8859-n --- */ - -int -ldap_t61_to_8859( char **bufp, ber_len_t *buflenp, int free_input ) -{ - Byte *s, *oo, *o; - unsigned int n; - int c; - ber_len_t len; - - Debug( LDAP_DEBUG_TRACE, "ldap_t61_to_8859 input length: %ld\n", - *buflenp, 0, 0 ); - - len = *buflenp; - s = (Byte *) *bufp; - - if ( (o = oo = (Byte *)LDAP_MALLOC( 2 * len + 64 )) == NULL ) { - return( 1 ); - } - - while ( (char *)s - *(char **)bufp < len ) { - switch ( *s >> 4 ) { - - case 0xA: case 0xB: - o = c_to_cc( o, &trans_t61a_iso8859[ *s - 0xA0 ], *s ); - s++; - break; - - case 0xD: case 0xE: case 0xF: - o = c_to_cc( o, &trans_t61b_iso8859[ *s - 0xD0 ], *s ); - s++; - break; - - case 0xC: - if ( (*s == 0xC0) || (*s == 0xC9) || (*s == 0xCC) ) { - o = c_to_hh( o, *s++ ); - break; - } - - n = (*s++) - 0xC0; - switch ( *s ) { - - case 'A': c = letter_w_diacritic[n][0]; break; - case 'C': c = letter_w_diacritic[n][1]; break; - case 'D': c = letter_w_diacritic[n][2]; break; - case 'E': c = letter_w_diacritic[n][3]; break; - case 'G': c = letter_w_diacritic[n][4]; break; - case 'H': c = letter_w_diacritic[n][5]; break; - case 'I': c = letter_w_diacritic[n][6]; break; - case 'J': c = letter_w_diacritic[n][7]; break; - case 'K': c = letter_w_diacritic[n][8]; break; - case 'L': c = letter_w_diacritic[n][9]; break; - case 'N': c = letter_w_diacritic[n][10]; break; - case 'O': c = letter_w_diacritic[n][11]; break; - case 'R': c = letter_w_diacritic[n][12]; break; - case 'S': c = letter_w_diacritic[n][13]; break; - case 'T': c = letter_w_diacritic[n][14]; break; - case 'U': c = letter_w_diacritic[n][15]; break; - case 'W': c = letter_w_diacritic[n][16]; break; - case 'Y': c = letter_w_diacritic[n][17]; break; - case 'Z': c = letter_w_diacritic[n][18]; break; - - case 'a': c = letter_w_diacritic[n][19]; break; - case 'c': c = letter_w_diacritic[n][20]; break; - case 'd': c = letter_w_diacritic[n][21]; break; - case 'e': c = letter_w_diacritic[n][22]; break; - case 'g': c = letter_w_diacritic[n][23]; break; - case 'h': c = letter_w_diacritic[n][24]; break; - case 'i': c = letter_w_diacritic[n][25]; break; - case 'j': c = letter_w_diacritic[n][26]; break; - case 'k': c = letter_w_diacritic[n][27]; break; - case 'l': c = letter_w_diacritic[n][28]; break; - case 'n': c = letter_w_diacritic[n][29]; break; - case 'o': c = letter_w_diacritic[n][30]; break; - case 'r': c = letter_w_diacritic[n][31]; break; - case 's': c = letter_w_diacritic[n][32]; break; - case 't': c = letter_w_diacritic[n][33]; break; - case 'u': c = letter_w_diacritic[n][34]; break; - case 'w': c = letter_w_diacritic[n][35]; break; - case 'y': c = letter_w_diacritic[n][36]; break; - case 'z': c = letter_w_diacritic[n][37]; break; - - case ALONE: c = (( !diacritic[n].b ) ? diacritic[n].a : -1); - break; - - default: c = 0; - } - - if ( c > 0 ) { - *o++ = c; s++; - } else { - *o++ = '{'; - if ( c == -1 ) { - *o++ = ( ( *s == ALONE ) ? ' ' : *s ); - s++; - } else { - *o++ = '"'; - } - *o++ = diacritic[n].a; - *o++ = '}'; - } - break; - -#if (ISO_8859 == 0) - case 0x8: case 0x9: - *o++ = 0x1B; /* */ - *o++ = *s++ - 0x40; - break; -#endif - - default: - *o++ = *s++; - } - } - - len = o - oo; - o = oo; - - if ( (oo = (Byte *)LDAP_REALLOC( o, len )) == NULL ) { - LDAP_FREE( o ); - return( 1 ); - } - - if ( free_input ) { - LDAP_FREE( *bufp ); - } - *bufp = (char *) oo; - *buflenp = len; - return( 0 ); -} - - -static int -hh_to_c( const Byte *h ) -{ - Byte c; - - if ( (*h >= '0') && (*h <= '9') ) c = *h++ - '0'; - else if ( (*h >= 'A') && (*h <= 'F') ) c = *h++ - 'A' + 10; - else if ( (*h >= 'a') && (*h <= 'f') ) c = *h++ - 'a' + 10; - else return -1; - - c <<= 4; - - if ( (*h >= '0') && (*h <= '9') ) c |= *h - '0'; - else if ( (*h >= 'A') && (*h <= 'F') ) c |= *h - 'A' + 10; - else if ( (*h >= 'a') && (*h <= 'f') ) c |= *h - 'a' + 10; - else return -1; - - return c; -} - - -static Byte * -cc_to_t61( Byte *o, const Byte *s ) -{ - int n, c = 0; - - switch ( *(s + 1) ) { - - case '`': c = -1; break; /* */ - - case '!': - switch ( *s ) { - case '!': c = 0x7C; break; /* */ - case '(': c = 0x7B; break; /* */ - case '-': c = 0xAD; break; /* */ - default: c = -1; /* */ - } - break; - -#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \ - (ISO_8859 == 4) || (ISO_8859 == 9) - case 0xB4: -#endif - case '\'': c = -2; break; /* */ - - case '^': c = -3; break; /* */ - - case '>': - switch ( *s ) { - case ')': c = 0x5D; break; /* */ - case '>': c = 0xBB; break; /* */ - case '-': c = 0xAE; break; /* */ - default: c = -3; /* */ - } - break; - - case '~': - case '?': c = -4; break; /* */ - -#if (ISO_8859 == 1) || (ISO_8859 == 4) || (ISO_8859 == 9) - case 0xAF: c = -5; break; /* */ -#endif - - case '-': - switch ( *s ) { - case '-': c = 0xFF; break; /* */ - case '<': c = 0xAC; break; /* */ - case '+': c = 0xB1; break; /* */ - case 'd': c = 0xF3; break; /* */ - default: c = -5; /* */ - } - break; - -#if (ISO_8859 == 2) || (ISO_8859 == 3) - case 0xA2: c = -6; break; /* */ -#endif - - case '(': - if ( *s == '<' ) c = 0x5B; /* */ - else c = -6; /* */ - break; - -#if (ISO_8859 == 2) || (ISO_8859 == 3) || (ISO_8859 == 4) - case 0xFF: c = -7; break; /* */ -#endif - - case '.': - switch ( *s ) { - case 'i': c = 0xF5; break; /* */ - case 'L': c = 0xE7; break; /* */ - case 'l': c = 0xF7; break; /* */ - default: c = -7; /* */ - } - break; - -#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \ - (ISO_8859 == 4) || (ISO_8859 == 9) - case 0xA8: c = -8; break; /* */ -#endif - - case ':': - if ( *s == '-') c = 0xB8; /* */ - else c = -8; /* */ - break; - -#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \ - (ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10) - case 0xB0: -#endif - case '0': c = -10; break; /* */ - -#if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \ - (ISO_8859 == 4) || (ISO_8859 == 9) - case 0xB8: -#endif - case ',': c = -11; break; /* */ - -#if (ISO_8859 == 2) - case 0xBD: -#endif - case '"': c = -13; break; /* */ - -#if (ISO_8859 == 2) || (ISO_8859 == 4) - case 0xB2: -#endif - case ';': c = -14; break; /* */ - -#if (ISO_8859 == 2) || (ISO_8859 == 4) - case 0xB7: c = -15; break; /* */ -#endif - - case ')': - if ( *s == '!' ) c = 0x7D; /* */ - break; - - case '<': - if ( *s == '<' ) c = 0xAB; /* */ - else c = -15; /* */ - break; - - case '/': - switch ( *s ) { - case '/': c = 0x5C; break; /* */ - case 'D': c = 0xE2; break; /* */ - case 'd': c = 0xF2; break; /* */ - case 'H': c = 0xE4; break; /* */ - case 'h': c = 0xF4; break; /* */ - case 'L': c = 0xE8; break; /* */ - case 'l': c = 0xF8; break; /* */ - case 'O': c = 0xE9; break; /* */ - case 'o': c = 0xF9; break; /* */ - case 'T': c = 0xED; break; /* */ - case 't': c = 0xFD; break; /* */ - } - break; - - case '2': - if ( *s == '1' ) c = 0xBD; /* */ - break; - - case '4': - switch ( *s ) { - case '1': c = 0xBC; break; /* */ - case '3': c = 0xBE; break; /* */ - } - break; - - case '6': - switch ( *s ) { - case '\'': c = 0xA9; break; /* */ - case '"': c = 0xAA; break; /* */ - } - break; - - case '8': - switch ( *s ) { - case '1': c = 0xDC; break; /* */ - case '3': c = 0xDD; break; /* */ - case '5': c = 0xDE; break; /* */ - case '7': c = 0xDF; break; /* */ - case 'M': c = 0xD5; break; /* */ - } - break; - - case '9': - switch ( *s ) { - case '\'': c = 0xB9; break; /* */ - case '"': c = 0xBA; break; /* */ - } - break; - - case 'A': - if ( *s == 'A' ) c = -10; /* + */ - break; - - case 'a': - switch ( *s ) { - case '-': c = 0xE3; break; /* */ - case 'a': c = -10; break; /* + */ - } - break; - - case 'B': - if ( *s == 'B' ) c = 0xD7; /* */ - break; - - case 'b': - if ( *s == 'N' ) c = 0xA6; /* */ - break; - - case 'd': - if ( *s == 'P' ) c = 0xA3; /* */ - break; - - case 'E': - switch ( *s ) { - case 'S': c = 0xA7; break; /* */ - case 'A': c = 0xE1; break; /* */ - case 'O': c = 0xEA; break; /* */ - } - break; - - case 'e': - switch ( *s ) { - case 'a': c = 0xF1; break; /* */ - case 'o': c = 0xFA; break; /* */ - case 'Y': c = 0xA5; break; /* */ - } - break; - - case 'G': - switch ( *s ) { - case 'D': c = 0xB0; break; /* */ - case 'N': c = 0xEE; break; /* */ - } - break; - - case 'g': - switch ( *s ) { - case 'R': c = 0xD2; break; /* */ - case 'n': c = 0xFE; break; /* */ - } - break; - - case 'H': - if ( *s == 'T' ) c = 0xEC; /* */ - break; - - case 'h': - if ( *s == 't' ) c = 0xFC; /* */ - break; - - case 'I': - switch ( *s ) { - case 'P': c = 0xB6; break; /* */ - case '!': c = 0xA1; break; /* */ - case '?': c = 0xBF; break; /* */ - } - break; - - case 'J': - if ( *s == 'I' ) c = 0xE6; /* */ - break; - - case 'j': - if ( *s == 'i' ) c = 0xF6; /* */ - break; - - case 'k': - if ( *s == 'k' ) c = 0xF0; /* */ - break; - - case 'M': - switch ( *s ) { - case '.': c = 0xB7; break; /* */ - case '-': c = 0xD0; break; /* */ - case 'T': c = 0xD4; break; /* */ - } - break; - - case 'm': - switch ( *s ) { - case '\'': /* RFC 1345 */ - case ' ': c = -5; break; /* */ - case 'O': c = 0xE0; break; /* */ - } - break; - - case 'n': - if ( *s == '\'' ) c = 0xEF; /* */ - break; - - case 'O': - switch ( *s ) { - case 'D': c = 0xA4; break; /* */ - case 'N': c = 0xD6; break; /* */ - } - break; - - case 'o': - switch ( *s ) { - case 'C': c = 0xD3; break; /* */ - case '-': c = 0xEB; break; /* */ - } - break; - - case 'S': - switch ( *s ) { - case '1': c = 0xD1; break; /* */ - case '2': c = 0xB2; break; /* */ - case '3': c = 0xB3; break; /* */ - case 'N': c = 0xA0; break; /* */ - } - break; - - case 's': - if ( *s == 's' ) c = 0xFB; /* */ - break; - - case 't': - if ( *s == 'C' ) c = 0xA2; /* */ - break; - - case 'u': - if ( *s == 'C' ) c = 0xA8; /* */ - break; - - case 'v': - if ( *s == '-' ) c = 0xAF; /* */ - break; - - case 'X': - if ( *s == '*' ) c = 0xB4; /* */ - break; - - case 'y': - if ( *s == 'M' ) c = 0xB5; /* */ - break; - } - - if ( c > 0 ) { - *o++ = c; - return o; - } else if ( !c ) - return NULL; - - /* else: c < 0 */ - n = -c; - switch ( *s ) { - - case 'A': c = letter_w_diacritic[n][0]; break; - case 'C': c = letter_w_diacritic[n][1]; break; - case 'D': c = letter_w_diacritic[n][2]; break; - case 'E': c = letter_w_diacritic[n][3]; break; - case 'G': c = letter_w_diacritic[n][4]; break; - case 'H': c = letter_w_diacritic[n][5]; break; - case 'I': c = letter_w_diacritic[n][6]; break; - case 'J': c = letter_w_diacritic[n][7]; break; - case 'K': c = letter_w_diacritic[n][8]; break; - case 'L': c = letter_w_diacritic[n][9]; break; - case 'N': c = letter_w_diacritic[n][10]; break; - case 'O': c = letter_w_diacritic[n][11]; break; - case 'R': c = letter_w_diacritic[n][12]; break; - case 'S': c = letter_w_diacritic[n][13]; break; - case 'T': c = letter_w_diacritic[n][14]; break; - case 'U': c = letter_w_diacritic[n][15]; break; - case 'W': c = letter_w_diacritic[n][16]; break; - case 'Y': c = letter_w_diacritic[n][17]; break; - case 'Z': c = letter_w_diacritic[n][18]; break; - - case 'a': c = letter_w_diacritic[n][19]; break; - case 'c': c = letter_w_diacritic[n][20]; break; - case 'd': c = letter_w_diacritic[n][21]; break; - case 'e': c = letter_w_diacritic[n][22]; break; - case 'g': c = letter_w_diacritic[n][23]; break; - case 'h': c = letter_w_diacritic[n][24]; break; - case 'i': c = letter_w_diacritic[n][25]; break; - case 'j': c = letter_w_diacritic[n][26]; break; - case 'k': c = letter_w_diacritic[n][27]; break; - case 'l': c = letter_w_diacritic[n][28]; break; - case 'n': c = letter_w_diacritic[n][29]; break; - case 'o': c = letter_w_diacritic[n][30]; break; - case 'r': c = letter_w_diacritic[n][31]; break; - case 's': c = letter_w_diacritic[n][32]; break; - case 't': c = letter_w_diacritic[n][33]; break; - case 'u': c = letter_w_diacritic[n][34]; break; - case 'w': c = letter_w_diacritic[n][35]; break; - case 'y': c = letter_w_diacritic[n][36]; break; - case 'z': c = letter_w_diacritic[n][37]; break; - - case '\'': - case ' ': c = -1; break; - - default: c = 0; - } - - if ( !c ) - return NULL; - - *o++ = n + 0xC0; - *o++ = ( ( (*s == ' ') || (*s == '\'') ) ? ALONE : *s ); - return o; -} - - -/* --- routine to convert from ISO 8859-n to T.61 --- */ - -int -ldap_8859_to_t61( char **bufp, ber_len_t *buflenp, int free_input ) -{ - Byte *s, *oo, *o, *aux; - int c; - ber_len_t len; - const Couple *cc; - - Debug( LDAP_DEBUG_TRACE, "ldap_8859_to_t61 input length: %ld\n", - *buflenp, 0, 0 ); - - len = *buflenp; - s = (Byte *) *bufp; - - if ( (o = oo = (Byte *)LDAP_MALLOC( 2 * len + 64 )) == NULL ) { - return( 1 ); - } - - while ( (char *)s - *(char **)bufp < len ) { - switch( *s >> 5 ) { - - case 2: - switch ( *s ) { - - case '^': *o++ = 0xC3; *o++ = ALONE; s++; break; - - case '\\': - s++; - if ( (c = hh_to_c( s )) != -1 ) { - *o++ = c; - s += 2; - } else - *o++ = '\\'; - break; - - default: *o++ = *s++; - } - break; - - case 3: - switch ( *s ) { - - case '`': *o++ = 0xC1; *o++ = ALONE; s++; break; - case '~': *o++ = 0xC4; *o++ = ALONE; s++; break; - - case '{': - s++; - if ( *(s + 2) == '}' ) { - if ( (aux = cc_to_t61( o, s )) != NULL ) { - o = aux; - s += 3; - } else { - *o++ = '{'; - } - } else if ( (*(s + 3) == '}') && ( (*s == 'x') || (*s == 'X') ) && - ( (c = hh_to_c( s + 1 )) != -1 ) ) { - *o++ = c; - s += 4; - } else { - *o++ = '{'; - } - break; - - default: - *o++ = *s++; - } - break; - -#if (ISO_8859 == 0) - case 4: case 5: case 6: case 7: - s++; - break; -#else - case 5: case 6: case 7: -# if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \ - (ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10) - if ( (*(cc = &trans_iso8859_t61[ *s - 0xA0 ])).a ) { - *o++ = (*cc).a; - if ( (*cc).b ) *o++ = (*cc).b; - } -# endif - s++; - break; -#endif - - default: - *o++ = *s++; - } - } - - len = o - oo; - o = oo; - - if ( (oo = (Byte *)LDAP_REALLOC( o, len )) == NULL ) { - LDAP_FREE( o ); - return( 1 ); - } - - if ( free_input ) { - LDAP_FREE( *bufp ); - } - *bufp = (char *) oo; - *buflenp = len; - return( 0 ); -} - - -#ifdef NOT_NEEDED_IN_LIBLDAP /* mcs@umich.edu 12 Oct 1995 */ -/* --- routine to convert "escaped" (\hh) characters to 8bits --- */ - -void convert_escaped_to_8bit( s ) -char *s; -{ - char *o = s; - int c; - - while ( *s ) { - if ( *s == '\\' ) { - if ( (c = hh_to_c( (Byte *) ++s )) != -1 ) { - *o++ = c; - s += 2; - } else - *o++ = '\\'; - } else - *o++ = *s++; - } - *o = '\0'; -} - -/* --- routine to convert 8bits characters to the "escaped" (\hh) form --- */ - -char *convert_8bit_to_escaped( s ) -const Byte *s; -{ - Byte *o, *oo; - Byte n; - - if ( (o = oo = (Byte *)LDAP_MALLOC( 2 * strlen( s ) + 64 )) == NULL ) { - return( NULL ); - } - - while ( *s ) { - if ( *s < 0x80 ) - *o++ = *s++; - else { - *o++ = '\\'; - n = *s >> 4; - *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n; - n = *s++ & 0x0F; - *o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n; - } - } - *o = '\0'; - - o = oo; - - if ( (oo = (Byte *)LDAP_REALLOC( o, strlen( o ) + 1 )) == NULL ) { - LDAP_FREE( o ); - return( NULL ); - } - - return( (char *)oo ); -} - -/* --- routine to convert from T.61 to printable characters --- */ - -/* - printable characters [RFC 1488]: 'A'..'Z', 'a'..'z', '0'..'9', - '\'', '(', ')', '+', ',', '-', '.', '/', ':', '?, ' '. - - that conversion is language dependent. -*/ - -static const Couple last_t61_printabled[32] = { - {0,0}, {'A','E'}, {'D',0}, {0,0}, - {'H',0}, {0,0}, {'I','J'}, {'L',0}, - {'L',0}, {'O',0}, {'O','E'}, {0,0}, - {'T','H'}, {'T',0}, {'N','G'}, {'n',0}, - {'k',0}, {'a','e'}, {'d',0}, {'d',0}, - {'h',0}, {'i',0}, {'i','j'}, {'l',0}, - {'l',0}, {'o',0}, {'o','e'}, {'s','s'}, - {'t','h'}, {'t',0}, {'n','g'}, {0,0} -}; - -char *t61_printable( s ) -Byte *s; -{ - Byte *o, *oo; - Byte n; - const Couple *cc; - - if ( (o = oo = (Byte *)LDAP_MALLOC( 2 * strlen( s ) + 64 )) == NULL ) { - return( NULL ); - } - - while ( *s ) { - if ( ( (*s >= 'A') && (*s <= 'Z') ) || - ( (*s >= 'a') && (*s <= 'z') ) || - ( (*s >= '0') && (*s <= '9') ) || - ( (*s >= '\'') && (*s <= ')') ) || - ( (*s >= '+') && (*s <= '/') ) || - ( *s == '?' ) || ( *s == ' ' ) ) - *o++ = *s++; - else { - if ( *s >= 0xE0 ) { - if ( (*(cc = &last_t61_printabled[ *s - 0xE0 ])).a ) { - *o++ = (*cc).a; - if ( (*cc).b ) *o++ = (*cc).b; - } - } - else if ( (*s >> 4) == 0xC ) { - switch ( *s ) { - case 0xCA: /* ring */ - switch ( *(s + 1) ) { - case 'A': *o++ = 'A'; *o++ = 'A'; s++; break; /* Swedish */ - case 'a': *o++ = 'a'; *o++ = 'a'; s++; break; /* Swedish */ - } - break; - - case 0xC8: /* diaeresis */ - switch ( *(s + 1) ) { - case 'Y': *o++ = 'I'; *o++ = 'J'; s++; break; /* Dutch */ - case 'y': *o++ = 'i'; *o++ = 'j'; s++; break; /* Dutch */ - } - break; - } - } - s++; - } - } - *o = '\0'; - - o = oo; - - if ( (oo = (Byte *)LDAP_REALLOC( o, strlen( o ) + 1 )) == NULL ) { - LDAP_FREE( o ); - return( NULL ); - } - - return( (char *)oo ); -} -#endif /* NOT_NEEDED_IN_LIBLDAP */ /* mcs@umich.edu 12 Oct 1995 */ - -#endif /* LDAP_CHARSET_8859 */ -#endif /* STR_TRANSLATION */ diff --git a/libraries/libldap/cldap.c b/libraries/libldap/cldap.c index de6208136b..50839df1fa 100644 --- a/libraries/libldap/cldap.c +++ b/libraries/libldap/cldap.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -94,10 +94,20 @@ cldap_open( LDAP_CONST char *host, int port ) ld->ld_cldapnaddr = 0; ld->ld_cldapaddrs = NULL; - if (ber_pvt_sb_set_io( &(ld->ld_sb), &ber_pvt_sb_io_udp, NULL )<0) { + if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_udp, + LBER_SBIOD_LEVEL_PROVIDER, (void *)&s ) < 0 ) { ldap_ld_free(ld, 1, NULL, NULL ); + tcp_close( s ); return NULL; } + if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_readahead, + LBER_SBIOD_LEVEL_PROVIDER, NULL ) < 0 ) { + ldap_ld_free( ld, 1, NULL, NULL ); + return NULL; + } +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_debug, INT_MAX, NULL ); +#endif ld->ld_version = LDAP_VERSION2; @@ -129,9 +139,9 @@ cldap_open( LDAP_CONST char *host, int port ) } for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) { - SAFEMEMCPY( (char *)&sock.sin_addr.s_addr, + SAFEMEMCPY( (char *)&sock.sin_addr, (char *)hp->h_addr_list[ i ], - sizeof(sock.sin_addr.s_addr)); + sizeof(sock.sin_addr)); if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { ldap_ld_free( ld, 1, NULL, NULL ); LDAP_FREE( host_dup ); @@ -162,13 +172,14 @@ cldap_open( LDAP_CONST char *host, int port ) } if ( ld->ld_cldapaddrs == NULL - || ( ld->ld_defconn = ldap_new_connection( ld, NULL, 1,0,0 )) == NULL + || ( ld->ld_defconn = ldap_new_connection( ld, NULL, 1,0,NULL )) == NULL ) { ldap_ld_free( ld, 0, NULL, NULL ); DO_RETURN( NULL ); } - ber_pvt_sb_udp_set_dst( &ld->ld_sb, ld->ld_cldapaddrs[0] ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST, + ld->ld_cldapaddrs[0] ); cldap_setretryinfo( ld, 0, 0 ); @@ -216,7 +227,7 @@ cldap_search_s( LDAP *ld, *res = NULL; - (void) memset( &cri, 0, sizeof( cri )); + (void) memset( &cri, '\0', sizeof( cri )); if ( logdn != NULL ) { ld->ld_cldapdn = logdn; @@ -229,8 +240,8 @@ cldap_search_s( LDAP *ld, --ld->ld_msgid; /* use same id as before */ } - ber_pvt_sb_udp_set_dst( &(ld->ld_sb), - ld->ld_cldapaddrs[ cri.cri_useaddr ] ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST, + (void *)ld->ld_cldapaddrs[cri.cri_useaddr] ); Debug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n", cri.cri_try, inet_ntoa( ((struct sockaddr_in *) @@ -287,7 +298,6 @@ static int cldap_result( LDAP *ld, int msgid, LDAPMessage **res, struct cldap_retinfo *crip, const char *base ) { - Sockbuf *sb = &ld->ld_sb; BerElement ber; char *logdn; int ret, fromaddr, i; @@ -365,7 +375,7 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, * got a result: determine which server it came from * decode into ldap message chain */ - src = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( sb ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_GET_SRC, (void *)&src ); for ( fromaddr = 0; fromaddr < ld->ld_cldapnaddr; ++fromaddr ) { if ( memcmp( &((struct sockaddr_in *) @@ -401,7 +411,8 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, if ( i == fromaddr ) { continue; } - ber_pvt_sb_udp_set_dst( sb, ld->ld_cldapaddrs[i] ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST, + (void *)ld->ld_cldapaddrs[i] ); Debug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n", msgid, inet_ntoa( ((struct sockaddr_in *) diff --git a/libraries/libldap/compare.c b/libraries/libldap/compare.c index e7ddcc70aa..9cfa56963a 100644 --- a/libraries/libldap/compare.c +++ b/libraries/libldap/compare.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -68,7 +68,7 @@ ldap_compare_ext( if ( ber_printf( ber, "{it{s{sO}}", /* '}' */ ++ld->ld_msgid, - LDAP_REQ_COMPARE, dn, attr, &bvalue ) == -1 ) + LDAP_REQ_COMPARE, dn, attr, bvalue ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); diff --git a/libraries/libldap/controls.c b/libraries/libldap/controls.c index cc07664c90..34f49f5343 100644 --- a/libraries/libldap/controls.c +++ b/libraries/libldap/controls.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -151,7 +151,7 @@ int ldap_int_get_controls( return LDAP_NO_MEMORY; } - ctrls[nctrls] = NULL; + *ctrls[nctrls] = NULL; for( tag = ber_first_element( ber, &len, &opaque ); tag != LBER_ERROR; @@ -226,7 +226,9 @@ int ldap_int_get_controls( void ldap_control_free( LDAPControl *c ) { +#ifdef LDAP_MEMORY_DEBUG assert( c != NULL ); +#endif if ( c != NULL ) { if( c->ldctl_oid != NULL) { @@ -247,7 +249,9 @@ ldap_control_free( LDAPControl *c ) void ldap_controls_free( LDAPControl **controls ) { +#ifdef LDAP_MEMORY_DEBUG assert( controls != NULL ); +#endif if ( controls != NULL ) { int i; @@ -357,3 +361,81 @@ ldap_control_dup( const LDAPControl *c ) new->ldctl_iscritical = c->ldctl_iscritical; return new; } + +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */ +/*--- + * This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Modification to OpenLDAP source by Novell, Inc. + * June 2000 sfs Added control utilities + */ +/*--- + ldap_int_create_control + + Internal function to create an LDAP control from the encoded BerElement. + + requestOID (IN) The OID to use in creating the control. + + ber (IN) The encoded BerElement to use in creating the control. + + iscritical (IN) 0 - Indicates the control is not critical to the operation. + non-zero - The control is critical to the operation. + + ctrlp (OUT) Returns a pointer to the LDAPControl created. This control + SHOULD be freed by calling ldap_control_free() when done. +---*/ + +LIBLDAP_F( int ) +ldap_int_create_control( + const char *requestOID, + BerElement *ber, + int iscritical, + LDAPControl **ctrlp ) +{ + LDAPControl *ctrl; + struct berval *bvalp; + + if ( requestOID == NULL || ber == NULL || ctrlp == NULL ) { + return LDAP_PARAM_ERROR; + } + + if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) { + return LDAP_NO_MEMORY; + } + + ctrl = (LDAPControl *) LBER_MALLOC( sizeof(LDAPControl) ); + if ( ctrl == NULL ) { + ber_bvfree( bvalp ); + return LDAP_NO_MEMORY; + } + + ctrl->ldctl_value = *bvalp; + LDAP_FREE( bvalp ); + + ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); + ctrl->ldctl_iscritical = iscritical; + + if ( ctrl->ldctl_oid == NULL ) { + LBER_FREE( ctrl ); + return LDAP_NO_MEMORY; + } + + *ctrlp = ctrl; + return LDAP_SUCCESS; +} diff --git a/libraries/libldap/delete.c b/libraries/libldap/delete.c index 6d463e17f6..e750ecb9d8 100644 --- a/libraries/libldap/delete.c +++ b/libraries/libldap/delete.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/digest.c b/libraries/libldap/digest.c deleted file mode 100644 index 69aa80c120..0000000000 --- a/libraries/libldap/digest.c +++ /dev/null @@ -1,382 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ -/* digest.c: - * DIGEST-MD5 routines - */ - -#include "portable.h" - -#ifdef DIGEST_MD5 - -#include -#include -#include - -#include "ldap-int.h" -#include "ldap_pvt.h" - -#define TK_NOENDQUOTE -2 -#define TK_OUTOFMEM -1 - -#define TK_EOS 0 -#define TK_UNEXPCHAR 1 -#define TK_BAREWORD 2 -#define TK_COMMA 3 -#define TK_EQUALS 4 -#define TK_QDSTRING 5 - -struct token { - int type; - char *sval; -}; - -static int -get_token(const char ** sp, char ** token_val) -{ - int kind; - const char * p; - const char * q; - char * res; - - *token_val = NULL; - - if( (**sp) != '\0' || iscntrl(**sp) || !isascii(**sp) ) { - (*sp)++; - return TK_UNEXPCHAR; - } - - switch (**sp) { - case '\0': - kind = TK_EOS; - (*sp)++; - break; - - case ',': - kind = TK_COMMA; - (*sp)++; - break; - - case '=': - kind = TK_EQUALS; - (*sp)++; - break; - - case '\"': - kind = TK_QDSTRING; - (*sp)++; - - for (p = *sp; - **sp != '\"' && **sp != '\0' && isascii(**sp); - (*sp)++ ) - { - if(**sp == '\\') { - (*sp)++; - if( **sp == '\0' ) break; - } - } - - if ( **sp == '\"' ) { - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - (*sp)++; - - } else { - kind = TK_NOENDQUOTE; - } - - break; - - default: - kind = TK_BAREWORD; - p = *sp; - while ( isascii(**sp) && - !iscntrl(**sp) && - !isspace(**sp) && - **sp != '(' && - **sp != ')' && - **sp != '<' && - **sp != '>' && - **sp != '@' && - **sp != ',' && - **sp != ';' && - **sp != ':' && - **sp != '\\'&& - **sp != '\"'&& - **sp != '/' && - **sp != '[' && - **sp != ']' && - **sp != '?' && - **sp != '=' && - **sp != '{' && - **sp != '}' && - **sp != '\0' ) - (*sp)++; - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - } - - return kind; -} - -struct kv { - char *key; - char *value; -}; - -static void kv_destory( struct kv **kv ) -{ - int i; - - if( kv == NULL ) return; - - for( i=0; kv[i] != NULL; i++ ) { - if( kv[i]->key != NULL ) { - LDAP_FREE( kv[i]->key ); - } - - if( kv[i]->value != NULL ) { - LDAP_FREE( kv[i]->value ); - } - - LDAP_FREE( kv[i] ); - } - - LDAP_FREE( kv ); -} - -static int kv_add( struct kv ***kvs, const struct kv *kv ) -{ - int n; - struct kv **tmp_kvs; - struct kv *tmp_kv; - - assert( kvs != NULL ); - assert( kv != NULL ); - - tmp_kv = LDAP_MALLOC( sizeof(struct kv) ); - - if( tmp_kv == NULL ) { - return -1; - } - - *tmp_kv = *kv; - - if( *kvs == NULL ) { - tmp_kvs = LDAP_MALLOC( 2 * sizeof(struct kv *) ); - n = 0; - - } else { - for( n=0; (*kvs)[n] != NULL; n++ ) { - /* EMPTY */ ; - } - - tmp_kvs = LDAP_REALLOC( kvs, (n+2) * sizeof(struct kv *) ); - } - - if( tmp_kvs == NULL ) { - LDAP_FREE( tmp_kv ); - return -1; - } - - *kvs = tmp_kvs; - kvs[n] = tmp_kvs; - kvs[n+1] = NULL; - - return 0; -} - -#define ST_ERROR -1 -#define ST_DONE 0 -#define ST_KEY 1 -#define ST_EQUALS 2 -#define ST_VALUE 3 -#define ST_SEP 4 - -static int -parse_key_value( - struct kv ***kvsp, - const char *str ) -{ - int rc = 0; - int kind, state; - const char *ss = str; - char *sval; - - struct kv **kvs = NULL; - struct kv kv; - - assert( kvsp != NULL ); - assert( str != NULL ); - - kv.key = NULL; - kv.value = NULL; - - state = ST_KEY; - - while( state > ST_DONE ) { - kind = get_token( &ss, &sval ); - switch( kind ) { - case TK_EOS: - state = ( state == ST_SEP ) - ? ST_DONE : ST_ERROR; - break; - - case TK_BAREWORD: - if( state == ST_KEY ) { - state = ST_EQUALS; - - assert( kv.key == NULL ); - assert( kv.value == NULL ); - kv.key = sval; - - } else if ( state == ST_VALUE ) { - state = ST_SEP; - - assert( kv.key != NULL ); - assert( kv.value == NULL ); - kv.value = sval; - - } else { - state = ST_ERROR; - } - break; - - case TK_COMMA: - state = ( state == ST_SEP ) - ? ST_KEY : ST_ERROR; - break; - - case TK_EQUALS: - state = ( state == ST_EQUALS ) - ? ST_VALUE : ST_ERROR; - break; - - case TK_QDSTRING: - if( state == ST_VALUE ) { - state = ST_SEP; - - assert( kv.key != NULL ); - assert( kv.value == NULL ); - kv.value = sval; - - } else { - state = ST_ERROR; - } - break; - - default: - state = ST_ERROR; - } - - if( state == ST_SEP ) { - /* add kv to return */ - if( kv_add( &kvs, &kv ) != 0 ) { - state = ST_ERROR; - kind = TK_OUTOFMEM; - - } else { - kv.key = NULL; - kv.value = NULL; - } - } - } - - if( state == ST_ERROR ) { - if( kv.key != NULL ) LDAP_FREE(kv.key); - if( kv.value != NULL ) LDAP_FREE( kv.value ); - - kv_destory( kvs ); - kvs = NULL; - - rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ; - } - - *kvsp = kvs; - return rc; -} - -static int -parse_value_list( - char ***valuesp, - const char* str ) -{ - int rc = 0; - char **values = NULL; - - int kind, state; - const char *ss = str; - char *sval; - - assert( valuesp != NULL ); - assert( str != NULL ); - - state = ST_VALUE; - - while( state > ST_DONE ) { - kind = get_token( &ss, &sval ); - switch( kind ) { - case TK_EOS: - state = ( state == ST_SEP ) - ? ST_DONE : ST_ERROR; - break; - - case TK_BAREWORD: - if( state == ST_VALUE ) { - state = ST_SEP; - - } else { - state = ST_ERROR; - } - break; - - case TK_COMMA: - state = ( state == ST_SEP ) - ? ST_VALUE : ST_ERROR; - break; - - default: - state = ST_ERROR; - } - - if( state == ST_SEP ) { - if( ldap_charray_add( &values, sval ) != 0 ) { - state = ST_ERROR; - kind = TK_OUTOFMEM; - } - - LDAP_FREE( sval ); - sval = NULL; - } - } - - if( state == ST_ERROR ) { - if( sval != NULL ) LDAP_FREE( sval ); - - LDAP_VFREE( values ); - values = NULL; - - rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ; - } - - *valuesp = values; - return rc; -} - -#endif diff --git a/libraries/libldap/disptmpl.c b/libraries/libldap/disptmpl.c index 40c2b77343..82dcfe8f3d 100644 --- a/libraries/libldap/disptmpl.c +++ b/libraries/libldap/disptmpl.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -149,13 +149,13 @@ ldap_init_templates_buf( char *buf, ber_len_t buflen, *tmpllistp = prevtmpl = NULL; - if ( next_line_tokens( &buf, &buflen, &toks ) != 2 || + if ( ldap_int_next_line_tokens( &buf, &buflen, &toks ) != 2 || strcasecmp( toks[ 0 ], "version" ) != 0 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); return( LDAP_TMPL_ERR_SYNTAX ); } version = atoi( toks[ 1 ] ); - free_strarray( toks ); + LDAP_VFREE( toks ); if ( version != LDAP_TEMPLATE_VERSION ) { return( LDAP_TMPL_ERR_VERSION ); } @@ -226,7 +226,7 @@ free_disptmpl( struct ldap_disptmpl *tmpl ) for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { nextocp = ocp->oc_next; - free_strarray( ocp->oc_objclasses ); + LDAP_VFREE( ocp->oc_objclasses ); LDAP_FREE( ocp ); } } @@ -260,7 +260,7 @@ free_disptmpl( struct ldap_disptmpl *tmpl ) LDAP_FREE( colp->ti_label ); } if ( colp->ti_args != NULL ) { - free_strarray( colp->ti_args ); + LDAP_VFREE( colp->ti_args ); } LDAP_FREE( colp ); } @@ -457,14 +457,14 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * template name comes first */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); } if (( tmpl = (struct ldap_disptmpl *)LDAP_CALLOC( 1, sizeof( struct ldap_disptmpl ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); return( LDAP_TMPL_ERR_MEM ); } tmpl->dt_name = toks[ 0 ]; @@ -473,8 +473,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * template plural name comes next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -484,8 +484,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * template icon name is next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -495,8 +495,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * template options come next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) < 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -507,15 +507,15 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, } } } - free_strarray( toks ); + LDAP_VFREE( toks ); /* * object class list is next */ - while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { + while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) { if (( ocp = (struct ldap_oclist *)LDAP_CALLOC( 1, sizeof( struct ldap_oclist ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_MEM ); } @@ -535,8 +535,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * read name of attribute to authenticate as */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -550,8 +550,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * read default attribute to use for RDN */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -561,8 +561,8 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * read default location for new entries */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -576,7 +576,7 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, /* * read list of rules used to define default values for new entries */ - while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { + while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) { if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) { adsource = LDAP_ADSRC_CONSTANTVALUE; } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) { @@ -587,14 +587,14 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, if ( adsource == 0 || tokcnt < 2 || ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } if (( adp = (struct ldap_adddeflist *)LDAP_CALLOC( 1, sizeof( struct ldap_adddeflist ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_MEM ); } @@ -618,17 +618,17 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, * item list is next */ samerow = 0; - while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { + while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) { if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { if ( tokcnt < 4 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } if (( ip = (struct ldap_tmplitem *)LDAP_CALLOC( 1, sizeof( struct ldap_tmplitem ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_MEM ); } @@ -644,7 +644,7 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, } } if ( itemoptions[ i ] == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -657,7 +657,7 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, } } if ( itemtypes[ i ] == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } @@ -698,10 +698,10 @@ read_next_tmpl( char **bufp, ber_len_t *blenp, struct ldap_disptmpl **tmplp, previp = ip; samerow = 0; } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); samerow = 1; } else { - free_strarray( toks ); + LDAP_VFREE( toks ); free_disptmpl( tmpl ); return( LDAP_TMPL_ERR_SYNTAX ); } diff --git a/libraries/libldap/dn.c b/libraries/libldap/dn.c index fc1c6ead88..d0ba92f886 100644 --- a/libraries/libldap/dn.c +++ b/libraries/libldap/dn.c @@ -1,7 +1,7 @@ /* dn.c - routines for dealing with distinguished names */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -217,25 +217,7 @@ ldap_dn_parent( } /* - * no =, assume it is a dns name, like blah@some.domain.name - * if the blah@ part is there, return some.domain.name. if - * it's just some.domain.name, return domain.name. - */ - if ( strchr( dn, '=' ) == NULL ) { - if ( (s = strchr( dn, '@' )) == NULL ) { - if ( (s = strchr( dn, '.' )) == NULL ) { - return( NULL ); - } - } - if ( *(s + 1) == '\0' ) { - return( NULL ); - } else { - return( LDAP_STRDUP( &s[1] ) ); - } - } - - /* - * else assume it is an X.500-style name, which looks like + * assume it is an X.500-style name, which looks like * foo=bar,sha=baz,... */ @@ -288,25 +270,8 @@ char * ldap_dn_rdn( return NULL; } -#ifdef DNS_DN - /* - * no =, assume it is a dns name, like blah@some.domain.name - * if the blah@ part is there, return some.domain.name. if - * it's just some.domain.name, return domain.name. - */ - if ( strchr( rdn, '=' ) == NULL ) { - if ( (s = strchr( rdn, '@' )) == NULL ) { - if ( (s = strchr( rdn, '.' )) == NULL ) { - return( rdn ); - } - } - *s = '\0'; - return( rdn ); - } -#endif - /* - * else assume it is an X.500-style name, which looks like + * assume it is an X.500-style name, which looks like * foo=bar,sha=baz,... */ diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c new file mode 100644 index 0000000000..ae963012a5 --- /dev/null +++ b/libraries/libldap/dnssrv.c @@ -0,0 +1,307 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +/* + * locate LDAP servers using DNS SRV records. + * Location code based on MIT Kerberos KDC location code. + */ +#include "portable.h" + +#include + +#include + +#include +#include +#include +#include + +#include "ldap-int.h" + +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif +#ifdef HAVE_RESOLV_H +#include +#endif + +/* Sometimes this is not defined. */ +#ifndef T_SRV +#define T_SRV 33 +#endif /* T_SRV */ + +int ldap_dn2domain( + LDAP_CONST char *dn_in, + char **domainp) +{ + int i; + char *domain = NULL; + char **dn; + + if( dn_in == NULL || domainp == NULL ) { + return -1; + } + + dn = ldap_explode_dn( dn_in, 0 ); + + if( dn == NULL ) { + return -2; + } + + for( i=0; dn[i] != NULL; i++ ) { + char ** rdn = ldap_explode_rdn( dn[i], 0 ); + + if( rdn == NULL || *rdn == NULL ) { + LDAP_FREE( rdn ); + LDAP_FREE( domain ); + LDAP_VFREE( dn ); + return -3; + } + + + if( rdn[1] == NULL ) { + /* + * single-valued RDN + */ + char *dc; + +#define LDAP_DC "dc=" +#define LDAP_DCOID "0.9.2342.19200300.100.1.25=" + + if( strncasecmp( rdn[0], + LDAP_DC, sizeof(LDAP_DC)-1 ) == 0 ) + { + dc = &rdn[0][sizeof(LDAP_DC)-1]; + + } else if( strncmp( rdn[0], + LDAP_DCOID, sizeof(LDAP_DCOID)-1 ) == 0 ) + { + dc = &rdn[0][sizeof(LDAP_DCOID)-1]; + + } else { + dc = NULL; + } + + if( dc != NULL ) { + char *ndomain; + + if( *dc == '\0' ) { + /* dc value is empty! */ + LDAP_FREE( rdn ); + LDAP_FREE( domain ); + LDAP_VFREE( dn ); + LDAP_VFREE( rdn ); + return -4; + } + + ndomain = LDAP_REALLOC( domain, + ( domain == NULL ? 0 : strlen(domain) ) + + strlen(dc) + sizeof(".") ); + + if( ndomain == NULL ) { + LDAP_FREE( rdn ); + LDAP_FREE( domain ); + LDAP_VFREE( dn ); + LDAP_VFREE( rdn ); + return -5; + } + + if( domain == NULL ) { + ndomain[0] = '\0'; + } else { + strcat( ndomain, "." ); + } + + strcat( ndomain, dc ); + + domain = ndomain; + continue; + } + } + + /* + * multi-valued RDN or fall thru + */ + + LDAP_VFREE( rdn ); + LDAP_FREE( domain ); + domain = NULL; + } + + if( domain != NULL && *domain == '\0' ) { + LDAP_FREE( domain ); + domain = NULL; + } + + *domainp = domain; + return 0; +} + +int ldap_domain2dn( + LDAP_CONST char *domain_in, + char **dnp) +{ + char *domain, *s, *tok_r, *dn; + size_t loc; + + if (domain_in == NULL || dnp == NULL) { + return LDAP_NO_MEMORY; + } + domain = LDAP_STRDUP(domain_in); + if (domain == NULL) { + return LDAP_NO_MEMORY; + } + dn = NULL; + loc = 0; + + for (s = ldap_pvt_strtok(domain, ".", &tok_r); + s != NULL; + s = ldap_pvt_strtok(NULL, ".", &tok_r)) { + size_t len = strlen(s); + + dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len ); + if (dn == NULL) { + LDAP_FREE(domain); + return LDAP_NO_MEMORY; + } + if (loc > 0) { + /* not first time. */ + strcpy(dn + loc, ","); + loc++; + } + strcpy(dn + loc, "dc="); + loc += sizeof("dc=")-1; + + strcpy(dn + loc, s); + loc += len; + } + + LDAP_FREE(domain); + + *dnp = dn; + + return LDAP_SUCCESS; +} + +/* + * Lookup and return LDAP servers for domain (using the DNS + * SRV record _ldap._tcp.domain). + */ +int ldap_domain2hostlist( + LDAP_CONST char *domain, + char **list ) +{ +#ifdef HAVE_RES_QUERY + char *request; + char *dn; + char *hostlist = NULL; + int rc, len, cur = 0; + unsigned char reply[1024]; + + if( domain == NULL || *domain == '\0' ) { + return LDAP_PARAM_ERROR; + } + + if( list == NULL ) { + return LDAP_PARAM_ERROR; + } + + request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp.")); + if (request == NULL) { + rc = LDAP_NO_MEMORY; + goto out; + } + sprintf(request, "_ldap._tcp.%s", domain); + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex); +#endif + + rc = LDAP_UNAVAILABLE; + len = res_query(request, C_IN, T_SRV, reply, sizeof(reply)); + if (len >= 0) { + unsigned char *p; + char host[1024]; + int status; + u_short port; + /* int priority, weight; */ + + /* Parse out query */ + p = reply; + p += sizeof(HEADER); + status = dn_expand(reply, reply + len, p, host, sizeof(host)); + if (status < 0) { + goto out; + } + p += status; + p += 4; + + while (p < reply + len) { + int type, class, ttl, size; + status = dn_expand(reply, reply + len, p, host, sizeof(host)); + if (status < 0) { + goto out; + } + p += status; + type = (p[0] << 8) | p[1]; + p += 2; + class = (p[0] << 8) | p[1]; + p += 2; + ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + size = (p[0] << 8) | p[1]; + p += 2; + if (type == T_SRV) { + int buflen; + status = dn_expand(reply, reply + len, p + 6, host, sizeof(host)); + if (status < 0) { + goto out; + } + /* ignore priority and weight for now */ + /* priority = (p[0] << 8) | p[1]; */ + /* weight = (p[2] << 8) | p[3]; */ + port = (p[4] << 8) | p[5]; + + buflen = strlen(host) + sizeof(":65355"); + hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen); + if (hostlist == NULL) { + rc = LDAP_NO_MEMORY; + goto out; + } + if (cur > 0) { + /* not first time around */ + hostlist[cur++] = ' '; + } + cur += sprintf(&hostlist[cur], "%s:%hd", host, port); + } + p += size; + } + } + if (hostlist == NULL) { + /* No LDAP servers found in DNS. */ + rc = LDAP_UNAVAILABLE; + goto out; + } + + rc = LDAP_SUCCESS; + *list = hostlist; + + out: +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex); +#endif + + if (request != NULL) { + LDAP_FREE(request); + } + if (rc != LDAP_SUCCESS && hostlist != NULL) { + LDAP_FREE(hostlist); + } + return rc; +#else + return LDAP_NOT_SUPPORTED; +#endif /* HAVE_RES_QUERY */ +} diff --git a/libraries/libldap/dsparse.c b/libraries/libldap/dsparse.c index 336025db55..8ec7116fd9 100644 --- a/libraries/libldap/dsparse.c +++ b/libraries/libldap/dsparse.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -39,9 +39,8 @@ static int next_line LDAP_P(( char **bufp, ber_len_t *blenp, char **linep )); static char *next_token LDAP_P(( char ** sp )); - int -next_line_tokens( char **bufp, ber_len_t *blenp, char ***toksp ) +ldap_int_next_line_tokens( char **bufp, ber_len_t *blenp, char ***toksp ) { char *p, *line, *token, **toks; int rc, tokcnt; @@ -72,7 +71,7 @@ next_line_tokens( char **bufp, ber_len_t *blenp, char ***toksp ) if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) { tokcnt = 0; - free_strarray( toks ); + LDAP_VFREE( toks ); toks = NULL; } @@ -195,17 +194,3 @@ next_token( char **sp ) return( LDAP_STRDUP( tokstart )); } - - -void -free_strarray( char **sap ) -{ - int i; - - if ( sap != NULL ) { - for ( i = 0; sap[ i ] != NULL; ++i ) { - LBER_FREE( sap[ i ] ); - } - LBER_FREE( (char *)sap ); - } -} diff --git a/libraries/libldap/error.c b/libraries/libldap/error.c index ff15bfe462..34cac4600b 100644 --- a/libraries/libldap/error.c +++ b/libraries/libldap/error.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -50,7 +50,7 @@ static const struct ldaperror ldap_errlist[] = { {LDAP_NO_SUCH_OBJECT, "No such object" }, {LDAP_ALIAS_PROBLEM, "Alias problem" }, {LDAP_INVALID_DN_SYNTAX, "Invalid DN syntax" }, - {LDAP_IS_LEAF, "Object is a leaf" }, + {LDAP_IS_LEAF, "Entry is a leaf" }, {LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" }, {LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" }, @@ -71,6 +71,8 @@ static const struct ldaperror ldap_errlist[] = { {LDAP_AFFECTS_MULTIPLE_DSAS, "Operation affects multiple DSAs" }, {LDAP_OTHER, "Unknown error" }, + + /* API ResultCodes */ {LDAP_SERVER_DOWN, "Can't contact LDAP server" }, {LDAP_LOCAL_ERROR, "Local error" }, {LDAP_ENCODING_ERROR, "Encoding error" }, @@ -160,6 +162,7 @@ ldap_perror( LDAP *ld, LDAP_CONST char *str ) fflush( stderr ); } +/* deprecated */ int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) { @@ -168,7 +171,7 @@ ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) rc = ldap_parse_result( ld, r, &err, NULL, NULL, NULL, NULL, freeit ); - return rc != LDAP_SUCCESS ? err : rc; + return err != LDAP_SUCCESS ? err : rc; } /* @@ -206,9 +209,7 @@ ldap_parse_result( int freeit ) { LDAPMessage *lm; - ber_int_t errcode; - char* matcheddn; - char* errmsg; + ber_int_t errcode = LDAP_SUCCESS; int rc; ber_tag_t tag; @@ -224,6 +225,7 @@ ldap_parse_result( return LDAP_PARAM_ERROR; } + if(errcodep != NULL) *errcodep = LDAP_SUCCESS; if(matcheddnp != NULL) *matcheddnp = NULL; if(errmsgp != NULL) *errmsgp = NULL; if(referralsp != NULL) *referralsp = NULL; @@ -244,10 +246,6 @@ ldap_parse_result( return ld->ld_errno; } - errcode = LDAP_SUCCESS; - matcheddn = NULL; - errmsg = NULL; - if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; @@ -263,11 +261,11 @@ ldap_parse_result( if ( ld->ld_version < LDAP_VERSION2 ) { tag = ber_scanf( ber, "{ia}", - &errcode, &ld->ld_error ); + &ld->ld_errno, &ld->ld_error ); } else { ber_len_t len; tag = ber_scanf( ber, "{iaa" /*}*/, - &errcode, &ld->ld_matched, &ld->ld_error ); + &ld->ld_errno, &ld->ld_matched, &ld->ld_error ); if( tag != LBER_ERROR ) { /* peek for referrals */ @@ -321,7 +319,7 @@ ldap_parse_result( } if ( tag == LBER_ERROR ) { - errcode = LDAP_DECODING_ERROR; + ld->ld_errno = errcode = LDAP_DECODING_ERROR; } if( ber != NULL ) { @@ -329,10 +327,10 @@ ldap_parse_result( } /* return */ + if( errcodep != NULL ) { + *errcodep = ld->ld_errno; + } if ( errcode == LDAP_SUCCESS ) { - if( errcodep != NULL ) { - *errcodep = ld->ld_errno; - } if( matcheddnp != NULL ) { *matcheddnp = LDAP_STRDUP( ld->ld_matched ); } @@ -357,6 +355,5 @@ ldap_parse_result( ldap_msgfree( r ); } - ld->ld_errno = errcode; - return( ld->ld_errno ); + return( errcode ); } diff --git a/libraries/libldap/extended.c b/libraries/libldap/extended.c index e284b485fd..f42afd281a 100644 --- a/libraries/libldap/extended.c +++ b/libraries/libldap/extended.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -181,7 +181,7 @@ ldap_parse_extended_result ( return ld->ld_errno; } - if( res->lm_msgtype == LDAP_RES_EXTENDED ) { + if( res->lm_msgtype != LDAP_RES_EXTENDED ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } @@ -189,8 +189,6 @@ ldap_parse_extended_result ( if( retoidp != NULL ) *retoidp = NULL; if( retdatap != NULL ) *retdatap = NULL; - ber = ber_dup( res->lm_ber ); - if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; @@ -201,8 +199,15 @@ ldap_parse_extended_result ( ld->ld_matched = NULL; } + ber = ber_dup( res->lm_ber ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + rc = ber_scanf( ber, "{iaa" /*}*/, &errcode, - &ld->ld_matched, &ld->ld_matched ); + &ld->ld_matched, &ld->ld_error ); if( rc == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; @@ -217,11 +222,13 @@ ldap_parse_extended_result ( if( tag == LDAP_TAG_REFERRAL ) { /* skip over referral */ - tag = ber_scanf( ber, "x" ); - - if( tag != LBER_ERROR ) { - tag = ber_peek_tag( ber, &len ); + if( ber_scanf( ber, "x" ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; } + + tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_RES_OID ) { @@ -237,7 +244,7 @@ ldap_parse_extended_result ( if( tag == LDAP_TAG_EXOP_RES_VALUE ) { /* we have a resdata */ - if( ber_scanf( ber, "O", &resoid ) == LBER_ERROR ) { + if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; ber_free( ber, 0 ); if( resoid != NULL ) LDAP_FREE( resoid ); @@ -245,6 +252,8 @@ ldap_parse_extended_result ( } } + ber_free( ber, 0 ); + if( retoidp != NULL ) { *retoidp = resoid; } else { diff --git a/libraries/libldap/free.c b/libraries/libldap/free.c index 120e1605b0..e20ffbd24d 100644 --- a/libraries/libldap/free.c +++ b/libraries/libldap/free.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/friendly.c b/libraries/libldap/friendly.c index ec37982a70..3078fee693 100644 --- a/libraries/libldap/friendly.c +++ b/libraries/libldap/friendly.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/getattr.c b/libraries/libldap/getattr.c index 079db4b9f3..9a511ee2ea 100644 --- a/libraries/libldap/getattr.c +++ b/libraries/libldap/getattr.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c index 0110e298e7..0d8b488e19 100644 --- a/libraries/libldap/getdn.c +++ b/libraries/libldap/getdn.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -23,7 +23,11 @@ #include "ldap-int.h" -static char **explode_name( const char *name, int notypes, int is_dn ); +#define NAME_TYPE_LDAP_RDN 0 +#define NAME_TYPE_LDAP_DN 1 +#define NAME_TYPE_DCE_DN 2 + +static char **explode_name( const char *name, int notypes, int is_type ); char * ldap_get_dn( LDAP *ld, LDAPMessage *entry ) @@ -59,28 +63,26 @@ ldap_dn2ufn( LDAP_CONST char *dn ) return NULL; } - if ( ldap_is_dns_dn( dn ) || - ( p = strchr( dn, '=' ) ) == NULL ) - { + if ( ( p = ldap_utf8_strpbrk( dn, "=" ) ) == NULL ) { return( LDAP_STRDUP( dn ) ); } - - ufn = LDAP_STRDUP( ++p ); + if( ufn == NULL ) return NULL; + #define INQUOTE 1 #define OUTQUOTE 2 state = OUTQUOTE; - for ( p = ufn, r = ufn; *p; p++ ) { + for ( p = ufn, r = ufn; *p; LDAP_UTF8_INCR(p) ) { switch ( *p ) { case '\\': - if ( *++p == '\0' ) - p--; - else { + if ( p[1] != '\0' ) { *r++ = '\\'; - *r++ = *p; + LDAP_UTF8_COPY(r,++p); + LDAP_UTF8_INCR(r); } break; + case '"': if ( state == INQUOTE ) state = OUTQUOTE; @@ -88,6 +90,7 @@ ldap_dn2ufn( LDAP_CONST char *dn ) state = INQUOTE; *r++ = *p; break; + case ';': case ',': if ( state == OUTQUOTE ) @@ -95,17 +98,22 @@ ldap_dn2ufn( LDAP_CONST char *dn ) else *r++ = *p; break; + case '=': - if ( state == INQUOTE ) + if ( state == INQUOTE ) { *r++ = *p; - else { + } else { char *rsave = r; - *r-- = '\0'; - while ( !isspace( (unsigned char) *r ) + *r = '\0'; + LDAP_UTF8_DECR( r ); + + while ( !ldap_utf8_isspace( r ) && *r != ';' && *r != ',' && r > ufn ) - r--; - r++; + { + LDAP_UTF8_DECR( r ); + } + LDAP_UTF8_INCR( r ); if ( strcasecmp( r, "c" ) && strcasecmp( r, "o" ) @@ -118,8 +126,10 @@ ldap_dn2ufn( LDAP_CONST char *dn ) } } break; + default: - *r++ = *p; + LDAP_UTF8_COPY(r, p); + LDAP_UTF8_INCR(r); break; } } @@ -129,84 +139,134 @@ ldap_dn2ufn( LDAP_CONST char *dn ) } char ** -ldap_explode_dns( LDAP_CONST char *dn_in ) +ldap_explode_dn( LDAP_CONST char *dn, int notypes ) { - char *s; - char **rdns; - char *tok_r; - char *dn; + Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); - int ncomps; - int maxcomps = 8; + return explode_name( dn, notypes, NAME_TYPE_LDAP_DN ); +} - if ( (dn = LDAP_STRDUP( dn_in )) == NULL ) { - return( NULL ); - } +char ** +ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) +{ + Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); + return explode_name( rdn, notypes, NAME_TYPE_LDAP_RDN ); +} - if ( (rdns = (char **) LDAP_MALLOC( maxcomps * sizeof(char *) )) == NULL ) { - LDAP_FREE( dn ); - return( NULL ); +char * +ldap_dn2dcedn( LDAP_CONST char *dn ) +{ + char *dce, *q, **rdns, **p; + int len = 0; + + Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 ); + + rdns = explode_name( dn, 0, NAME_TYPE_LDAP_DN ); + if ( rdns == NULL ) { + return NULL; + } + + for ( p = rdns; *p != NULL; p++ ) { + len += strlen( *p ) + 1; } - ncomps = 0; - for ( s = ldap_pvt_strtok( dn, "@.", &tok_r ); s != NULL; - s = ldap_pvt_strtok( NULL, "@.", &tok_r ) ) - { - if ( ncomps == maxcomps ) { - maxcomps *= 2; - if ( (rdns = (char **) LDAP_REALLOC( rdns, maxcomps * - sizeof(char *) )) == NULL ) - { - LDAP_FREE( dn ); - return NULL; - } - } - rdns[ncomps++] = LDAP_STRDUP( s ); + q = dce = LDAP_MALLOC( len + 1 ); + if ( dce == NULL ) { + return NULL; } - LDAP_FREE(dn); - rdns[ncomps] = NULL; + p--; /* get back past NULL */ - /* trim rdns */ - rdns = (char **) LDAP_REALLOC( rdns, (ncomps+1) * sizeof(char*) ); - return( rdns ); + for ( ; p != rdns; p-- ) { + strcpy( q, "/" ); + q++; + strcpy( q, *p ); + q += strlen( *p ); + } + + strcpy( q, "/" ); + q++; + strcpy( q, *p ); + + return dce; } -char ** -ldap_explode_dn( LDAP_CONST char *dn, int notypes ) +char * +ldap_dcedn2dn( LDAP_CONST char *dce ) { - Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); + char *dn, *q, **rdns, **p; + int len; + + Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 ); + + rdns = explode_name( dce, 0, NAME_TYPE_DCE_DN ); + if ( rdns == NULL ) { + return NULL; + } + + len = 0; - if ( ldap_is_dns_dn( dn ) ) { - return( ldap_explode_dns( dn ) ); + for ( p = rdns; *p != NULL; p++ ) { + len += strlen( *p ) + 1; } - return explode_name( dn, notypes, 1 ); -} -char ** -ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) -{ - Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); - return explode_name( rdn, notypes, 0 ); + q = dn = LDAP_MALLOC( len ); + if ( dn == NULL ) { + return NULL; + } + + p--; + + for ( ; p != rdns; p-- ) { + strcpy( q, *p ); + q += strlen( *p ); + strcpy( q, "," ); + q++; + } + + if ( *dce == '/' ) { + /* the name was fully qualified, thus the most-significant + * RDN was empty. trash the last comma */ + q--; + *q = '\0'; + } else { + /* the name was relative. copy the most significant RDN */ + strcpy( q, *p ); + } + + return dn; } static char ** -explode_name( const char *name, int notypes, int is_dn ) +explode_name( const char *name, int notypes, int is_type ) { - const char *p, *q; + const char *p, *q, *rdn; char **parts = NULL; - int state, count = 0, endquote, len; + int offset, state, have_equals, count = 0, endquote, len; - p = name-1; + /* safe guard */ + if(name == NULL) name = ""; + + /* skip leading whitespace */ + while( ldap_utf8_isspace( name )) { + LDAP_UTF8_INCR( name ); + } + + p = rdn = name; + offset = 0; state = OUTQUOTE; + have_equals=0; do { + /* step forward */ + p += offset; + offset = 1; - ++p; switch ( *p ) { case '\\': - if ( *++p == '\0' ) - p--; + if ( p[1] != '\0' ) { + offset = LDAP_UTF8_OFFSET(++p); + } break; case '"': if ( state == INQUOTE ) @@ -214,19 +274,28 @@ explode_name( const char *name, int notypes, int is_dn ) else state = INQUOTE; break; + case '=': + if( state == OUTQUOTE ) have_equals++; + break; case '+': - if (!is_dn) + if (is_type == NAME_TYPE_LDAP_RDN) + goto end_part; + break; + case '/': + if (is_type == NAME_TYPE_DCE_DN) goto end_part; break; case ';': case ',': - if (!is_dn) - break; - goto end_part; + if (is_type == NAME_TYPE_LDAP_DN) + goto end_part; + break; case '\0': end_part: if ( state == OUTQUOTE ) { ++count; + have_equals=0; + if ( parts == NULL ) { if (( parts = (char **)LDAP_MALLOC( 8 * sizeof( char *))) == NULL ) @@ -237,31 +306,45 @@ explode_name( const char *name, int notypes, int is_dn ) == NULL ) return( NULL ); } + parts[ count ] = NULL; endquote = 0; + if ( notypes ) { - for ( q = name; - q < p && *q != '='; ++q ) { - ; + for ( q = rdn; q < p && *q != '='; ++q ) { + /* EMPTY */; } + if ( q < p ) { - name = ++q; + rdn = ++q; } - if ( *name == '"' ) { - ++name; + + if ( *rdn == '"' ) { + ++rdn; } - if ( *(p-1) == '"' ) { + if ( p[-1] == '"' ) { endquote = 1; --p; } } - len = p - name; + len = p - rdn; + if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1, - len + 1 )) != NULL ) { - SAFEMEMCPY( parts[ count-1 ], name, - len ); + len + 1 )) != NULL ) + { + SAFEMEMCPY( parts[ count-1 ], rdn, len ); + + if( !endquote ) { + /* skip trailing spaces */ + while( len > 0 && ldap_utf8_isspace( + &parts[count-1][len-1] ) ) + { + --len; + } + } + parts[ count-1 ][ len ] = '\0'; } @@ -273,24 +356,12 @@ explode_name( const char *name, int notypes, int is_dn ) if ( endquote == 1 ) p++; - name = *p ? p + 1 : p; - while ( isascii( *name ) && isspace( *name ) ) - ++name; - } - break; + rdn = *p ? &p[1] : p; + while ( ldap_utf8_isspace( rdn ) ) + ++rdn; + } break; } } while ( *p ); return( parts ); } - - -int -ldap_is_dns_dn( LDAP_CONST char *dn ) -{ - return( dn[ 0 ] != '\0' - && strchr( dn, '=' ) == NULL - && strchr( dn, ',' ) == NULL - && strchr( dn, ';' ) == NULL ); -} - diff --git a/libraries/libldap/getdxbyname.c b/libraries/libldap/getdxbyname.c deleted file mode 100644 index 602721a05e..0000000000 --- a/libraries/libldap/getdxbyname.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ -/* Portions - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - * - * ldap_getdxbyname - retrieve DX records from the DNS (from TXT records for now) - */ - -#include "portable.h" - -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - -#include -#include - -#include -#include -#include -#include - -#include "ldap-int.h" - -static char ** decode_answer LDAP_P(( unsigned char *answer, ber_len_t len )); - -#define MAX_TO_SORT 32 - - -/* - * ldap_getdxbyname - lookup DNS DX records for domain and return an ordered - * array. - */ -char ** -ldap_getdxbyname( const char *domain ) -{ - unsigned char buf[ PACKETSZ ]; - char **dxs; - int rc; - - Debug( LDAP_DEBUG_TRACE, "ldap_getdxbyname( %s )\n", domain, 0, 0 ); - - memset( buf, 0, sizeof( buf )); - - if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0 - || ( dxs = decode_answer( buf, rc )) == NULL ) { - /* - * punt: return list conisting of the original domain name only - */ - if (( dxs = (char **)LDAP_MALLOC( 2 * sizeof( char * ))) == NULL || - ( dxs[ 0 ] = LDAP_STRDUP( domain )) == NULL ) { - if ( dxs != NULL ) { - LDAP_FREE( dxs ); - } - dxs = NULL; - } else { - dxs[ 1 ] = NULL; - } - } - - return( dxs ); -} - - -static char ** -decode_answer( unsigned char *answer, ber_len_t len ) -{ - HEADER *hp; - char buf[ 256 ], **dxs; - unsigned char *eom, *p; - int ancount, err, rc, type, class, dx_count, rr_len; - int dx_pref[ MAX_TO_SORT ]; - -#ifdef LDAP_DEBUG -#ifdef notdef - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { - __p_query( answer ); - } -#endif -#endif /* LDAP_DEBUG */ - - dxs = NULL; - hp = (HEADER *)answer; - eom = answer + len; - - if ( ntohs( hp->qdcount ) != 1 ) { - h_errno = NO_RECOVERY; - return( NULL ); - } - - ancount = ntohs( hp->ancount ); - if ( ancount < 1 ) { - h_errno = NO_DATA; - return( NULL ); - } - - /* - * skip over the query - */ - p = answer + HFIXEDSZ; - if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) { - h_errno = NO_RECOVERY; - return( NULL ); - } - p += ( rc + QFIXEDSZ ); - - /* - * pull out the answers we are interested in - */ - err = dx_count = 0; - while ( ancount > 0 && err == 0 && p < eom ) { - if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) { - err = NO_RECOVERY; - continue; - } - p += rc; /* skip over name */ - type = _getshort( p ); - p += INT16SZ; - class = _getshort( p ); - p += INT16SZ; - p += INT32SZ; /* skip over TTL */ - rr_len = _getshort( p ); - p += INT16SZ; - if ( class == C_IN && type == T_TXT ) { - int pref, txt_len; - char *q, *r; - - q = (char *)p; - while ( q < (char *)p + rr_len && err == 0 ) { - if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) { - txt_len = *q - 3; - r = q + 4; - while ( isspace( (unsigned char) *r )) { - ++r; - --txt_len; - } - pref = 0; - while ( isdigit( (unsigned char) *r )) { - pref *= 10; - pref += ( *r - '0' ); - ++r; - --txt_len; - } - if ( dx_count < MAX_TO_SORT - 1 ) { - dx_pref[ dx_count ] = pref; - } - while ( isspace( (unsigned char) *r )) { - ++r; - --txt_len; - } - dxs = (char **)LDAP_REALLOC( dxs, - ( dx_count + 2 ) * sizeof( char * )); - if ( dxs == NULL || ( dxs[ dx_count ] = - (char *)LDAP_CALLOC( 1, txt_len + 1 )) == NULL ) { - err = NO_RECOVERY; - continue; - } - memcpy( dxs[ dx_count ], r, txt_len ); - dxs[ ++dx_count ] = NULL; - } - q += ( *q + 1 ); /* move past last TXT record */ - } - } - p += rr_len; - } - - if ( err == 0 ) { - if ( dx_count == 0 ) { - err = NO_DATA; - } else { - /* - * sort records based on associated preference value - */ - int i, j, sort_count, tmp_pref; - char *tmp_dx; - - sort_count = ( dx_count < MAX_TO_SORT ) ? dx_count : MAX_TO_SORT; - for ( i = 0; i < sort_count; ++i ) { - for ( j = i + 1; j < sort_count; ++j ) { - if ( dx_pref[ i ] > dx_pref[ j ] ) { - tmp_pref = dx_pref[ i ]; - dx_pref[ i ] = dx_pref[ j ]; - dx_pref[ j ] = tmp_pref; - tmp_dx = dxs[ i ]; - dxs[ i ] = dxs[ j ]; - dxs[ j ] = tmp_dx; - } - } - } - } - } - - h_errno = err; - return( dxs ); -} - -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ diff --git a/libraries/libldap/getentry.c b/libraries/libldap/getentry.c index 09721f1d8e..2cf17681d8 100644 --- a/libraries/libldap/getentry.c +++ b/libraries/libldap/getentry.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/getfilter.c b/libraries/libldap/getfilter.c index efafeb5067..2d8b89c8a8 100644 --- a/libraries/libldap/getfilter.c +++ b/libraries/libldap/getfilter.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -102,7 +102,7 @@ ldap_init_getfilter_buf( char *buf, ber_len_t buflen ) fip = NULL; tag = NULL; - while ( buflen > 0 && ( tokcnt = next_line_tokens( &buf, &buflen, &tok )) + while ( buflen > 0 && ( tokcnt = ldap_int_next_line_tokens( &buf, &buflen, &tok )) > 0 ) { switch( tokcnt ) { @@ -131,7 +131,7 @@ ldap_init_getfilter_buf( char *buf, ber_len_t buflen ) nextflp->lfl_pattern, error ); errno = EINVAL; #endif /* LDAP_LIBUI */ - free_strarray( tok ); + LDAP_VFREE( tok ); return( NULL ); } regfree(&re); @@ -157,7 +157,7 @@ ldap_init_getfilter_buf( char *buf, ber_len_t buflen ) if (( nextfip = (LDAPFiltInfo *)LDAP_CALLOC( 1, sizeof( LDAPFiltInfo ))) == NULL ) { ldap_getfilter_free( lfdp ); - free_strarray( tok ); + LDAP_VFREE( tok ); return( NULL ); } if ( fip == NULL ) { /* first one */ @@ -177,7 +177,7 @@ ldap_init_getfilter_buf( char *buf, ber_len_t buflen ) } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) { nextfip->lfi_scope = LDAP_SCOPE_BASE; } else { - free_strarray( tok ); + LDAP_VFREE( tok ); ldap_getfilter_free( lfdp ); errno = EINVAL; return( NULL ); @@ -194,7 +194,7 @@ ldap_init_getfilter_buf( char *buf, ber_len_t buflen ) break; default: - free_strarray( tok ); + LDAP_VFREE( tok ); ldap_getfilter_free( lfdp ); errno = EINVAL; return( NULL ); diff --git a/libraries/libldap/getvalues.c b/libraries/libldap/getvalues.c index a5d5f0ee9d..0fb1e2511f 100644 --- a/libraries/libldap/getvalues.c +++ b/libraries/libldap/getvalues.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index 69ffdec8ef..03fee191de 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ #include "portable.h" @@ -13,21 +13,21 @@ #include #include +#include + #include "ldap-int.h" #include "ldap_defaults.h" struct ldapoptions ldap_int_global_options = { LDAP_UNINITIALIZED, LDAP_DEBUG_NONE }; -#undef gopts -#define gopts ldap_int_global_options - #define ATTR_NONE 0 #define ATTR_BOOL 1 #define ATTR_INT 2 #define ATTR_KV 3 #define ATTR_STRING 4 #define ATTR_TLS 5 +#define ATTR_URIS 6 struct ol_keyvalue { const char * key; @@ -43,57 +43,77 @@ static const struct ol_keyvalue deref_kv[] = { }; static const struct ol_attribute { + int useronly; int type; const char * name; const void * data; size_t offset; } attrs[] = { - {ATTR_KV, "DEREF", deref_kv, /* or &deref_kv[0] */ + {0, ATTR_KV, "DEREF", deref_kv, /* or &deref_kv[0] */ offsetof(struct ldapoptions, ldo_deref)}, - {ATTR_INT, "SIZELIMIT", NULL, + {0, ATTR_INT, "SIZELIMIT", NULL, offsetof(struct ldapoptions, ldo_sizelimit)}, - {ATTR_INT, "TIMELIMIT", NULL, + {0, ATTR_INT, "TIMELIMIT", NULL, offsetof(struct ldapoptions, ldo_timelimit)}, - {ATTR_STRING, "BASE", NULL, + {1, ATTR_STRING, "BINDDN", NULL, + offsetof(struct ldapoptions, ldo_defbinddn)}, + {0, ATTR_STRING, "BASE", NULL, offsetof(struct ldapoptions, ldo_defbase)}, - {ATTR_STRING, "HOST", NULL, - offsetof(struct ldapoptions, ldo_defhost)}, - {ATTR_INT, "PORT", NULL, + {0, ATTR_INT, "PORT", NULL, offsetof(struct ldapoptions, ldo_defport)}, - {ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS}, - {ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, - {ATTR_BOOL, "DNS", NULL, LDAP_BOOL_DNS}, - {ATTR_BOOL, "TLS", NULL, LDAP_OPT_X_TLS}, - {ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, - {ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, - {ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, - {ATTR_TLS, "TLS_CACERTDIR",NULL, LDAP_OPT_X_TLS_CACERTDIR}, - {ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, - {ATTR_NONE, NULL, NULL, 0} + /* **** keep this around for backward compatibility */ + {0, ATTR_URIS, "HOST", NULL, 1}, + /* **** */ + {0, ATTR_URIS, "URI", NULL, 0}, + {0, ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS}, + {0, ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, + {0, ATTR_TLS, "TLS", NULL, LDAP_OPT_X_TLS}, + {0, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, + {0, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, + {0, ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, + {0, ATTR_TLS, "TLS_CACERTDIR",NULL, LDAP_OPT_X_TLS_CACERTDIR}, + {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, +#ifdef HAVE_CYRUS_SASL + {0, ATTR_INT, "SASL_MINSSF", NULL, + offsetof(struct ldapoptions, ldo_sasl_minssf)}, + {0, ATTR_INT, "SASL_MAXSSF", NULL, + offsetof(struct ldapoptions, ldo_sasl_maxssf)}, +#endif + {0, ATTR_NONE, NULL, NULL, 0} }; #define MAX_LDAP_ATTR_LEN sizeof("TLS_CACERTDIR") #define MAX_LDAP_ENV_PREFIX_LEN 8 -static void openldap_ldap_init_w_conf(const char *file) +static void openldap_ldap_init_w_conf( + const char *file, int userconf ) { char linebuf[128]; FILE *fp; int i; char *cmd, *opt; char *start, *end; + struct ldapoptions *gopts; + + if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { + return; /* Could not allocate mem for global options */ + } if (file == NULL) { /* no file name */ return; } + Debug(LDAP_DEBUG_TRACE, "ldap_init: trying %s\n", file, 0, 0); + fp = fopen(file, "r"); if(fp == NULL) { /* could not open file */ return; } + Debug(LDAP_DEBUG_TRACE, "ldap_init: using %s\n", file, 0, 0); + while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) { /* skip lines starting with '#' */ if(*start == '#') continue; @@ -126,13 +146,17 @@ static void openldap_ldap_init_w_conf(const char *file) *start++ = '\0'; - /* we must have some non-whitespace to skip */ + /* we must have some whitespace to skip */ while(isspace((unsigned char)*start)) start++; opt = start; for(i=0; attrs[i].type != ATTR_NONE; i++) { void *p; + if( !userconf && attrs[i].useronly ) { + continue; + } + if(strcasecmp(cmd, attrs[i].name) != 0) { continue; } @@ -143,16 +167,16 @@ static void openldap_ldap_init_w_conf(const char *file) || (strcasecmp(opt, "yes") == 0) || (strcasecmp(opt, "true") == 0)) { - LDAP_BOOL_SET(&gopts, attrs[i].offset); + LDAP_BOOL_SET(gopts, attrs[i].offset); } else { - LDAP_BOOL_CLR(&gopts, attrs[i].offset); + LDAP_BOOL_CLR(gopts, attrs[i].offset); } break; case ATTR_INT: - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; * (int*) p = atoi(opt); break; @@ -164,7 +188,7 @@ static void openldap_ldap_init_w_conf(const char *file) kv++) { if(strcasecmp(opt, kv->key) == 0) { - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; * (int*) p = kv->value; break; } @@ -172,26 +196,39 @@ static void openldap_ldap_init_w_conf(const char *file) } break; case ATTR_STRING: - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; if (* (char**) p != NULL) LDAP_FREE(* (char**) p); * (char**) p = LDAP_STRDUP(opt); break; case ATTR_TLS: #ifdef HAVE_TLS - ldap_pvt_tls_config( &gopts, attrs[i].offset, opt ); + ldap_pvt_tls_config( gopts, attrs[i].offset, opt ); #endif break; + case ATTR_URIS: + if (attrs[i].offset == 0) { + ldap_set_option( NULL, LDAP_OPT_URI, opt ); + } else { + ldap_set_option( NULL, LDAP_OPT_HOST_NAME, opt ); + } + break; } + break; } } fclose(fp); } +static void openldap_ldap_init_w_sysconf(const char *file) +{ + openldap_ldap_init_w_conf( file, 0 ); +} + static void openldap_ldap_init_w_userconf(const char *file) { char *home; - char *path; + char *path = NULL; if (file == NULL) { /* no file name */ @@ -201,9 +238,12 @@ static void openldap_ldap_init_w_userconf(const char *file) home = getenv("HOME"); if (home != NULL) { + Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is %s\n", + home, 0, 0); path = LDAP_MALLOC(strlen(home) + strlen(file) + 3); } else { - path = LDAP_MALLOC(strlen(file) + 3); + Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is NULL\n", + 0, 0, 0); } if(home != NULL && path != NULL) { @@ -211,11 +251,11 @@ static void openldap_ldap_init_w_userconf(const char *file) /* try ~/file */ sprintf(path, "%s/%s", home, file); - openldap_ldap_init_w_conf(path); + openldap_ldap_init_w_conf(path, 1); /* try ~/.file */ sprintf(path, "%s/.%s", home, file); - openldap_ldap_init_w_conf(path); + openldap_ldap_init_w_conf(path, 1); } if(path != NULL) { @@ -223,10 +263,12 @@ static void openldap_ldap_init_w_userconf(const char *file) } /* try file */ - openldap_ldap_init_w_conf(file); + openldap_ldap_init_w_conf(file, 1); } -static void openldap_ldap_init_w_env(const char *prefix) +static void openldap_ldap_init_w_env( + struct ldapoptions *gopts, + const char *prefix) { char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN]; int len; @@ -256,15 +298,15 @@ static void openldap_ldap_init_w_env(const char *prefix) || (strcasecmp(value, "yes") == 0) || (strcasecmp(value, "true") == 0)) { - LDAP_BOOL_SET(&gopts, attrs[i].offset); + LDAP_BOOL_SET(gopts, attrs[i].offset); } else { - LDAP_BOOL_CLR(&gopts, attrs[i].offset); + LDAP_BOOL_CLR(gopts, attrs[i].offset); } break; case ATTR_INT: - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; * (int*) p = atoi(value); break; @@ -276,7 +318,7 @@ static void openldap_ldap_init_w_env(const char *prefix) kv++) { if(strcasecmp(value, kv->key) == 0) { - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; * (int*) p = kv->value; break; } @@ -284,7 +326,7 @@ static void openldap_ldap_init_w_env(const char *prefix) } break; case ATTR_STRING: - p = &((char *) &gopts)[attrs[i].offset]; + p = &((char *) gopts)[attrs[i].offset]; if (* (char**) p != NULL) LDAP_FREE(* (char**) p); if (*value == '\0') { * (char**) p = NULL; @@ -294,75 +336,117 @@ static void openldap_ldap_init_w_env(const char *prefix) break; case ATTR_TLS: #ifdef HAVE_TLS - ldap_pvt_tls_config( attrs[i].offset, value ); + ldap_pvt_tls_config( gopts, attrs[i].offset, value ); #endif break; + case ATTR_URIS: + if (attrs[i].offset == 0) { + ldap_set_option( NULL, LDAP_OPT_URI, value ); + } else { + ldap_set_option( NULL, LDAP_OPT_HOST_NAME, value ); + } + break; } } } -void ldap_int_initialize( void ) +/* + * Initialize the global options structure with default values. + */ +void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl ) { - if ( gopts.ldo_valid == LDAP_INITIALIZED ) { - return; - } + if (dbglvl) + gopts->ldo_debug = *dbglvl; + else + gopts->ldo_debug = 0; - ldap_int_utils_init(); + gopts->ldo_version = LDAP_VERSION2; + gopts->ldo_deref = LDAP_DEREF_NEVER; + gopts->ldo_timelimit = LDAP_NO_LIMIT; + gopts->ldo_sizelimit = LDAP_NO_LIMIT; -#ifdef HAVE_TLS - ldap_pvt_tls_init(); -#endif + gopts->ldo_tm_api = (struct timeval *)NULL; + gopts->ldo_tm_net = (struct timeval *)NULL; - if ( ldap_int_tblsize == 0 ) - ldap_int_ip_init(); + /* ldo_defludp is leaked, we should have an at_exit() handler + * to free this and whatever else needs to cleaned up. + */ + ldap_url_parselist(&gopts->ldo_defludp, "ldap://localhost/"); + gopts->ldo_defport = LDAP_PORT; + + gopts->ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; + gopts->ldo_rebindproc = NULL; - gopts.ldo_debug = 0; + LDAP_BOOL_ZERO(gopts); - gopts.ldo_version = LDAP_VERSION2; - gopts.ldo_deref = LDAP_DEREF_NEVER; - gopts.ldo_timelimit = LDAP_NO_LIMIT; - gopts.ldo_sizelimit = LDAP_NO_LIMIT; + LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS); - gopts.ldo_tm_api = (struct timeval *)NULL; - gopts.ldo_tm_net = (struct timeval *)NULL; +#ifdef HAVE_TLS + gopts->ldo_tls_ctx = NULL; +#endif +#ifdef HAVE_CYRUS_SASL + gopts->ldo_sasl_minssf = 0; + gopts->ldo_sasl_maxssf = INT_MAX; +#endif - gopts.ldo_defhost = LDAP_STRDUP("localhost"); - gopts.ldo_defport = LDAP_PORT; + gopts->ldo_valid = LDAP_INITIALIZED; - gopts.ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; + return; +} - LDAP_BOOL_ZERO(&gopts); +void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) +{ + if ( gopts->ldo_valid == LDAP_INITIALIZED ) { + return; + } - LDAP_BOOL_SET(&gopts, LDAP_BOOL_REFERRALS); + ldap_int_utils_init(); #ifdef HAVE_TLS - gopts.ldo_tls_ctx = NULL; + ldap_pvt_tls_init(); #endif - gopts.ldo_valid = LDAP_INITIALIZED; +#ifdef HAVE_CYRUS_SASL + ldap_pvt_sasl_init(); +#endif + + if ( ldap_int_tblsize == 0 ) + ldap_int_ip_init(); + + ldap_int_initialize_global_options(gopts, NULL); if( getenv("LDAPNOINIT") != NULL ) { return; } - openldap_ldap_init_w_conf(LDAP_CONF_FILE); + openldap_ldap_init_w_sysconf(LDAP_CONF_FILE); openldap_ldap_init_w_userconf(LDAP_USERRC_FILE); { char *altfile = getenv(LDAP_ENV_PREFIX "CONF"); if( altfile != NULL ) { - openldap_ldap_init_w_conf( altfile ); + Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", + LDAP_ENV_PREFIX "CONF", altfile, 0); + openldap_ldap_init_w_sysconf( altfile ); } + else + Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", + LDAP_ENV_PREFIX "CONF", 0, 0); } { char *altfile = getenv(LDAP_ENV_PREFIX "RC"); if( altfile != NULL ) { + Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", + LDAP_ENV_PREFIX "RC", altfile, 0); openldap_ldap_init_w_userconf( altfile ); } + else + Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", + LDAP_ENV_PREFIX "RC", 0, 0); } - openldap_ldap_init_w_env(NULL); + openldap_ldap_init_w_env(gopts, NULL); } diff --git a/libraries/libldap/kbind.c b/libraries/libldap/kbind.c index 731a8b5fc6..fd6d59ab7f 100644 --- a/libraries/libldap/kbind.c +++ b/libraries/libldap/kbind.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -16,7 +16,7 @@ * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND * krbv42ldap [1] OCTET STRING * krbv42dsa [2] OCTET STRING #endif @@ -33,7 +33,7 @@ #include "portable.h" -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND #include #include @@ -63,9 +63,6 @@ ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn ) char *cred; int rc; ber_len_t credlen; -#ifdef STR_TRANSLATION - int str_translation_on; -#endif /* STR_TRANSLATION */ Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 ); @@ -83,23 +80,10 @@ ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn ) return( -1 ); } -#ifdef STR_TRANSLATION - if (( str_translation_on = (( ber->ber_options & - LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */ - ber->ber_options &= ~LBER_TRANSLATE_STRINGS; - } -#endif /* STR_TRANSLATION */ - /* fill it in */ rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen ); -#ifdef STR_TRANSLATION - if ( str_translation_on ) { /* restore translation */ - ber->ber_options |= LBER_TRANSLATE_STRINGS; - } -#endif /* STR_TRANSLATION */ - if ( rc == -1 ) { LDAP_FREE( cred ); ber_free( ber, 1 ); @@ -157,9 +141,6 @@ ldap_kerberos_bind2( LDAP *ld, LDAP_CONST char *dn ) char *cred; int rc; ber_len_t credlen; -#ifdef STR_TRANSLATION - int str_translation_on; -#endif /* STR_TRANSLATION */ Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 ); @@ -177,24 +158,11 @@ ldap_kerberos_bind2( LDAP *ld, LDAP_CONST char *dn ) return( -1 ); } -#ifdef STR_TRANSLATION - if (( str_translation_on = (( ber->ber_options & - LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */ - ber->ber_options &= ~LBER_TRANSLATE_STRINGS; - } -#endif /* STR_TRANSLATION */ - /* fill it in */ rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen ); -#ifdef STR_TRANSLATION - if ( str_translation_on ) { /* restore translation */ - ber->ber_options |= LBER_TRANSLATE_STRINGS; - } -#endif /* STR_TRANSLATION */ - LDAP_FREE( cred ); if ( rc == -1 ) { @@ -269,10 +237,17 @@ ldap_get_kerberosv4_credentials( fprintf( stderr, "krb_get_tf_realm failed (%s)\n", krb_err_txt[err] ); #endif /* LDAP_LIBUI */ - ld->ld_errno = LDAP_INVALID_CREDENTIALS; + ld->ld_errno = LDAP_AUTH_UNKNOWN; return( NULL ); } + if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) { + /* not connected yet */ + int rc = ldap_open_defconn( ld ); + + if( rc < 0 ) return NULL; + } + krbinstance = ld->ld_defconn->lconn_krbinstance; if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 )) @@ -280,7 +255,7 @@ ldap_get_kerberosv4_credentials( #ifdef LDAP_LIBUI fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] ); #endif /* LDAP_LIBUI */ - ld->ld_errno = LDAP_INVALID_CREDENTIALS; + ld->ld_errno = LDAP_AUTH_UNKNOWN; return( NULL ); } @@ -296,4 +271,4 @@ ldap_get_kerberosv4_credentials( } #endif /* !AUTHMAN */ -#endif /* HAVE_KERBEROS */ +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index ab446da5a9..36993c8afd 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -19,13 +19,33 @@ #include "../liblber/lber-int.h" -#define ldap_debug (ldap_int_global_options.ldo_debug) +/* + * Support needed if the library is running in the kernel + */ +#if LDAP_INT_IN_KERNEL + /* + * Platform specific function to return a pointer to the + * process-specific global options. + * + * This function should perform the following functions: + * Allocate and initialize a global options struct on a per process basis + * Use callers process identifier to return its global options struct + * Note: Deallocate structure when the process exits + */ +# define LDAP_INT_GLOBAL_OPT() ldap_int_global_opt() + struct ldapoptions *ldap_int_global_opt(void); +#else +# define LDAP_INT_GLOBAL_OPT() (&ldap_int_global_options) +#endif + +#define ldap_debug ((LDAP_INT_GLOBAL_OPT())->ldo_debug) + +#include "ldap_log.h" + #undef Debug #define Debug( level, fmt, arg1, arg2, arg3 ) \ ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) ) -#include "ldap_log.h" - #include "ldap.h" #include "ldap_pvt.h" @@ -36,6 +56,10 @@ LDAP_BEGIN_DECL #define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1) #define LDAPS_URL_PREFIX "ldaps://" #define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1) +#define LDAPI_URL_PREFIX "ldapi://" +#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1) +#define LDAPIS_URL_PREFIX "ldapis://" +#define LDAPIS_URL_PREFIX_LEN (sizeof(LDAPIS_URL_PREFIX)-1) #define LDAP_URL_URLCOLON "URL:" #define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1) #define NULLLDAPURLDESC ((LDAPURLDesc *)NULL) @@ -45,16 +69,11 @@ LDAP_BEGIN_DECL #define LDAP_LDAP_REF_STR LDAP_URL_PREFIX #define LDAP_LDAP_REF_STR_LEN (sizeof(LDAP_LDAP_REF_STR)-1) -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS -#define LDAP_DX_REF_STR "dx://" -#define LDAP_DX_REF_STR_LEN (sizeof(LDAP_DX_REF_STR)-1) -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ #define LDAP_DEFAULT_REFHOPLIMIT 5 #define LDAP_BOOL_REFERRALS 0 #define LDAP_BOOL_RESTART 1 -#define LDAP_BOOL_DNS 2 #define LDAP_BOOL_TLS 3 #define LDAP_BOOLEANS unsigned long @@ -95,14 +114,15 @@ struct ldapoptions { struct timeval *ldo_tm_api; struct timeval *ldo_tm_net; - ber_int_t ldo_version; /* version to connect at */ + ber_int_t ldo_version; ber_int_t ldo_deref; ber_int_t ldo_timelimit; ber_int_t ldo_sizelimit; + LDAPURLDesc *ldo_defludp; int ldo_defport; char* ldo_defbase; - char* ldo_defhost; + char* ldo_defbinddn; /* simple bind dn */ #ifdef LDAP_CONNECTIONLESS int ldo_cldaptries; /* connectionless search retry count */ @@ -114,11 +134,18 @@ struct ldapoptions { /* LDAPv3 server and client controls */ LDAPControl **ldo_sctrls; LDAPControl **ldo_cctrls; + /* LDAPV3 rebind callback function + */ + LDAP_REBIND_PROC *ldo_rebindproc; #ifdef HAVE_TLS /* tls context */ void *ldo_tls_ctx; int ldo_tls_mode; +#endif +#ifdef HAVE_CYRUS_SASL + sasl_ssf_t ldo_sasl_minssf; + sasl_ssf_t ldo_sasl_maxssf; #endif LDAP_BOOLEANS ldo_booleans; /* boolean options */ }; @@ -131,6 +158,7 @@ typedef struct ldap_server { char *lsrv_host; char *lsrv_dn; /* if NULL, use default */ int lsrv_port; +/* int lsrv_protocol; */ struct ldap_server *lsrv_next; } LDAPServer; @@ -142,11 +170,13 @@ typedef struct ldap_conn { Sockbuf *lconn_sb; int lconn_refcnt; time_t lconn_lastused; /* time */ + int lconn_rebind_inprogress; /* set if rebind in progress */ + char ***lconn_rebind_queue; /* used if rebind in progress */ int lconn_status; #define LDAP_CONNST_NEEDSOCKET 1 #define LDAP_CONNST_CONNECTING 2 #define LDAP_CONNST_CONNECTED 3 - LDAPServer *lconn_server; + LDAPURLDesc *lconn_server; char *lconn_krbinstance; struct ldap_conn *lconn_next; BerElement *lconn_ber;/* ber receiving on this conn. */ @@ -159,6 +189,7 @@ typedef struct ldap_conn { typedef struct ldapreq { ber_int_t lr_msgid; /* the message id */ int lr_status; /* status of request */ +#define LDAP_REQST_COMPLETED 0 #define LDAP_REQST_INPROGRESS 1 #define LDAP_REQST_CHASINGREFS 2 #define LDAP_REQST_NOTCONNECTED 3 @@ -194,6 +225,15 @@ typedef struct ldapcache { #define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002 } LDAPCache; +/* + * structure containing referral request info for rebind procedure + */ +typedef struct ldapreqinfo { + ber_len_t ri_msgid; + int ri_request; + char *ri_url; +} LDAPreqinfo; + /* * handy macro for checking if handle is connectionless */ @@ -205,7 +245,7 @@ typedef struct ldapcache { */ struct ldap { - Sockbuf ld_sb; /* socket descriptor & buffer */ + Sockbuf *ld_sb; /* socket descriptor & buffer */ struct ldapoptions ld_options; @@ -216,6 +256,7 @@ struct ldap { #define ld_timelimit ld_options.ldo_timelimit #define ld_sizelimit ld_options.ldo_sizelimit +#define ld_defbinddn ld_options.ldo_defbinddn #define ld_defbase ld_options.ldo_defbase #define ld_defhost ld_options.ldo_defhost #define ld_defport ld_options.ldo_defport @@ -226,8 +267,9 @@ struct ldap { #define ld_sctrls ld_options.ldo_sctrls #define ld_cctrls ld_options.ldo_cctrls +#define ld_rebindproc ld_options.ldo_rebindproc - ber_int_t ld_version; /* version connected at */ +#define ld_version ld_options.ldo_version char *ld_host; int ld_port; @@ -255,25 +297,29 @@ struct ldap { void **ld_cldapaddrs;/* addresses to send request to */ /* do not mess with the rest though */ - BERTranslateProc ld_lber_encode_translate_proc; - BERTranslateProc ld_lber_decode_translate_proc; LDAPConn *ld_defconn; /* default connection */ LDAPConn *ld_conns; /* list of server connections */ void *ld_selectinfo; /* platform specifics for select */ - int (*ld_rebindproc)( struct ldap *ld, char **dnp, - char **passwdp, int *authmethodp, int freeit ); - /* routine to get info needed for re-bind */ +#ifdef HAVE_CYRUS_SASL + sasl_conn_t *ld_sasl_context; +#endif /* HAVE_CYRUS_SASL */ }; #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) +#if defined(HAVE_RES_QUERY) && defined(LDAP_R_COMPILE) +#include +extern ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; +#endif /* HAVE_RES_QUERY && LDAP_R_COMPILE */ + /* * in init.c */ -extern struct ldapoptions ldap_int_global_options; -void ldap_int_initialize LDAP_P((void)); - +LIBLDAP_F ( struct ldapoptions ) ldap_int_global_options; +LIBLDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *)); +LIBLDAP_F ( void ) ldap_int_initialize_global_options LDAP_P(( + struct ldapoptions *, int *)); /* memory.c */ /* simple macros to realloc for now */ @@ -294,125 +340,129 @@ void ldap_int_initialize LDAP_P((void)); /* * in unit-int.c */ -void ldap_int_utils_init LDAP_P(( void )); +LIBLDAP_F (void) ldap_int_utils_init LDAP_P(( void )); /* * in print.c */ -int ldap_log_printf LDAP_P((LDAP *ld, int level, const char *fmt, ...)) - LDAP_GCCATTR((format(printf, 3, 4))); +LIBLDAP_F (int) ldap_log_printf LDAP_P((LDAP *ld, int level, const char *fmt, ...)) LDAP_GCCATTR((format(printf, 3, 4))); /* * in cache.c */ -void ldap_add_request_to_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, +LIBLDAP_F (void) ldap_add_request_to_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request )); -void ldap_add_result_to_cache LDAP_P(( LDAP *ld, LDAPMessage *result )); -int ldap_check_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request )); +LIBLDAP_F (void) ldap_add_result_to_cache LDAP_P(( LDAP *ld, LDAPMessage *result )); +LIBLDAP_F (int) ldap_check_cache LDAP_P(( LDAP *ld, ber_tag_t msgtype, BerElement *request )); /* * in controls.c */ -LDAPControl *ldap_control_dup LDAP_P(( +LIBLDAP_F (LDAPControl *) ldap_control_dup LDAP_P(( const LDAPControl *ctrl )); -LDAPControl **ldap_controls_dup LDAP_P(( +LIBLDAP_F (LDAPControl **) ldap_controls_dup LDAP_P(( LDAPControl *const *ctrls )); -int ldap_int_get_controls LDAP_P(( +LIBLDAP_F (int) ldap_int_get_controls LDAP_P(( BerElement *be, LDAPControl ***ctrlsp)); -int ldap_int_put_controls LDAP_P(( +LIBLDAP_F (int) ldap_int_put_controls LDAP_P(( LDAP *ld, LDAPControl *const *ctrls, BerElement *ber )); +LIBLDAP_F( int ) +ldap_int_create_control LDAP_P(( + const char *requestOID, + BerElement *ber, + int iscritical, + LDAPControl **ctrlp )); + /* * in dsparse.c */ -int next_line_tokens LDAP_P(( char **bufp, ber_len_t *blenp, char ***toksp )); -void free_strarray LDAP_P(( char **sap )); +LIBLDAP_F (int) ldap_int_next_line_tokens LDAP_P(( char **bufp, ber_len_t *blenp, char ***toksp )); -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND /* * in kerberos.c */ -char *ldap_get_kerberosv4_credentials LDAP_P(( +LIBLDAP_F (char *) ldap_get_kerberosv4_credentials LDAP_P(( LDAP *ld, LDAP_CONST char *who, LDAP_CONST char *service, ber_len_t *len )); -#endif /* HAVE_KERBEROS */ +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ /* * in open.c */ -int open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport, - char **krbinstancep, int async ); - +LIBLDAP_F (int) ldap_open_defconn( LDAP *ld ); +LIBLDAP_F (int) open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srvlist, char **krbinstancep, int async ); /* * in os-ip.c */ -extern int ldap_int_tblsize; -int ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm ); -int ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, - unsigned long address, int port, int async ); - -void ldap_close_connection( Sockbuf *sb ); - -#ifdef HAVE_KERBEROS -char *ldap_host_connected_to( Sockbuf *sb ); -#endif /* HAVE_KERBEROS */ - -void ldap_int_ip_init( void ); -int do_ldap_select( LDAP *ld, struct timeval *timeout ); -void *ldap_new_select_info( void ); -void ldap_free_select_info( void *sip ); -void ldap_mark_select_write( LDAP *ld, Sockbuf *sb ); -void ldap_mark_select_read( LDAP *ld, Sockbuf *sb ); -void ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ); -int ldap_is_read_ready( LDAP *ld, Sockbuf *sb ); -int ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); +LIBLDAP_F (int) ldap_int_tblsize; +LIBLDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm ); +LIBLDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, unsigned long address, int port, int async ); + +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) +LIBLDAP_F (char *) ldap_host_connected_to( Sockbuf *sb ); +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ + +LIBLDAP_F (void) ldap_int_ip_init( void ); +LIBLDAP_F (int) do_ldap_select( LDAP *ld, struct timeval *timeout ); +LIBLDAP_F (void *) ldap_new_select_info( void ); +LIBLDAP_F (void) ldap_free_select_info( void *sip ); +LIBLDAP_F (void) ldap_mark_select_write( LDAP *ld, Sockbuf *sb ); +LIBLDAP_F (void) ldap_mark_select_read( LDAP *ld, Sockbuf *sb ); +LIBLDAP_F (void) ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ); +LIBLDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb ); +LIBLDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); +/* + * in os-local.c + */ +#ifdef LDAP_PF_UNIX +LIBLDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, const char *path, int async ); +#endif /* LDAP_PF_UNIX */ /* * in request.c */ -ber_int_t ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype, +LIBLDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype, const char *dn, BerElement *ber ); -BerElement *ldap_alloc_ber_with_options( LDAP *ld ); -void ldap_set_ber_options( LDAP *ld, BerElement *ber ); - -int ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, - LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc, - int bind ); -LDAPConn *ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, - int connect, int bind ); -LDAPRequest *ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ); -void ldap_free_request( LDAP *ld, LDAPRequest *lr ); -void ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ); -void ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); -void ldap_dump_requests_and_responses( LDAP *ld ); - -int ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ); -int ldap_append_referral( LDAP *ld, char **referralsp, char *s ); +LIBLDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld ); +LIBLDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber ); + +LIBLDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc *srvlist, LDAPConn *lc, LDAPreqinfo *bind ); +LIBLDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb, int connect, LDAPreqinfo *bind ); +LIBLDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ); +LIBLDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr ); +LIBLDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ); +LIBLDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); +LIBLDAP_F (void) ldap_dump_requests_and_responses( LDAP *ld ); +LIBLDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ); +LIBLDAP_F (int) ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, char **referralsp, int *hadrefp ); +LIBLDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s ); /* * in result.c: */ #ifdef LDAP_CONNECTIONLESS -int cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ); +LIBLDAP_F (int) cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ); #endif /* * in search.c */ -BerElement *ldap_build_search_req LDAP_P(( +LIBLDAP_F (BerElement *) ldap_build_search_req LDAP_P(( LDAP *ld, const char *base, ber_int_t scope, @@ -432,40 +482,44 @@ BerElement *ldap_build_search_req LDAP_P(( /* * in unbind.c */ -int ldap_ld_free LDAP_P(( +LIBLDAP_F (int) ldap_ld_free LDAP_P(( LDAP *ld, int close, LDAPControl **sctrls, LDAPControl **cctrls )); -int ldap_send_unbind LDAP_P(( +LIBLDAP_F (int) ldap_send_unbind LDAP_P(( LDAP *ld, Sockbuf *sb, LDAPControl **sctrls, LDAPControl **cctrls )); -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS /* - * in getdxbyname.c + * in url.c */ -char **ldap_getdxbyname( const char *domain ); -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ +LIBLDAP_F (LDAPURLDesc *) ldap_url_dup LDAP_P(( + LDAPURLDesc *ludp )); + +LIBLDAP_F (LDAPURLDesc *) ldap_url_duplist LDAP_P(( + LDAPURLDesc *ludlist )); + +LIBLDAP_F (int) ldap_url_parselist LDAP_P(( + LDAPURLDesc **ludlist, + const char *url )); + +LIBLDAP_F (int) ldap_url_parsehosts LDAP_P(( + LDAPURLDesc **ludlist, + const char *hosts )); + +LIBLDAP_F (char *) ldap_url_list2hosts LDAP_P(( + LDAPURLDesc *ludlist )); + +LIBLDAP_F (char *) ldap_url_list2urls LDAP_P(( + LDAPURLDesc *ludlist )); + +LIBLDAP_F (void) ldap_free_urllist LDAP_P(( + LDAPURLDesc *ludlist )); -#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET ) -/* - * in charset.c - * - * added-in this stuff so that libldap.a would build, i.e. refs to - * these routines from open.c would resolve. - * hodges@stanford.edu 5-Feb-96 - */ -#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET -extern -int ldap_t61_to_8859( char **bufp, ber_len_t *buflenp, int free_input ); -extern -int ldap_8859_to_t61( char **bufp, ber_len_t *buflenp, int free_input ); -#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */ -#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */ LDAP_END_DECL diff --git a/libraries/libldap/libldap.dsp b/libraries/libldap/libldap.dsp index 48692feb92..5a9f03affc 100644 --- a/libraries/libldap/libldap.dsp +++ b/libraries/libldap/libldap.dsp @@ -38,9 +38,10 @@ CPP=cl.exe # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\Release" -# PROP Intermediate_Dir "Release\libldap" +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\libldap" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -48,7 +49,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Release\oldap32.lib" +# ADD LIB32 /nologo /out:"..\..\Release\oldap32.lib" !ELSEIF "$(CFG)" == "libldap - Win32 Debug" @@ -59,9 +60,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\Debug" -# PROP Intermediate_Dir "Debug\libldap" +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\libldap" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -69,7 +71,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Debug\oldap32.lib" +# ADD LIB32 /nologo /out:"..\..\Debug\oldap32.lib" !ELSEIF "$(CFG)" == "libldap - Win32 Single Debug" @@ -80,9 +82,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\SDebug" -# PROP Intermediate_Dir "SDebug\libldap" +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\libldap" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -90,7 +93,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Debug\oldap32.lib" -# ADD LIB32 /nologo /out:"..\SDebug\oldap32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\oldap32.lib" !ELSEIF "$(CFG)" == "libldap - Win32 Single Release" @@ -101,9 +104,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\SRelease" -# PROP Intermediate_Dir "SRelease\libldap" +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\libldap" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -111,7 +115,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Release\oldap32.lib" -# ADD LIB32 /nologo /out:"..\SRelease\oldap32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\oldap32.lib" !ENDIF @@ -147,10 +151,6 @@ SOURCE=.\charray.c # End Source File # Begin Source File -SOURCE=.\charset.c -# End Source File -# Begin Source File - SOURCE=.\cldap.c # End Source File # Begin Source File @@ -167,10 +167,6 @@ SOURCE=.\delete.c # End Source File # Begin Source File -SOURCE=.\digest.c -# End Source File -# Begin Source File - SOURCE=.\disptmpl.c # End Source File # Begin Source File @@ -183,6 +179,10 @@ SOURCE=.\dn.c # End Source File # Begin Source File +SOURCE=.\dnssrv.c +# End Source File +# Begin Source File + SOURCE=.\dsparse.c # End Source File # Begin Source File @@ -211,10 +211,6 @@ SOURCE=.\getdn.c # End Source File # Begin Source File -SOURCE=.\getdxbyname.c -# End Source File -# Begin Source File - SOURCE=.\getentry.c # End Source File # Begin Source File @@ -335,6 +331,10 @@ SOURCE=.\sort.c # End Source File # Begin Source File +SOURCE=.\sortctrl.c +# End Source File +# Begin Source File + SOURCE=.\srchpref.c # End Source File # Begin Source File @@ -347,6 +347,10 @@ SOURCE=.\string.c # End Source File # Begin Source File +SOURCE=.\tls.c +# End Source File +# Begin Source File + SOURCE=.\ufn.c # End Source File # Begin Source File @@ -359,7 +363,15 @@ SOURCE=.\url.c # End Source File # Begin Source File +SOURCE=".\utf-8.c" +# End Source File +# Begin Source File + SOURCE=".\util-int.c" # End Source File +# Begin Source File + +SOURCE=.\vlvctrl.c +# End Source File # End Target # End Project diff --git a/libraries/libldap/ltest.dsp b/libraries/libldap/ltest.dsp new file mode 100644 index 0000000000..16e6f1444c --- /dev/null +++ b/libraries/libldap/ltest.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="ltest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ltest - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ltest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ltest.mak" CFG="ltest - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ltest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ltest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ltest - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ltest - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ltest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ltest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "ltest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ltest___" +# PROP BASE Intermediate_Dir "ltest___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ltest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ltest - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ltest___" +# PROP BASE Intermediate_Dir "ltest___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ltest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "ltest - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ltest__0" +# PROP BASE Intermediate_Dir "ltest__0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ltest" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ENDIF + +# Begin Target + +# Name "ltest - Win32 Release" +# Name "ltest - Win32 Debug" +# Name "ltest - Win32 Single Release" +# Name "ltest - Win32 Single Debug" +# Begin Source File + +SOURCE=.\test.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap/messages.c b/libraries/libldap/messages.c index 57e331daeb..57cd4dbd43 100644 --- a/libraries/libldap/messages.c +++ b/libraries/libldap/messages.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* diff --git a/libraries/libldap/modify.c b/libraries/libldap/modify.c index a758fc1607..83a4b67a3e 100644 --- a/libraries/libldap/modify.c +++ b/libraries/libldap/modify.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions diff --git a/libraries/libldap/modrdn.c b/libraries/libldap/modrdn.c index 209ec4315a..29108a3f38 100644 --- a/libraries/libldap/modrdn.c +++ b/libraries/libldap/modrdn.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -59,8 +59,8 @@ ldap_rename( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, LDAP_CONST char *newSuperior, + int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) @@ -141,16 +141,16 @@ ldap_rename2( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, - LDAP_CONST char *newSuperior ) + LDAP_CONST char *newSuperior, + int deleteoldrdn ) { int msgid; int rc; Debug( LDAP_DEBUG_TRACE, "ldap_rename2\n", 0, 0, 0 ); - rc = ldap_rename( ld, dn, newrdn, deleteoldrdn, newSuperior, - NULL, NULL, &msgid ); + rc = ldap_rename( ld, dn, newrdn, newSuperior, + deleteoldrdn, NULL, NULL, &msgid ); return rc == LDAP_SUCCESS ? msgid : -1; } @@ -173,13 +173,13 @@ ldap_modrdn2( LDAP *ld, LDAP_CONST char *newrdn, int deleteoldrdn ) { - return ldap_rename2( ld, dn, newrdn, deleteoldrdn, NULL ); + return ldap_rename2( ld, dn, newrdn, NULL, deleteoldrdn ); } int ldap_modrdn( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) { - return( ldap_rename2( ld, dn, newrdn, 1, NULL ) ); + return( ldap_rename2( ld, dn, newrdn, NULL, 1 ) ); } @@ -188,8 +188,8 @@ ldap_rename_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, LDAP_CONST char *newSuperior, + int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls ) { @@ -197,8 +197,8 @@ ldap_rename_s( int msgid; LDAPMessage *res; - rc = ldap_rename( ld, dn, newrdn, deleteoldrdn, - newSuperior, sctrls, cctrls, &msgid ); + rc = ldap_rename( ld, dn, newrdn, newSuperior, + deleteoldrdn, sctrls, cctrls, &msgid ); if( rc != LDAP_SUCCESS ) { return rc; @@ -218,21 +218,22 @@ ldap_rename2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, - int deleteoldrdn, - LDAP_CONST char *newSuperior ) + LDAP_CONST char *newSuperior, + int deleteoldrdn ) { - return ldap_rename_s( ld, dn, newrdn, deleteoldrdn, newSuperior, NULL, NULL ); + return ldap_rename_s( ld, dn, newrdn, newSuperior, + deleteoldrdn, NULL, NULL ); } int ldap_modrdn2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn ) { - return ldap_rename_s( ld, dn, newrdn, deleteoldrdn, NULL, NULL, NULL ); + return ldap_rename_s( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL ); } int ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) { - return ldap_rename_s( ld, dn, newrdn, 1, NULL, NULL, NULL ); + return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL ); } diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index e8785387f5..938739d7eb 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -13,19 +13,29 @@ #include "portable.h" #include +#include #include +#include #include #include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #include "ldap-int.h" +int ldap_open_defconn( LDAP *ld ) +{ + if (( ld->ld_defconn = ldap_new_connection( ld, ld->ld_options.ldo_defludp, 1,1,NULL )) == NULL ) + { + ld->ld_errno = LDAP_SERVER_DOWN; + return -1; + } + + ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ + + return 0; +} /* * ldap_open - initialize and connect to an ldap server. A magic cookie to @@ -40,8 +50,8 @@ LDAP * ldap_open( LDAP_CONST char *host, int port ) { + int rc; LDAP *ld; - LDAPServer *srv; Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 ); @@ -49,22 +59,12 @@ ldap_open( LDAP_CONST char *host, int port ) return( NULL ); } - if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer ))) == - NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = - LDAP_STRDUP( ld->ld_defhost )) == NULL )) { - if(srv != NULL) LDAP_FREE( (char*) srv ); - ldap_ld_free( ld, 0, NULL, NULL ); - return( NULL ); - } - srv->lsrv_port = ld->ld_defport; + rc = ldap_open_defconn( ld ); - if (( ld->ld_defconn = ldap_new_connection( ld, &srv, 1,1,0 )) == NULL ) { - if ( ld->ld_defhost != NULL ) LDAP_FREE( srv->lsrv_host ); - LDAP_FREE( (char *)srv ); + if( rc < 0 ) { ldap_ld_free( ld, 0, NULL, NULL ); return( NULL ); } - ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ Debug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n", ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); @@ -73,22 +73,22 @@ ldap_open( LDAP_CONST char *host, int port ) } -/* - * ldap_init - initialize the LDAP library. A magic cookie to be used for - * future communication is returned on success, NULL on failure. - * "host" may be a space-separated list of hosts or IP addresses - * - * Example: - * LDAP *ld; - * ld = ldap_open( host, port ); - */ -LDAP * -ldap_init( LDAP_CONST char *defhost, int defport ) + +int +ldap_create( LDAP **ldp ) { LDAP *ld; + struct ldapoptions *gopts; - if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) { - ldap_int_initialize(); + *ldp = NULL; + /* Get pointer to global option structure */ + if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { + return LDAP_NO_MEMORY; + } + + /* Initialize the global options, if not already done. */ + if( gopts->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(gopts, NULL); } Debug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); @@ -96,15 +96,12 @@ ldap_init( LDAP_CONST char *defhost, int defport ) #ifdef HAVE_WINSOCK2 { WORD wVersionRequested; WSADATA wsaData; - int err; wVersionRequested = MAKEWORD( 2, 0 ); - - err = WSAStartup( wVersionRequested, &wsaData ); - if ( err != 0 ) { + if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) { /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ - return NULL; + return LDAP_LOCAL_ERROR; } /* Confirm that the WinSock DLL supports 2.0.*/ @@ -119,164 +116,235 @@ ldap_init( LDAP_CONST char *defhost, int defport ) /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ WSACleanup( ); - return NULL; + return LDAP_LOCAL_ERROR; } } /* The WinSock DLL is acceptable. Proceed. */ #elif HAVE_WINSOCK { WSADATA wsaData; if ( WSAStartup( 0x0101, &wsaData ) != 0 ) { - return( NULL ); + return LDAP_LOCAL_ERROR; } } #endif if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { WSACleanup( ); - return( NULL ); + return( LDAP_NO_MEMORY ); } /* copy the global options */ - memcpy(&ld->ld_options, &ldap_int_global_options, - sizeof(ld->ld_options)); + memcpy(&ld->ld_options, gopts, sizeof(ld->ld_options)); ld->ld_valid = LDAP_VALID_SESSION; /* but not pointers to malloc'ed items */ - ld->ld_options.ldo_defbase = NULL; - ld->ld_options.ldo_defhost = NULL; + ld->ld_options.ldo_defludp = NULL; ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; - if ( defhost != NULL ) { - ld->ld_options.ldo_defhost = LDAP_STRDUP( defhost ); - } else { - ld->ld_options.ldo_defhost = LDAP_STRDUP( - ldap_int_global_options.ldo_defhost); - } + ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); - if ( ld->ld_options.ldo_defhost == NULL ) { + if ( ld->ld_options.ldo_defludp == NULL ) { LDAP_FREE( (char*)ld ); WSACleanup( ); - return( NULL ); - } - - if ( ldap_int_global_options.ldo_defbase != NULL ) { - ld->ld_options.ldo_defbase = LDAP_STRDUP( - ldap_int_global_options.ldo_defbase); + return LDAP_NO_MEMORY; } if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) { - LDAP_FREE( (char*) ld->ld_options.ldo_defhost ); - if ( ld->ld_options.ldo_defbase == NULL ) { - LDAP_FREE( (char*) ld->ld_options.ldo_defbase ); - } + ldap_free_urllist( ld->ld_options.ldo_defludp ); LDAP_FREE( (char*) ld ); WSACleanup( ); - return( NULL ); + return LDAP_NO_MEMORY; } - if(defport != 0) { - ld->ld_defport = defport; + ld->ld_lberoptions = LBER_USE_DER; + + ld->ld_sb = ber_sockbuf_alloc( ); + if ( ld->ld_sb == NULL ) { + ldap_free_urllist( ld->ld_options.ldo_defludp ); + LDAP_FREE( (char*) ld ); + WSACleanup( ); + return LDAP_NO_MEMORY; } - ld->ld_lberoptions = LBER_USE_DER; + *ldp = ld; + return LDAP_SUCCESS; +} -#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET ) - ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS; -#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET - ldap_set_string_translators( ld, ldap_8859_to_t61, ldap_t61_to_8859 ); -#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */ -#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */ +/* + * ldap_init - initialize the LDAP library. A magic cookie to be used for + * future communication is returned on success, NULL on failure. + * "host" may be a space-separated list of hosts or IP addresses + * + * Example: + * LDAP *ld; + * ld = ldap_open( host, port ); + */ +LDAP * +ldap_init( LDAP_CONST char *defhost, int defport ) +{ + LDAP *ld; + int rc; + + rc = ldap_create(&ld); + if ( rc != LDAP_SUCCESS ) + return NULL; - /* we'll assume we're talking version 2 for now */ - ld->ld_version = LDAP_VERSION2; + if (defport != 0) + ld->ld_options.ldo_defport = defport; - ber_pvt_sb_init( &(ld->ld_sb) ); + if (defhost != NULL) { + rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost); + if ( rc != LDAP_SUCCESS ) { + ldap_ld_free(ld, 1, NULL, NULL); + return NULL; + } + } return( ld ); } int -open_ldap_connection( LDAP *ld, Sockbuf *sb, const char *host, int defport, +ldap_initialize( LDAP **ldp, LDAP_CONST char *url ) +{ + int rc; + LDAP *ld; + + *ldp = NULL; + rc = ldap_create(&ld); + if ( rc != LDAP_SUCCESS ) + return rc; + + if (url != NULL) { + rc = ldap_set_option(ld, LDAP_OPT_URI, url); + if ( rc != LDAP_SUCCESS ) { + ldap_ld_free(ld, 1, NULL, NULL); + return rc; + } + } + + *ldp = ld; + return LDAP_SUCCESS; +} + +int +ldap_start_tls ( LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ +#ifdef HAVE_TLS + LDAPConn *lc; + int rc; + char *rspoid = NULL; + struct berval *rspdata = NULL; + + if (ld->ld_conns == NULL) { + rc = ldap_open_defconn( ld ); + if (rc != LDAP_SUCCESS) + return(rc); + } + + for (lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next) { + if (ldap_pvt_tls_inplace(lc->lconn_sb) != 0) + return LDAP_OPERATIONS_ERROR; + rc = ldap_extended_operation_s(ld, LDAP_EXOP_START_TLS, + NULL, serverctrls, clientctrls, &rspoid, &rspdata); + if (rc != LDAP_SUCCESS) + return rc; + if (rspoid != NULL) + LDAP_FREE(rspoid); + if (rspdata != NULL) + ber_bvfree(rspdata); + rc = ldap_pvt_tls_start( ld, lc->lconn_sb, ld->ld_options.ldo_tls_ctx ); + if (rc != LDAP_SUCCESS) + return rc; + } + return LDAP_SUCCESS; +#else + return LDAP_NOT_SUPPORTED; +#endif +} + +int +open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, char **krbinstancep, int async ) { - int rc = -1; - int port; - const char *p, *q; - char *r, *curhost, hostname[ 2*MAXHOSTNAMELEN ]; + int rc = -1; + int port; + long addr; Debug( LDAP_DEBUG_TRACE, "open_ldap_connection\n", 0, 0, 0 ); - defport = htons( (short) defport ); - - if ( host != NULL ) { - for ( p = host; p != NULL && *p != '\0'; p = q ) { - if (( q = strchr( p, ' ' )) != NULL ) { - strncpy( hostname, p, q - p ); - hostname[ q - p ] = '\0'; - curhost = hostname; - while ( *q == ' ' ) { - ++q; - } - } else { - curhost = (char *) p; /* avoid copy if possible */ - q = NULL; - } - - if (( r = strchr( curhost, ':' )) != NULL ) { - if ( curhost != hostname ) { - strcpy( hostname, curhost ); /* now copy */ - r = hostname + ( r - curhost ); - curhost = hostname; - } - *r++ = '\0'; - port = htons( (short) atoi( r ) ); - } else { - port = defport; - } - - if (( rc = ldap_connect_to_host( ld, sb, curhost, 0L, - port, async )) != -1 ) { - break; - } - } - } else { - rc = ldap_connect_to_host( ld, sb, 0, htonl( INADDR_LOOPBACK ), - defport, async ); + port = srv->lud_port; + if (port == 0) + port = ld->ld_options.ldo_defport; + port = htons( (short) port ); + + addr = 0; + if ( srv->lud_host == NULL || *srv->lud_host == 0 ) + addr = htonl( INADDR_LOOPBACK ); + + switch ( ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { + case LDAP_PROTO_TCP: + rc = ldap_connect_to_host( ld, sb, srv->lud_host, + addr, port, async ); + if ( rc == -1 ) + return rc; + ber_sockbuf_add_io( sb, &ber_sockbuf_io_tcp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; + case LDAP_PROTO_UDP: + rc = ldap_connect_to_host( ld, sb, srv->lud_host, + addr, port, async ); + if ( rc == -1 ) + return rc; + ber_sockbuf_add_io( sb, &ber_sockbuf_io_udp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; + case LDAP_PROTO_IPC: +#ifdef LDAP_PF_UNIX + /* only IPC mechanism supported is PF_UNIX */ + rc = ldap_connect_to_path( ld, sb, srv->lud_host, + async ); + if ( rc == -1 ) + return rc; + ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; +#endif /* LDAP_PF_UNIX */ + default: + return -1; + break; } - if ( rc == -1 ) { - return( rc ); - } - - ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL ); + ber_sockbuf_add_io( sb, &ber_sockbuf_io_readahead, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, INT_MAX, NULL ); +#endif #ifdef HAVE_TLS - if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ) { - /* - * Fortunately, the lib uses blocking io... - */ - if ( ldap_pvt_tls_connect( sb, ld->ld_options.ldo_tls_ctx ) < - 0 ) { - return -1; - } - /* FIXME: hostname of server must be compared with name in - * certificate.... - */ + if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || + strcmp( srv->lud_scheme, "ldaps" ) == 0 ) + { + rc = ldap_pvt_tls_start( ld, sb, ld->ld_options.ldo_tls_ctx ); + if (rc != LDAP_SUCCESS) + return rc; } #endif + if ( krbinstancep != NULL ) { -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char *c; if (( *krbinstancep = ldap_host_connected_to( sb )) != NULL && ( c = strchr( *krbinstancep, '.' )) != NULL ) { *c = '\0'; } -#else /* HAVE_KERBEROS */ - krbinstancep = NULL; -#endif /* HAVE_KERBEROS */ +#else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ + *krbinstancep = NULL; +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ } return( 0 ); diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index 12edf629fc..879c70f3a8 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -16,6 +16,8 @@ #include "ldap-int.h" +#define LDAP_OPT_REBIND_PROC 0x4e814d + static const LDAPAPIFeatureInfo features[] = { #ifdef LDAP_API_FEATURE_X_OPENLDAP { /* OpenLDAP Extensions API Feature */ @@ -61,13 +63,6 @@ static const LDAPAPIFeatureInfo features[] = { LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE }, #endif -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - { /* DNS */ - LDAP_FEATURE_INFO_VERSION, - "X_OPENLDAP_V2_DNS", - LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - }, -#endif #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS { /* V2 Referrals */ LDAP_FEATURE_INFO_VERSION, @@ -80,20 +75,23 @@ static const LDAPAPIFeatureInfo features[] = { int ldap_get_option( - LDAP_CONST LDAP *ld, + LDAP *ld, int option, void *outvalue) { - LDAP_CONST struct ldapoptions *lo; + struct ldapoptions *lo; - if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) { - ldap_int_initialize(); + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if (NULL == lo) { + return LDAP_NO_MEMORY; } - if(ld == NULL) { - lo = &ldap_int_global_options; + if( lo->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(lo, NULL); + } - } else { + if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { @@ -149,12 +147,12 @@ ldap_get_option( } break; case LDAP_OPT_DESC: - if(ld == NULL) { + if( ld == NULL || ld->ld_sb == NULL ) { /* bad param */ break; } - * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue ); return LDAP_OPT_SUCCESS; case LDAP_OPT_TIMEOUT: @@ -193,16 +191,8 @@ ldap_get_option( * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART); return LDAP_OPT_SUCCESS; - case LDAP_OPT_DNS: /* LDAPv2 */ - * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS); - return LDAP_OPT_SUCCESS; - case LDAP_OPT_PROTOCOL_VERSION: - if ((ld != NULL) && ld->ld_version) { - * (int *) outvalue = ld->ld_version; - } else { - * (int *) outvalue = lo->ldo_version; - } + * (int *) outvalue = lo->ldo_version; return LDAP_OPT_SUCCESS; case LDAP_OPT_SERVER_CONTROLS: @@ -218,7 +208,11 @@ ldap_get_option( return LDAP_OPT_SUCCESS; case LDAP_OPT_HOST_NAME: - * (char **) outvalue = LDAP_STRDUP(lo->ldo_defhost); + * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp); + return LDAP_OPT_SUCCESS; + + case LDAP_OPT_URI: + * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp); return LDAP_OPT_SUCCESS; case LDAP_OPT_ERROR_NUMBER: @@ -287,7 +281,11 @@ ldap_get_option( default: #ifdef HAVE_TLS - if ( ldap_pvt_tls_get_option(lo, option, outvalue ) == 0 ) + if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 ) + return LDAP_OPT_SUCCESS; +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 ) return LDAP_OPT_SUCCESS; #endif /* bad param */ @@ -304,15 +302,27 @@ ldap_set_option( LDAP_CONST void *invalue) { struct ldapoptions *lo; + int *dbglvl = NULL; - if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) { - ldap_int_initialize(); + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if (lo == NULL) { + return LDAP_NO_MEMORY; } - if(ld == NULL) { - lo = &ldap_int_global_options; + /* + * The architecture to turn on debugging has a chicken and egg + * problem. Thus, we introduce a fix here. + */ + + if (option == LDAP_OPT_DEBUG_LEVEL) + dbglvl = (int *) invalue; + + if( lo->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(lo, dbglvl); + } - } else { + if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { @@ -407,6 +417,11 @@ ldap_set_option( return LDAP_OPT_ERROR; } } return LDAP_OPT_SUCCESS; + + /* Only accessed from inside this function by ldap_set_rebind_proc() */ + case LDAP_OPT_REBIND_PROC: { + lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue; + } return LDAP_OPT_SUCCESS; } if(invalue == NULL) { @@ -440,39 +455,77 @@ ldap_set_option( /* not supported */ break; } - ld->ld_version = vers; + lo->ldo_version = vers; } return LDAP_OPT_SUCCESS; case LDAP_OPT_HOST_NAME: { const char *host = (const char *) invalue; + LDAPURLDesc *ludlist = NULL; + int rc = LDAP_OPT_SUCCESS; + + if(host != NULL) { + rc = ldap_url_parsehosts(&ludlist, host); + + } else if(ld == NULL) { + /* + * must want global default returned + * to initial condition. + */ + rc = ldap_url_parselist(&ludlist, "ldap://localhost/"); - if(lo->ldo_defhost != NULL) { - LDAP_FREE(lo->ldo_defhost); - lo->ldo_defhost = NULL; + } else { + /* + * must want the session default + * updated to the current global default + */ + ludlist = ldap_url_duplist( + ldap_int_global_options.ldo_defludp); + if (ludlist == NULL) + rc = LDAP_NO_MEMORY; } - if(host != NULL) { - lo->ldo_defhost = LDAP_STRDUP(host); - return LDAP_OPT_SUCCESS; + if (rc == LDAP_OPT_SUCCESS) { + if (lo->ldo_defludp != NULL) + ldap_free_urllist(lo->ldo_defludp); + lo->ldo_defludp = ludlist; } + return rc; + } - if(ld == NULL) { + case LDAP_OPT_URI: { + const char *urls = (const char *) invalue; + LDAPURLDesc *ludlist = NULL; + int rc = LDAP_OPT_SUCCESS; + + if(urls != NULL) { + rc = ldap_url_parselist(&ludlist, urls); + + } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ - lo->ldo_defhost = LDAP_STRDUP("localhost"); + rc = ldap_url_parselist(&ludlist, "ldap://localhost/"); } else { /* * must want the session default * updated to the current global default */ - lo->ldo_defhost = LDAP_STRDUP( - ldap_int_global_options.ldo_defhost); + ludlist = ldap_url_duplist( + ldap_int_global_options.ldo_defludp); + if (ludlist == NULL) + rc = LDAP_NO_MEMORY; } - } return LDAP_OPT_SUCCESS; + + if (rc == LDAP_OPT_SUCCESS) { + if (lo->ldo_defludp != NULL) + ldap_free_urllist(lo->ldo_defludp); + lo->ldo_defludp = ludlist; + } + return rc; + } case LDAP_OPT_ERROR_NUMBER: { int err = * (const int *) invalue; @@ -525,11 +578,21 @@ ldap_set_option( default: #ifdef HAVE_TLS - if ( ldap_pvt_tls_set_option( lo, option, invalue ) == 0 ) - return LDAP_OPT_SUCCESS; + if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 ) + return LDAP_OPT_SUCCESS; +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 ) + return LDAP_OPT_SUCCESS; #endif /* bad param */ break; } return LDAP_OPT_ERROR; } + +LIBLDAP_F(int) +ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc) +{ + return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc)); +} diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 2eb1c02eff..c1c75e894b 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -46,7 +46,7 @@ int ldap_int_tblsize = 0; #define osip_debug(ld,fmt,arg1,arg2,arg3) \ do { \ - ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ + ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ } while(0) static void @@ -67,7 +67,7 @@ ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src ) return 0; } - new = (struct timeval *) malloc(sizeof(struct timeval)); + new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval)); if( new == NULL ) { *dest = NULL; @@ -117,8 +117,13 @@ ldap_pvt_prepare_socket(LDAP *ld, int fd) #ifdef TCP_NODELAY { int dummy = 1; - if ( setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char*) &dummy, sizeof(dummy) ) == -1 ) - return -1; + if ( setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, + (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) + { + osip_debug(ld, "ldap_prepare_socket: " + "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", + fd, 0, 0); + } } #endif return 0; @@ -127,10 +132,10 @@ ldap_pvt_prepare_socket(LDAP *ld, int fd) #undef TRACE #define TRACE do { \ osip_debug(ld, \ - "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \ + "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \ s, \ errno, \ - strerror(errno) ); \ + sock_errstr(errno) ); \ } while( 0 ) /* @@ -182,6 +187,9 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_in *sin, int async) { struct timeval tv, *opt_tv=NULL; fd_set wfds, *z=NULL; +#ifdef HAVE_WINSOCK + fd_set efds; +#endif if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) { tv.tv_usec = opt_tv->tv_usec; @@ -216,9 +224,30 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_in *sin, int async) FD_ZERO(&wfds); FD_SET(s, &wfds ); - if ( select(ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL) == -1) +#ifdef HAVE_WINSOCK + FD_ZERO(&efds); + FD_SET(s, &efds ); +#endif + + if ( select(ldap_int_tblsize, z, &wfds, +#ifdef HAVE_WINSOCK + &efds, +#else + z, +#endif + opt_tv ? &tv : NULL) == -1) return ( -1 ); +#ifdef HAVE_WINSOCK + /* This means the connection failed */ + if (FD_ISSET(s, &efds)) + { + ldap_pvt_set_errno(WSAECONNREFUSED); + osip_debug(ld, "ldap_pvt_connect: error on socket %d: " + "errno: %d (%s)\n", s, errno, sock_errstr(errno)); + return -1; + } +#endif if ( FD_ISSET(s, &wfds) ) { if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return ( -1 ); @@ -295,12 +324,12 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, break; } - (void)memset((char *)&sin, 0, sizeof(struct sockaddr_in)); + (void)memset((char *)&sin, '\0', sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = port; - p = (char *)&sin.sin_addr.s_addr; + p = (char *)&sin.sin_addr; q = use_hp ? (char *)hp->h_addr_list[i] : (char *)&address; - SAFEMEMCPY(p, q, sizeof(p) ); + SAFEMEMCPY(p, q, sizeof(sin.sin_addr) ); osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),0); @@ -308,7 +337,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, rc = ldap_pvt_connect(ld, s, &sin, async); if ( (rc == 0) || (rc == -2) ) { - ber_pvt_sb_set_desc( sb, s ); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s ); break; } @@ -321,19 +350,11 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, return rc; } -void -ldap_close_connection( Sockbuf *sb ) -{ - ber_pvt_sb_close( sb ); -} - - -#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS ) +#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL ) char * ldap_host_connected_to( Sockbuf *sb ) { struct hostent *hp; - char *p; socklen_t len; struct sockaddr_in sin; @@ -341,12 +362,14 @@ ldap_host_connected_to( Sockbuf *sb ) struct hostent he_buf; int local_h_errno; char *ha_buf=NULL; + ber_socket_t sd; #define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x); - (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); + (void)memset( (char *)&sin, '\0', sizeof( struct sockaddr_in )); len = sizeof( sin ); - if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) { return( NULL ); } @@ -370,7 +393,7 @@ ldap_host_connected_to( Sockbuf *sb ) } #undef DO_RETURN -#endif /* HAVE_KERBEROS || HAVE_TLS */ +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND || HAVE_TLS */ /* for UNIX */ @@ -386,11 +409,13 @@ void ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; + ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; - if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) { - FD_SET( (u_int) sb->sb_sd, &sip->si_writefds ); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + if ( !FD_ISSET( sd, &sip->si_writefds )) { + FD_SET( sd, &sip->si_writefds ); } } @@ -399,11 +424,13 @@ void ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; + ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; - if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) { - FD_SET( (u_int) sb->sb_sd, &sip->si_readfds ); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + if ( !FD_ISSET( sd, &sip->si_readfds )) { + FD_SET( sd, &sip->si_readfds ); } } @@ -412,11 +439,13 @@ void ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; + ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; - FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds ); - FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds ); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + FD_CLR( sd, &sip->si_writefds ); + FD_CLR( sd, &sip->si_readfds ); } @@ -424,10 +453,12 @@ int ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; + ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; - return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds )); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + return( FD_ISSET( sd, &sip->si_use_writefds )); } @@ -435,10 +466,12 @@ int ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) { struct selectinfo *sip; + ber_socket_t sd; sip = (struct selectinfo *)ld->ld_selectinfo; - return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds )); + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + return( FD_ISSET( sd, &sip->si_use_readfds )); } diff --git a/libraries/libldap/os-local.c b/libraries/libldap/os-local.c new file mode 100644 index 0000000000..6d45b2589a --- /dev/null +++ b/libraries/libldap/os-local.c @@ -0,0 +1,219 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * Copyright (c) 1999 PADL Software Pty Ltd. + * os-ip.c -- platform-specific domain socket code + */ + + +#include "portable.h" + +#ifdef LDAP_PF_UNIX + +#include + +#include + +#include +#include +#include +#include +#include + +/* XXX non-portable */ +#include + +#ifdef HAVE_IO_H +#include +#endif /* HAVE_IO_H */ + +#include "ldap-int.h" + +/* int ldap_int_tblsize = 0; */ + +#define oslocal_debug(ld,fmt,arg1,arg2,arg3) \ +do { \ + ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \ +} while(0) + +static void +ldap_pvt_set_errno(int err) +{ + errno = err; +} + +static int +ldap_pvt_ndelay_on(LDAP *ld, int fd) +{ + oslocal_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0); + return ber_pvt_socket_set_nonblock( fd, 1 ); +} + +static int +ldap_pvt_ndelay_off(LDAP *ld, int fd) +{ + oslocal_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0); + return ber_pvt_socket_set_nonblock( fd, 0 ); +} + +static ber_socket_t +ldap_pvt_socket(LDAP *ld) +{ + ber_socket_t s = socket(AF_UNIX, SOCK_STREAM, 0); + oslocal_debug(ld, "ldap_new_socket: %d\n",s,0,0); + return ( s ); +} + +static int +ldap_pvt_close_socket(LDAP *ld, int s) +{ + oslocal_debug(ld, "ldap_close_socket: %d\n",s,0,0); + return tcp_close(s); +} + +#undef TRACE +#define TRACE do { \ + oslocal_debug(ld, \ + "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \ + s, \ + errno, \ + strerror(errno) ); \ +} while( 0 ) + +/* + * check the socket for errors after select returned. + */ +static int +ldap_pvt_is_socket_ready(LDAP *ld, int s) +{ + oslocal_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0); + +#if defined( notyet ) /* && defined( SO_ERROR ) */ +{ + int so_errno; + int dummy = sizeof(so_errno); + if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) == -1 ) { + return -1; + } + if ( so_errno ) { + ldap_pvt_set_errno(so_errno); + TRACE; + return -1; + } + return 0; +} +#else +{ + /* error slippery */ + struct sockaddr_un sun; + char ch; + int dummy = sizeof(sun); + if ( getpeername( s, (struct sockaddr *) &sun, &dummy ) == -1 ) { + /* XXX: needs to be replace with ber_stream_read() */ + read(s, &ch, 1); + TRACE; + return -1; + } + return 0; +} +#endif + return -1; +} +#undef TRACE + +static int +ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sun, int async) +{ + struct timeval tv, *opt_tv=NULL; + fd_set wfds, *z=NULL; + + if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) { + tv.tv_usec = opt_tv->tv_usec; + tv.tv_sec = opt_tv->tv_sec; + } + + oslocal_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n", + s, opt_tv ? tv.tv_sec : -1L, async); + + if ( ldap_pvt_ndelay_on(ld, s) == -1 ) + return ( -1 ); + + if ( connect(s, (struct sockaddr *) sun, sizeof(struct sockaddr_un)) == 0 ) + { + if ( ldap_pvt_ndelay_off(ld, s) == -1 ) + return ( -1 ); + return ( 0 ); + } + + if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) { + return ( -1 ); + } + +#ifdef notyet + if ( async ) return ( -2 ); +#endif + + FD_ZERO(&wfds); + FD_SET(s, &wfds ); + + if ( select(ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL) == -1) + return ( -1 ); + + if ( FD_ISSET(s, &wfds) ) { + if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) + return ( -1 ); + if ( ldap_pvt_ndelay_off(ld, s) == -1 ) + return ( -1 ); + return ( 0 ); + } + oslocal_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0); + ldap_pvt_set_errno( ETIMEDOUT ); + return ( -1 ); +} + +int +ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async) +{ + struct sockaddr_un server; + ber_socket_t s = AC_SOCKET_INVALID; + int rc, i, len; + char *ha_buf=NULL, *p, *q; + + oslocal_debug(ld, "ldap_connect_to_path\n",0,0,0); + + if ( (s = ldap_pvt_socket( ld )) == -1 ) { + return -1; + } + + if ( path == NULL || path[0] == '\0' ) { + path = "/tmp/.ldap-sock"; + } else { + if ( strlen(path) > (sizeof( server.sun_path ) - 1) ) { + ldap_pvt_set_errno( ENAMETOOLONG ); + return -1; + } + } + + oslocal_debug(ld, "ldap_connect_to_path: Trying %s\n", path, 0, 0); + + memset( &server, '\0', sizeof(server) ); + server.sun_family = AF_UNIX; + strcpy( server.sun_path, path ); + + rc = ldap_pvt_connect(ld, s, &server, async); + + if (rc == 0) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, (void *)&s ); + } else { + ldap_pvt_close_socket(ld, s); + } + return rc; +} +#else +static int dummy; +#endif /* LDAP_PF_UNIX */ diff --git a/libraries/libldap/print.c b/libraries/libldap/print.c index a6616c53ec..02b95bcc05 100644 --- a/libraries/libldap/print.c +++ b/libraries/libldap/print.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -26,7 +26,7 @@ static int ldap_log_check( LDAP *ld, int loglvl ) if(ld == NULL) { errlvl = ldap_debug; } else { - errlvl = ld->ld_errno; + errlvl = ld->ld_debug; } return errlvl & loglvl ? 1 : 0; diff --git a/libraries/libldap/references.c b/libraries/libldap/references.c index 371919db10..c42f652057 100644 --- a/libraries/libldap/references.c +++ b/libraries/libldap/references.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -132,7 +132,7 @@ free_and_return: *referralsp = refs; } else { - ldap_value_free( refs ); + LDAP_VFREE( refs ); } if( freeit ) { diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index 07da8e9bce..cb645b18a7 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -1,12 +1,29 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions * Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. + */ +/*--- + * This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Modification to OpenLDAP source by Novell, Inc. + * April 2000 sfs Added code to chase V3 referrals * request.c - sending of ldap requests; handling of referrals */ @@ -25,19 +42,16 @@ #include "ldap-int.h" #include "lber.h" -static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPServer *srv, int any )); +static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any )); static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc )); -static void free_servers LDAP_P(( LDAPServer *srvlist )); -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS -static LDAPServer *dn2servers LDAP_P(( LDAP *ld, const char *dn )); -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ static BerElement *re_encode_request LDAP_P(( LDAP *ld, BerElement *origber, ber_int_t msgid, - char **dnp )); + char **dnp, + int *type)); BerElement * @@ -47,10 +61,6 @@ ldap_alloc_ber_with_options( LDAP *ld ) if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; -#ifdef STR_TRANSLATION - } else { - ldap_set_ber_options( ld, ber ); -#endif /* STR_TRANSLATION */ } return( ber ); @@ -61,13 +71,6 @@ void ldap_set_ber_options( LDAP *ld, BerElement *ber ) { ber->ber_options = ld->ld_lberoptions; -#ifdef STR_TRANSLATION - if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) { - ber_set_string_translators( ber, - ld->ld_lber_encode_translate_proc, - ld->ld_lber_decode_translate_proc ); - } -#endif /* STR_TRANSLATION */ } @@ -78,67 +81,25 @@ ldap_send_initial_request( const char *dn, BerElement *ber ) { - LDAPServer *servers, *srv; + LDAPURLDesc *servers; + int rc; Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 ); - if ( ! ber_pvt_sb_in_use(&ld->ld_sb ) ) { + if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) { /* not connected yet */ + int rc = ldap_open_defconn( ld ); - if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer ))) == - NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = - LDAP_STRDUP( ld->ld_defhost )) == NULL )) - { - if (srv != NULL) LDAP_FREE( srv ); + if( rc < 0 ) { ber_free( ber, 1 ); - ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } - srv->lsrv_port = ld->ld_defport; - - if (( ld->ld_defconn = ldap_new_connection( ld, &srv, 1,1,0 )) - == NULL ) - { - if ( ld->ld_defhost != NULL ) LDAP_FREE( srv->lsrv_host ); - LDAP_FREE( (char *)srv ); - ber_free( ber, 1 ); - ld->ld_errno = LDAP_SERVER_DOWN; - return( -1 ); - } - ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ - Debug( LDAP_DEBUG_TRACE, "ldap_delayed_open successful, ld_host is %s\n", ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); } - -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_DNS ) - && ldap_is_dns_dn( dn ) ) - { - if (( servers = dn2servers( ld, dn )) == NULL ) { - ber_free( ber, 1 ); - return( -1 ); - } - -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - LDAPServer *srv; - - for ( srv = servers; srv != NULL; - srv = srv->lsrv_next ) { - fprintf( stderr, - "LDAP server %s: dn %s, port %d\n", - srv->lsrv_host, ( srv->lsrv_dn == NULL ) ? - "(default)" : srv->lsrv_dn, - srv->lsrv_port ); - } - } -#endif /* LDAP_DEBUG */ - } else -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ { /* * use of DNS is turned off or this is an X.500 DN... @@ -147,8 +108,11 @@ ldap_send_initial_request( servers = NULL; } - return( ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, servers, - NULL, 0 )); + rc = ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, + servers, NULL, NULL ); + if (servers) + ldap_free_urllist(servers); + return(rc); } @@ -159,9 +123,9 @@ ldap_send_server_request( BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, - LDAPServer *srvlist, + LDAPURLDesc *srvlist, LDAPConn *lc, - int bind ) + LDAPreqinfo *bind ) { LDAPRequest *lr; int incparent; @@ -177,14 +141,13 @@ ldap_send_server_request( } else { if (( lc = find_connection( ld, srvlist, 1 )) == NULL ) { - if ( bind && (parentreq != NULL) ) { + if ( (bind != NULL) && (parentreq != NULL) ) { /* Remember the bind in the parent */ incparent = 1; ++parentreq->lr_outrefcnt; } - lc = ldap_new_connection( ld, &srvlist, 0, 1, bind ); + lc = ldap_new_connection( ld, srvlist, 0, 1, bind ); } - free_servers( srvlist ); } } @@ -267,15 +230,15 @@ ldap_send_server_request( return( msgid ); } - LDAPConn * -ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, - int connect, int bind ) +ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb, + int connect, LDAPreqinfo *bind ) { LDAPConn *lc; - LDAPServer *prevsrv, *srv; + LDAPURLDesc *srv; Sockbuf *sb; + Debug( LDAP_DEBUG_TRACE, "ldap_new_connection\n", 0, 0, 0 ); /* * make a new LDAP server connection * XXX open connection synchronously for now @@ -289,35 +252,27 @@ ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, return( NULL ); } - lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb; + lc->lconn_sb = ( use_ldsb ) ? ld->ld_sb : sb; if ( connect ) { - prevsrv = NULL; - - for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) { + for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) { if ( open_ldap_connection( ld, lc->lconn_sb, - srv->lsrv_host, srv->lsrv_port, - &lc->lconn_krbinstance, 0 ) != -1 ) { + srv, &lc->lconn_krbinstance, 0 ) != -1 ) + { break; } - prevsrv = srv; } if ( srv == NULL ) { - if ( !use_ldsb ) { - ber_sockbuf_free( lc->lconn_sb ); - } + if ( !use_ldsb ) { + ber_sockbuf_free( lc->lconn_sb ); + } LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_SERVER_DOWN; return( NULL ); } - if ( prevsrv == NULL ) { - *srvlistp = srv->lsrv_next; - } else { - prevsrv->lsrv_next = srv->lsrv_next; - } - lc->lconn_server = srv; + lc->lconn_server = ldap_url_dup(srv); } lc->lconn_status = LDAP_CONNST_CONNECTED; @@ -328,71 +283,79 @@ ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, * XXX for now, we always do a synchronous bind. This will have * to change in the long run... */ - if ( bind ) { - int err, freepasswd, authmethod; - char *binddn, *passwd; + if ( bind != NULL) { + int err = 0; LDAPConn *savedefconn; - freepasswd = err = 0; - - if ( ld->ld_rebindproc == 0 ) { - binddn = passwd = ""; - authmethod = LDAP_AUTH_SIMPLE; - } else { - if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd, - &authmethod, 0 )) == LDAP_SUCCESS ) { - freepasswd = 1; + /* Set flag to prevent additional referrals from being processed on this + * connection until the bind has completed + */ + lc->lconn_rebind_inprogress = 1; + /* V3 rebind function */ + if ( ld->ld_rebindproc != NULL) { + LDAPURLDesc *srvfunc; + if( ( srvfunc = ldap_url_dup( srvlist)) == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + err = -1; } else { - ld->ld_errno = err; + savedefconn = ld->ld_defconn; + ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; + + Debug( LDAP_DEBUG_TRACE, "Call application rebindproc\n", 0, 0, 0); + err = (*ld->ld_rebindproc)( ld, bind->ri_url, bind->ri_request, bind->ri_msgid); + + ld->ld_defconn = savedefconn; + --lc->lconn_refcnt; + + if( err != 0) { err = -1; + ldap_free_connection( ld, lc, 1, 0 ); + lc = NULL; } + ldap_free_urldesc( srvfunc); } - - - if ( err == 0 ) { + } else { savedefconn = ld->ld_defconn; - ld->ld_defconn = lc; ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != - LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "anonymous rebind via ldap_bind_s\n", 0, 0, 0); + if ( ldap_bind_s( ld, "", "", LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) { err = -1; } - --lc->lconn_refcnt; ld->ld_defconn = savedefconn; - } - - if ( freepasswd ) { - (*ld->ld_rebindproc)( ld, &binddn, &passwd, - &authmethod, 1 ); - } + --lc->lconn_refcnt; if ( err != 0 ) { ldap_free_connection( ld, lc, 1, 0 ); lc = NULL; } } + if( lc != NULL) + lc->lconn_rebind_inprogress = 0; + } return( lc ); } static LDAPConn * -find_connection( LDAP *ld, LDAPServer *srv, int any ) +find_connection( LDAP *ld, LDAPURLDesc *srv, int any ) /* * return an existing connection (if any) to the server srv * if "any" is non-zero, check for any server in the "srv" chain */ { LDAPConn *lc; - LDAPServer *ls; + LDAPURLDesc *ls; for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) { - if ( lc->lconn_server->lsrv_host != NULL && - ls->lsrv_host != NULL && strcasecmp( - ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0 - && ls->lsrv_port == lc->lconn_server->lsrv_port ) { + for ( ls = srv; ls != NULL; ls = ls->lud_next ) { + if ( lc->lconn_server->lud_host != NULL && + ls->lud_host != NULL && strcasecmp( + ls->lud_host, lc->lconn_server->lud_host ) == 0 + && ls->lud_port == lc->lconn_server->lud_port ) { return( lc ); } if ( !any ) { @@ -427,12 +390,12 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) if ( unbind ) { ldap_send_unbind( ld, lc->lconn_sb, NULL, NULL ); } - ldap_close_connection( lc->lconn_sb ); - ber_pvt_sb_destroy( lc->lconn_sb ); - if( lc->lconn_ber != NULL ) { - ber_free( lc->lconn_ber, 1 ); - } } + + if( lc->lconn_ber != NULL ) { + ber_free( lc->lconn_ber, 1 ); + } + prevlc = NULL; for ( tmplc = ld->ld_conns; tmplc != NULL; tmplc = tmplc->lconn_next ) { @@ -446,13 +409,20 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) } prevlc = tmplc; } - free_servers( lc->lconn_server ); + ldap_free_urllist( lc->lconn_server ); if ( lc->lconn_krbinstance != NULL ) { LDAP_FREE( lc->lconn_krbinstance ); } - if ( lc->lconn_sb != &ld->ld_sb ) { + if ( lc->lconn_sb != ld->ld_sb ) { ber_sockbuf_free( lc->lconn_sb ); } + if( lc->lconn_rebind_queue != NULL) { + int i; + for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++) { + LDAP_VFREE(lc->lconn_rebind_queue[i]); + } + LDAP_FREE( lc->lconn_rebind_queue); + } LDAP_FREE( lc ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: actually freed\n", 0, 0, 0 ); @@ -475,17 +445,33 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ) for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) { if ( lc->lconn_server != NULL ) { fprintf( stderr, "* host: %s port: %d%s\n", - ( lc->lconn_server->lsrv_host == NULL ) ? "(null)" - : lc->lconn_server->lsrv_host, - lc->lconn_server->lsrv_port, ( lc->lconn_sb == - &ld->ld_sb ) ? " (default)" : "" ); + ( lc->lconn_server->lud_host == NULL ) ? "(null)" + : lc->lconn_server->lud_host, + lc->lconn_server->lud_port, ( lc->lconn_sb == + ld->ld_sb ) ? " (default)" : "" ); } fprintf( stderr, " refcnt: %d status: %s\n", lc->lconn_refcnt, ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ? "NeedSocket" : ( lc->lconn_status == LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" ); - fprintf( stderr, " last used: %s\n", + fprintf( stderr, " last used: %s", ldap_pvt_ctime( &lc->lconn_lastused, timebuf )); + if( lc->lconn_rebind_inprogress ) { + fprintf( stderr, " rebind in progress\n"); + if( lc->lconn_rebind_queue != NULL) { + int i = 0; + for( ;lc->lconn_rebind_queue[i] != NULL; i++) { + int j = 0; + for( ;lc->lconn_rebind_queue[i][j] != 0; j++) { + fprintf( stderr, " queue %d entry %d - %s\n", + i, j, lc->lconn_rebind_queue[i][j]); + } + } + } else { + fprintf( stderr, " queue is empty\n"); + } + } + fprintf(stderr, "\n"); if ( !all ) { break; } @@ -505,11 +491,12 @@ ldap_dump_requests_and_responses( LDAP *ld ) } for ( ; lr != NULL; lr = lr->lr_next ) { fprintf( stderr, " * msgid %d, origid %d, status %s\n", - lr->lr_msgid, lr->lr_origid, ( lr->lr_status == - LDAP_REQST_INPROGRESS ) ? "InProgress" : + lr->lr_msgid, lr->lr_origid, + ( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" : ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" : ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" : - "Writing" ); + ( lr->lr_status == LDAP_REQST_WRITING) ? "Writing" : + ( lr->lr_status == LDAP_REQST_COMPLETED ? "Request Completed" : "Invalid Status")); fprintf( stderr, " outstanding referrals %d, parent count %d\n", lr->lr_outrefcnt, lr->lr_parentcnt ); } @@ -578,25 +565,202 @@ ldap_free_request( LDAP *ld, LDAPRequest *lr ) LDAP_FREE( lr ); } - -static void -free_servers( LDAPServer *srvlist ) +/* + * Chase v3 referrals + * + * Parameters: + * (IN) ld = LDAP connection handle + * (IN) lr = LDAP Request structure + * (IN) refs = array of pointers to referral strings that we will chase + * The array will be free'd by this function when no longer needed + * (OUT) errstrp = Place to return a string of referrals which could not be followed + * (OUT) hadrefp = 1 if sucessfully followed referral + * + * Return value - number of referrals followed + */ +LIBLDAP_F(int) +ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, char **errstrp, int *hadrefp ) { - LDAPServer *nextsrv; + char *unfollowed; + int unfollowedcnt = 0; + LDAPRequest *origreq; + LDAPURLDesc *srv = NULL; + BerElement *ber; + char **refarray = NULL; + LDAPConn *lc; + int rc, count, i, j; + LDAPreqinfo rinfo; + + ld->ld_errno = LDAP_SUCCESS; /* optimistic */ + *hadrefp = 0; + + Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 ); + + unfollowed = NULL; + rc = count = 0; - while ( srvlist != NULL ) { - nextsrv = srvlist->lsrv_next; - if ( srvlist->lsrv_dn != NULL ) { - LDAP_FREE( srvlist->lsrv_dn ); + /* If no referrals in array, return */ + if ( (refs == NULL) || ( (refs)[0] == NULL) ) { + rc = 0; + goto done; } - if ( srvlist->lsrv_host != NULL ) { - LDAP_FREE( srvlist->lsrv_host ); + + /* Check for hop limit exceeded */ + if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { + Debug( LDAP_DEBUG_ANY, + "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); + ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED; + rc = -1; + goto done; } - LDAP_FREE( srvlist ); - srvlist = nextsrv; - } -} + /* find original request */ + for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { + ; + } + + refarray = refs; + refs = NULL; + /* parse out & follow referrals */ + for( i=0; refarray[i] != NULL; i++) { + /* Parse the referral URL */ + if (( rc = ldap_url_parse( refarray[i], &srv)) != LDAP_SUCCESS) { + ld->ld_errno = rc; + rc = -1; + goto done; + } + + /* treat ldap://hostpart and ldap://hostpart/ the same */ + if ( srv->lud_dn && srv->lud_dn[0] == '\0' ) { + LDAP_FREE( srv->lud_dn ); + srv->lud_dn = NULL; + } + + /* check connection for re-bind in progress */ + if (( lc = find_connection( ld, srv, 1 )) != NULL ) { + if( lc->lconn_rebind_inprogress) { + /* We are already chasing a referral or search reference and a + * bind on that connection is in progress. We must queue + * referrals on that connection, so we don't get a request + * going out before the bind operation completes. This happens + * if two search references come in one behind the other + * for the same server with different contexts. + */ + Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals: queue referral \"%s\"\n", + refarray[i], 0, 0); + if( lc->lconn_rebind_queue == NULL ) { + /* Create a referral list */ + if( (lc->lconn_rebind_queue = (char ***)LDAP_MALLOC( sizeof(void *) * 2)) == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + rc = -1; + goto done; + } + lc->lconn_rebind_queue[0] = refarray; + lc->lconn_rebind_queue[1] = NULL; + refarray = NULL; + } else { + /* Count how many referral arrays we already have */ + for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) { + ; + } + /* Add the new referral to the list */ + if( (lc->lconn_rebind_queue = (char ***)LDAP_REALLOC( + lc->lconn_rebind_queue, sizeof(void *) * (j + 2))) == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + rc = -1; + goto done; + } + lc->lconn_rebind_queue[j] = refarray; + lc->lconn_rebind_queue[j+1] = NULL; + refarray = NULL; + } + /* We have queued the referral/reference, now just return */ + rc = 0; + *hadrefp = 1; + count = 1; /* Pretend we already followed referral */ + goto done; + } + } + /* Re-encode the request with the new starting point of the search. + * Note: In the future we also need to replace the filter if one + * was provided with the search reference + */ + if (( ber = re_encode_request( ld, origreq->lr_ber, + ++ld->ld_msgid, &srv->lud_dn, &rinfo.ri_request )) == NULL ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + rc = -1; + goto done; + } + + Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referral: msgid %d, url \"%s\"\n", + lr->lr_msgid, refarray[i], 0); + + /* Send the new request to the server - may require a bind */ + rinfo.ri_msgid = origreq->lr_origid; + rinfo.ri_url = refarray[i]; + if ( (rc = ldap_send_server_request( ld, ber, ld->ld_msgid, + origreq, srv, NULL, &rinfo )) < 0 ) { + /* Failure, try next referral in the list */ + Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%s)\n", + refarray[i], ldap_err2string( ld->ld_errno ), 0); + unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i]); + ldap_free_urllist(srv); + srv = NULL; + } else { + /* Success, no need to try this referral list further */ + rc = 0; + ++count; + *hadrefp = 1; + + /* check if there is a queue of referrals that came in during bind */ + if( lc == NULL) { + if (( lc = find_connection( ld, srv, 1 )) == NULL ) { + ld->ld_errno = LDAP_OPERATIONS_ERROR; + rc = -1; + goto done; + } + } + + if( lc->lconn_rebind_queue != NULL) { + /* Release resources of previous list */ + LDAP_VFREE(refarray); + refarray = NULL; + ldap_free_urllist(srv); + srv = NULL; + + /* Pull entries off end of queue so list always null terminated */ + for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) { + ; + } + refarray = lc->lconn_rebind_queue[j-1]; + lc->lconn_rebind_queue[j-1] = NULL; + /* we pulled off last entry from queue, free queue */ + if ( j == 1 ) { + LDAP_FREE( lc->lconn_rebind_queue); + lc->lconn_rebind_queue = NULL; + } + /* restart the loop the with new referral list */ + i = -1; + continue; + } + break; /* referral followed, break out of for loop */ + } + } /* end for loop */ +done: + LDAP_VFREE(refarray); + ldap_free_urllist(srv); + LDAP_FREE( *errstrp ); + + if( rc == 0) { + *errstrp = NULL; + LDAP_FREE( unfollowed ); + return count; + } else { + ld->ld_errno = LDAP_REFERRAL; + *errstrp = unfollowed; + return rc; + } +} /* * XXX merging of errors in this routine needs to be improved @@ -605,13 +769,11 @@ int ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ) { int rc, count, len, newdn; -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - int ldapref; -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ char *p, *ports, *ref, *tmpref, *refdn, *unfollowed; LDAPRequest *origreq; - LDAPServer *srv; + LDAPURLDesc *srv; BerElement *ber; + LDAPreqinfo rinfo; Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 ); @@ -655,9 +817,6 @@ ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ) /* parse out & follow referrals */ for ( ref = p; rc == 0 && ref != NULL; ref = p ) { -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - ldapref = 0; -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ if (( p = strchr( ref, '\n' )) != NULL ) { *p++ = '\0'; @@ -665,22 +824,16 @@ ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ) p = NULL; } + ldap_pvt_hex_unescape( ref ); len = strlen( ref ); + + /* FIXME: we should use the URL Parser */ + if ( len > LDAP_LDAP_REF_STR_LEN && strncasecmp( ref, LDAP_LDAP_REF_STR, LDAP_LDAP_REF_STR_LEN ) == 0 ) { Debug( LDAP_DEBUG_TRACE, "chasing LDAP referral: <%s>\n", ref, 0, 0 ); -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - ldapref = 1; -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ tmpref = ref + LDAP_LDAP_REF_STR_LEN; -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - } else if ( len > LDAP_DX_REF_STR_LEN && strncasecmp( ref, - LDAP_DX_REF_STR, LDAP_DX_REF_STR_LEN ) == 0 ) { - Debug( LDAP_DEBUG_TRACE, - "chasing DX referral: <%s>\n", ref, 0, 0 ); - tmpref = ref + LDAP_DX_REF_STR_LEN; -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ } else { Debug( LDAP_DEBUG_TRACE, "ignoring unknown referral <%s>\n", ref, 0, 0 ); @@ -689,50 +842,55 @@ ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ) continue; } + /* copy the complete referral for rebind process */ + rinfo.ri_url = LDAP_STRDUP( ref ); + *hadrefp = 1; + if (( refdn = strchr( tmpref, '/' )) != NULL ) { *refdn++ = '\0'; - newdn = 1; + newdn = refdn[0] != '?' && refdn[0] != '\0'; + if( !newdn ) refdn = NULL; } else { newdn = 0; } if (( ber = re_encode_request( ld, origreq->lr_ber, - ++ld->ld_msgid, &refdn )) == NULL ) { + ++ld->ld_msgid, &refdn, &rinfo.ri_request )) == NULL ) { return( -1 ); } -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - if ( ldapref ) { -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ - if (( srv = (LDAPServer *)LDAP_CALLOC( 1, - sizeof( LDAPServer ))) == NULL ) { + if (( srv = (LDAPURLDesc *)LDAP_CALLOC( 1, + sizeof( LDAPURLDesc ))) == NULL ) { ber_free( ber, 1 ); ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } - if (( srv->lsrv_host = LDAP_STRDUP( tmpref )) == NULL ) { + if (( srv->lud_scheme = LDAP_STRDUP("ldap")) == NULL ) { LDAP_FREE( (char *)srv ); ber_free( ber, 1 ); ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } - if (( ports = strchr( srv->lsrv_host, ':' )) != NULL ) { + if (( srv->lud_host = LDAP_STRDUP( tmpref )) == NULL ) { + LDAP_FREE( (char *)srv ); + ber_free( ber, 1 ); + ld->ld_errno = LDAP_NO_MEMORY; + return( -1 ); + } + + if (( ports = strchr( srv->lud_host, ':' )) != NULL ) { *ports++ = '\0'; - srv->lsrv_port = atoi( ports ); + srv->lud_port = atoi( ports ); } else { - srv->lsrv_port = ldap_int_global_options.ldo_defport; + srv->lud_port = (LDAP_INT_GLOBAL_OPT())->ldo_defport; } -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - } else { - srv = dn2servers( ld, tmpref ); - } -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ + rinfo.ri_msgid = origreq->lr_origid; if ( srv != NULL && ldap_send_server_request( ld, ber, ld->ld_msgid, - lr, srv, NULL, 1 ) >= 0 ) { + lr, srv, NULL, &rinfo ) >= 0 ) { ++count; } else { Debug( LDAP_DEBUG_ANY, @@ -740,6 +898,10 @@ ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp ) ldap_err2string( ld->ld_errno ), 0, 0 ); rc = ldap_append_referral( ld, &unfollowed, ref ); } + LDAP_FREE( rinfo.ri_url); + + if (srv != NULL) + ldap_free_urllist(srv); if ( !newdn && refdn != NULL ) { LDAP_FREE( refdn ); @@ -786,13 +948,12 @@ ldap_append_referral( LDAP *ld, char **referralsp, char *s ) static BerElement * -re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp ) +re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp, int *type ) { /* * XXX this routine knows way too much about how the lber library works! */ ber_int_t along; - ber_len_t len; ber_tag_t tag; ber_int_t ver; int rc; @@ -806,31 +967,34 @@ re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp ) tmpber = *origber; /* - * all LDAP requests are sequences that start with a message id, - * followed by a sequence that is tagged with the operation code + * all LDAP requests are sequences that start with a message id. + * For all except delete, this is followed by a sequence that is + * tagged with the operation code. For delete, the provided DN + * is not wrapped by a sequence. */ - if ( ber_scanf( &tmpber, "{i", /*}*/ &along ) != LDAP_TAG_MSGID || - ( tag = ber_skip_tag( &tmpber, &len )) == LBER_DEFAULT ) { - ld->ld_errno = LDAP_DECODING_ERROR; + rc = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag ); + + if ( rc == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } - if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) { - return( NULL ); - } + assert( tag != 0); + if ( tag == LDAP_REQ_BIND ) { + /* bind requests have a version number before the DN & other stuff */ + rc = ber_scanf( &tmpber, "{ia" /*}*/, &ver, &orig_dn ); - /* bind requests have a version number before the DN & other stuff */ - if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, &ver ) == - LBER_DEFAULT ) { - ld->ld_errno = LDAP_DECODING_ERROR; - ber_free( ber, 1 ); - return( NULL ); + } else if ( tag == LDAP_REQ_DELETE ) { + /* delete requests don't have a DN wrapping sequence */ + rc = ber_scanf( &tmpber, "a", &orig_dn ); + + } else { + rc = ber_scanf( &tmpber, "{a" /*}*/, &orig_dn ); } - /* the rest of the request is the DN followed by other stuff */ - if ( ber_get_stringa( &tmpber, &orig_dn ) == LBER_DEFAULT ) { - ber_free( ber, 1 ); - return( NULL ); + if( rc == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return NULL; } if ( *dnp == NULL ) { @@ -839,20 +1003,29 @@ re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp ) LDAP_FREE( orig_dn ); } + if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + if ( tag == LDAP_REQ_BIND ) { rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, *dnp ); + } else if ( tag == LDAP_REQ_DELETE ) { + rc = ber_printf( ber, "{its}", msgid, tag, *dnp ); } else { rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, *dnp ); } if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } - if ( ber_write( ber, tmpber.ber_ptr, ( tmpber.ber_end - - tmpber.ber_ptr ), 0 ) != ( tmpber.ber_end - tmpber.ber_ptr ) || - ber_printf( ber, /*{{*/ "}}" ) == -1 ) { + if ( tag != LDAP_REQ_DELETE && ( + ber_write(ber, tmpber.ber_ptr, ( tmpber.ber_end - tmpber.ber_ptr ), 0) + != ( tmpber.ber_end - tmpber.ber_ptr ) || + ber_printf( ber, /*{{*/ "}}" ) == -1 ) ) + { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); @@ -866,6 +1039,7 @@ re_encode_request( LDAP *ld, BerElement *origber, ber_int_t msgid, char **dnp ) } #endif /* LDAP_DEBUG */ + *type = tag; /* return request type */ return( ber ); } @@ -876,6 +1050,9 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ) LDAPRequest *lr; for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { + if( lr->lr_status == LDAP_REQST_COMPLETED ) { + continue; /* Skip completed requests */ + } if ( msgid == lr->lr_msgid ) { break; } @@ -885,86 +1062,3 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ) } -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS -static LDAPServer * -dn2servers( LDAP *ld, const char *dn ) /* dn can also be a domain.... */ -{ - char *p, *host, *server_dn, **dxs; - const char *domain; - int i, port; - LDAPServer *srvlist, *prevsrv, *srv; - - if (( domain = strrchr( dn, '@' )) != NULL ) { - ++domain; - } else { - domain = dn; - } - - if (( dxs = ldap_getdxbyname( domain )) == NULL ) { - ld->ld_errno = LDAP_NO_MEMORY; - return( NULL ); - } - - srvlist = NULL; - - for ( i = 0; dxs[ i ] != NULL; ++i ) { - port = ldap_int_global_options.ldo_defport; - server_dn = NULL; - if ( strchr( dxs[ i ], ':' ) == NULL ) { - host = dxs[ i ]; - } else if ( strlen( dxs[ i ] ) >= 7 && - strncmp( dxs[ i ], "ldap://", 7 ) == 0 ) { - host = dxs[ i ] + 7; - if (( p = strchr( host, ':' )) == NULL ) { - p = host; - } else { - *p++ = '\0'; - port = atoi( p ); - } - if (( p = strchr( p, '/' )) != NULL ) { - server_dn = ++p; - if ( *server_dn == '\0' ) { - server_dn = NULL; - } - } - } else { - host = NULL; - } - - if ( host != NULL ) { /* found a server we can use */ - if (( srv = (LDAPServer *)LDAP_CALLOC( 1, - sizeof( LDAPServer ))) == NULL ) { - free_servers( srvlist ); - srvlist = NULL; - break; /* exit loop & return */ - } - - /* add to end of list of servers */ - if ( srvlist == NULL ) { - srvlist = srv; - } else { - prevsrv->lsrv_next = srv; - } - prevsrv = srv; - - /* copy in info. */ - if (( srv->lsrv_host = LDAP_STRDUP( host )) == NULL || - ( server_dn != NULL && ( srv->lsrv_dn = - LDAP_STRDUP( server_dn )) == NULL )) { - free_servers( srvlist ); - srvlist = NULL; - break; /* exit loop & return */ - } - srv->lsrv_port = port; - } - } - - ldap_value_free( dxs ); - - if ( srvlist == NULL ) { - ld->ld_errno = LDAP_SERVER_DOWN; - } - - return( srvlist ); -} -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index a47e0577e9..475effc9d5 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -1,11 +1,29 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions * Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. + */ +/*--- + * This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Modification to OpenLDAP source by Novell, Inc. + * April 2000 sfs Add code to process V3 referrals and search results * * result.c - wait for an ldap result */ @@ -114,7 +132,7 @@ ldap_result( if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { LDAPMessage *tmp; - if ( all == 0 + if ( all == LDAP_MSG_ONE || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE /* LDAPv3 */ && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) @@ -138,14 +156,17 @@ ldap_result( } if ( lastlm == NULL ) { - ld->ld_responses = (all == 0 && lm->lm_chain != NULL + ld->ld_responses = (all == LDAP_MSG_ONE && lm->lm_chain != NULL ? lm->lm_chain : lm->lm_next); } else { - lastlm->lm_next = (all == 0 && lm->lm_chain != NULL + lastlm->lm_next = (all == LDAP_MSG_ONE && lm->lm_chain != NULL ? lm->lm_chain : lm->lm_next); } - if ( all == 0 ) + if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) + { + lm->lm_chain->lm_next = lm->lm_next; lm->lm_chain = NULL; + } lm->lm_next = NULL; *result = lm; @@ -197,7 +218,8 @@ wait4msg( } #endif /* LDAP_DEBUG */ for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - if ( ber_pvt_sb_data_ready(lc->lconn_sb) ) { + if ( ber_sockbuf_ctrl( lc->lconn_sb, + LBER_SB_OPT_DATA_READY, NULL ) ) { rc = try_read1msg( ld, msgid, all, lc->lconn_sb, lc, result ); break; @@ -276,10 +298,15 @@ try_read1msg( ber_tag_t tag; ber_len_t len; int foundit = 0; - LDAPRequest *lr; + LDAPRequest *lr, *tmplr; BerElement tmpber; int rc, refer_cnt, hadref, simple_request; ber_int_t lderr; + /* + * v3ref = flag for V3 referral / search reference + * 0 = not a ref, 1 = sucessfully chased ref, -1 = pass ref to application + */ + int v3ref; assert( ld != NULL ); assert( lc != NULL ); @@ -335,6 +362,7 @@ try_read1msg( /* if it's been abandoned, toss it */ if ( ldap_abandoned( ld, id ) ) { ber_free( ber, 1 ); + Debug( LDAP_DEBUG_ANY, "abandoned\n", 0, 0, 0); return( -2 ); /* continue looking */ } @@ -353,10 +381,10 @@ try_read1msg( return( -1 ); } - Debug( LDAP_DEBUG_TRACE, "ldap_read: %s msgid %ld, original id %ld\n", + Debug( LDAP_DEBUG_TRACE, "ldap_read: message type %s msgid %ld, original id %ld\n", ( tag == LDAP_RES_SEARCH_ENTRY ) ? "entry" : ( tag == LDAP_RES_SEARCH_REFERENCE ) ? "reference" : "result", - (long) id, (long) lr->lr_origid ); + (long) lr->lr_msgid, (long) lr->lr_origid ); id = lr->lr_origid; refer_cnt = 0; @@ -364,12 +392,96 @@ try_read1msg( rc = -2; /* default is to keep looking (no response found) */ lr->lr_res_msgtype = tag; - if ( tag != LDAP_RES_SEARCH_ENTRY ) { + /* + * This code figures out if we are going to chase a + * referral / search reference, or pass it back to the application + */ + v3ref = 0; /* Assume not a V3 search reference or referral */ + if( (tag != LDAP_RES_SEARCH_ENTRY) && (ld->ld_version > LDAP_VERSION2) ) { + BerElement tmpber = *ber; /* struct copy */ + char **refs = NULL; + + if( tag == LDAP_RES_SEARCH_REFERENCE) { + /* This is a V3 search reference */ + /* Assume we do not chase the reference, but pass it to application */ + v3ref = -1; + if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || + (lr->lr_parent != NULL) ) + { + /* Get the referral list */ + if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + } else { + /* Note: refs arrary is freed by ldap_chase_v3referrals */ + refer_cnt = ldap_chase_v3referrals( ld, lr, refs, + &lr->lr_res_error, &hadref ); + if ( refer_cnt > 0 ) { /* sucessfully chased reference */ + /* If haven't got end search, set chasing referrals */ + if( lr->lr_status != LDAP_REQST_COMPLETED) { + lr->lr_status = LDAP_REQST_CHASINGREFS; + Debug( LDAP_DEBUG_TRACE, + "read1msg: search ref chased, mark request chasing refs, id = %d\n", + lr->lr_msgid, 0, 0); + } + v3ref = 1; /* We sucessfully chased the reference */ + } + } + } + } else { + /* Check for V3 referral */ + ber_len_t len; + if ( ber_scanf( &tmpber, "{iaa",/*}*/ &lderr, + &lr->lr_res_matched, &lr->lr_res_error ) + != LBER_ERROR ) { + /* Check if V3 referral */ + if( ber_peek_tag( &tmpber, &len) == LDAP_TAG_REFERRAL ) { + /* We have a V3 referral, assume we cannot chase it */ + v3ref = -1; + if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) + || (lr->lr_parent != NULL) ) + { + v3ref = -1; /* Assume referral not chased and return it to app */ + /* Get the referral list */ + if( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) { + rc = LDAP_DECODING_ERROR; + lr->lr_status = LDAP_REQST_COMPLETED; + Debug( LDAP_DEBUG_TRACE, + "read1msg: referral decode error, mark request completed, id = %d\n", + lr->lr_msgid, 0, 0); + } else { + /* Chase the referral + * Note: refs arrary is freed by ldap_chase_v3referrals + */ + refer_cnt = ldap_chase_v3referrals( ld, lr, refs, + &lr->lr_res_error, &hadref ); + lr->lr_status = LDAP_REQST_COMPLETED; + Debug( LDAP_DEBUG_TRACE, + "read1msg: referral chased, mark request completed, id = %d\n", + lr->lr_msgid, 0, 0); + if( refer_cnt > 0) { + v3ref = 1; /* Referral successfully chased */ + } + } + } + } + } + } + } + + /* All results that just return a status, i.e. don't return data + * go through the following code. This code also chases V2 referrals + * and checks if all referrals have been chased. + */ + if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref > -1) ) { + /* For a v3 search referral/reference, only come here if already chased it */ if ( ld->ld_version >= LDAP_VERSION2 && ( lr->lr_parent != NULL || LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ) ) { tmpber = *ber; /* struct copy */ + if ( v3ref == 1 ) { + ; /* V3 search reference or V3 referral sucessfully chased */ + } else if ( ber_scanf( &tmpber, "{iaa}", &lderr, &lr->lr_res_matched, &lr->lr_res_error ) != LBER_ERROR ) { @@ -377,6 +489,9 @@ try_read1msg( /* referrals are in error string */ refer_cnt = ldap_chase_referrals( ld, lr, &lr->lr_res_error, &hadref ); + lr->lr_status = LDAP_REQST_COMPLETED; + Debug( LDAP_DEBUG_TRACE, + "read1msg: V2 referral chased, mark request completed, id = %d\n", lr->lr_msgid, 0, 0); } /* save errno, message, and matched string */ @@ -405,7 +520,7 @@ Debug( LDAP_DEBUG_TRACE, if ( refer_cnt < 0 ) { return( -1 ); /* fatal error */ } - lr->lr_status = LDAP_REQST_CHASINGREFS; + lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */ } else { if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { /* request without any referrals */ @@ -416,6 +531,9 @@ Debug( LDAP_DEBUG_TRACE, ber = NULL; } + lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */ + Debug( LDAP_DEBUG_TRACE, + "read1msg: mark request completed, id = %d\n", lr->lr_msgid, 0, 0); while ( lr->lr_parent != NULL ) { merge_error_info( ld, lr->lr_parent, lr ); @@ -425,7 +543,15 @@ Debug( LDAP_DEBUG_TRACE, } } - if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { + /* Check if all requests are finished, lr is now parent */ + for(tmplr=lr ; tmplr != NULL; tmplr=tmplr->lr_refnext) { + if( tmplr->lr_status != LDAP_REQST_COMPLETED) { + break; + } + } + + /* This is the parent request if the request has referrals */ + if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL && tmplr == NULL ) { id = lr->lr_msgid; tag = lr->lr_res_msgtype; Debug( LDAP_DEBUG_ANY, "request %ld done\n", @@ -474,9 +600,10 @@ lr->lr_res_matched ? lr->lr_res_matched : "" ); /* is this the one we're looking for? */ if ( msgid == LDAP_RES_ANY || id == msgid ) { - if ( all == 0 + if ( all == LDAP_MSG_ONE || (new->lm_msgtype != LDAP_RES_SEARCH_RESULT - && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) { + && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY + && new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) ) { *result = new; ld->ld_errno = LDAP_SUCCESS; return( tag ); @@ -515,8 +642,9 @@ lr->lr_res_matched ? lr->lr_res_matched : "" ); (long) new->lm_msgid, (long) new->lm_msgtype, 0 ); /* part of a search response - add to end of list of entries */ - for ( tmp = l; tmp->lm_chain != NULL && - tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY; + for ( tmp = l; (tmp->lm_chain != NULL) && + ((tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY) || + (tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE)); tmp = tmp->lm_chain ) ; /* NULL */ tmp->lm_chain = new; @@ -643,7 +771,7 @@ int ldap_msgtype( LDAPMessage *lm ) { assert( lm != NULL ); - return ( lm == NULL ) ? lm->lm_msgtype : -1; + return ( lm != NULL ) ? lm->lm_msgtype : -1; } @@ -652,7 +780,7 @@ ldap_msgid( LDAPMessage *lm ) { assert( lm != NULL ); - return ( lm == NULL ) ? lm->lm_msgid : -1; + return ( lm != NULL ) ? lm->lm_msgid : -1; } @@ -761,14 +889,16 @@ cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ) int rc; ber_tag_t tag; ber_len_t len; + ber_socket_t sd; - if ( ! ber_pvt_sb_data_ready(&ld->ld_sb) ) { + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + if ( sd != AC_SOCKET_INVALID ) { /* restored from ldap_select1() in result.c version 1.24 */ fd_set readfds; if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); FD_ZERO( &readfds ); - FD_SET( ber_pvt_sb_get_desc(&ld->ld_sb), &readfds ); + FD_SET( sd, &readfds ); rc = select( ldap_int_tblsize, &readfds, 0, 0, timeout ); if ( rc == -1 || rc == 0 ) { @@ -779,7 +909,7 @@ cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ) } /* get the next message */ - if ( (tag = ber_get_next( &ld->ld_sb, &len, ber )) + if ( (tag = ber_get_next( ld->ld_sb, &len, ber )) != LDAP_TAG_MESSAGE ) { ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : LDAP_LOCAL_ERROR); diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index a397288c4d..1243454d76 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -10,7 +10,7 @@ * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND * krbv42ldap [1] OCTET STRING * krbv42dsa [2] OCTET STRING #endif @@ -32,18 +32,20 @@ #include #include #include +#include #include "ldap-int.h" /* - * ldap_sasl_bind - bind to the ldap server (and X.500). The dn, mechanism, and - * credentials of the entry to which to bind are supplied. The message id - * of the request initiated is provided upon successful (LDAP_SUCCESS) return. + * ldap_sasl_bind - bind to the ldap server (and X.500). + * The dn (usually NULL), mechanism, and credentials are provided. + * The message id of the request initiated is provided upon successful + * (LDAP_SUCCESS) return. * * Example: - * ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", - * "mechanism", "secret", NULL, NULL, &msgid ) + * ldap_sasl_bind( ld, NULL, "mechanism", + * cred, NULL, NULL, &msgid ) */ int @@ -70,15 +72,20 @@ ldap_sasl_bind( return ld->ld_errno; } - if( mechanism != LDAP_SASL_SIMPLE - && ld->ld_version < LDAP_VERSION3) - { + if( mechanism == LDAP_SASL_SIMPLE ) { + if( dn == NULL && cred != NULL ) { + /* use default binddn */ + dn = ld->ld_defbinddn; + } + + } else if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } - if ( dn == NULL ) + if ( dn == NULL ) { dn = ""; + } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { @@ -143,16 +150,6 @@ ldap_sasl_bind( return LDAP_SUCCESS; } -/* - * ldap_sasl_bind_s - bind to the ldap server (and X.500) using simple - * authentication. The dn and password of the entry to which to bind are - * supplied. LDAP_SUCCESS is returned upon success, the ldap error code - * otherwise. - * - * Example: - * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * "mechanism", "secret", NULL, NULL, &servercred ) - */ int ldap_sasl_bind_s( @@ -195,19 +192,21 @@ ldap_sasl_bind_s( rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 ); } - if( rc != LDAP_SUCCESS ) { + if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { ldap_msgfree( result ); return( rc ); } rc = ldap_result2error( ld, result, 1 ); - if( rc == LDAP_SUCCESS ) { + if ( rc == LDAP_SUCCESS || rc == LDAP_SASL_BIND_IN_PROGRESS ) { if( servercredp != NULL ) { *servercredp = scredp; + scredp = NULL; } + } - } else if (scredp != NULL ) { + if ( scredp != NULL ) { ber_bvfree(scredp); } @@ -216,18 +215,18 @@ ldap_sasl_bind_s( /* - * Parse BindResponse: - * - * BindResponse ::= [APPLICATION 1] SEQUENCE { - * COMPONENTS OF LDAPResult, - * serverSaslCreds [7] OCTET STRING OPTIONAL } - * - * LDAPResult ::= SEQUENCE { - * resultCode ENUMERATED, - * matchedDN LDAPDN, - * errorMessage LDAPString, - * referral [3] Referral OPTIONAL } - */ +* Parse BindResponse: +* +* BindResponse ::= [APPLICATION 1] SEQUENCE { +* COMPONENTS OF LDAPResult, +* serverSaslCreds [7] OCTET STRING OPTIONAL } +* +* LDAPResult ::= SEQUENCE { +* resultCode ENUMERATED, +* matchedDN LDAPDN, +* errorMessage LDAPString, +* referral [3] Referral OPTIONAL } +*/ int ldap_parse_sasl_bind_result( @@ -252,19 +251,18 @@ ldap_parse_sasl_bind_result( return LDAP_PARAM_ERROR; } - if(servercredp != NULL) { + if( servercredp != NULL ) { if( ld->ld_version < LDAP_VERSION2 ) { return LDAP_NOT_SUPPORTED; } *servercredp = NULL; } - if( res->lm_msgtype == LDAP_RES_BIND ) { + if( res->lm_msgtype != LDAP_RES_BIND ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } - errcode = LDAP_SUCCESS; scred = NULL; if ( ld->ld_error ) { @@ -280,55 +278,838 @@ ldap_parse_sasl_bind_result( ber = ber_dup( res->lm_ber ); + if( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + if ( ld->ld_version < LDAP_VERSION2 ) { tag = ber_scanf( ber, "{ia}", &errcode, &ld->ld_error ); + if( tag == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } + } else { ber_len_t len; tag = ber_scanf( ber, "{iaa" /*}*/, &errcode, &ld->ld_matched, &ld->ld_error ); - if( tag != LBER_ERROR ) { - tag = ber_peek_tag(ber, &len); + if( tag == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; } + tag = ber_peek_tag(ber, &len); + if( tag == LDAP_TAG_REFERRAL ) { /* skip 'em */ - tag = ber_scanf( ber, "x" ); - - if( tag != LBER_ERROR ) { - tag = ber_peek_tag(ber, &len); + if( ber_scanf( ber, "x" ) == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; } + + tag = ber_peek_tag(ber, &len); } - /* need to clean out misc items */ if( tag == LDAP_TAG_SASL_RES_CREDS ) { - tag = ber_scanf( ber, "O", &scred ); + if( ber_scanf( ber, "O", &scred ) == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } } } - if ( tag == LBER_ERROR ) { - errcode = LDAP_DECODING_ERROR; - } - - if( ber != NULL ) { - ber_free( ber, 0 ); - } + ber_free( ber, 0 ); - /* return */ - if ( errcode == LDAP_SUCCESS && servercredp != NULL ) { + if ( servercredp != NULL ) { *servercredp = scred; } else if ( scred != NULL ) { ber_bvfree( scred ); } + ld->ld_errno = errcode; + if ( freeit ) { ldap_msgfree( res ); } - ld->ld_errno = errcode; return( ld->ld_errno ); } + +#ifdef HAVE_CYRUS_SASL +/* +* Various Cyrus SASL related stuff. +*/ + +#define MAX_BUFF_SIZE 65536 +#define MIN_BUFF_SIZE 4096 + +static char * +array2str( char **a ) +{ + char *s, **v, *p; + int len = 0; + + for ( v = a; *v != NULL; v++ ) { + len += strlen( *v ) + 1; /* for a space */ + } + + if ( len == 0 ) { + return NULL; + } + + s = LDAP_MALLOC ( len ); /* last space holds \0 */ + + if ( s == NULL ) { + return NULL; + } + + p = s; + for ( v = a; *v != NULL; v++ ) { + int len; + + if ( v != a ) { + strncpy( p, " ", 1 ); + ++p; + } + len = strlen( *v ); + strncpy( p, *v, len ); + p += len; + } + + *p = '\0'; + + return s; +} + +int ldap_pvt_sasl_init( void ) +{ + /* XXX not threadsafe */ + static int sasl_initialized = 0; + + if ( sasl_initialized ) { + return 0; + } +#ifndef CSRIMALLOC + sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree ); +#endif /* CSRIMALLOC */ + + if ( sasl_client_init( NULL ) == SASL_OK ) { + sasl_initialized = 1; + return 0; + } + + return -1; +} + +/* + * SASL encryption support for LBER Sockbufs + */ + +struct sb_sasl_data { + sasl_conn_t *sasl_context; + Sockbuf_Buf sec_buf_in; + Sockbuf_Buf buf_in; + Sockbuf_Buf buf_out; +}; + +static int +sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct sb_sasl_data *p; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) + return -1; + p->sasl_context = (sasl_conn_t *)arg; + ber_pvt_sb_buf_init( &p->sec_buf_in ); + ber_pvt_sb_buf_init( &p->buf_in ); + ber_pvt_sb_buf_init( &p->buf_out ); + if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, MIN_BUFF_SIZE ) < 0 ) { + errno = ENOMEM; + return -1; + } + + sbiod->sbiod_pvt = p; + + return 0; +} + +static int +sb_sasl_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct sb_sasl_data *p; + + assert( sbiod != NULL ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + ber_pvt_sb_buf_destroy( &p->sec_buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_out ); + LBER_FREE( p ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static ber_len_t +sb_sasl_pkt_length( const char *buf, int debuglevel ) +{ + ber_len_t size; + long tmp; + + assert( buf != NULL ); + + tmp = *((long *)buf); + size = ntohl( tmp ); + + if ( size > MAX_BUFF_SIZE ) { + /* somebody is trying to mess me up. */ + ber_log_printf( LDAP_DEBUG_ANY, debuglevel, + "sb_sasl_pkt_length: received illegal packet length " + "of %lu bytes\n", (unsigned long)size ); + size = 16; /* this should lead to an error. */ +} + + return size + 4; /* include the size !!! */ +} + +/* Drop a processed packet from the input buffer */ +static void +sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel ) +{ + ber_slen_t len; + + len = sec_buf_in->buf_ptr - sec_buf_in->buf_end; + if ( len > 0 ) + memmove( sec_buf_in->buf_base, sec_buf_in->buf_base + + sec_buf_in->buf_end, len ); + + if ( len >= 4 ) { + sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base, + debuglevel); + } + else { + sec_buf_in->buf_end = 0; + } + sec_buf_in->buf_ptr = len; +} + +static ber_slen_t +sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_data *p; + ber_slen_t ret, bufptr; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + /* Are there anything left in the buffer? */ + ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); + bufptr = ret; + len -= ret; + + if ( len == 0 ) + return bufptr; + + ber_pvt_sb_buf_destroy( &p->buf_in ); + + /* Read the length of the packet */ + while ( p->sec_buf_in.buf_ptr < 4 ) { + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base, + 4 - p->sec_buf_in.buf_ptr ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* The new packet always starts at p->sec_buf_in.buf_base */ + ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base, + sbiod->sbiod_sb->sb_debug ); + + /* Grow the packet buffer if neccessary */ + if ( ( p->sec_buf_in.buf_size < ret ) && + ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) { + errno = ENOMEM; + return -1; + } + p->sec_buf_in.buf_end = ret; + + /* Did we read the whole encrypted packet? */ + while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { + /* No, we have got only a part of it */ + ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; + + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + + p->sec_buf_in.buf_ptr, ret ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* Decode the packet */ + ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base, + p->sec_buf_in.buf_end, &p->buf_in.buf_base, + (unsigned *)&p->buf_in.buf_end ); + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_read: failed to decode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + sb_sasl_drop_packet( &p->sec_buf_in, + sbiod->sbiod_sb->sb_debug ); + errno = EIO; + return -1; + } + + /* Drop the packet from the input buffer */ + sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug ); + + p->buf_in.buf_size = p->buf_in.buf_end; + + bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); + + return bufptr; +} + +static ber_slen_t +sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_data *p; + int ret; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + /* Are there anything left in the buffer? */ + if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + if ( ret <= 0 ) + return ret; + } + + /* now encode the next packet. */ + ber_pvt_sb_buf_destroy( &p->buf_out ); + ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base, + (unsigned *)&p->buf_out.buf_size ); + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_write: failed to encode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + return -1; + } + p->buf_out.buf_end = p->buf_out.buf_size; + + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + if ( ret <= 0 ) + return ret; + return len; +} + +static int +sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct sb_sasl_data *p; + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) + return 1; + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +Sockbuf_IO ldap_pvt_sockbuf_io_sasl = +{ + sb_sasl_setup, /* sbi_setup */ + sb_sasl_remove, /* sbi_remove */ + sb_sasl_ctrl, /* sbi_ctrl */ + sb_sasl_read, /* sbi_read */ + sb_sasl_write, /* sbi_write */ + NULL /* sbi_close */ +}; + +int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg ) +{ + /* don't install the stuff unless security has been negotiated */ + + if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, + &ldap_pvt_sockbuf_io_sasl ) ) + ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl, + LBER_SBIOD_LEVEL_APPLICATION, ctx_arg ); + + return LDAP_SUCCESS; +} + +static int +sasl_err2ldap( int saslerr ) +{ + int rc; + + switch (saslerr) { + case SASL_CONTINUE: + rc = LDAP_MORE_RESULTS_TO_RETURN; + break; + case SASL_OK: + rc = LDAP_SUCCESS; + break; + case SASL_FAIL: + rc = LDAP_LOCAL_ERROR; + break; + case SASL_NOMEM: + rc = LDAP_NO_MEMORY; + break; + case SASL_NOMECH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_BADAUTH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_NOAUTHZ: + rc = LDAP_PARAM_ERROR; + break; + case SASL_TOOWEAK: + case SASL_ENCRYPT: + rc = LDAP_AUTH_UNKNOWN; + break; + default: + rc = LDAP_LOCAL_ERROR; + break; + } + + assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); + return rc; +} + +int +ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) +{ + /* we need to query the server for supported mechs anyway */ + LDAPMessage *res, *e; + char *attrs[] = { "supportedSASLMechanisms", NULL }; + char **values, *mechlist; + int rc; + + Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_getmech\n", 0, 0, 0 ); + + rc = ldap_search_s( ld, NULL, LDAP_SCOPE_BASE, + NULL, attrs, 0, &res ); + + if ( rc != LDAP_SUCCESS ) { + return ld->ld_errno; + } + + e = ldap_first_entry( ld, res ); + if ( e == NULL ) { + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = LDAP_UNAVAILABLE; + } + return ld->ld_errno; + } + + values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); + if ( values == NULL ) { + ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE; + ldap_msgfree( res ); + return ld->ld_errno; + } + + mechlist = array2str( values ); + if ( mechlist == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + LDAP_VFREE( values ); + ldap_msgfree( res ); + return ld->ld_errno; + } + + LDAP_VFREE( values ); + ldap_msgfree( res ); + + *pmechlist = mechlist; + + return LDAP_SUCCESS; +} + +int +ldap_pvt_sasl_bind( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechs, + LDAP_CONST sasl_callback_t *callbacks, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + const char *mech; + int saslrc, rc; + sasl_ssf_t *ssf = NULL; + unsigned credlen; + struct berval ccred, *scred; + char *host; + sasl_interact_t *client_interact = NULL; + struct sockaddr_in sin; + socklen_t len; + sasl_security_properties_t secprops; + ber_socket_t sd; + + Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 ); + + /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ + if (ld->ld_version < LDAP_VERSION3) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + + if ( sd == AC_SOCKET_INVALID ) { + /* not connected yet */ + int rc = ldap_open_defconn( ld ); + + if( rc < 0 ) return ld->ld_errno; + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + } + + /* XXX this doesn't work with PF_LOCAL hosts */ + host = ldap_host_connected_to( ld->ld_sb ); + + if ( host == NULL ) { + ld->ld_errno = LDAP_UNAVAILABLE; + return ld->ld_errno; + } + + if ( ld->ld_sasl_context != NULL ) { + sasl_dispose( &ld->ld_sasl_context ); + } + + saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER, + &ld->ld_sasl_context ); + + LDAP_FREE( host ); + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + ld->ld_errno = sasl_err2ldap( saslrc ); + sasl_dispose( &ld->ld_sasl_context ); + return ld->ld_errno; + } + + len = sizeof( sin ); + if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) { + Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n", + 0, 0, 0 ); + ld->ld_errno = LDAP_OPERATIONS_ERROR; + return ld->ld_errno; + } + sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin ); + + len = sizeof( sin ); + if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) { + Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n", + 0, 0, 0 ); + ld->ld_errno = LDAP_OPERATIONS_ERROR; + return ld->ld_errno; + } + sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin ); + + memset( &secprops, '\0', sizeof( secprops ) ); + secprops.min_ssf = ld->ld_options.ldo_sasl_minssf; + secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf; + secprops.security_flags = SASL_SECURITY_LAYER; + secprops.maxbufsize = 65536; + sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops ); + + ccred.bv_val = NULL; + ccred.bv_len = 0; + + saslrc = sasl_client_start( ld->ld_sasl_context, + mechs, + NULL, + &client_interact, + &ccred.bv_val, + &credlen, + &mech ); + + ccred.bv_len = credlen; + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + ld->ld_errno = sasl_err2ldap( saslrc ); + sasl_dispose( &ld->ld_sasl_context ); + return ld->ld_errno; + } + + scred = NULL; + + do { + unsigned credlen; + sasl_interact_t *client_interact = NULL; + + rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred ); + if ( rc == LDAP_SUCCESS ) { + break; + } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) { + if ( ccred.bv_val != NULL ) { + LDAP_FREE( ccred.bv_val ); + } + sasl_dispose( &ld->ld_sasl_context ); + return ld->ld_errno; + } + + if ( ccred.bv_val != NULL ) { + LDAP_FREE( ccred.bv_val ); + ccred.bv_val = NULL; + } + + saslrc = sasl_client_step( ld->ld_sasl_context, + (scred == NULL) ? NULL : scred->bv_val, + (scred == NULL) ? 0 : scred->bv_len, + &client_interact, + &ccred.bv_val, + &credlen ); + + ccred.bv_len = credlen; + ber_bvfree( scred ); + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + ld->ld_errno = sasl_err2ldap( saslrc ); + sasl_dispose( &ld->ld_sasl_context ); + return ld->ld_errno; + } + } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); + + assert ( rc == LDAP_SUCCESS ); + + if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf ) + == SASL_OK && ssf && *ssf ) { + ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context ); + } + + return rc; +} + +/* based on sample/sample-client.c */ +static int +ldap_pvt_sasl_getsecret(sasl_conn_t *conn, + void *context, int id, sasl_secret_t **psecret) +{ + struct berval *passphrase = (struct berval *)context; + size_t len; + + if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) { + return SASL_BADPARAM; + } + + len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0; + + *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len ); + if ( *psecret == NULL ) { + return SASL_NOMEM; + } + + (*psecret)->len = passphrase->bv_len; + + if ( passphrase != NULL ) { + memcpy((*psecret)->data, passphrase->bv_val, len); + } + + return SASL_OK; +} + +static int +ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len) +{ + const char *value = (const char *)context; + + if ( result == NULL ) { + return SASL_BADPARAM; + } + + switch ( id ) { + case SASL_CB_USER: + case SASL_CB_AUTHNAME: + *result = value; + if ( len ) + *len = value ? strlen( value ) : 0; + break; + case SASL_CB_LANGUAGE: + *result = NULL; + if ( len ) + *len = 0; + break; + default: + return SASL_BADPARAM; + } + + return SASL_OK; +} + +int +ldap_pvt_sasl_get_option( LDAP *ld, int option, void *arg ) +{ + sasl_ssf_t *ssf; + + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_MINSSF: + *(int *)arg = ld->ld_options.ldo_sasl_minssf; + break; + case LDAP_OPT_X_SASL_MAXSSF: + *(int *)arg = ld->ld_options.ldo_sasl_maxssf; + break; + case LDAP_OPT_X_SASL_ACTSSF: + if ( ld->ld_sasl_context == NULL ) { + *(int *)arg = -1; + break; + } + if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, + (void **) &ssf ) != SASL_OK ) + { + return -1; + } + *(int *)arg = *ssf; + break; + default: + return -1; + } + return 0; +} + +int +ldap_pvt_sasl_set_option( LDAP *ld, int option, void *arg ) +{ + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_MINSSF: + ld->ld_options.ldo_sasl_minssf = *(int *)arg; + break; + case LDAP_OPT_X_SASL_MAXSSF: + ld->ld_options.ldo_sasl_maxssf = *(int *)arg; + break; + case LDAP_OPT_X_SASL_ACTSSF: + /* This option is read-only */ + default: + return -1; + } + return 0; +} + +/* + * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500) + * using SASL authentication. + * + * This routine attempts to authenticate the user referred by the + * authentication id using the provided password. An optional + * authorization identity may be provided. An DN is generally not + * provided [see AuthMethod]. + * + * If the mechanism negotiated does not require a password, the + * passwd field is ignored. [A callback mechanism should really + * be used]. + * + * LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. + * + * Examples: + * ldap_negotiated_sasl_bind_s( ld, NULL, + * NULL, NULL, NULL, + * NULL, NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "user@OPENLDAP.ORG", NULL, NULL, + * "GSSAPI", NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "manager", "dn:cn=user,dc=openldap,dc=org", NULL, + * "DIGEST-MD5", NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "root@OPENLDAP.ORG", "u:user@OPENLDAP.ORG", NULL, + * "GSSAPI", NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "manager", "dn:cn=user,dc=openldap,dc=org", NULL, + * "DIGEST-MD5", NULL, NULL, NULL ); + */ +int +ldap_negotiated_sasl_bind_s( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *authenticationId, + LDAP_CONST char *authorizationId, /* commonly NULL */ + LDAP_CONST char *saslMechanism, + struct berval *passPhrase, + LDAPControl **serverControls, + LDAPControl **clientControls) +{ + int n; + sasl_callback_t callbacks[4]; + int rc; + + Debug( LDAP_DEBUG_TRACE, "ldap_negotiated_sasl_bind_s\n", 0, 0, 0 ); + + if( saslMechanism == NULL || *saslMechanism == '\0' ) { + char *mechs; + rc = ldap_pvt_sasl_getmechs( ld, &mechs ); + + if( rc != LDAP_SUCCESS ) { + return rc; + } + + saslMechanism = mechs; + } + + /* SASL Authentication Identity */ + callbacks[n=0].id = SASL_CB_AUTHNAME; + callbacks[n].proc = ldap_pvt_sasl_getsimple; + callbacks[n].context = (void *)authenticationId; + + /* SASL Authorization Identity (userid) */ + if( authorizationId != NULL ) { + callbacks[++n].id = SASL_CB_USER; + callbacks[n].proc = ldap_pvt_sasl_getsimple; + callbacks[n].context = (void *)authorizationId; + } + + callbacks[++n].id = SASL_CB_PASS; + callbacks[n].proc = ldap_pvt_sasl_getsecret; + callbacks[n].context = (void *)passPhrase; + + callbacks[++n].id = SASL_CB_LIST_END; + callbacks[n].proc = NULL; + callbacks[n].context = NULL; + + assert( n * sizeof(sasl_callback_t) < sizeof(callbacks) ); + + rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks, + serverControls, clientControls); + + return rc; +} +#endif /* HAVE_CYRUS_SASL */ diff --git a/libraries/libldap/sbind.c b/libraries/libldap/sbind.c index 96d9a78433..ffcce85888 100644 --- a/libraries/libldap/sbind.c +++ b/libraries/libldap/sbind.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -16,7 +16,7 @@ * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING -- passwd -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND * krbv42ldap [1] OCTET STRING * krbv42dsa [2] OCTET STRING #endif diff --git a/libraries/libldap/schema.c b/libraries/libldap/schema.c index 78fbe8a3fa..cae5dfc660 100644 --- a/libraries/libldap/schema.c +++ b/libraries/libldap/schema.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1999-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -21,7 +21,6 @@ #include - static LDAP_CONST char * choose_name( char *names[], LDAP_CONST char *fallback ) { @@ -212,9 +211,9 @@ print_qdescrs(safe_string *ss, char **sa) */ if ( !sa[0] || ( sa[0] && sa[1] ) ) { print_whsp(ss); - print_literal(ss,"("); + print_literal(ss,"("/*)*/); print_qdescrlist(ss,sa); - print_literal(ss,")"); + print_literal(ss,/*(*/")"); return(print_whsp(ss)); } else { return(print_qdescr(ss,*sa)); @@ -245,10 +244,10 @@ static int print_oids(safe_string *ss, char **sa) { if ( sa[0] && sa[1] ) { - print_literal(ss,"("); + print_literal(ss,"("/*)*/); print_oidlist(ss,sa); print_whsp(ss); - return(print_literal(ss,")")); + return(print_literal(ss,/*(*/")")); } else { return(print_woid(ss,*sa)); } @@ -268,6 +267,25 @@ print_noidlen(safe_string *ss, char *s, int l) return(ret); } +static int +print_extensions(safe_string *ss, LDAP_SCHEMA_EXTENSION_ITEM **extensions) +{ + LDAP_SCHEMA_EXTENSION_ITEM **ext; + + if ( extensions ) { + print_whsp(ss); + for ( ext = extensions; *ext != NULL; ext++ ) { + print_literal(ss, (*ext)->lsei_name); + print_whsp(ss); + /* Should be print_qdstrings */ + print_qdescrs(ss, (*ext)->lsei_values); + print_whsp(ss); + } + } + + return 0; +} + char * ldap_syntax2str( const LDAP_SYNTAX * syn ) { @@ -278,7 +296,7 @@ ldap_syntax2str( const LDAP_SYNTAX * syn ) if ( !ss ) return NULL; - print_literal(ss,"("); + print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, syn->syn_oid); @@ -290,7 +308,10 @@ ldap_syntax2str( const LDAP_SYNTAX * syn ) } print_whsp(ss); - print_literal(ss,")"); + + print_extensions(ss, syn->syn_extensions); + + print_literal(ss,/*(*/ ")"); retstring = LDAP_STRDUP(safe_string_val(ss)); safe_string_free(ss); @@ -307,7 +328,7 @@ ldap_matchingrule2str( const LDAP_MATCHING_RULE * mr ) if ( !ss ) return NULL; - print_literal(ss,"("); + print_literal(ss,"(" /*)*/); print_whsp(ss); print_numericoid(ss, mr->mr_oid); @@ -336,7 +357,10 @@ ldap_matchingrule2str( const LDAP_MATCHING_RULE * mr ) } print_whsp(ss); - print_literal(ss,")"); + + print_extensions(ss, mr->mr_extensions); + + print_literal(ss,/*(*/")"); retstring = LDAP_STRDUP(safe_string_val(ss)); safe_string_free(ss); @@ -353,7 +377,7 @@ ldap_objectclass2str( const LDAP_OBJECT_CLASS * oc ) if ( !ss ) return NULL; - print_literal(ss,"("); + print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, oc->oc_oid); @@ -412,7 +436,10 @@ ldap_objectclass2str( const LDAP_OBJECT_CLASS * oc ) } print_whsp(ss); - print_literal(ss,")"); + + print_extensions(ss, oc->oc_extensions); + + print_literal(ss, /*(*/")"); retstring = LDAP_STRDUP(safe_string_val(ss)); safe_string_free(ss); @@ -429,7 +456,7 @@ ldap_attributetype2str( const LDAP_ATTRIBUTE_TYPE * at ) if ( !ss ) return NULL; - print_literal(ss,"("); + print_literal(ss,"("/*)*/); print_whsp(ss); print_numericoid(ss, at->at_oid); @@ -512,7 +539,10 @@ ldap_attributetype2str( const LDAP_ATTRIBUTE_TYPE * at ) } print_whsp(ss); - print_literal(ss,")"); + + print_extensions(ss, at->at_extensions); + + print_literal(ss,/*(*/")"); retstring = LDAP_STRDUP(safe_string_val(ss)); safe_string_free(ss); @@ -649,7 +679,7 @@ parse_whsp(const char **sp) /* Parse a sequence of dot-separated decimal strings */ static char * -parse_numericoid(const char **sp, int *code, const int allow_quoted) +parse_numericoid(const char **sp, int *code, const int flags) { char * res; const char * start = *sp; @@ -657,7 +687,7 @@ parse_numericoid(const char **sp, int *code, const int allow_quoted) int quoted = 0; /* Netscape puts the SYNTAX value in quotes (incorrectly) */ - if ( allow_quoted && **sp == '\'' ) { + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { quoted = 1; (*sp)++; start++; @@ -689,7 +719,7 @@ parse_numericoid(const char **sp, int *code, const int allow_quoted) } strncpy(res,start,len); res[len] = '\0'; - if ( allow_quoted && quoted ) { + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { if ( **sp == '\'' ) { (*sp)++; } else { @@ -805,12 +835,12 @@ parse_noidlen(const char **sp, int *code, int *len, int allow_quoted) if ( !sval ) { return NULL; } - if ( **sp == '{' ) { + if ( **sp == '{' /*}*/ ) { (*sp)++; *len = atoi(*sp); while ( isdigit(**sp) ) (*sp)++; - if ( **sp != '}' ) { + if ( **sp != /*{*/ '}' ) { *code = LDAP_SCHERR_UNEXPTOKEN; LDAP_FREE(sval); return NULL; @@ -936,23 +966,73 @@ parse_oids(const char **sp, int *code, const int allow_quoted) } } +static int +add_extension(LDAP_SCHEMA_EXTENSION_ITEM ***extensions, + char * name, char ** values) +{ + int n; + LDAP_SCHEMA_EXTENSION_ITEM **tmp, *ext; + + ext = LDAP_CALLOC(1, sizeof(LDAP_SCHEMA_EXTENSION_ITEM)); + if ( !ext ) + return 1; + ext->lsei_name = name; + ext->lsei_values = values; + + if ( !*extensions ) { + *extensions = + LDAP_CALLOC(2, sizeof(LDAP_SCHEMA_EXTENSION_ITEM *)); + if ( !*extensions ) + return 1; + n = 0; + } else { + for ( n=0; (*extensions)[n] != NULL; n++ ) + ; + tmp = LDAP_REALLOC(*extensions, + (n+2)*sizeof(LDAP_SCHEMA_EXTENSION_ITEM *)); + if ( !tmp ) + return 1; + *extensions = tmp; + } + (*extensions)[n] = ext; + (*extensions)[n+1] = NULL; + return 0; +} + +static void +free_extensions(LDAP_SCHEMA_EXTENSION_ITEM **extensions) +{ + LDAP_SCHEMA_EXTENSION_ITEM **ext; + + if ( extensions ) { + for ( ext = extensions; *ext != NULL; ext++ ) { + LDAP_FREE((*ext)->lsei_name); + LDAP_VFREE((*ext)->lsei_values); + LDAP_FREE(*ext); + } + LDAP_FREE(extensions); + } +} + void ldap_syntax_free( LDAP_SYNTAX * syn ) { LDAP_FREE(syn->syn_oid); LDAP_FREE(syn->syn_desc); + free_extensions(syn->syn_extensions); LDAP_FREE(syn); } LDAP_SYNTAX * -ldap_str2syntax( const char * s, int * code, const char ** errp ) +ldap_str2syntax( const char * s, int * code, const char ** errp, const int flags ) { int kind; const char * ss = s; char * sval; + int seen_name = 0; int seen_desc = 0; LDAP_SYNTAX * syn; - char ** ssdummy; + char ** ext_vals; if ( !s ) { *code = LDAP_SCHERR_EMPTY; @@ -1000,7 +1080,24 @@ ldap_str2syntax( const char * s, int * code, const char ** errp ) case TK_RIGHTPAREN: return syn; case TK_BAREWORD: - if ( !strcmp(sval,"DESC") ) { + if ( !strcmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_syntax_free(syn); + return(NULL); + } + seen_name = 1; + syn->syn_names = parse_qdescrs(&ss,code); + if ( !syn->syn_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_syntax_free(syn); + return NULL; + } + } else if ( !strcmp(sval,"DESC") ) { LDAP_FREE(sval); if ( seen_desc ) { *code = LDAP_SCHERR_DUPOPT; @@ -1021,11 +1118,18 @@ ldap_str2syntax( const char * s, int * code, const char ** errp ) syn->syn_desc = sval; parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { - LDAP_FREE(sval); /* Should be parse_qdstrings */ - ssdummy = parse_qdescrs(&ss, code); - if ( !ssdummy ) { + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_syntax_free(syn); + return NULL; + } + if ( add_extension(&syn->syn_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; + LDAP_FREE(sval); ldap_syntax_free(syn); return NULL; } @@ -1054,22 +1158,22 @@ ldap_matchingrule_free( LDAP_MATCHING_RULE * mr ) LDAP_VFREE(mr->mr_names); LDAP_FREE(mr->mr_desc); LDAP_FREE(mr->mr_syntax_oid); + free_extensions(mr->mr_extensions); LDAP_FREE(mr); } LDAP_MATCHING_RULE * -ldap_str2matchingrule( const char * s, int * code, const char ** errp ) +ldap_str2matchingrule( const char * s, int * code, const char ** errp, const int flags ) { int kind; const char * ss = s; char * sval; - int be_liberal = 1; /* Future additional argument */ int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; int seen_syntax = 0; LDAP_MATCHING_RULE * mr; - char ** ssdummy; + char ** ext_vals; const char * savepos; if ( !s ) { @@ -1096,9 +1200,9 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp ) parse_whsp(&ss); savepos = ss; - mr->mr_oid = parse_numericoid(&ss,code,be_liberal); + mr->mr_oid = parse_numericoid(&ss,code,flags); if ( !mr->mr_oid ) { - if ( be_liberal ) { + if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); @@ -1197,7 +1301,7 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp ) seen_syntax = 1; parse_whsp(&ss); mr->mr_syntax_oid = - parse_numericoid(&ss,code,be_liberal); + parse_numericoid(&ss,code,flags); if ( !mr->mr_syntax_oid ) { *errp = ss; ldap_matchingrule_free(mr); @@ -1205,11 +1309,18 @@ ldap_str2matchingrule( const char * s, int * code, const char ** errp ) } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { - LDAP_FREE(sval); /* Should be parse_qdstrings */ - ssdummy = parse_qdescrs(&ss, code); - if ( !ssdummy ) { + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_matchingrule_free(mr); + return NULL; + } + if ( add_extension(&mr->mr_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; *errp = ss; + LDAP_FREE(sval); ldap_matchingrule_free(mr); return NULL; } @@ -1242,16 +1353,16 @@ ldap_attributetype_free(LDAP_ATTRIBUTE_TYPE * at) LDAP_FREE(at->at_ordering_oid); LDAP_FREE(at->at_substr_oid); LDAP_FREE(at->at_syntax_oid); + free_extensions(at->at_extensions); LDAP_FREE(at); } LDAP_ATTRIBUTE_TYPE * -ldap_str2attributetype( const char * s, int * code, const char ** errp ) +ldap_str2attributetype( const char * s, int * code, const char ** errp, const int flags ) { int kind; const char * ss = s; char * sval; - int be_liberal = 1; /* Future additional argument */ int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; @@ -1262,7 +1373,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp ) int seen_syntax = 0; int seen_usage = 0; LDAP_ATTRIBUTE_TYPE * at; - char ** ssdummy; + char ** ext_vals; const char * savepos; if ( !s ) { @@ -1298,7 +1409,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp ) savepos = ss; at->at_oid = parse_numericoid(&ss,code,0); if ( !at->at_oid ) { - if ( be_liberal ) { + if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); @@ -1468,7 +1579,7 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp ) parse_noidlen(&ss, code, &at->at_syntax_len, - be_liberal); + flags); if ( !at->at_syntax_oid ) { *errp = ss; ldap_attributetype_free(at); @@ -1545,14 +1656,21 @@ ldap_str2attributetype( const char * s, int * code, const char ** errp ) LDAP_FREE(sval); parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { - LDAP_FREE(sval); /* Should be parse_qdstrings */ - ssdummy = parse_qdescrs(&ss, code); - if ( !ssdummy ) { + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { *errp = ss; ldap_attributetype_free(at); return NULL; } + if ( add_extension(&at->at_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; @@ -1580,16 +1698,16 @@ ldap_objectclass_free(LDAP_OBJECT_CLASS * oc) LDAP_VFREE(oc->oc_sup_oids); LDAP_VFREE(oc->oc_at_oids_must); LDAP_VFREE(oc->oc_at_oids_may); + free_extensions(oc->oc_extensions); LDAP_FREE(oc); } LDAP_OBJECT_CLASS * -ldap_str2objectclass( const char * s, int * code, const char ** errp ) +ldap_str2objectclass( const char * s, int * code, const char ** errp, const int flags ) { int kind; const char * ss = s; char * sval; - int be_liberal = 1; /* Future additional argument */ int seen_name = 0; int seen_desc = 0; int seen_obsolete = 0; @@ -1598,7 +1716,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp ) int seen_must = 0; int seen_may = 0; LDAP_OBJECT_CLASS * oc; - char ** ssdummy; + char ** ext_vals; const char * savepos; if ( !s ) { @@ -1634,7 +1752,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp ) savepos = ss; oc->oc_oid = parse_numericoid(&ss,code,0); if ( !oc->oc_oid ) { - if ( be_liberal ) { + if ( flags & LDAP_SCHEMA_ALLOW_ALL ) { /* Backtracking */ ss = savepos; kind = get_token(&ss,&sval); @@ -1737,7 +1855,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp ) seen_sup = 1; oc->oc_sup_oids = parse_oids(&ss, code, - be_liberal); + flags); if ( !oc->oc_sup_oids ) { *errp = ss; ldap_objectclass_free(oc); @@ -1809,14 +1927,21 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp ) } parse_whsp(&ss); } else if ( sval[0] == 'X' && sval[1] == '-' ) { - LDAP_FREE(sval); /* Should be parse_qdstrings */ - ssdummy = parse_qdescrs(&ss, code); - if ( !ssdummy ) { + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { *errp = ss; ldap_objectclass_free(oc); return NULL; } + if ( add_extension(&oc->oc_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } } else { *code = LDAP_SCHERR_UNEXPTOKEN; *errp = ss; @@ -1836,7 +1961,7 @@ ldap_str2objectclass( const char * s, int * code, const char ** errp ) } static char *const err2text[] = { - "", + "Success", "Out of memory", "Unexpected token", "Missing opening parenthesis", @@ -1852,7 +1977,7 @@ static char *const err2text[] = { char * ldap_scherr2str(int code) { - if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) { + if ( code < 0 || code >= (sizeof(err2text)/sizeof(char *)) ) { return "Unknown error"; } else { return err2text[code]; diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index f6d84d10d1..4f9984affe 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -98,12 +98,21 @@ ldap_search_ext( Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); /* - * if timeout is provided, use only tv_sec as timelimit. - * otherwise, use default. + * if timeout is provided, both tv_sec and tv_usec must + * be non-zero */ - timelimit = (timeout != NULL) - ? timeout->tv_sec - : -1; + if( timeout != NULL ) { + if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) { + return LDAP_PARAM_ERROR; + } + + /* timelimit must be non-zero if timeout is provided */ + timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1; + + } else { + /* no timeout, no timelimit */ + timelimit = -1; + } ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timelimit, sizelimit ); @@ -157,8 +166,16 @@ ldap_search_ext_s( return( rc ); } - if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) + rc = ldap_result( ld, msgid, 1, timeout, res ); + + if( rc <= 0 ) { + /* error(-1) or timeout(0) */ + return( ld->ld_errno ); + } + + if( rc == LDAP_RES_SEARCH_REFERENCE) { return( ld->ld_errno ); + } return( ldap_result2error( ld, *res, 0 ) ); } @@ -294,7 +311,11 @@ ldap_build_search_req( return( NULL ); } - filter = LDAP_STRDUP( filter_in ); + if( filter_in != NULL ) { + filter = LDAP_STRDUP( filter_in ); + } else { + filter = LDAP_STRDUP( "(objectclass=*)" ); + } err = put_filter( ber, filter ); LDAP_FREE( filter ); @@ -348,7 +369,6 @@ static int ldap_is_attr_oid ( const char *attr ) } return digit; - } static int ldap_is_attr_desc ( const char *attr ) @@ -412,12 +432,12 @@ static int hex2value( int c ) } char * -ldap_pvt_find_wildcard( char *s ) +ldap_pvt_find_wildcard( const char *s ) { for( ; *s != '\0' ; s++ ) { switch( *s ) { case '*': /* found wildcard */ - return s; + return (char *) s; case '\\': s++; /* skip over escape */ @@ -556,6 +576,10 @@ put_filter( BerElement *ber, char *str ) case '(': str++; parens++; + + /* skip spaces */ + while( isspace( *str ) ) str++; + switch ( *str ) { case '&': Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n", diff --git a/libraries/libldap/sort.c b/libraries/libldap/sort.c index c62961b773..5734022c58 100644 --- a/libraries/libldap/sort.c +++ b/libraries/libldap/sort.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -40,8 +40,8 @@ static int et_cmp LDAP_P(( const void *aa, const void *bb)); int ldap_sort_strcasecmp( - const void *a, - const void *b + LDAP_CONST void *a, + LDAP_CONST void *b ) { return( strcasecmp( *(char *const *)a, *(char *const *)b ) ); @@ -135,7 +135,7 @@ ldap_sort_entries( *ep = et[i].et_msg; ep = &(*ep)->lm_chain; - ldap_value_free( et[i].et_vals ); + LDAP_VFREE( et[i].et_vals ); } *ep = last; LDAP_FREE( (char *) et ); @@ -147,7 +147,7 @@ int ldap_sort_values( LDAP *ld, char **vals, - int (*cmp) (const void *, const void *) + int (*cmp) (LDAP_CONST void *, LDAP_CONST void *) ) { int nel; diff --git a/libraries/libldap/sortctrl.c b/libraries/libldap/sortctrl.c new file mode 100644 index 0000000000..3f04a20529 --- /dev/null +++ b/libraries/libldap/sortctrl.c @@ -0,0 +1,467 @@ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */ +/*--- + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND + * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT + * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS + * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" + * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION + * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP + * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT + * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + * + *---*/ + +#include "portable.h" + +#include +#include +#include +#include +#include + +#include "ldap-int.h" + +#define LDAP_MATCHRULE_IDENTIFIER 0x80L +#define LDAP_REVERSEORDER_IDENTIFIER 0x81L +#define LDAP_ATTRTYPES_IDENTIFIER 0x80L + + + +/* --------------------------------------------------------------------------- + countKeys + + Internal function to determine the number of keys in the string. + + keyString (IN) String of items separated by whitespace. + ---------------------------------------------------------------------------*/ + +static int countKeys(char *keyString) +{ + char *p = keyString; + int count = 0; + + for (;;) + { + while (isspace(*p)) /* Skip leading whitespace */ + p++; + + if (*p == '\0') /* End of string? */ + return count; + + count++; /* Found start of a key */ + + while (!isspace(*p)) /* Skip till next space or end of string. */ + if (*p++ == '\0') + return count; + } +} + + +/* --------------------------------------------------------------------------- + readNextKey + + Internal function to parse the next sort key in the string. + Allocate an LDAPSortKey structure and initialize it with + attribute name, reverse flag, and matching rule OID. + + Each sort key in the string has the format: + [whitespace][-]attribute[:[OID]] + + pNextKey (IN/OUT) Points to the next key in the sortkey string to parse. + The pointer is updated to point to the next character + after the sortkey being parsed. + + key (OUT) Points to the address of an LDAPSortKey stucture + which has been allocated by this routine and + initialized with information from the next sortkey. + ---------------------------------------------------------------------------*/ + +static int readNextKey( char **pNextKey, LDAPSortKey **key) +{ + char *p = *pNextKey; + int rev = 0; + char *attrStart; + int attrLen; + char *oidStart = NULL; + int oidLen = 0; + + /* Skip leading white space. */ + while (isspace(*p)) + p++; + + if (*p == '-') /* Check if the reverse flag is present. */ + { + rev=1; + p++; + } + + /* We're now positioned at the start of the attribute. */ + attrStart = p; + + /* Get the length of the attribute until the next whitespace or ":". */ + attrLen = strcspn(p, " \t:"); + p += attrLen; + + if (attrLen == 0) /* If no attribute name was present, quit. */ + return LDAP_PARAM_ERROR; + + if (*p == ':') + { + oidStart = ++p; /* Start of the OID, after the colon */ + oidLen = strcspn(p, " \t"); /* Get length of OID till next whitespace */ + p += oidLen; + } + + *pNextKey = p; /* Update argument to point to next key */ + + /* Allocate an LDAPSortKey structure */ + *key = LDAP_MALLOC(sizeof(LDAPSortKey)); + if (*key == NULL) return LDAP_NO_MEMORY; + + /* Allocate memory for the attribute and copy to it. */ + (*key)->attributeType = LDAP_MALLOC(attrLen+1); + if ((*key)->attributeType == NULL) { + LDAP_FREE(*key); + return LDAP_NO_MEMORY; + } + + strncpy((*key)->attributeType, attrStart, attrLen); + (*key)->attributeType[attrLen] = 0; + + /* If present, allocate memory for the OID and copy to it. */ + if (oidLen) { + (*key)->orderingRule = LDAP_MALLOC(oidLen+1); + if ((*key)->orderingRule == NULL) { + LDAP_FREE((*key)->attributeType); + LDAP_FREE(*key); + return LDAP_NO_MEMORY; + } + strncpy((*key)->orderingRule, oidStart, oidLen); + (*key)->orderingRule[oidLen] = 0; + + } else { + (*key)->orderingRule = NULL; + } + + (*key)->reverseOrder = rev; + + return LDAP_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + ldap_create_sort_keylist + + Create an array of pointers to LDAPSortKey structures, containing the + information specified by the string representation of one or more + sort keys. + + sortKeyList (OUT) Points to a null-terminated array of pointers to + LDAPSortKey structures allocated by this routine. + This memory SHOULD be freed by the calling program + using ldap_free_sort_keylist(). + + keyString (IN) Points to a string of one or more sort keys. + + ---------------------------------------------------------------------------*/ + +LIBLDAP_F(int) +ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString ) +{ + int numKeys, rc, i; + char *nextKey; + LDAPSortKey **keyList = NULL; + + if (( sortKeyList == NULL ) || ( keyString == NULL )) { + return LDAP_PARAM_ERROR; + } + *sortKeyList = NULL; + + /* Determine the number of sort keys so we can allocate memory. */ + if (( numKeys = countKeys(keyString)) == 0) { + return LDAP_PARAM_ERROR; + } + + /* Allocate the array of pointers. Initialize to NULL. */ + keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*)); + if ( keyList == NULL) return LDAP_NO_MEMORY; + + /* For each sort key in the string, create an LDAPSortKey structure + and add it to the list. + */ + nextKey = keyString; /* Points to the next key in the string */ + for (i=0; i < numKeys; i++) { + rc = readNextKey(&nextKey, &keyList[i]); + + if (rc != LDAP_SUCCESS) { + ldap_free_sort_keylist(keyList); + return rc; + } + } + + *sortKeyList = keyList; + return LDAP_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + ldap_free_sort_keylist + + Frees the sort key structures created by ldap_create_sort_keylist(). + Frees the memory referenced by the LDAPSortKey structures, + the LDAPSortKey structures themselves, and the array of pointers + to the structures. + + keyList (IN) Points to an array of pointers to LDAPSortKey structures. + ---------------------------------------------------------------------------*/ + +LIBLDAP_F(void) +ldap_free_sort_keylist ( LDAPSortKey **keyList ) +{ + int i; + LDAPSortKey *nextKeyp; + + if (keyList == NULL) return; + + i=0; + while ( 0 != (nextKeyp = keyList[i++]) ) { + if (nextKeyp->attributeType) { + LBER_FREE(nextKeyp->attributeType); + } + + if (nextKeyp->orderingRule != NULL) { + LBER_FREE(nextKeyp->orderingRule); + } + + LBER_FREE(nextKeyp); + } + + LBER_FREE(keyList); +} + + +/* --------------------------------------------------------------------------- + ldap_create_sort_control + + Create and encode the server-side sort control. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + keyList (IN) Points to a null-terminated array of pointers to + LDAPSortKey structures, containing a description of + each of the sort keys to be used. The description + consists of an attribute name, ascending/descending flag, + and an optional matching rule (OID) to use. + + isCritical (IN) 0 - Indicates the control is not critical to the operation. + non-zero - The control is critical to the operation. + + ctrlp (OUT) Returns a pointer to the LDAPControl created. This control + SHOULD be freed by calling ldap_control_free() when done. + + + Ber encoding + + SortKeyList ::= SEQUENCE OF SEQUENCE { + attributeType AttributeDescription, + orderingRule [0] MatchingRuleId OPTIONAL, + reverseOrder [1] BOOLEAN DEFAULT FALSE } + + ---------------------------------------------------------------------------*/ + +LIBLDAP_F( int ) +ldap_create_sort_control ( + LDAP *ld, + LDAPSortKey **keyList, + int isCritical, + LDAPControl **ctrlp ) +{ + int i; + BerElement *ber; + ber_tag_t tag; + + + if ( (ld == NULL) || (keyList == NULL) || (ctrlp == NULL) ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return( ld->ld_errno ); + } + + tag = ber_printf(ber, "{" /*}*/); + if (tag == LBER_ERROR) goto exit; + + for (i = 0; keyList[i] != NULL; i++) { + tag = ber_printf(ber, "{s" /*}*/, (keyList[i])->attributeType); + if (tag == LBER_ERROR) goto exit; + + if ((keyList[i])->orderingRule != NULL) { + tag = ber_printf( ber, "ts", + LDAP_MATCHRULE_IDENTIFIER, + (keyList[i])->orderingRule ); + + if( tag == LBER_ERROR ) goto exit; + } + + if ((keyList[i])->reverseOrder) { + tag = ber_printf(ber, "tb", + LDAP_REVERSEORDER_IDENTIFIER, + (keyList[i])->reverseOrder ); + + if( tag == LBER_ERROR ) goto exit; + } + + tag = ber_printf(ber, /*{*/ "}"); + if( tag == LBER_ERROR ) goto exit; + } + + tag = ber_printf(ber, /*{*/ "}"); + if( tag == LBER_ERROR ) goto exit; + + ld->ld_errno = ldap_int_create_control( LDAP_CONTROL_SORTREQUEST, + ber, isCritical, ctrlp); + + ber_free(ber, 1); + + return(ld->ld_errno); + +exit: + ber_free(ber, 1); + ld->ld_errno = LDAP_ENCODING_ERROR; + return(ld->ld_errno); +} + + +/* --------------------------------------------------------------------------- + ldap_parse_sort_control + + Decode the server-side sort control return information. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + ctrls (IN) The address of a NULL-terminated array of LDAPControl + structures, typically obtained by a call to + ldap_parse_result(). + + returnCode (OUT) This result parameter is filled in with the sort control + result code. This parameter MUST not be NULL. + + attribute (OUT) If an error occured the server may return a string + indicating the first attribute in the sortkey list + that was in error. If a string is returned, the memory + should be freed with ldap_memfree. If this parameter is + NULL, no string is returned. + + + Ber encoding for sort control + + SortResult ::= SEQUENCE { + sortResult ENUMERATED { + success (0), -- results are sorted + operationsError (1), -- server internal failure + timeLimitExceeded (3), -- timelimit reached before + -- sorting was completed + strongAuthRequired (8), -- refused to return sorted + -- results via insecure + -- protocol + adminLimitExceeded (11), -- too many matching entries + -- for the server to sort + noSuchAttribute (16), -- unrecognized attribute + -- type in sort key + inappropriateMatching (18), -- unrecognized or inappro- + -- priate matching rule in + -- sort key + insufficientAccessRights (50), -- refused to return sorted + -- results to this client + busy (51), -- too busy to process + unwillingToPerform (53), -- unable to sort + other (80) + }, + attributeType [0] AttributeDescription OPTIONAL } + ---------------------------------------------------------------------------*/ + +LIBLDAP_F( int ) +ldap_parse_sort_control( + LDAP *ld, + LDAPControl **ctrls, + unsigned long *returnCode, + char **attribute ) +{ + BerElement *ber; + LDAPControl *pControl; + int i; + ber_tag_t tag, berTag; + ber_len_t berLen; + + if (ld == NULL) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if (ctrls == NULL) { + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + } + + if (attribute) { + *attribute = NULL; + } + + /* Search the list of control responses for a sort control. */ + for (i=0; ctrls[i]; i++) { + pControl = ctrls[i]; + if (!strcmp(LDAP_CONTROL_SORTRESPONSE, pControl->ldctl_oid)) + goto foundSortControl; + } + + /* No sort control was found. */ + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + +foundSortControl: + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init(&pControl->ldctl_value); + + if (ber == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return(ld->ld_errno); + } + + /* Extract the result code from the control. */ + tag = ber_scanf(ber, "{e" /*}*/, returnCode); + + if( tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + + /* If caller wants the attribute name, and if it's present in the control, + extract the attribute name which caused the error. */ + if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen))) + { + tag = ber_scanf(ber, "ta", &berTag, attribute); + + if (tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + } + + ber_free(ber,1); + + ld->ld_errno = LDAP_SUCCESS; + return(ld->ld_errno); +} diff --git a/libraries/libldap/srchpref.c b/libraries/libldap/srchpref.c index adfca3de10..8f34f509f2 100644 --- a/libraries/libldap/srchpref.c +++ b/libraries/libldap/srchpref.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -111,13 +111,13 @@ ldap_init_searchprefs_buf( *solistp = prevso = NULL; - if ( next_line_tokens( &buf, &buflen, &toks ) != 2 || + if ( ldap_int_next_line_tokens( &buf, &buflen, &toks ) != 2 || strcasecmp( toks[ 0 ], "version" ) != 0 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } version = atoi( toks[ 1 ] ); - free_strarray( toks ); + LDAP_VFREE( toks ); if ( version != LDAP_SEARCHPREF_VERSION && version != LDAP_SEARCHPREF_VERSION_ZERO ) { return( LDAP_SEARCHPREF_ERR_VERSION ); @@ -250,14 +250,14 @@ read_next_searchobj( /* * Object type prompt comes first */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX ); } if (( so = (struct ldap_searchobj *)LDAP_CALLOC( 1, sizeof( struct ldap_searchobj ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); return( LDAP_SEARCHPREF_ERR_MEM ); } so->so_objtypeprompt = toks[ 0 ]; @@ -267,8 +267,8 @@ read_next_searchobj( * if this is post-version zero, options come next */ if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) { - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) < 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -279,14 +279,14 @@ read_next_searchobj( } } } - free_strarray( toks ); + LDAP_VFREE( toks ); } /* * "Fewer choices" prompt is next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -296,8 +296,8 @@ read_next_searchobj( /* * Filter prefix for "More Choices" searching is next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -307,8 +307,8 @@ read_next_searchobj( /* * "Fewer Choices" filter tag comes next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -318,8 +318,8 @@ read_next_searchobj( /* * Selection (disambiguation) attribute comes next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -329,8 +329,8 @@ read_next_searchobj( /* * Label for selection (disambiguation) attribute */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -340,8 +340,8 @@ read_next_searchobj( /* * Search scope is next */ - if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { - free_strarray( toks ); + if (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } @@ -355,22 +355,22 @@ read_next_searchobj( ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } - free_strarray( toks ); + LDAP_VFREE( toks ); /* * "More Choices" search option list comes next */ sa = &( so->so_salist ); - while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { + while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) { if ( tokcnt < 5 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } if (( *sa = ( struct ldap_searchattr * ) LDAP_CALLOC( 1, sizeof( struct ldap_searchattr ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_MEM ); } @@ -395,15 +395,15 @@ read_next_searchobj( * Match types are last */ sm = &( so->so_smlist ); - while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { + while (( tokcnt = ldap_int_next_line_tokens( bufp, blenp, &toks )) > 0 ) { if ( tokcnt < 2 ) { - free_strarray( toks ); + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_SYNTAX ); } if (( *sm = ( struct ldap_searchmatch * ) LDAP_CALLOC( 1, sizeof( struct ldap_searchmatch ))) == NULL ) { - free_strarray( toks ); + LDAP_VFREE( toks ); ldap_free_searchprefs( so ); return( LDAP_SEARCHPREF_ERR_MEM ); } diff --git a/libraries/libldap/string.c b/libraries/libldap/string.c index cd9994ad06..df8069ccaa 100644 --- a/libraries/libldap/string.c +++ b/libraries/libldap/string.c @@ -1,9 +1,14 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ +/* + * Locale-specific 1-byte character versions + * See utf-8.c for UTF-8 versions + */ + #include "portable.h" #include @@ -92,20 +97,6 @@ char *(ldap_pvt_strtok)( char *str, const char *delim, char **pos ) return str; } -char * -(ldap_pvt_strdup)( const char *s ) -{ - char *p; - size_t len = strlen( s ) + 1; - - if ( (p = (char *) malloc( len )) == NULL ) { - return( NULL ); - } - - memcpy( p, s, len ); - return( p ); -} - char * ldap_pvt_str2upper( char *str ) { diff --git a/libraries/libldap/test.c b/libraries/libldap/test.c index d52859042b..404ffbfe29 100644 --- a/libraries/libldap/test.c +++ b/libraries/libldap/test.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -229,38 +229,37 @@ get_modlist( char *prompt1, char *prompt2, char *prompt3 ) static int -bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp, - int freeit ) +bind_prompt( LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid) { static char dn[256], passwd[256]; + int authmethod; - if ( !freeit ) { -#ifdef HAVE_KERBEROS + printf("rebind for request=%d msgid=%ld url=%s\n", + request, (long) msgid, url ); + +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND getline( dn, sizeof(dn), stdin, "re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " ); - if (( *authmethodp = atoi( dn )) == 3 ) { - *authmethodp = LDAP_AUTH_KRBV4; + if (( authmethod = atoi( dn )) == 3 ) { + authmethod = LDAP_AUTH_KRBV4; } else { - *authmethodp |= 0x80; + authmethod |= 0x80; } -#else /* HAVE_KERBEROS */ - *authmethodp = LDAP_AUTH_SIMPLE; -#endif /* HAVE_KERBEROS */ +#else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ + authmethod = LDAP_AUTH_SIMPLE; +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ getline( dn, sizeof(dn), stdin, "re-bind dn? " ); strcat( dn, dnsuffix ); - *dnp = dn; - if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { + if ( authmethod == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { getline( passwd, sizeof(passwd), stdin, "re-bind password? " ); } else { passwd[0] = '\0'; } - *passwdp = passwd; - } - return( LDAP_SUCCESS ); + return ldap_bind_s( ld, dn, passwd, authmethod); } @@ -324,12 +323,12 @@ main( int argc, char **argv ) case 't': /* copy ber's to given file */ copyfname = strdup( optarg ); - copyoptions = LBER_TO_FILE; +/* copyoptions = LBER_TO_FILE; */ break; case 'T': /* only output ber's to given file */ copyfname = strdup( optarg ); - copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); +/* copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */ break; default: @@ -365,12 +364,12 @@ main( int argc, char **argv ) } if ( copyfname != NULL ) { - if ( (ld->ld_sb.sb_fd = open( copyfname, O_WRONLY | O_CREAT, + if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY | O_CREAT, 0600 )) == -1 ) { perror( copyfname ); exit ( EXIT_FAILURE ); } - ld->ld_sb.sb_options = copyoptions; + ld->ld_sb->sb_options = copyoptions; } bound = 0; @@ -413,13 +412,13 @@ main( int argc, char **argv ) break; case 'b': /* asynch bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND getline( line, sizeof(line), stdin, "method (0->simple, 1->krbv41, 2->krbv42)? " ); method = atoi( line ) | 0x80; -#else /* HAVE_KERBEROS */ +#else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ method = LDAP_AUTH_SIMPLE; -#endif /* HAVE_KERBEROS */ +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); @@ -439,7 +438,7 @@ main( int argc, char **argv ) break; case 'B': /* synch bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND getline( line, sizeof(line), stdin, "method 0->simple 1->krbv41 2->krbv42 3->krb? " ); method = atoi( line ); @@ -447,9 +446,9 @@ main( int argc, char **argv ) method = LDAP_AUTH_KRBV4; else method = method | 0x80; -#else /* HAVE_KERBEROS */ +#else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ method = LDAP_AUTH_SIMPLE; -#endif /* HAVE_KERBEROS */ +#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); @@ -764,33 +763,6 @@ main( int argc, char **argv ) LDAP_BOOL_ZERO(&ld->ld_options); -#ifdef STR_TRANSLATION - getline( line, sizeof(line), stdin, - "Automatic translation of T.61 strings (0=no, 1=yes)?" ); - if ( atoi( line ) == 0 ) { - ld->ld_lberoptions &= ~LBER_TRANSLATE_STRINGS; - } else { - ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS; -#ifdef LDAP_CHARSET_8859 - getline( line, sizeof(line), stdin, - "Translate to/from ISO-8859 (0=no, 1=yes?" ); - if ( atoi( line ) != 0 ) { - ldap_set_string_translators( ld, - ldap_8859_to_t61, - ldap_t61_to_8859 ); - } -#endif /* LDAP_CHARSET_8859 */ - } -#endif /* STR_TRANSLATION */ - -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS - getline( line, sizeof(line), stdin, - "Use DN & DNS to determine where to send requests (0=no, 1=yes)?" ); - if ( atoi( line ) != 0 ) { - LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_DNS); - } -#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_DNS */ - getline( line, sizeof(line), stdin, "Recognize and chase referrals (0=no, 1=yes)?" ); if ( atoi( line ) != 0 ) { diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 0a6f47fe22..9e49d64197 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file * * tls.c - Handle tls/ssl using SSLeay or OpenSSL. @@ -27,6 +27,8 @@ #ifdef HAVE_OPENSSL_SSL_H #include +#include +#include #elif defined( HAVE_SSL_H ) #include #endif @@ -39,30 +41,20 @@ static char *tls_opt_cacertdir = NULL; static int tls_opt_require_cert = 0; static char *tls_opt_ciphersuite = NULL; -#define HAS_TLS( sb ) ((sb)->sb_io==&tls_io) +#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ + (void *)&ldap_pvt_sockbuf_io_tls ) -static int tls_setup( Sockbuf *sb, void *arg ); -static int tls_remove( Sockbuf *sb ); -static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len ); -static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len ); -static int tls_close( Sockbuf *sb ); -static int tls_report_error( void ); - -static Sockbuf_IO tls_io= -{ - tls_setup, - tls_remove, - tls_read, - tls_write, - tls_close -}; +static void tls_report_error( void ); static void tls_info_cb( SSL *ssl, int where, int ret ); static int tls_verify_cb( int ok, X509_STORE_CTX *ctx ); static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ); -static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir ); +#if 0 /* Currently this is not used by anyone */ +static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); +#endif + static SSL_CTX *tls_def_ctx = NULL; #ifdef LDAP_R_COMPILE @@ -74,9 +66,9 @@ static ldap_pvt_thread_mutex_t tls_mutexes[CRYPTO_NUM_LOCKS]; static void tls_locking_cb( int mode, int type, const char *file, int line ) { if ( mode & CRYPTO_LOCK ) { - ldap_pvt_thread_mutex_lock( tls_mutexes+type ); + ldap_pvt_thread_mutex_lock( &tls_mutexes[type] ); } else { - ldap_pvt_thread_mutex_unlock( tls_mutexes+type ); + ldap_pvt_thread_mutex_unlock( &tls_mutexes[type] ); } } @@ -91,7 +83,7 @@ static void tls_init_threads( void ) int i; for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) { - ldap_pvt_thread_mutex_init( tls_mutexes+i ); + ldap_pvt_thread_mutex_init( &tls_mutexes[i] ); } CRYPTO_set_locking_callback( tls_locking_cb ); /* FIXME: the thread id should be added somehow... */ @@ -109,7 +101,8 @@ ldap_pvt_tls_init( void ) static int tls_initialized = 0; if ( tls_initialized ) - return -1; + return 0; + tls_initialized = 1; #ifdef LDAP_R_COMPILE tls_init_threads(); #endif @@ -147,25 +140,28 @@ ldap_pvt_tls_init_def_ctx( void ) tls_report_error(); goto error_exit; } - if ( !SSL_CTX_load_verify_locations( tls_def_ctx, - tls_opt_cacertfile, - tls_opt_cacertdir ) || - !SSL_CTX_set_default_verify_paths( tls_def_ctx ) ) { - Debug( LDAP_DEBUG_ANY, - "TLS: could not load verify locations (file:`%s',dir:`%s').\n", - tls_opt_cacertfile,tls_opt_cacertdir,0); - tls_report_error(); - goto error_exit; - } - calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir ); - if ( !calist ) { - Debug( LDAP_DEBUG_ANY, - "TLS: could not load client CA list (file:`%s',dir:`%s').\n", - tls_opt_cacertfile,tls_opt_cacertdir,0); - tls_report_error(); - goto error_exit; + if (tls_opt_cacertfile != NULL || tls_opt_cacertdir != NULL) { + if ( !SSL_CTX_load_verify_locations( tls_def_ctx, + tls_opt_cacertfile, + tls_opt_cacertdir ) + || !SSL_CTX_set_default_verify_paths( tls_def_ctx ) ) + { + Debug( LDAP_DEBUG_ANY, + "TLS: could not load verify locations (file:`%s',dir:`%s').\n", + tls_opt_cacertfile,tls_opt_cacertdir,0); + tls_report_error(); + goto error_exit; + } + calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir ); + if ( !calist ) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not load client CA list (file:`%s',dir:`%s').\n", + tls_opt_cacertfile,tls_opt_cacertdir,0); + tls_report_error(); + goto error_exit; + } + SSL_CTX_set_client_CA_list( tls_def_ctx, calist ); } - SSL_CTX_set_client_CA_list( tls_def_ctx, calist ); if ( tls_opt_keyfile && !SSL_CTX_use_PrivateKey_file( tls_def_ctx, tls_opt_keyfile, @@ -208,6 +204,10 @@ ldap_pvt_tls_init_def_ctx( void ) #endif return 0; error_exit: + if ( tls_def_ctx != NULL ) { + SSL_CTX_free( tls_def_ctx ); + tls_def_ctx = NULL; + } #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); #endif @@ -230,9 +230,8 @@ get_ca_list( char * bundle, char * dir ) } static SSL * -alloc_handle( Sockbuf *sb, void *ctx_arg ) +alloc_handle( void *ctx_arg ) { - int err; SSL_CTX *ctx; SSL *ssl; @@ -253,18 +252,277 @@ alloc_handle( Sockbuf *sb, void *ctx_arg ) if ( tls_opt_trace ) { SSL_set_info_callback( ssl, tls_info_cb ); } - sb->sb_iodata = ssl; - SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) ); return ssl; } -static void -update_flags( Sockbuf *sb, SSL * ssl ) +static int +update_flags( Sockbuf *sb, SSL * ssl, int rc ) +{ + int err = SSL_get_error(ssl, rc); + + sb->sb_trans_needs_read = 0; + sb->sb_trans_needs_write = 0; + if (err == SSL_ERROR_WANT_READ) + { + sb->sb_trans_needs_read = 1; + return 1; + } else if (err == SSL_ERROR_WANT_WRITE) + { + sb->sb_trans_needs_write = 1; + return 1; + } else if (err == SSL_ERROR_WANT_CONNECT) + { + return 1; + } + return 0; +} + +/* + * TLS support for LBER Sockbufs + */ + +struct tls_data { + SSL *ssl; + Sockbuf_IO_Desc *sbiod; +}; + +extern BIO_METHOD ldap_pvt_sb_bio_method; + +static int +sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct tls_data *p; + BIO *bio; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) + return -1; + + p->ssl = (SSL *)arg; + p->sbiod = sbiod; + bio = BIO_new( &ldap_pvt_sb_bio_method ); + bio->ptr = (void *)p; + SSL_set_bio( p->ssl, bio, bio ); + sbiod->sbiod_pvt = p; + return 0; +} + +static int +sb_tls_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct tls_data *p; + + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + p = (struct tls_data *)sbiod->sbiod_pvt; + SSL_free( p->ssl ); + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static int +sb_tls_close( Sockbuf_IO_Desc *sbiod ) +{ + struct tls_data *p; + + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + p = (struct tls_data *)sbiod->sbiod_pvt; + SSL_shutdown( p->ssl ); + return 0; +} + +static int +sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct tls_data *p; + + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + p = (struct tls_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_GET_SSL ) { + *((SSL **)arg) = p->ssl; + return 1; + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +static ber_slen_t +sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *p; + ber_slen_t ret; + int err; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct tls_data *)sbiod->sbiod_pvt; + + ret = SSL_read( p->ssl, (char *)buf, len ); +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); +#endif + err = SSL_get_error( p->ssl, ret ); + if (err == SSL_ERROR_WANT_READ ) { + sbiod->sbiod_sb->sb_trans_needs_read = 1; +#ifdef WIN32 + errno = EWOULDBLOCK; +#endif + } + else + sbiod->sbiod_sb->sb_trans_needs_read = 0; + return ret; +} + +static ber_slen_t +sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *p; + ber_slen_t ret; + int err; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct tls_data *)sbiod->sbiod_pvt; + + ret = SSL_write( p->ssl, (char *)buf, len ); +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); +#endif + err = SSL_get_error( p->ssl, ret ); + if (err == SSL_ERROR_WANT_WRITE ) { + sbiod->sbiod_sb->sb_trans_needs_write = 1; +#ifdef WIN32 + errno = EWOULDBLOCK; +#endif + } + else + sbiod->sbiod_sb->sb_trans_needs_write = 0; + return ret; +} + +Sockbuf_IO ldap_pvt_sockbuf_io_tls = +{ + sb_tls_setup, /* sbi_setup */ + sb_tls_remove, /* sbi_remove */ + sb_tls_ctrl, /* sbi_ctrl */ + sb_tls_read, /* sbi_read */ + sb_tls_write, /* sbi_write */ + sb_tls_close /* sbi_close */ +}; + +static int +sb_tls_bio_create( BIO *b ) { + b->init = 1; + b->num = 0; + b->ptr = NULL; + b->flags = 0; + return 1; +} + +static int +sb_tls_bio_destroy( BIO *b ) +{ + if ( b == NULL ) + return 0; + + b->ptr = NULL; /* sb_tls_remove() will free it */ + b->init = 0; + b->flags = 0; + return 1; +} + +static int +sb_tls_bio_read( BIO *b, char *buf, int len ) +{ + struct tls_data *p; + int ret; + + if ( buf == NULL || len <= 0 ) + return 0; + + p = (struct tls_data *)b->ptr; + + if ( p == NULL || p->sbiod == NULL ) + return 0; + + ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len ); + + BIO_clear_retry_flags( b ); + if ( ret < 0 && errno == EWOULDBLOCK ) + BIO_set_retry_read( b ); + + return ret; +} + +static int +sb_tls_bio_write( BIO *b, char *buf, int len ) +{ + struct tls_data *p; + int ret; + + if ( buf == NULL || len <= 0 ) + return 0; + + p = (struct tls_data *)b->ptr; + + if ( p == NULL || p->sbiod == NULL ) + return 0; + + ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, buf, len ); + + BIO_clear_retry_flags( b ); + if ( ret < 0 && errno == EWOULDBLOCK ) + BIO_set_retry_write( b ); + + return ret; +} + +static long +sb_tls_bio_ctrl( BIO *b, int cmd, long num, char *ptr ) +{ + if ( cmd == BIO_CTRL_FLUSH ) { + /* The OpenSSL library needs this */ + return 1; + } + return 0; +} + +static int +sb_tls_bio_gets( BIO *b, char *buf, int len ) { - sb->sb_trans_needs_read = SSL_want_read(ssl) ? 1 : 0; - sb->sb_trans_needs_write = SSL_want_write(ssl) ? 1 : 0; + return -1; } +static int +sb_tls_bio_puts( BIO *b, char *str ) +{ + return sb_tls_bio_write( b, str, strlen( str ) ); +} + +BIO_METHOD ldap_pvt_sb_bio_method = +{ + ( 100 | 0x400 ), /* it's a source/sink BIO */ + "sockbuf glue", + sb_tls_bio_write, + sb_tls_bio_read, + sb_tls_bio_puts, + sb_tls_bio_gets, + sb_tls_bio_ctrl, + sb_tls_bio_create, + sb_tls_bio_destroy +}; + /* * Call this to do a TLS connect on a sockbuf. ctx_arg can be * a SSL_CTX * or NULL, in which case the default ctx is used. @@ -279,38 +537,44 @@ update_flags( Sockbuf *sb, SSL * ssl ) */ int -ldap_pvt_tls_connect( Sockbuf *sb, void *ctx_arg ) +ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg ) { int err; SSL *ssl; if ( HAS_TLS( sb ) ) { - ssl = (SSL *) sb->sb_iodata; + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); } else { - ssl = alloc_handle( sb, ctx_arg ); + ssl = alloc_handle( ctx_arg ); if ( ssl == NULL ) return -1; - ber_pvt_sb_clear_io( sb ); - ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl ); +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); +#endif + ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); } err = SSL_connect( ssl ); - if ( err <= 0 ) { - if ( -#ifdef EWOULDBLOCK - (errno==EWOULDBLOCK) || +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); #endif -#ifdef EAGAIN - (errno==EAGAIN) || -#endif - (0)) { - update_flags( sb, ssl ); + if ( err <= 0 ) { + if ( update_flags( sb, ssl, err )) return 1; + if ((err = ERR_peek_error())) { + char buf[256]; + ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf)); } Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0); - ber_pvt_sb_clear_io( sb ); - ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL ); + ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls, + LBER_SBIOD_LEVEL_TRANSPORT ); +#ifdef LDAP_DEBUG + ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT ); +#endif return -1; } return 0; @@ -327,39 +591,76 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) SSL *ssl; if ( HAS_TLS( sb ) ) { - ssl = (SSL *) sb->sb_iodata; + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); } else { - ssl = alloc_handle( sb, ctx_arg ); + ssl = alloc_handle( ctx_arg ); if ( ssl == NULL ) return -1; - ber_pvt_sb_clear_io( sb ); - ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl ); +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); +#endif + ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); } err = SSL_accept( ssl ); +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); +#endif if ( err <= 0 ) { - if ( !SSL_want_nothing( ssl ) ) { - update_flags( sb, ssl ); + if ( update_flags( sb, ssl, err )) return 1; - } Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 ); tls_report_error(); - ber_pvt_sb_clear_io( sb ); - ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL ); + ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls, + LBER_SBIOD_LEVEL_TRANSPORT ); +#ifdef LDAP_DEBUG + ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT ); +#endif return -1; } return 0; } +int +ldap_pvt_tls_inplace ( Sockbuf *sb ) +{ + if ( HAS_TLS( sb ) ) + return(1); + return(0); +} + +void * +ldap_pvt_tls_sb_handle( Sockbuf *sb ) +{ + void *p; + + if (HAS_TLS( sb )) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p ); + return p; + } + return NULL; +} + +void * +ldap_pvt_tls_get_handle( LDAP *ld ) +{ + return ldap_pvt_tls_sb_handle( ld->ld_sb ); +} + const char * ldap_pvt_tls_get_peer( LDAP *ld ) { + return NULL; } const char * ldap_pvt_tls_get_peer_issuer( LDAP *ld ) { + return NULL; } int @@ -379,21 +680,19 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) ( strcasecmp( arg, "true" ) == 0 ) ); return ldap_pvt_tls_set_option( NULL, option, (void *) &i ); case LDAP_OPT_X_TLS: + i = -1; if ( strcasecmp( arg, "never" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_NEVER ); + i = LDAP_OPT_X_TLS_NEVER ; if ( strcasecmp( arg, "demand" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_DEMAND ); + i = LDAP_OPT_X_TLS_DEMAND ; if ( strcasecmp( arg, "allow" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_ALLOW ); + i = LDAP_OPT_X_TLS_ALLOW ; if ( strcasecmp( arg, "try" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_TRY ); + i = LDAP_OPT_X_TLS_TRY ; if ( strcasecmp( arg, "hard" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_HARD ); + i = LDAP_OPT_X_TLS_HARD ; + if (i >= 0) + return ldap_pvt_tls_set_option( lo, option, &i ); return -1; default: return -1; @@ -409,9 +708,9 @@ ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg ) break; case LDAP_OPT_X_TLS_CERT: if ( lo == NULL ) - arg = (void *) tls_def_ctx; + *(void **)arg = (void *) tls_def_ctx; else - arg = lo->ldo_tls_ctx; + *(void **)arg = lo->ldo_tls_ctx; break; case LDAP_OPT_X_TLS_CACERTFILE: *(char **)arg = tls_opt_cacertfile ? @@ -449,21 +748,28 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg ) case LDAP_OPT_X_TLS_ALLOW: case LDAP_OPT_X_TLS_TRY: case LDAP_OPT_X_TLS_HARD: - lo->ldo_tls_mode = *(int *)arg; - break; - default: - return -1; + if (lo != NULL) { + lo->ldo_tls_mode = *(int *)arg; + } + + return 0; } - break; + return -1; + case LDAP_OPT_X_TLS_CERT: - if ( lo == NULL ) + if ( lo == NULL ) { tls_def_ctx = (SSL_CTX *) arg; - else + + } else { lo->ldo_tls_ctx = arg; - break; + } + return 0; } - if ( lo != NULL ) + + if ( lo != NULL ) { return -1; + } + switch( option ) { case LDAP_OPT_X_TLS_CACERTFILE: if ( tls_opt_cacertfile ) free( tls_opt_cacertfile ); @@ -494,43 +800,21 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg ) return 0; } -static int -tls_setup( Sockbuf *sb, void *arg ) -{ - sb->sb_iodata = arg; - return 0; -} - -static int -tls_remove( Sockbuf *sb ) -{ - SSL_free( (SSL *) sb->sb_iodata ); - return 0; -} - -static ber_slen_t -tls_write( Sockbuf *sb, void *buf, ber_len_t sz ) -{ - int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz ); - - update_flags(sb, (SSL *)sb->sb_iodata ); - return ret; -} - -static ber_slen_t -tls_read( Sockbuf *sb, void *buf, ber_len_t sz ) +int +ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg ) { - int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz ); + /* + * Fortunately, the lib uses blocking io... + */ + if ( ldap_pvt_tls_connect( ld, sb, ctx_arg ) < 0 ) { + return LDAP_CONNECT_ERROR; + } - update_flags(sb, (SSL *)sb->sb_iodata ); - return ret; -} + /* FIXME: hostname of server must be compared with name in + * certificate.... + */ -static int -tls_close( Sockbuf *sb ) -{ - tcp_close( ber_pvt_sb_get_desc( sb ) ); - return 0; + return LDAP_SUCCESS; } /* Derived from openssl/apps/s_cb.c */ @@ -603,15 +887,15 @@ tls_verify_cb( int ok, X509_STORE_CTX *ctx ) sname ? sname : "-unknown-", iname ? iname : "-unknown-" ); if ( sname ) - free ( sname ); + CRYPTO_free ( sname ); if ( iname ) - free ( iname ); + CRYPTO_free ( iname ); - return 1; + return ok; } /* Inspired by ERR_print_errors in OpenSSL */ -static int +static void tls_report_error( void ) { unsigned long l; @@ -642,11 +926,13 @@ tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ) return tmp_rsa; } +#if 0 static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ) { return NULL; } +#endif #else static int dummy; diff --git a/libraries/libldap/tmplout.c b/libraries/libldap/tmplout.c index 8b480a3ef5..385312256f 100644 --- a/libraries/libldap/tmplout.c +++ b/libraries/libldap/tmplout.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -12,6 +12,7 @@ #include +#include #include #include @@ -477,11 +478,11 @@ do_entry2text_search( #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, - "objectClass=*", ocattrs, 0, &ldmp, NULL ); + NULL, ocattrs, 0, &ldmp, NULL ); else #endif /* LDAP_CONNECTIONLESS */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, - "objectClass=*", ocattrs, 0, &timeout, &ldmp ); + NULL, ocattrs, 0, &timeout, &ldmp ); if ( err == LDAP_SUCCESS ) { entry = ldap_first_entry( ld, ldmp ); @@ -510,11 +511,11 @@ do_entry2text_search( #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_CLDAP( ld )) - err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, NULL, fetchattrs, 0, &ldmp, NULL ); else #endif /* LDAP_CONNECTIONLESS */ - err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL, fetchattrs, 0, &timeout, &ldmp ); if ( freedn ) { @@ -900,7 +901,7 @@ time2text( char *ldtimestr, int dateonly ) return( fmterr ); } - memset( (char *)&t, 0, sizeof( struct tm )); + memset( (char *)&t, '\0', sizeof( struct tm )); p = ldtimestr; @@ -909,8 +910,17 @@ time2text( char *ldtimestr, int dateonly ) /* POSIX says tm_year should be year - 1900 */ t.tm_year = 100 * GET2BYTENUM( p ) - 1900; p += 2; + t.tm_year += GET2BYTENUM( p ); p += 2; + + } else { + /* came without a century */ + t.tm_year = GET2BYTENUM( p ); p += 2; + + /* Y2K hack - 2 digit years < 70 are 21st century */ + if( t.tm_year < 70 ) { + t.tm_year += 100; + } } - t.tm_year = GET2BYTENUM( p ); p += 2; t.tm_mon = GET2BYTENUM( p ) - 1; p += 2; t.tm_mday = GET2BYTENUM( p ); p += 2; diff --git a/libraries/libldap/tmpltest.c b/libraries/libldap/tmpltest.c index bbdae7fa1a..728724690d 100644 --- a/libraries/libldap/tmpltest.c +++ b/libraries/libldap/tmpltest.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ #include "portable.h" diff --git a/libraries/libldap/ufn.c b/libraries/libldap/ufn.c index 9d215cdec9..d5e1a5206b 100644 --- a/libraries/libldap/ufn.c +++ b/libraries/libldap/ufn.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -185,7 +185,7 @@ ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix, if ( err == -1 || err == LDAP_USER_CANCELLED ) { if ( dns != NULL ) { - ldap_value_free( dns ); + LDAP_VFREE( dns ); dns = NULL; } return( err ); @@ -198,7 +198,7 @@ ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix, goto tryagain; } else { if ( dns != NULL ) { - ldap_value_free( dns ); + LDAP_VFREE( dns ); dns = NULL; } return( err ); @@ -209,7 +209,7 @@ ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix, if ( phase == 1 ) phase++; if ( dns != NULL ) { - ldap_value_free( dns ); + LDAP_VFREE( dns ); dns = NULL; } } @@ -246,7 +246,7 @@ ldap_ufn_search_ct( attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); if ( ldap_count_entries( ld, *res ) > 0 ) { - ldap_value_free( ufncomp ); + LDAP_VFREE( ufncomp ); return( err ); } else { ldap_msgfree( *res ); @@ -255,21 +255,21 @@ ldap_ufn_search_ct( } if ( ld->ld_ufnprefix == NULL ) { - ldap_value_free( ufncomp ); + LDAP_VFREE( ufncomp ); return( err ); } /* if that failed, or < 2 components, use the prefix */ if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) { - ldap_value_free( ufncomp ); + LDAP_VFREE( ufncomp ); return( ld->ld_errno = LDAP_LOCAL_ERROR ); } for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ ) ; /* NULL */ if ( (pbuf = (char *) LDAP_MALLOC( strlen( ld->ld_ufnprefix ) + 1 )) == NULL ) { - ldap_value_free( ufncomp ); - ldap_value_free( prefixcomp ); + LDAP_VFREE( ufncomp ); + LDAP_VFREE( prefixcomp ); return( ld->ld_errno = LDAP_NO_MEMORY ); } @@ -293,8 +293,8 @@ ldap_ufn_search_ct( } } - ldap_value_free( ufncomp ); - ldap_value_free( prefixcomp ); + LDAP_VFREE( ufncomp ); + LDAP_VFREE( prefixcomp ); LDAP_FREE( pbuf ); return( err ); @@ -478,7 +478,8 @@ ldap_ufn_setprefix( LDAP *ld, LDAP_CONST char *prefix ) if ( ld->ld_ufnprefix != NULL ) LDAP_FREE( ld->ld_ufnprefix ); - ld->ld_ufnprefix = LDAP_STRDUP( prefix ); + ld->ld_ufnprefix = prefix == NULL + ? NULL : LDAP_STRDUP( prefix ); } int diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c index 852926f785..36810f3d8d 100644 --- a/libraries/libldap/unbind.c +++ b/libraries/libldap/unbind.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -37,6 +37,15 @@ ldap_unbind_ext( return ldap_ld_free( ld, 1, sctrls, cctrls ); } +int +ldap_unbind_ext_s( + LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + return ldap_unbind_ext( ld, sctrls, cctrls ); +} + int ldap_unbind( LDAP *ld ) { @@ -124,14 +133,9 @@ ldap_ld_free( ld->ld_selectinfo = NULL; } - if ( ld->ld_options.ldo_defbase != NULL ) { - LDAP_FREE( ld->ld_options.ldo_defbase ); - ld->ld_options.ldo_defbase = NULL; - } - - if ( ld->ld_options.ldo_defhost != NULL ) { - LDAP_FREE( ld->ld_options.ldo_defhost ); - ld->ld_options.ldo_defhost = NULL; + if ( ld->ld_options.ldo_defludp != NULL ) { + ldap_free_urllist( ld->ld_options.ldo_defludp ); + ld->ld_options.ldo_defludp = NULL; } if ( ld->ld_options.ldo_tm_api != NULL ) { @@ -144,7 +148,13 @@ ldap_ld_free( ld->ld_options.ldo_tm_net = NULL; } - ber_pvt_sb_destroy( &(ld->ld_sb) ); +#ifdef HAVE_CYRUS_SASL + if ( ld->ld_sasl_context != NULL ) { + sasl_dispose( &ld->ld_sasl_context ); + } +#endif + + ber_sockbuf_free( ld->ld_sb ); LDAP_FREE( (char *) ld ); diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c index b632c688f8..f604098c1a 100644 --- a/libraries/libldap/url.c +++ b/libraries/libldap/url.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -10,7 +10,7 @@ * LIBLDAP url.c -- LDAP URL (RFC 2255) related routines * * LDAP URLs look like this: - * ldap[s]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] + * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] * * where: * attributes is a comma separated list @@ -40,48 +40,98 @@ static const char* skip_url_prefix LDAP_P(( const char *url, int *enclosedp, - int *ldaps )); + const char **scheme )); +int ldap_pvt_url_scheme2proto( const char *scheme ) +{ + assert( scheme ); + + if( scheme == NULL ) { + return -1; + } + + if( strcmp("ldap", scheme) == 0 ) { + return LDAP_PROTO_TCP; + } + + if( strcmp("ldapi", scheme) == 0 ) { + return LDAP_PROTO_IPC; + } + + if( strcmp("ldaps", scheme) == 0 ) { + return LDAP_PROTO_TCP; + } + + return -1; +} + +int ldap_pvt_url_scheme2tls( const char *scheme ) +{ + assert( scheme ); + + if( scheme == NULL ) { + return -1; + } + + return strcmp("ldaps", scheme) == 0; +} int ldap_is_ldap_url( LDAP_CONST char *url ) { int enclosed; - int ldaps; + const char * scheme; if( url == NULL ) { return 0; } - if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) { + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } - return !ldaps; + return 1; } int ldap_is_ldaps_url( LDAP_CONST char *url ) { int enclosed; - int ldaps; + const char * scheme; if( url == NULL ) { return 0; } - if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) { + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { return 0; } - return ldaps; + return strcmp(scheme, "ldaps") == 0; +} + +int +ldap_is_ldapi_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return strcmp(scheme, "ldapi") == 0; } static const char* skip_url_prefix( const char *url, int *enclosedp, - int *ldaps ) + const char **scheme ) { /* * return non-zero if this looks like a LDAP URL; zero if not @@ -113,7 +163,7 @@ skip_url_prefix( if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { /* skip over "ldap://" prefix and return success */ p += LDAP_URL_PREFIX_LEN; - *ldaps = 0; + *scheme = "ldap"; return( p ); } @@ -121,7 +171,15 @@ skip_url_prefix( if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { /* skip over "ldaps://" prefix and return success */ p += LDAPS_URL_PREFIX_LEN; - *ldaps = 1; + *scheme = "ldaps"; + return( p ); + } + + /* check for "ldapi://" prefix */ + if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldapi://" prefix and return success */ + p += LDAPI_URL_PREFIX_LEN; + *scheme = "ldapi"; return( p ); } @@ -160,7 +218,8 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) LDAPURLDesc *ludp; char *p, *q; - int i, enclosed, ldaps; + int i, enclosed; + const char *scheme = NULL; const char *url_tmp; char *url; @@ -168,19 +227,29 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_ERR_PARAM; } +#ifndef LDAP_INT_IN_KERNEL + /* Global options may not be created yet + * We can't test if the global options are initialized + * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate + * the options and cause infinite recursion + */ Debug( LDAP_DEBUG_TRACE, "ldap_url_parse(%s)\n", url_in, 0, 0 ); +#endif *ludpp = NULL; /* pessimistic */ - url_tmp = skip_url_prefix( url_in, &enclosed, &ldaps ); + url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); if ( url_tmp == NULL ) { - return LDAP_URL_ERR_NOTLDAP; + return LDAP_URL_ERR_BADSCHEME; } + assert( scheme ); + /* make working copy of the remainder of the URL */ - if (( url = LDAP_STRDUP( url_tmp )) == NULL ) { - return( LDAP_URL_ERR_MEM ); + url = LDAP_STRDUP( url_tmp ); + if ( url == NULL ) { + return LDAP_URL_ERR_MEM; } if ( enclosed ) { @@ -202,17 +271,18 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_ERR_MEM; } + ludp->lud_next = NULL; ludp->lud_host = NULL; ludp->lud_port = 0; - ludp->lud_dn = NULL; - ludp->lud_attrs = NULL; - ludp->lud_filter = NULL; - ludp->lud_ldaps = ldaps; + ludp->lud_dn = NULL; + ludp->lud_attrs = NULL; + ludp->lud_filter = NULL; ludp->lud_scope = LDAP_SCOPE_BASE; + ludp->lud_filter = NULL; - ludp->lud_filter = LDAP_STRDUP("(objectClass=*)"); + ludp->lud_scheme = LDAP_STRDUP( scheme ); - if( ludp->lud_filter == NULL ) { + if ( ludp->lud_scheme == NULL ) { LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_MEM; @@ -226,7 +296,9 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) *p++ = '\0'; } - if (( q = strchr( url, ':' )) != NULL ) { + q = strchr( url, ':' ); + + if ( q != NULL ) { *q++ = '\0'; ldap_pvt_hex_unescape( q ); @@ -248,6 +320,36 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_ERR_MEM; } + /* + * Kludge. ldap://111.222.333.444:389??cn=abc,o=company + * + * On early Novell releases, search references/referrals were returned + * in this format, i.e., the dn was kind of in the scope position, + * but the required slash is missing. The whole thing is illegal syntax, + * but we need to account for it. Fortunately it can't be confused with + * anything real. + */ + if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { + q++; + /* ? immediately followed by question */ + if( *q == '?') { + q++; + if( *q != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( q ); + ludp->lud_dn = LDAP_STRDUP( q ); + } else { + ludp->lud_dn = LDAP_STRDUP( "" ); + } + + if( ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + } + } + if( p == NULL ) { LDAP_FREE( url ); *ludpp = ludp; @@ -414,6 +516,268 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_SUCCESS; } +LDAPURLDesc * +ldap_url_dup ( LDAPURLDesc *ludp ) +{ + LDAPURLDesc *dest; + + if ( ludp == NULL ) { + return NULL; + } + + dest = LDAP_MALLOC( sizeof(LDAPURLDesc) ); + if (dest == NULL) + return NULL; + + *dest = *ludp; + dest->lud_scheme = NULL; + dest->lud_host = NULL; + dest->lud_dn = NULL; + dest->lud_filter = NULL; + dest->lud_attrs = NULL; + dest->lud_exts = NULL; + dest->lud_next = NULL; + + if ( ludp->lud_scheme != NULL ) { + dest->lud_scheme = LDAP_STRDUP( ludp->lud_scheme ); + if (dest->lud_scheme == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_host != NULL ) { + dest->lud_host = LDAP_STRDUP( ludp->lud_host ); + if (dest->lud_host == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_dn != NULL ) { + dest->lud_dn = LDAP_STRDUP( ludp->lud_dn ); + if (dest->lud_dn == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_filter != NULL ) { + dest->lud_filter = LDAP_STRDUP( ludp->lud_filter ); + if (dest->lud_filter == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_attrs != NULL ) { + dest->lud_attrs = ldap_charray_dup( ludp->lud_attrs ); + if (dest->lud_attrs == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_exts != NULL ) { + dest->lud_exts = ldap_charray_dup( ludp->lud_exts ); + if (dest->lud_exts == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + return dest; +} + +LDAPURLDesc * +ldap_url_duplist (LDAPURLDesc *ludlist) +{ + LDAPURLDesc *dest, *tail, *ludp, *newludp; + + dest = NULL; + tail = NULL; + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + newludp = ldap_url_dup(ludp); + if (newludp == NULL) { + ldap_free_urllist(dest); + return NULL; + } + if (tail == NULL) + dest = newludp; + else + tail->lud_next = newludp; + tail = newludp; + } + return dest; +} + +int +ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) +{ + int i, rc; + LDAPURLDesc *ludp; + char **urls; + + *ludlist = NULL; + + if (url == NULL) + return LDAP_PARAM_ERROR; + + urls = ldap_str2charray((char *)url, ", "); + if (urls == NULL) + return LDAP_NO_MEMORY; + + /* count the URLs... */ + for (i = 0; urls[i] != NULL; i++) ; + /* ...and put them in the "stack" backward */ + while (--i >= 0) { + rc = ldap_url_parse( urls[i], &ludp ); + if ( rc != 0 ) { + ldap_charray_free(urls); + ldap_free_urllist(*ludlist); + *ludlist = NULL; + return rc; + } + ludp->lud_next = *ludlist; + *ludlist = ludp; + } + ldap_charray_free(urls); + return LDAP_SUCCESS; +} + +int +ldap_url_parsehosts (LDAPURLDesc **ludlist, const char *hosts ) +{ + int i; + LDAPURLDesc *ludp; + char **specs, *p; + + *ludlist = NULL; + + if (hosts == NULL) + return LDAP_PARAM_ERROR; + + specs = ldap_str2charray((char *)hosts, ", "); + if (specs == NULL) + return LDAP_NO_MEMORY; + + /* count the URLs... */ + for (i = 0; specs[i] != NULL; i++) /* EMPTY */; + + /* ...and put them in the "stack" backward */ + while (--i >= 0) { + ludp = LDAP_CALLOC( 1, sizeof(LDAPURLDesc) ); + if (ludp == NULL) { + ldap_charray_free(specs); + ldap_free_urllist(*ludlist); + *ludlist = NULL; + return LDAP_NO_MEMORY; + } + ludp->lud_host = specs[i]; + specs[i] = NULL; + p = strchr(ludp->lud_host, ':'); + if (p != NULL) { + *p++ = 0; + ldap_pvt_hex_unescape(p); + ludp->lud_port = atoi(p); + } + ldap_pvt_hex_unescape(ludp->lud_host); + ludp->lud_scheme = LDAP_STRDUP("ldap"); + ludp->lud_next = *ludlist; + *ludlist = ludp; + } + + /* this should be an array of NULLs now */ + ldap_charray_free(specs); + return LDAP_SUCCESS; +} + +char * +ldap_url_list2hosts (LDAPURLDesc *ludlist) +{ + LDAPURLDesc *ludp; + int size; + char *s, *p, buf[32]; /* big enough to hold a long decimal # (overkill) */ + + if (ludlist == NULL) + return NULL; + + /* figure out how big the string is */ + size = 1; /* nul-term */ + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + size += strlen(ludp->lud_host) + 1; /* host and space */ + if (ludp->lud_port != 0) + size += sprintf(buf, ":%d", ludp->lud_port); + } + s = LDAP_MALLOC(size); + if (s == NULL) + return NULL; + + p = s; + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + strcpy(p, ludp->lud_host); + p += strlen(ludp->lud_host); + if (ludp->lud_port != 0) + p += sprintf(p, ":%d", ludp->lud_port); + *p++ = ' '; + } + if (p != s) + p--; /* nuke that extra space */ + *p = 0; + return s; +} + +char * +ldap_url_list2urls( + LDAPURLDesc *ludlist ) +{ + LDAPURLDesc *ludp; + int size; + char *s, *p, buf[32]; /* big enough to hold a long decimal # (overkill) */ + + if (ludlist == NULL) + return NULL; + + /* figure out how big the string is */ + size = 1; /* nul-term */ + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + size += strlen(ludp->lud_scheme) + strlen(ludp->lud_host); + size += sizeof(":/// "); + + if (ludp->lud_port != 0) { + size += sprintf(buf, ":%d", ludp->lud_port); + } + } + + s = LDAP_MALLOC(size); + if (s == NULL) { + return NULL; + } + + p = s; + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + p += sprintf(p, "%s://%s", ludp->lud_scheme, ludp->lud_host); + if (ludp->lud_port != 0) + p += sprintf(p, ":%d", ludp->lud_port); + *p++ = '/'; + *p++ = ' '; + } + if (p != s) + p--; /* nuke that extra space */ + *p = 0; + return s; +} + +void +ldap_free_urllist( LDAPURLDesc *ludlist ) +{ + LDAPURLDesc *ludp, *next; + + for (ludp = ludlist; ludp != NULL; ludp = next) { + next = ludp->lud_next; + ldap_free_urldesc(ludp); + } +} void ldap_free_urldesc( LDAPURLDesc *ludp ) @@ -422,6 +786,10 @@ ldap_free_urldesc( LDAPURLDesc *ludp ) return; } + if ( ludp->lud_scheme != NULL ) { + LDAP_FREE( ludp->lud_scheme ); + } + if ( ludp->lud_host != NULL ) { LDAP_FREE( ludp->lud_host ); } @@ -453,7 +821,7 @@ ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) int err; LDAPURLDesc *ludp; BerElement *ber; - LDAPServer *srv = NULL; + LDAPreqinfo bind; if ( ldap_url_parse( url, &ludp ) != 0 ) { ld->ld_errno = LDAP_PARAM_ERROR; @@ -465,38 +833,19 @@ ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) -1, -1 ); if ( ber == NULL ) { - return( -1 ); - } - - err = 0; - - if ( ludp->lud_host != NULL || ludp->lud_port != 0 ) { - if (( srv = (LDAPServer *)LDAP_CALLOC( 1, sizeof( LDAPServer ))) - == NULL || ( srv->lsrv_host = LDAP_STRDUP( ludp->lud_host == - NULL ? ld->ld_defhost : ludp->lud_host )) == NULL ) { - if ( srv != NULL ) { - LDAP_FREE( srv ); - } - ld->ld_errno = LDAP_NO_MEMORY; - err = -1; - } else { - if ( ludp->lud_port == 0 ) { - srv->lsrv_port = ldap_int_global_options.ldo_defport; - } else { - srv->lsrv_port = ludp->lud_port; - } - } - } - - if ( err != 0 ) { - ber_free( ber, 1 ); + err = -1; } else { - err = ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, srv, - NULL, 1 ); + bind.ri_request = LDAP_REQ_SEARCH; + bind.ri_msgid = ld->ld_msgid; + bind.ri_url = (char *)url; + err = ldap_send_server_request( + ld, ber, ld->ld_msgid, NULL, + (ludp->lud_host != NULL || ludp->lud_port != 0) + ? ludp : NULL, + NULL, &bind ); } ldap_free_urldesc( ludp ); - return( err ); } @@ -547,9 +896,9 @@ void ldap_pvt_hex_unescape( char *s ) { /* - * Remove URL hex escapes from s... done in place. The basic concept for - * this routine is borrowed from the WWW library HTUnEscape() routine. - */ +* Remove URL hex escapes from s... done in place. The basic concept for +* this routine is borrowed from the WWW library HTUnEscape() routine. +*/ char *p; for ( p = s; *s != '\0'; ++s ) { diff --git a/libraries/libldap/utf-8.c b/libraries/libldap/utf-8.c new file mode 100644 index 0000000000..0d12f010a3 --- /dev/null +++ b/libraries/libldap/utf-8.c @@ -0,0 +1,461 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +/* + * Basic UTF-8 routines + * + * These routines are "dumb". Though they understand UTF-8, + * they don't grok Unicode. That is, they can push bits, + * but don't have a clue what the bits represent. That's + * good enough for use with the LDAP Client SDK. + * + * These routines are not optimized. + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include + +#include "ldap-int.h" +#include "ldap_defaults.h" + +#undef ISASCII +#define ISASCII(uc) ((uc) < 0x100) +#undef UCS4_INVALID +#define UCS4_INVALID 0x80000000U + +/* + * Basic UTF-8 routines + */ + +/* + * return the number of bytes required to hold the + * NULL-terminated UTF-8 string NOT INCLUDING the + * termination. + */ +ber_len_t ldap_utf8_bytes( const char * p ) +{ + ber_len_t bytes; + + for( bytes=0; p[bytes]; bytes++ ) { + /* EMPTY */ ; + } + + return bytes; +} + +ber_len_t ldap_utf8_chars( const char * p ) +{ + /* could be optimized and could check for invalid sequences */ + ber_len_t chars=0; + + for( ; *p ; LDAP_UTF8_INCR(p) ) { + chars++; + }; + + return chars; +} + +/* return offset to next character */ +int ldap_utf8_offset( const char * p ) +{ + return LDAP_UTF8_NEXT(p) - p; +} + +/* + * Returns length indicated by first byte. + * + * This function should use a table lookup. + */ +int ldap_utf8_charlen( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if ((c & 0xfe ) == 0xfc) { + return 6; + } + + if ((c & 0xfc ) == 0xf8) { + return 5; + } + + if ((c & 0xf8 ) == 0xf0) { + return 4; + } + + if ((c & 0xf0 ) == 0xe0) { + return 3; + } + + if ((c & 0xe0 ) == 0xc0) { + return 2; + } + + if ((c & 0x80 ) == 0x80) { + /* INVALID */ + return 0; + } + + return 1; +} + +/* conv UTF-8 to UCS-4, useful for comparisons */ +ldap_ucs4_t ldap_utf8_to_ucs4( const char * p ) +{ + const unsigned char *c = p; + ldap_ucs4_t ch; + int len, i; + static unsigned char mask[] = { + 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + + len = LDAP_UTF8_CHARLEN(p); + + if( len == 0 ) return UCS4_INVALID; + + ch = c[0] & mask[len]; + + for(i=1; i < len; i++) { + if ((c[i] & 0xc0) != 0x80) { + return UCS4_INVALID; + } + + ch <<= 6; + ch |= c[i] & 0x3f; + } + + return ch; +} + +/* conv UCS-4 to UTF-8, not used */ +int ldap_ucs4_to_utf8( ldap_ucs4_t c, char *buf ) +{ + int len=0; + unsigned char* p = buf; + if(buf == NULL) return 0; + + if ( c < 0 ) { + /* not a valid Unicode character */ + + } else if( c < 0x80 ) { + p[len++] = c; + + } else if( c < 0x800 ) { + p[len++] = 0xc0 | ( c >> 6 ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x10000 ) { + p[len++] = 0xe0 | ( c >> 12 ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x200000 ) { + p[len++] = 0xf0 | ( c >> 18 ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x400000 ) { + p[len++] = 0xf8 | ( c >> 24 ); + p[len++] = 0x80 | ( (c >> 18) & 0x3f ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else /* if( c < 0x80000000 ) */ { + p[len++] = 0xfc | ( c >> 30 ); + p[len++] = 0x80 | ( (c >> 24) & 0x3f ); + p[len++] = 0x80 | ( (c >> 18) & 0x3f ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + } + + buf[len] = '\0'; + return len; +} + +/* + * Advance to the next UTF-8 character + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +char* ldap_utf8_next( const char * p ) +{ + int i; + const unsigned char *u = p; + + if( LDAP_UTF8_ISASCII(u) ) { + return (char *) &p[1]; + } + + for( i=1; i<6; i++ ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return (char *) &p[i]; + } + } + + return (char *) &p[i]; +} + +/* + * Advance to the previous UTF-8 character + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +char* ldap_utf8_prev( const char * p ) +{ + int i; + const unsigned char *u = p; + + for( i=-1; i>-6 ; i-- ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return (char *) &p[i]; + } + } + + return (char *) &p[i]; +} + +/* + * Copy one UTF-8 character from src to dst returning + * number of bytes copied. + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +int ldap_utf8_copy( char* dst, const char *src ) +{ + int i; + const unsigned char *u = src; + + dst[0] = src[0]; + + if( LDAP_UTF8_ISASCII(u) ) { + return 1; + } + + for( i=1; i<6; i++ ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return i; + } + dst[i] = src[i]; + } + + return i; +} + +/* + * UTF-8 ctype routines + * Only deals with characters < 0x100 (ie: US-ASCII) + */ + +int ldap_utf8_isascii( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + return ISASCII(c); +} + +int ldap_utf8_isdigit( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return c >= '0' && c <= '9'; +} + +int ldap_utf8_isxdigit( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return ( c >= '0' && c <= '9' ) + || ( c >= 'A' && c <= 'F' ) + || ( c >= 'a' && c <= 'f' ); +} + +int ldap_utf8_isspace( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + switch(c) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\v': + case '\f': + return 1; + } + + return 0; +} + +#ifndef UTF8_ALPHA_CTYPE +/* + * These are not needed by the C SDK and are + * not "good enough" for general use. + */ +int ldap_utf8_isalpha( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return ( c >= 'A' && c <= 'Z' ) + || ( c >= 'a' && c <= 'z' ); +} + +int ldap_utf8_isalnum( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return ( c >= '0' && c <= '9' ) + || ( c >= 'A' && c <= 'Z' ) + || ( c >= 'a' && c <= 'z' ); +} + +int ldap_utf8_islower( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return ( c >= 'a' && c <= 'z' ); +} + +int ldap_utf8_isupper( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!ISASCII(c)) return 0; + + return ( c >= 'A' && c <= 'Z' ); +} +#endif + + +/* + * UTF-8 string routines + */ + +/* like strchr() */ +char * (ldap_utf8_strchr)( const char *str, const char *chr ) +{ + for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { + if( ldap_utf8_to_ucs4( str ) == ldap_utf8_to_ucs4( chr ) ) { + return (char *) str; + } + } + + return NULL; +} + +/* like strcspn() but returns number of bytes, not characters */ +ber_len_t (ldap_utf8_strcspn)( const char *str, const char *set ) +{ + const char *cstr; + const char *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { + if( ldap_utf8_to_ucs4( cstr ) == ldap_utf8_to_ucs4( cset ) ) { + return cstr - str; + } + } + } + + return cstr - str; +} + +/* like strspn() but returns number of bytes, not characters */ +ber_len_t (ldap_utf8_strspn)( const char *str, const char *set ) +{ + const char *cstr; + const char *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + + for( cset = set; ; LDAP_UTF8_INCR(cset) ) { + if( *cset == '\0' ) { + return cstr - str; + } + + if( ldap_utf8_to_ucs4( cstr ) == ldap_utf8_to_ucs4( cset ) ) { + break; + } + } + } + + return cstr - str; +} + +/* like strpbrk(), replaces strchr() as well */ +char *(ldap_utf8_strpbrk)( const char *str, const char *set ) +{ + for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { + const char *cset; + + for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { + if( ldap_utf8_to_ucs4( str ) == ldap_utf8_to_ucs4( cset ) ) { + return (char *) str; + } + } + } + + return NULL; +} + +/* like strtok_r(), not strtok() */ +char *(ldap_utf8_strtok)(char *str, const char *sep, char **last) +{ + char *begin; + char *end; + + if( last == NULL ) return NULL; + + begin = str ? str : *last; + + begin += ldap_utf8_strspn( begin, sep ); + + if( *begin == '\0' ) { + *last = NULL; + return NULL; + } + + end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; + + if( *end != '\0' ) { + char *next = LDAP_UTF8_NEXT( end ); + *end = '\0'; + end = next; + } + + *last = end; + return begin; +} diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c index a3128e6e17..b0484034a5 100644 --- a/libraries/libldap/util-int.c +++ b/libraries/libldap/util-int.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -58,11 +58,11 @@ # ifndef USE_CTIME_R static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex; # endif -# ifndef HAVE_GETHOSTBYNAME_R - static ldap_pvt_thread_mutex_t ldap_int_gethostbyname_mutex; +# if !defined( HAVE_GETHOSTBYNAME_R ) || !defined( HAVE_GETHOSTBYADDR_R ) + static ldap_pvt_thread_mutex_t ldap_int_gethostby_mutex; # endif -# ifndef HAVE_GETHOSTBYADDR_R - static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex; +# ifdef HAVE_RES_QUERY + ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; # endif #endif /* LDAP_R_COMPILE */ @@ -143,7 +143,7 @@ int ldap_pvt_gethostbyname_a( struct hostent *he; int retval; - ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyname_mutex ); + ldap_pvt_thread_mutex_lock( &ldap_int_gethostby_mutex ); he = gethostbyname( name ); @@ -158,7 +158,7 @@ int ldap_pvt_gethostbyname_a( retval = 0; } - ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyname_mutex ); + ldap_pvt_thread_mutex_unlock( &ldap_int_gethostby_mutex ); return retval; #else @@ -222,7 +222,7 @@ int ldap_pvt_gethostbyaddr_a( struct hostent *he; int retval; - ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyaddr_mutex ); + ldap_pvt_thread_mutex_lock( &ldap_int_gethostby_mutex ); he = gethostbyaddr( addr, len, type ); @@ -237,7 +237,7 @@ int ldap_pvt_gethostbyaddr_a( retval = 0; } - ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyaddr_mutex ); + ldap_pvt_thread_mutex_unlock( &ldap_int_gethostby_mutex ); return retval; #else /* gethostbyaddr() */ @@ -266,12 +266,12 @@ void ldap_int_utils_init( void ) ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex ); #endif -#if !defined( HAVE_GETHOSTBYNAME_R ) - ldap_pvt_thread_mutex_init( &ldap_int_gethostbyname_mutex ); +#if !defined( HAVE_GETHOSTBYNAME_R ) || !defined( HAVE_GETHOSTBYADDR_R ) + ldap_pvt_thread_mutex_init( &ldap_int_gethostby_mutex ); #endif -#if !defined( HAVE_GETHOSTBYADDR_R ) - ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex ); +#ifdef HAVE_RES_QUERY + ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex ); #endif /* call other module init functions here... */ @@ -314,24 +314,28 @@ static int copy_hostent( struct hostent *res, char **buf, struct hostent * src ) char **tp; char *tbuf; int name_len; - int n_alias; - int total_alias_len; - int n_addr; + int n_alias=0; + int total_alias_len=0; + int n_addr=0; int total_addr_len; int total_len; /* calculate the size needed for the buffer */ name_len = strlen( src->h_name ) + 1; - for( n_alias=total_alias_len=0, p=src->h_aliases; (*p) ; p++ ) { - total_alias_len += strlen( *p ) + 1; - n_alias++; + if( src->h_aliases != NULL ) { + for( p = src->h_aliases; (*p) != NULL; p++ ) { + total_alias_len += strlen( *p ) + 1; + n_alias++; + } } - for( n_addr=0, p=src->h_addr_list; (*p) ; p++ ) { - n_addr++; + if( src->h_addr_list != NULL ) { + for( p = src->h_addr_list; (*p) != NULL; p++ ) { + n_addr++; + } + total_addr_len = n_addr * src->h_length; } - total_addr_len = n_addr * src->h_length; total_len = (n_alias + n_addr + 2) * sizeof( char * ) + total_addr_len + total_alias_len + name_len; @@ -345,11 +349,15 @@ static int copy_hostent( struct hostent *res, char **buf, struct hostent * src ) res->h_name = tbuf; tbuf+=name_len; /* now the aliases */ res->h_aliases = tp; - tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); + if ( src->h_aliases != NULL ) { + tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); + } *tp++=NULL; /* finally the addresses */ res->h_addr_list = tp; - tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); + if ( src->h_addr_list != NULL ) { + tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); + } *tp++=NULL; return 0; } diff --git a/libraries/libldap/vlvctrl.c b/libraries/libldap/vlvctrl.c new file mode 100644 index 0000000000..04b5526a65 --- /dev/null +++ b/libraries/libldap/vlvctrl.c @@ -0,0 +1,280 @@ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */ +/*--- + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND + * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT + * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS + * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" + * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION + * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP + * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT + * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *---*/ + +#include "portable.h" + +#include +#include +#include +#include +#include + +#include "ldap-int.h" + +#define LDAP_VLVBYINDEX_IDENTIFIER 0xa0L +#define LDAP_VLVBYVALUE_IDENTIFIER 0x81L +#define LDAP_VLVCONTEXT_IDENTIFIER 0x04L + + +/*--- + ldap_create_vlv_control + + Create and encode the Virtual List View control. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents + are used to construct the value of the control + that is created. + + ctrlp (OUT) A result parameter that will be assigned the address + of an LDAPControl structure that contains the + VirtualListViewRequest control created by this function. + The memory occupied by the LDAPControl structure + SHOULD be freed when it is no longer in use by + calling ldap_control_free(). + + + Ber encoding + + VirtualListViewRequest ::= SEQUENCE { + beforeCount INTEGER (0 .. maxInt), + afterCount INTEGER (0 .. maxInt), + CHOICE { + byoffset [0] SEQUENCE, { + offset INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt) } + [1] greaterThanOrEqual assertionValue } + contextID OCTET STRING OPTIONAL } + + + Note: The first time the VLV control is created, the ldvlv_context + field of the LDAPVLVInfo structure should be set to NULL. + The context obtained from calling ldap_parse_vlv_control() + should be used as the context in the next ldap_create_vlv_control + call. + + ---*/ + +LIBLDAP_F( int ) +ldap_create_vlv_control( LDAP *ld, + LDAPVLVInfo *vlvinfop, + LDAPControl **ctrlp ) +{ + ber_tag_t tag; + BerElement *ber; + + if ( (ld==NULL) || (vlvinfop==NULL) || (ctrlp == NULL) ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return(LDAP_NO_MEMORY); + } + + tag = ber_printf(ber, "{ii" /*}*/, + vlvinfop->ldvlv_before_count, + vlvinfop->ldvlv_after_count); + if( tag == LBER_ERROR ) goto exit; + + if (vlvinfop->ldvlv_attrvalue == NULL) { + tag = ber_printf(ber, "t{ii}", + LDAP_VLVBYINDEX_IDENTIFIER, + vlvinfop->ldvlv_offset, + vlvinfop->ldvlv_count); + if( tag == LBER_ERROR ) goto exit; + + } else { + tag = ber_printf(ber, "tO", + LDAP_VLVBYVALUE_IDENTIFIER, + vlvinfop->ldvlv_attrvalue); + if( tag == LBER_ERROR ) goto exit; + } + + if (vlvinfop->ldvlv_context) { + tag = ber_printf(ber, "tO", + LDAP_VLVCONTEXT_IDENTIFIER, + vlvinfop->ldvlv_context); + if( tag == LBER_ERROR ) goto exit; + } + + tag = ber_printf(ber, /*{*/ "}"); + if( tag == LBER_ERROR ) goto exit; + + ld->ld_errno = ldap_int_create_control( + LDAP_CONTROL_VLVREQUEST, ber, 1, ctrlp); + + ber_free(ber, 1); + return(ld->ld_errno); + +exit: + ber_free(ber, 1); + ld->ld_errno = LDAP_ENCODING_ERROR; + return(ld->ld_errno); +} + + +/*--- + ldap_parse_vlv_control + + Decode the Virtual List View control return information. + + ld (IN) An LDAP session handle. + + ctrls (IN) The address of a NULL-terminated array of + LDAPControl structures, typically obtained + by a call to ldap_parse_result(). + + target_posp (OUT) This result parameter is filled in with the list + index of the target entry. If this parameter is + NULL, the target position is not returned. + + list_countp (OUT) This result parameter is filled in with the server's + estimate of the size of the list. If this parameter + is NULL, the size is not returned. + + contextp (OUT) This result parameter is filled in with the address + of a struct berval that contains the server- + generated context identifier if one was returned by + the server. If the server did not return a context + identifier, this parameter will be set to NULL, even + if an error occured. + The returned context SHOULD be used in the next call + to create a VLV sort control. The struct berval + returned SHOULD be disposed of by calling ber_bvfree() + when it is no longer needed. If NULL is passed for + contextp, the context identifier is not returned. + + errcodep (OUT) This result parameter is filled in with the VLV + result code. If this parameter is NULL, the result + code is not returned. + + + Ber encoding + + VirtualListViewResponse ::= SEQUENCE { + targetPosition INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt), + virtualListViewResult ENUMERATED { + success (0), + operatonsError (1), + unwillingToPerform (53), + insufficientAccessRights (50), + busy (51), + timeLimitExceeded (3), + adminLimitExceeded (11), + sortControlMissing (60), + offsetRangeError (61), + other (80) }, + contextID OCTET STRING OPTIONAL } + +---*/ + +LIBLDAP_F( int ) +ldap_parse_vlv_control( + LDAP *ld, + LDAPControl **ctrls, + unsigned long *target_posp, + unsigned long *list_countp, + struct berval **contextp, + int *errcodep ) +{ + BerElement *ber; + LDAPControl *pControl; + int i; + unsigned long pos, count, err; + ber_tag_t tag, berTag; + ber_len_t berLen; + + if (contextp) { + *contextp = NULL; /* Make sure we return a NULL if error occurs. */ + } + + if (ld == NULL) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if (ctrls == NULL) { + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + } + + /* Search the list of control responses for a VLV control. */ + for (i=0; ctrls[i]; i++) { + pControl = ctrls[i]; + if (!strcmp(LDAP_CONTROL_VLVRESPONSE, pControl->ldctl_oid)) + goto foundVLVControl; + } + + /* No sort control was found. */ + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + +foundVLVControl: + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init(&pControl->ldctl_value); + + if (ber == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return(ld->ld_errno); + } + + /* Extract the data returned in the control. */ + tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err); + + if( tag == LBER_ERROR) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + + + /* Since the context is the last item encoded, if caller doesn't want + it returned, don't decode it. */ + if (contextp) { + if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) { + tag = ber_scanf(ber, "tO", &berTag, contextp); + + if( tag == LBER_ERROR) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + } + } + + ber_free(ber, 1); + + /* Return data to the caller for items that were requested. */ + if (target_posp) { + *target_posp = pos; + } + if (list_countp) { + *list_countp = count; + } + if (errcodep) { + *errcodep = err; + } + + ld->ld_errno = LDAP_SUCCESS; + return(ld->ld_errno); +} diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in index fba054ecb0..a95fec2275 100644 --- a/libraries/libldap_r/Makefile.in +++ b/libraries/libldap_r/Makefile.in @@ -1,4 +1,6 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## Makefile.in for LDAP -lldap ## @@ -14,31 +16,53 @@ XXSRCS = apitest.c test.c tmpltest.c extended.c \ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ - request.c getdxbyname.c os-ip.c url.c charset.c \ + request.c os-ip.c url.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ - charray.c digest.c tls.c dn.c -SRCS = thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \ - thr_pth.c thr_sleep.c thr_stub.c rdwr.c -OBJS = extended.lo \ + charray.c tls.c dn.c os-local.c dnssrv.c \ + utf-8.c +SRCS = threads.c rdwr.c tpool.c \ + thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \ + thr_pth.c thr_stub.c +OBJS = threads.lo rdwr.lo tpool.lo \ + thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \ + thr_pth.lo thr_stub.lo \ + extended.lo \ bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ - request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \ + request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ - thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \ - thr_pth.lo thr_sleep.lo thr_stub.lo rdwr.lo \ - charray.lo digest.lo tls.lo dn.lo + charray.lo tls.lo dn.lo os-local.lo dnssrv.lo \ + utf-8.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries XDEFS = -DLDAP_R_COMPILE -I$(XXDIR) -XLIBS = -lldap_r -llber +XLIBS = -lldap_r -llber -llutil XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) XXXLIBS = $(LTHREAD_LIBS) +LINKAGE = @LT_LIB_LINKAGE@ + +NT_DYN_LIB_LIBS = -llber -llutil $(AC_LIBS) +NT_DYN_LIB_DEFS = -DLIBLBER_DECL=dllimport +NT_DYN_TEST_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport + +NT_XXLIBS = $(SECURITY_LIBS) + +UNIX_DYN_LIB_LIBS = -llber $(AC_LIBS) +UNIX_XXLIBS = $(SECURITY_LIBS) + +# Extras for building the library +EXTRA_DEFS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) +EXTRA_LIBS = $(@PLAT@_@LIB_LINKAGE@_LIB_LIBS) $(@PLAT@_XXLIBS) + +# Only the test programs will pick up these defs. +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_TEST_DEFS) + .links : @for i in $(XXSRCS); do \ $(RM) $$i ; \ @@ -61,5 +85,5 @@ ttest: $(LIBRARY) tmpltest.o $(LDAP_LIBLBER_DEPEND) $(LTLINK) $(LDFLAGS) -o $@ tmpltest.o $(LIBS) install-local: $(CFFILES) FORCE - -$(MKDIR) $(libdir) - $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(libdir) + -$(MKDIR) $(DESTDIR)$(libdir) + $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir) diff --git a/libraries/libldap_r/apitest_r.dsp b/libraries/libldap_r/apitest_r.dsp new file mode 100644 index 0000000000..3dbf1866e8 --- /dev/null +++ b/libraries/libldap_r/apitest_r.dsp @@ -0,0 +1,146 @@ +# Microsoft Developer Studio Project File - Name="apitest_r" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=apitest_r - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "apitest_r.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "apitest_r.mak" CFG="apitest_r - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "apitest_r - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "apitest_r - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "apitest_r - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "apitest_r - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "apitest_r - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\apitest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "apitest_r - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "apitest_r_" +# PROP BASE Intermediate_Dir "apitest_r_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\apitest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "apitest_r - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "apitest_r_" +# PROP BASE Intermediate_Dir "apitest_r_" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\apitest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap_r.lib olber32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "apitest_r - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "apitest_r0" +# PROP BASE Intermediate_Dir "apitest_r0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\apitest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap_r.lib olber32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "apitest_r - Win32 Release" +# Name "apitest_r - Win32 Debug" +# Name "apitest_r - Win32 Single Debug" +# Name "apitest_r - Win32 Single Release" +# Begin Source File + +SOURCE=..\libldap\apitest.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap_r/libldap_r.dsp b/libraries/libldap_r/libldap_r.dsp new file mode 100644 index 0000000000..86e5329c88 --- /dev/null +++ b/libraries/libldap_r/libldap_r.dsp @@ -0,0 +1,374 @@ +# Microsoft Developer Studio Project File - Name="libldap_r" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libldap_r - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libldap_r.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libldap_r.mak" CFG="libldap_r - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libldap_r - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libldap_r - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libldap_r - Win32 Single Debug" (based on\ + "Win32 (x86) Static Library") +!MESSAGE "libldap_r - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "libldap_r - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\libldap_r" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /D _WIN32_WINNT=0x0400 /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Release\oldap_r.lib" + +!ELSEIF "$(CFG)" == "libldap_r - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\libldap_r" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "_DEBUG" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /D _WIN32_WINNT=0x0400 /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Debug\oldap_r.lib" + +!ELSEIF "$(CFG)" == "libldap_r - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libldap_" +# PROP BASE Intermediate_Dir "libldap_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\libldap_r" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "_DEBUG" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "_DEBUG" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\oldap_r.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\oldap_r.lib" + +!ELSEIF "$(CFG)" == "libldap_r - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libldap0" +# PROP BASE Intermediate_Dir "libldap0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\libldap_r" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "LDAP_R_COMPILE" /D "WIN32" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\oldap_r.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\oldap_r.lib" + +!ENDIF + +# Begin Target + +# Name "libldap_r - Win32 Release" +# Name "libldap_r - Win32 Debug" +# Name "libldap_r - Win32 Single Debug" +# Name "libldap_r - Win32 Single Release" +# Begin Source File + +SOURCE=..\libldap\abandon.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\add.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\addentry.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\bind.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\cache.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\charray.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\cldap.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\compare.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\controls.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\delete.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\disptmpl.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\disptmpl.h +# End Source File +# Begin Source File + +SOURCE=..\libldap\dnssrv.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\dsparse.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\error.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\extended.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\free.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\friendly.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\getattr.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\getdn.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\getentry.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\getfilter.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\getvalues.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\init.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\kbind.c +# End Source File +# Begin Source File + +SOURCE="..\libldap\ldap-int.h" +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_cdefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_features.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_log.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_pvt.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldap_pvt_thread.h +# End Source File +# Begin Source File + +SOURCE=..\libldap\modify.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\modrdn.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\open.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\options.c +# End Source File +# Begin Source File + +SOURCE="..\libldap\os-ip.c" +# End Source File +# Begin Source File + +SOURCE=..\libldap\print.c +# End Source File +# Begin Source File + +SOURCE=.\rdwr.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\request.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\result.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\sasl.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\sbind.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\schema.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\search.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\sort.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\sortctrl.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\srchpref.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\srchpref.h +# End Source File +# Begin Source File + +SOURCE=..\libldap\string.c +# End Source File +# Begin Source File + +SOURCE=.\thr_nt.c +# End Source File +# Begin Source File + +SOURCE=.\thr_sleep.c +# End Source File +# Begin Source File + +SOURCE=.\thr_stub.c +# End Source File +# Begin Source File + +SOURCE=.\threads.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\tls.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\ufn.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\unbind.c +# End Source File +# Begin Source File + +SOURCE=..\libldap\url.c +# End Source File +# Begin Source File + +SOURCE="..\libldap\utf-8.c" +# End Source File +# Begin Source File + +SOURCE="..\libldap\util-int.c" +# End Source File +# Begin Source File + +SOURCE=..\libldap\vlvctrl.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap_r/ltest_r.dsp b/libraries/libldap_r/ltest_r.dsp new file mode 100644 index 0000000000..6e5711b030 --- /dev/null +++ b/libraries/libldap_r/ltest_r.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="ltest_r" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ltest_r - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ltest_r.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ltest_r.mak" CFG="ltest_r - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ltest_r - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ltest_r - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ltest_r - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "ltest_r - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ltest_r - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\ltest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 oldap32.lib olber32.lib olutil32.lib libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "ltest_r - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ltest_r___" +# PROP BASE Intermediate_Dir "ltest_r___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\ltest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 oldap32.lib olber32.lib olutil32.lib libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "ltest_r - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ltest_r_" +# PROP BASE Intermediate_Dir "ltest_r_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\ltest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 oldap32.lib olber32.lib olutil32.lib libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "ltest_r - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ltest_r0" +# PROP BASE Intermediate_Dir "ltest_r0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\ltest_r" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 oldap32.lib olber32.lib olutil32.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 oldap32.lib olber32.lib olutil32.lib libsasl.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ENDIF + +# Begin Target + +# Name "ltest_r - Win32 Release" +# Name "ltest_r - Win32 Debug" +# Name "ltest_r - Win32 Single Debug" +# Name "ltest_r - Win32 Single Release" +# Begin Source File + +SOURCE=..\libldap\test.c +# End Source File +# End Target +# End Project diff --git a/libraries/libldap_r/rdwr.c b/libraries/libldap_r/rdwr.c index ab31f426ae..6a43f66a18 100644 --- a/libraries/libldap_r/rdwr.c +++ b/libraries/libldap_r/rdwr.c @@ -7,13 +7,10 @@ ** ** Does not support cancellation nor does any status checking. */ - -/******************************************************** - * Adapted from: +/* Adapted from publically available examples for: * "Programming with Posix Threads" - * by David R Butenhof - * Addison-Wesley - ******************************************************** + * by David R Butenhof, Addison-Wesley + * http://cseng.aw.com/bookpage.taf?ISBN=0-201-63392-2 */ #include "portable.h" @@ -22,15 +19,39 @@ #include #include +#include +#include "ldap-int.h" #include "ldap_pvt_thread.h" +/* + * implementations that provide their own compatible + * reader/writer locks define LDAP_THREAD_HAVE_RDWR + * in ldap_pvt_thread.h + */ +#ifndef LDAP_THREAD_HAVE_RDWR + +struct ldap_int_thread_rdwr_s { + ldap_pvt_thread_mutex_t ltrw_mutex; + ldap_pvt_thread_cond_t ltrw_read; /* wait for read */ + ldap_pvt_thread_cond_t ltrw_write; /* wait for write */ + int ltrw_valid; +#define LDAP_PVT_THREAD_RDWR_VALID 0x0bad + int ltrw_r_active; + int ltrw_w_active; + int ltrw_r_wait; + int ltrw_w_wait; +}; + int -ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) +ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rwlock ) { - assert( rw != NULL ); + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); - memset( rw, 0, sizeof(ldap_pvt_thread_rdwr_t) ); + rw = (struct ldap_int_thread_rdwr_s *) LDAP_CALLOC( 1, + sizeof( struct ldap_int_thread_rdwr_s ) ); /* we should check return results */ ldap_pvt_thread_mutex_init( &rw->ltrw_mutex ); @@ -38,12 +59,19 @@ ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) ldap_pvt_thread_cond_init( &rw->ltrw_write ); rw->ltrw_valid = LDAP_PVT_THREAD_RDWR_VALID; + + *rwlock = rw; return 0; } int -ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) +ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -53,7 +81,7 @@ ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); /* active threads? */ - if( rw->ltrw_r_active > 0 || rw->ltrw_w_active > 1) { + if( rw->ltrw_r_active > 0 || rw->ltrw_w_active > 0) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } @@ -72,11 +100,18 @@ ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) ldap_pvt_thread_cond_destroy( &rw->ltrw_read ); ldap_pvt_thread_cond_destroy( &rw->ltrw_write ); + LDAP_FREE(rw); + *rwlock = NULL; return 0; } -int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -85,7 +120,7 @@ int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); - if( rw->ltrw_w_active > 1 ) { + if( rw->ltrw_w_active > 0 ) { /* writer is active */ rw->ltrw_r_wait++; @@ -93,7 +128,7 @@ int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) do { ldap_pvt_thread_cond_wait( &rw->ltrw_read, &rw->ltrw_mutex ); - } while( rw->ltrw_w_active > 1 ); + } while( rw->ltrw_w_active > 0 ); rw->ltrw_r_wait--; } @@ -105,8 +140,13 @@ int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -115,7 +155,7 @@ int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex ); - if( rw->ltrw_w_active > 1) { + if( rw->ltrw_w_active > 0) { ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex ); return LDAP_PVT_THREAD_EBUSY; } @@ -127,8 +167,13 @@ int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -148,8 +193,13 @@ int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -176,8 +226,13 @@ int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -198,8 +253,13 @@ int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) +int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rwlock ) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -222,7 +282,7 @@ int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) return 0; } -#ifdef LDAP_DEBUG +#ifdef LDAP_RDWR_DEBUG /* just for testing, * return 0 if false, suitable for assert(ldap_pvt_thread_rdwr_Xchk(rdwr)) @@ -234,24 +294,39 @@ int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) * a lock are caught. */ -int ldap_pvt_thread_rdwr_readers(ldap_pvt_thread_rdwr_t *rw) +int ldap_pvt_thread_rdwr_readers(ldap_pvt_thread_rdwr_t *rwlock) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); return( rw->ltrw_r_active ); } -int ldap_pvt_thread_rdwr_writers(ldap_pvt_thread_rdwr_t *rw) +int ldap_pvt_thread_rdwr_writers(ldap_pvt_thread_rdwr_t *rwlock) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); return( rw->ltrw_w_active ); } -int ldap_pvt_thread_rdwr_active(ldap_pvt_thread_rdwr_t *rw) +int ldap_pvt_thread_rdwr_active(ldap_pvt_thread_rdwr_t *rwlock) { + struct ldap_int_thread_rdwr_s *rw; + + assert( rwlock != NULL ); + rw = *rwlock; + assert( rw != NULL ); assert( rw->ltrw_valid == LDAP_PVT_THREAD_RDWR_VALID ); @@ -260,3 +335,5 @@ int ldap_pvt_thread_rdwr_active(ldap_pvt_thread_rdwr_t *rw) } #endif /* LDAP_DEBUG */ + +#endif /* LDAP_THREAD_HAVE_RDWR */ diff --git a/libraries/libldap_r/thr_cthreads.c b/libraries/libldap_r/thr_cthreads.c index 8d3949aa98..8e9049c7b1 100644 --- a/libraries/libldap_r/thr_cthreads.c +++ b/libraries/libldap_r/thr_cthreads.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -24,13 +24,13 @@ ***********************************************************************/ int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { return 0; } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { return 0; } diff --git a/libraries/libldap_r/thr_lwp.c b/libraries/libldap_r/thr_lwp.c index 3c1dff3389..69ddd72f00 100644 --- a/libraries/libldap_r/thr_lwp.c +++ b/libraries/libldap_r/thr_lwp.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -47,7 +47,7 @@ * Initialize LWP by spinning of a schedular */ int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { thread_t tid; stkalign_t *stack; @@ -62,7 +62,7 @@ ldap_pvt_thread_initialize( void ) } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { /* need to destory lwp_scheduler thread and clean up private variables */ @@ -76,7 +76,7 @@ struct stackinfo { static struct stackinfo *stacks; -static stkalign_t * ldap_pvt_thread_get_stack( int *stacknop ) +static stkalign_t * ldap_int_thread_get_stack( int *stacknop ) { int i; @@ -122,7 +122,7 @@ static stkalign_t * ldap_pvt_thread_get_stack( int *stacknop ) } static void -ldap_pvt_thread_free_stack( int stackno ) +ldap_int_thread_free_stack( int stackno ) { if ( stackno < 0 || stackno > MAX_THREADS ) { Debug( LDAP_DEBUG_ANY, "free_stack of bogus stack %d\n", @@ -137,7 +137,7 @@ lwp_create_stack( void *(*func)(), void *arg, int stackno ) { (*func)( arg ); - ldap_pvt_thread_free_stack( stackno ); + ldap_int_thread_free_stack( stackno ); } int @@ -149,7 +149,7 @@ ldap_pvt_thread_create( ldap_pvt_thread_t * thread, stkalign_t *stack; int stackno; - if ( (stack = ldap_pvt_thread_get_stack( &stackno )) == NULL ) { + if ( (stack = ldap_int_thread_get_stack( &stackno )) == NULL ) { return( -1 ); } return( lwp_create( thread, lwp_create_stack, MINPRIO, 0, @@ -308,7 +308,7 @@ ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, - ldap_pvt_thread_mutex_t *mutex ) + ldap_int_thread_mutex_t *mutex ) { if ( ! cond->lcv_created ) { cv_create( &cond->lcv_cv, *mutex ); diff --git a/libraries/libldap_r/thr_nt.c b/libraries/libldap_r/thr_nt.c index 20cca306ea..935bf4bd13 100644 --- a/libraries/libldap_r/thr_nt.c +++ b/libraries/libldap_r/thr_nt.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -18,13 +18,13 @@ #include "ldap_pvt_thread.h" int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { return 0; } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { return 0; } @@ -93,18 +93,18 @@ ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, - ldap_pvt_thread_mutex_t *mutex ) + ldap_pvt_thread_mutex_t *mutex ) { ReleaseMutex( *mutex ); - WaitForSingleObject( *cond, INFINITE ); + SignalObjectAndWait( *mutex, *cond, INFINITE, FALSE ); WaitForSingleObject( *mutex, INFINITE ); return( 0 ); } int -ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cv ) +ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) { - SetEvent( *cv ); + SetEvent( *cond ); return( 0 ); } diff --git a/libraries/libldap_r/thr_posix.c b/libraries/libldap_r/thr_posix.c index c44bee48c3..95d30f1b4b 100644 --- a/libraries/libldap_r/thr_posix.c +++ b/libraries/libldap_r/thr_posix.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -22,27 +22,24 @@ #if HAVE_PTHREADS_D4 -# define LDAP_PVT_THREAD_ATTR_DEFAULT pthread_attr_default -# define LDAP_PVT_THREAD_CONDATTR_DEFAULT pthread_condattr_default -# define LDAP_PVT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default +# define LDAP_INT_THREAD_ATTR_DEFAULT pthread_attr_default +# define LDAP_INT_THREAD_CONDATTR_DEFAULT pthread_condattr_default +# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default #else -# define LDAP_PVT_THREAD_ATTR_DEFAULT NULL -# define LDAP_PVT_THREAD_CONDATTR_DEFAULT NULL -# define LDAP_PVT_THREAD_MUTEXATTR_DEFAULT NULL +# define LDAP_INT_THREAD_ATTR_DEFAULT NULL +# define LDAP_INT_THREAD_CONDATTR_DEFAULT NULL +# define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL #endif int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { -#if defined( LDAP_THREAD_CONCURRENCY ) && HAVE_PTHREAD_SETCONCURRENCY - ldap_pvt_thread_set_concurrency( LDAP_THREAD_CONCURRENCY ); -#endif return 0; } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { return 0; } @@ -81,8 +78,19 @@ ldap_pvt_thread_create( ldap_pvt_thread_t * thread, void *(*start_routine)( void * ), void *arg) { - int rtn = pthread_create( thread, LDAP_PVT_THREAD_ATTR_DEFAULT, + int rtn; +#if defined(HAVE_PTHREADS_FINAL) && defined(PTHREAD_CREATE_UNDETACHED) + pthread_attr_t attr; + + pthread_attr_init(&attr); + if (!detach) + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED); + + rtn = pthread_create( thread, &attr, start_routine, arg ); +#else + rtn = pthread_create( thread, LDAP_INT_THREAD_ATTR_DEFAULT, start_routine, arg ); +#endif if( detach ) { #ifdef HAVE_PTHREADS_FINAL @@ -149,7 +157,7 @@ ldap_pvt_thread_yield( void ) int ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) { - return pthread_cond_init( cond, LDAP_PVT_THREAD_CONDATTR_DEFAULT ); + return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ); } int @@ -180,7 +188,7 @@ ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, int ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) { - return pthread_mutex_init( mutex, LDAP_PVT_THREAD_MUTEXATTR_DEFAULT ); + return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ); } int @@ -195,11 +203,63 @@ ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) return pthread_mutex_lock( mutex ); } +int +ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) +{ + return pthread_mutex_trylock( mutex ); +} + int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return pthread_mutex_unlock( mutex ); } +#ifdef LDAP_THREAD_HAVE_RDWR +#ifdef HAVE_PTHREAD_RWLOCK_DESTROY +int +ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_init( rw, NULL ); +} + +int +ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_destroy( rw ); +} + +int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_rdlock( rw ); +} + +int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_tryrdlock( rw ); +} + +int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_unlock( rw ); +} + +int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_wrlock( rw ); +} + +int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_trywrlock( rw ); +} + +int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pthread_rwlock_unlock( rw ); +} + +#endif /* HAVE_PTHREAD_RDLOCK_DESTROY */ +#endif /* LDAP_THREAD_HAVE_RDWR */ #endif /* HAVE_PTHREADS */ diff --git a/libraries/libldap_r/thr_pth.c b/libraries/libldap_r/thr_pth.c index 132644cff0..15fcac75a8 100644 --- a/libraries/libldap_r/thr_pth.c +++ b/libraries/libldap_r/thr_pth.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -26,15 +26,17 @@ static pth_attr_t detach_attr; int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { + if( !pth_init() ) { + return -1; + } detach_attr = pth_attr_new(); - pth_attr_set( detach_attr, PTH_ATTR_JOINABLE, FALSE ); - return pth_init(); + return pth_attr_set( detach_attr, PTH_ATTR_JOINABLE, FALSE ); } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { pth_attr_destroy(detach_attr); pth_kill(); @@ -99,7 +101,7 @@ ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, - ldap_pvt_thread_mutex_t *mutex ) + ldap_pvt_thread_mutex_t *mutex ) { return( pth_cond_await( cond, mutex, NULL ) ); } @@ -140,4 +142,48 @@ ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) return( pth_mutex_acquire( mutex, 1, NULL ) ); } +#ifdef LDAP_THREAD_HAVE_RDWR +int +ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_init( rw ); +} + +int +ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw ) +{ + return 0; +} + +int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_acquire( rw, PTH_RWLOCK_RD, 0, NULL ); +} + +int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_acquire( rw, PTH_RWLOCK_RD, 1, NULL ); +} + +int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_release( rw ); +} + +int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_acquire( rw, PTH_RWLOCK_RW, 0, NULL ); +} + +int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_acquire( rw, PTH_RWLOCK_RW, 1, NULL ); +} + +int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw ) +{ + return pth_rwlock_release( rw ); +} + +#endif /* LDAP_THREAD_HAVE_RDWR */ #endif /* HAVE_GNU_PTH */ diff --git a/libraries/libldap_r/thr_sleep.c b/libraries/libldap_r/thr_sleep.c deleted file mode 100644 index fac90d0825..0000000000 --- a/libraries/libldap_r/thr_sleep.c +++ /dev/null @@ -1,57 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright (c) 1996 Regents of the University of Michigan. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and that due credit is given - * to the University of Michigan at Ann Arbor. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. This software - * is provided ``as is'' without express or implied warranty. - */ - -/* - * ldap_pvt_thread_sleep.c - allow a thread to sleep without putting - * the whole process (e.g. pod under lwp) to sleep. - * - * Contains platform-specific code to allow this: - * - * Under non-preemptive threads packages like SunOS lwp, tsleep() adds - * the thread to a list of sleepers. The lwp_scheduler process takes - * care of resuming suspended threads. - * - * Under a fully-preemptive threads package, like Solaris threads, - * tsleep just calls sleep(), and there is no scheduler thread. Life - * is so much simpler... - */ - -#include "portable.h" - -#if !defined( HAVE_LWP ) - -#include -#include -#include /* get sleep() */ - -#include "ldap_pvt_thread.h" - - -/* - * Here we assume we have fully preemptive threads and that sleep() - * does the right thing. - */ -unsigned int -ldap_pvt_thread_sleep( - unsigned int interval -) -{ - sleep( interval ); - return 0; -} - -#else - -/* LWP implementation of sleep can be found in thr_lwp.c */ - -#endif /* HAVE_LWP */ diff --git a/libraries/libldap_r/thr_stub.c b/libraries/libldap_r/thr_stub.c index 60da3cec1f..e473e0e557 100644 --- a/libraries/libldap_r/thr_stub.c +++ b/libraries/libldap_r/thr_stub.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -25,13 +25,13 @@ ***********************************************************************/ int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { return 0; } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { return 0; } @@ -126,10 +126,52 @@ ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) return 0; } +int +ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex ) +{ + return 0; +} + int ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) { return 0; } +/* + * NO_THREADS requires a separate tpool implementation since + * generic ldap_pvt_thread_pool_wrapper loops forever. + */ +int +ldap_pvt_thread_pool_init ( + ldap_pvt_thread_pool_t *pool_out, + int max_concurrency, int max_pending ) +{ + *pool_out = NULL; + return(0); +} + +int +ldap_pvt_thread_pool_submit ( + ldap_pvt_thread_pool_t *pool, + void *(*start_routine)( void * ), void *arg ) +{ + (start_routine)(arg); + return(0); +} + +int +ldap_pvt_thread_pool_backload ( + ldap_pvt_thread_pool_t *pool ) +{ + return(0); +} + +int +ldap_pvt_thread_pool_destroy ( + ldap_pvt_thread_pool_t *pool, int run_pending ) +{ + return(0); +} + #endif /* NO_THREADS */ diff --git a/libraries/libldap_r/thr_thr.c b/libraries/libldap_r/thr_thr.c index bb3b10d6b7..ee89e2e640 100644 --- a/libraries/libldap_r/thr_thr.c +++ b/libraries/libldap_r/thr_thr.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -24,31 +24,32 @@ *******************/ int -ldap_pvt_thread_initialize( void ) +ldap_int_thread_initialize( void ) { -#ifdef LDAP_THREAD_CONCURRENCY - thr_setconcurrency( LDAP_THREAD_CONCURRENCY ); -#endif return 0; } int -ldap_pvt_thread_destroy( void ) +ldap_int_thread_destroy( void ) { return 0; } +#ifdef LDAP_THREAD_HAVE_SETCONCURRENCY int ldap_pvt_thread_set_concurrency(int n) { return thr_setconcurrency( n ); } +#endif +#ifdef LDAP_THREAD_HAVE_GETCONCURRENCY int ldap_pvt_thread_get_concurrency(void) { return thr_getconcurrency(); } +#endif int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, @@ -107,7 +108,7 @@ ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cv ) int ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, - ldap_pvt_thread_mutex_t *mutex ) + ldap_pvt_thread_mutex_t *mutex ) { return( cond_wait( cond, mutex ) ); } diff --git a/libraries/libldap_r/threads.c b/libraries/libldap_r/threads.c new file mode 100644 index 0000000000..9f845fe953 --- /dev/null +++ b/libraries/libldap_r/threads.c @@ -0,0 +1,87 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +#include "portable.h" + +#include +#include + +#include +#include + +#include "ldap_pvt_thread.h" + + +/* + * Common LDAP thread routines + * see thr_*.c for implementation specific routines + * see rdwr.c for generic reader/writer lock implementation + * see tpool.c for generic thread pool implementation + */ + + +int ldap_pvt_thread_initialize( void ) +{ + int rc; + static int init = 0; + + /* we only get one shot at this */ + if( init++ ) return -1; + + rc = ldap_int_thread_initialize(); + if( rc ) return rc; + +#ifndef LDAP_THREAD_HAVE_TPOOL + rc = ldap_int_thread_pool_startup(); + if( rc ) return rc; +#endif + + return 0; +} + +int ldap_pvt_thread_destroy( void ) +{ +#ifndef LDAP_THREAD_HAVE_TPOOL + (void) ldap_int_thread_pool_shutdown(); +#endif + (void) ldap_int_thread_destroy(); +} + +#ifndef LDAP_THREAD_HAVE_GETCONCURRENCY +int +ldap_pvt_thread_get_concurrency ( void ) +{ + return 1; +} +#endif + +#ifndef LDAP_THREAD_HAVE_SETCONCURRENCY +int +ldap_pvt_thread_set_concurrency ( int concurrency ) +{ + return 1; +} +#endif + +#ifndef LDAP_THREAD_HAVE_SLEEP +/* + * Here we assume we have fully preemptive threads and that sleep() + * does the right thing. + */ +unsigned int +ldap_pvt_thread_sleep( + unsigned int interval +) +{ + sleep( interval ); + return 0; +} +#endif diff --git a/libraries/libldap_r/tpool.c b/libraries/libldap_r/tpool.c new file mode 100644 index 0000000000..af0c4f739d --- /dev/null +++ b/libraries/libldap_r/tpool.c @@ -0,0 +1,396 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +#include "portable.h" + +#include +#include + +#include +#include +#include + +#include "ldap-int.h" +#include "ldap_pvt_thread.h" + +#ifndef LDAP_THREAD_HAVE_TPOOL + +enum ldap_int_thread_pool_state { + LDAP_INT_THREAD_POOL_RUNNING, + LDAP_INT_THREAD_POOL_FINISHING, + LDAP_INT_THREAD_POOL_STOPPING +}; + +typedef struct ldap_int_thread_list_element_s { + struct ldap_int_thread_list_element_s *next; +} ldap_int_thread_list_element_t, *ldap_int_thread_list_t; + +struct ldap_int_thread_pool_s { + struct ldap_int_thread_pool_s *ltp_next; + ldap_pvt_thread_mutex_t ltp_mutex; + ldap_pvt_thread_cond_t ltp_cond; + ldap_int_thread_list_t ltp_pending_list; + long ltp_state; + long ltp_max_count; + long ltp_max_pending; + long ltp_pending_count; + long ltp_active_count; + long ltp_open_count; +}; + +typedef struct ldap_int_thread_ctx_s { + struct ldap_int_thread_ctx_s *ltc_next; + void *(*ltc_start_routine)( void *); + void *ltc_arg; +} ldap_int_thread_ctx_t; + +static ldap_int_thread_list_t ldap_int_thread_pool_list = NULL; +static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex; + +static void *ldap_int_thread_pool_wrapper( + struct ldap_int_thread_pool_s *pool ); + +static void *ldap_int_thread_enlist( ldap_int_thread_list_t *list, void *elem ); +static void *ldap_int_thread_delist( ldap_int_thread_list_t *list, void *elem ); +static void *ldap_int_thread_onlist( ldap_int_thread_list_t *list, void *elem ); + +int +ldap_int_thread_pool_startup ( void ) +{ + return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex); +} + +int +ldap_int_thread_pool_shutdown ( void ) +{ + while (ldap_int_thread_pool_list != NULL) { + struct ldap_int_thread_pool_s *pool = + (struct ldap_int_thread_pool_s *) ldap_int_thread_pool_list; + + ldap_pvt_thread_pool_destroy( &pool, 0); + } + ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex); + return(0); +} + +int +ldap_pvt_thread_pool_init ( + ldap_pvt_thread_pool_t *tpool, + int max_concurrency, + int max_pending ) +{ + int rc; + ldap_pvt_thread_pool_t pool; + ldap_pvt_thread_t thr; + + *tpool = NULL; + pool = (ldap_pvt_thread_pool_t) LDAP_CALLOC(1, + sizeof(struct ldap_int_thread_pool_s)); + + if (pool == NULL) return(-1); + + ldap_pvt_thread_mutex_init(&pool->ltp_mutex); + ldap_pvt_thread_cond_init(&pool->ltp_cond); + pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING; + pool->ltp_max_count = max_concurrency; + pool->ltp_max_pending = max_pending; + ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); + ldap_int_thread_enlist(&ldap_int_thread_pool_list, pool); + ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); + + /* start up one thread, just so there is one */ + pool->ltp_open_count++; + + rc = ldap_pvt_thread_create( &thr, 1, + (void *) ldap_int_thread_pool_wrapper, pool ); + + if( rc != 0) { + /* couldn't start one? then don't start any */ + ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); + ldap_int_thread_delist(&ldap_int_thread_pool_list, pool); + ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); + ldap_pvt_thread_cond_destroy(&pool->ltp_cond); + ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex); + free(pool); + return(-1); + } + + *tpool = pool; + return(0); +} + +int +ldap_pvt_thread_pool_submit ( + ldap_pvt_thread_pool_t *tpool, + void *(*start_routine)( void * ), void *arg ) +{ + struct ldap_int_thread_pool_s *pool; + ldap_int_thread_ctx_t *ctx; + int need_thread = 0; + ldap_pvt_thread_t thr; + + if (tpool == NULL) + return(-1); + + pool = *tpool; + + if (pool == NULL) + return(-1); + + ctx = (ldap_int_thread_ctx_t *) LDAP_CALLOC(1, + sizeof(ldap_int_thread_ctx_t)); + + if (ctx == NULL) return(-1); + + ctx->ltc_start_routine = start_routine; + ctx->ltc_arg = arg; + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + if (pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING + || (pool->ltp_max_pending > 0 + && pool->ltp_pending_count >= pool->ltp_max_pending)) + { + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + free(ctx); + return(-1); + } + pool->ltp_pending_count++; + ldap_int_thread_enlist(&pool->ltp_pending_list, ctx); + ldap_pvt_thread_cond_signal(&pool->ltp_cond); + if ((pool->ltp_open_count <= 0 + || pool->ltp_pending_count > 1 + || pool->ltp_open_count == pool->ltp_active_count) + && (pool->ltp_max_count <= 0 + || pool->ltp_open_count < pool->ltp_max_count)) + { + pool->ltp_open_count++; + need_thread = 1; + } + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + + if (need_thread) { + int rc = ldap_pvt_thread_create( &thr, 1, + (void *)ldap_int_thread_pool_wrapper, pool ); + if (rc != 0) { + /* couldn't create thread. back out of + * ltp_open_count and check for even worse things. + */ + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + pool->ltp_open_count--; + if (pool->ltp_open_count == 0) { + /* no open threads at all?!? this will never happen + * because we always leave at least one thread open. + */ + if (ldap_int_thread_delist(&pool->ltp_pending_list, ctx)) { + /* no open threads, context not handled, so + * back out of ltp_pending_count, free the context, + * report the error. + */ + pool->ltp_pending_count++; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + free(ctx); + return(-1); + } + } + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + /* there is another open thread, so this + * context will be handled eventually. + * continue on and signal that the context + * is waiting. + */ + } + } + + return(0); +} + +int +ldap_pvt_thread_pool_backload ( ldap_pvt_thread_pool_t *tpool ) +{ + struct ldap_int_thread_pool_s *pool; + int count; + + if (tpool == NULL) + return(-1); + + pool = *tpool; + + if (pool == NULL) + return(0); + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + count = pool->ltp_pending_count + pool->ltp_active_count; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + return(count); +} + +int +ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending ) +{ + struct ldap_int_thread_pool_s *pool; + long waiting; + ldap_int_thread_ctx_t *ctx; + + if (tpool == NULL) + return(-1); + + pool = *tpool; + + if (pool == NULL) return(-1); + + ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex); + pool = ldap_int_thread_delist(&ldap_int_thread_pool_list, pool); + ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex); + + if (pool == NULL) return(-1); + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + pool->ltp_state = run_pending + ? LDAP_INT_THREAD_POOL_FINISHING + : LDAP_INT_THREAD_POOL_STOPPING; + waiting = pool->ltp_open_count; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + + /* broadcast could be used here, but only after + * it is fixed in the NT thread implementation + */ + while (--waiting >= 0) { + ldap_pvt_thread_cond_signal(&pool->ltp_cond); + } + + do { + ldap_pvt_thread_yield(); + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + waiting = pool->ltp_open_count; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + } while (waiting > 0); + + while (ctx = (ldap_int_thread_ctx_t *)ldap_int_thread_delist( + &pool->ltp_pending_list, NULL)) + { + free(ctx); + } + + ldap_pvt_thread_cond_destroy(&pool->ltp_cond); + ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex); + free(pool); + return(0); +} + +static void * +ldap_int_thread_pool_wrapper ( + struct ldap_int_thread_pool_s *pool ) +{ + ldap_int_thread_ctx_t *ctx; + + if (pool == NULL) + return NULL; + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + + while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) { + + ctx = ldap_int_thread_delist(&pool->ltp_pending_list, NULL); + if (ctx == NULL) { + if (pool->ltp_state == LDAP_INT_THREAD_POOL_FINISHING) + break; + /* we could check an idle timer here, and let the + * thread die if it has been inactive for a while. + * only die if there are other open threads (i.e., + * always have at least one thread open). + */ + + if (pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING) + ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); + + continue; + } + + pool->ltp_pending_count--; + pool->ltp_active_count++; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + + (ctx->ltc_start_routine)(ctx->ltc_arg); + free(ctx); + ldap_pvt_thread_yield(); + + /* if we use an idle timer, here's + * a good place to update it + */ + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + pool->ltp_active_count--; + } + + pool->ltp_open_count--; + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + + ldap_pvt_thread_exit(NULL); + return(NULL); +} + +static void * +ldap_int_thread_enlist( ldap_int_thread_list_t *list, void *elem ) +{ + ldap_int_thread_list_element_t *prev; + + if (elem == NULL) return(NULL); + + ((ldap_int_thread_list_element_t *)elem)->next = NULL; + if (*list == NULL) { + *list = elem; + return(elem); + } + + for (prev = *list ; prev->next != NULL; prev = prev->next) ; + prev->next = elem; + return(elem); +} + +static void * +ldap_int_thread_delist( ldap_int_thread_list_t *list, void *elem ) +{ + ldap_int_thread_list_element_t *prev; + + if (*list == NULL) return(NULL); + + if (elem == NULL) elem = *list; + + if (*list == elem) { + *list = ((ldap_int_thread_list_element_t *)elem)->next; + return(elem); + } + + for (prev = *list ; prev->next != NULL; prev = prev->next) { + if (prev->next == elem) { + prev->next = ((ldap_int_thread_list_element_t *)elem)->next; + return(elem); + } + } + return(NULL); +} + +static void * +ldap_int_thread_onlist( ldap_int_thread_list_t *list, void *elem ) +{ + ldap_int_thread_list_element_t *prev; + + if (elem == NULL || *list == NULL) return(NULL); + + for (prev = *list ; prev != NULL; prev = prev->next) { + if (prev == elem) + return(elem); + } + + return(NULL); +} + +#endif /* LDAP_HAVE_THREAD_POOL */ diff --git a/libraries/libldbm/Makefile.in b/libraries/libldbm/Makefile.in index 7926c3673d..a2679ab8a6 100644 --- a/libraries/libldbm/Makefile.in +++ b/libraries/libldbm/Makefile.in @@ -1,4 +1,6 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## Makefile for -lldbm ## @@ -11,8 +13,12 @@ OBJS = ldbm.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries +NT_DYN_LIB_DEFS = -DLIBLDAP_DECL=dllimport +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) + XLIBS = -lldbm -lavl XXLIBS = $(LDBM_LIBS) testldbm: libldbm.a testldbm.o $(CC) $(LDFLAGS) -o $@ testldbm.o $(LIBS) + diff --git a/libraries/libldbm/ldbm.c b/libraries/libldbm/ldbm.c index 461db8657e..2560fd8727 100644 --- a/libraries/libldbm/ldbm.c +++ b/libraries/libldbm/ldbm.c @@ -1,7 +1,7 @@ /* ldbm.c - ldap dbm compatibility routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -25,13 +25,12 @@ #include "ldbm.h" #include "ldap_pvt_thread.h" - void ldbm_datum_free( LDBM ldbm, Datum data ) { if ( data.dptr ) { free( data.dptr ); - memset( &data, 0, sizeof( Datum )); + memset( &data, '\0', sizeof( Datum )); data.dptr = NULL; } } @@ -59,32 +58,28 @@ ldbm_datum_dup( LDBM ldbm, Datum data ) static int ldbm_initialized = 0; -#ifndef HAVE_BERKELEY_DB2 -/* Everything but DB2 is non-reentrant */ +#ifdef HAVE_BERKELEY_DB_THREAD +#define LDBM_LOCK ((void)0) +#define LDBM_UNLOCK ((void)0) +#else +/* Only DB2 or DB3 with DB_THREAD is thread-free */ static ldap_pvt_thread_mutex_t ldbm_big_mutex; #define LDBM_LOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex)) #define LDBM_UNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex)) -int ldbm_initialize( void ) -{ - if(ldbm_initialized++) return 1; - - ldap_pvt_thread_mutex_init( &ldbm_big_mutex ); +#endif - return 0; -} -int ldbm_shutdown( void ) -{ - if( !ldbm_initialized ) return 1; - ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex ); +/******************************************************************* + * * + * Create some special functions to initialize Berkeley DB for * + * versions greater than 2. * + * * + *******************************************************************/ +#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2) - return 0; -} - -#else void * ldbm_malloc( size_t size ) @@ -105,13 +100,8 @@ ldbm_db_errcall( const char *prefix, char *message ) } /* a dbEnv for BERKELEYv2 */ -static DB_ENV ldbm_Env_internal; DB_ENV *ldbm_Env = NULL; -/* Berkeley DB 2.x is reentrant */ -#define LDBM_LOCK ((void)0) -#define LDBM_UNLOCK ((void)0) - int ldbm_initialize( void ) { int err; @@ -119,23 +109,37 @@ int ldbm_initialize( void ) if(ldbm_initialized++) return 1; - memset( &ldbm_Env_internal, 0, sizeof( DB_ENV )); - ldbm_Env = &ldbm_Env_internal; +#if DB_VERSION_MAJOR < 3 + ldbm_Env = calloc( 1, sizeof( DB_ENV )); + + if( ldbm_Env == NULL ) return 1; ldbm_Env->db_errcall = ldbm_db_errcall; ldbm_Env->db_errpfx = "==>"; +#else + ldbm_Env = NULL; +#endif - envFlags = DB_CREATE | DB_THREAD; + envFlags = +#if defined( HAVE_BERKELEY_DB_THREAD ) + DB_THREAD | +#endif + DB_CREATE; - if ( ( err = db_appinit( NULL, NULL, ldbm_Env, envFlags )) ) { - char error[BUFSIZ]; +#if DB_VERSION_MAJOR >= 3 + err = db_env_create( &ldbm_Env, 0 ); +#elif DB_VERSION_MAJOR >= 2 + err = db_appinit( NULL, NULL, ldbm_Env, envFlags ); +#endif + + if ( err ) { + char error[BUFSIZ]; if ( err < 0 ) { sprintf( error, "%ld\n", (long) err ); } else { sprintf( error, "%s\n", strerror( err )); } - #ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize(): FATAL error in db_appinit() : %s\n", @@ -144,6 +148,31 @@ int ldbm_initialize( void ) return( 1 ); } +#if DB_VERSION_MAJOR >= 3 + ldbm_Env->set_errcall( ldbm_Env, ldbm_db_errcall ); + ldbm_Env->set_errpfx( ldbm_Env, "==>" ); + + envFlags |= DB_INIT_MPOOL; + err = ldbm_Env->open( ldbm_Env, NULL, NULL, envFlags, 0 ); + if ( err != 0 ) + { + char error[BUFSIZ]; + + if ( err < 0 ) { + sprintf( error, "%ld\n", (long) err ); + } else { + sprintf( error, "%s\n", strerror( err )); + } +#ifdef LDAP_SYSLOG + syslog( LOG_INFO, + "ldbm_initialize(): FATAL error in db_appinit() : %s\n", + error ); +#endif + ldbm_Env->close( ldbm_Env, 0 ); + return( 1 ); + } +#endif + return 0; } @@ -151,12 +180,37 @@ int ldbm_shutdown( void ) { if( !ldbm_initialized ) return 1; +#if DB_VERSION_MAJOR >= 3 + ldbm_Env->close( ldbm_Env, 0 ); +#else db_appexit( ldbm_Env ); +#endif return 0; } -#endif +#else /* some DB other than Berkeley V2 or greater */ + +int ldbm_initialize( void ) +{ + if(ldbm_initialized++) return 1; + + ldap_pvt_thread_mutex_init( &ldbm_big_mutex ); + + return 0; +} + +int ldbm_shutdown( void ) +{ + if( !ldbm_initialized ) return 1; + + ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex ); + + return 0; +} + +#endif /* ifdef HAVE_BERKELEY_DB */ + #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE ) @@ -171,10 +225,45 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize ) { LDBM ret = NULL; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 3 + int err; + LDBM_LOCK; + err = db_create( &ret, ldbm_Env, 0 ); + if ( err != 0 ) + { + char error[BUFSIZ]; + + if ( err < 0 ) { + sprintf( error, "%ld\n", (long) err ); + } else { + sprintf( error, "%s\n", strerror( err )); + } + (void)ret->close(ret, 0); + return NULL; + } + + ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE ); + ret->set_malloc( ret, ldbm_malloc ); + ret->set_cachesize( ret, 0, dbcachesize, 0 ); + err = ret->open( ret, name, NULL, DB_TYPE, rw, mode); + LDBM_UNLOCK; + if ( err != 0 ) + { + char error[BUFSIZ]; + + if ( err < 0 ) { + sprintf( error, "%ld\n", (long) err ); + } else { + sprintf( error, "%s\n", strerror( err )); + } + (void)ret->close(ret, 0); + return NULL; + } + +#elif DB_VERSION_MAJOR >= 2 DB_INFO dbinfo; - memset( &dbinfo, 0, sizeof( dbinfo )); + memset( &dbinfo, '\0', sizeof( dbinfo )); #if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \ DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4 @@ -225,7 +314,9 @@ void ldbm_close( LDBM ldbm ) { LDBM_LOCK; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 3 + ldbm->close( ldbm, 0 ); +#elif DB_VERSION_MAJOR >= 2 (*ldbm->close)( ldbm, 0 ); #else (*ldbm->close)( ldbm ); @@ -248,8 +339,15 @@ ldbm_fetch( LDBM ldbm, Datum key ) int rc; LDBM_LOCK; +#if DB_VERSION_MAJOR >= 3 + ldbm_datum_init( data ); + + data.flags = DB_DBT_MALLOC; -#ifdef HAVE_BERKELEY_DB2 + if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) { + ldbm_datum_free( ldbm, data ); + +#elif DB_VERSION_MAJOR >= 2 ldbm_datum_init( data ); data.flags = DB_DBT_MALLOC; @@ -279,7 +377,21 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags ) LDBM_LOCK; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 3 + rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC ); + if ( rc != 0 ) + { + char error[BUFSIZ]; + + if ( rc < 0 ) { + sprintf( error, "%ld\n", (long) rc ); + } else { + sprintf( error, "%s\n", strerror( rc )); + } + } + rc = (-1) * rc; + +#elif DB_VERSION_MAJOR >= 2 rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC ); rc = (-1 ) * rc; #else @@ -301,7 +413,10 @@ ldbm_delete( LDBM ldbm, Datum key ) LDBM_LOCK; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 3 + rc = ldbm->del( ldbm, NULL, &key, 0 ); + rc = (-1 ) * rc; +#elif DB_VERSION_MAJOR >= 2 rc = (*ldbm->del)( ldbm, NULL, &key, 0 ); rc = (-1 ) * rc; #else @@ -319,7 +434,7 @@ ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ) { Datum key, data; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 2 LDBMCursor *dbci; ldbm_datum_init( key ); @@ -330,11 +445,12 @@ ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ) LDBM_LOCK; /* acquire a cursor for the DB */ +# if DB_VERSION_MAJOR >= 3 + if ( ldbm->cursor( ldbm, NULL, &dbci, 0 ) ) +# elif defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \ + (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6) -# if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \ - DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 - - if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) + if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) # else if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 )) @@ -362,7 +478,7 @@ ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ) key.dsize = 0; } -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 2 } #endif @@ -376,7 +492,7 @@ ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) { Datum data; -#ifdef HAVE_BERKELEY_DB2 +#if DB_VERSION_MAJOR >= 2 ldbm_datum_init( data ); ldbm_datum_free( ldbm, key ); @@ -413,6 +529,12 @@ ldbm_errno( LDBM ldbm ) return( errno ); } +/****************************************************************** + * * + * END Berkeley section * + * * + ******************************************************************/ + #elif defined( HAVE_GDBM ) #ifdef HAVE_ST_BLKSIZE @@ -523,6 +645,11 @@ ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp ) d = gdbm_firstkey( ldbm ); LDBM_UNLOCK; + if ( d.dptr != NULL ) { + *dbcp = (Datum *) malloc( sizeof( Datum ) ); + **dbcp = ldbm_datum_dup( ldbm, d ); + } + return d; } @@ -532,9 +659,17 @@ ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ) Datum d; LDBM_LOCK; - d = gdbm_nextkey( ldbm, key ); + d = gdbm_nextkey( ldbm, *dbcp ); LDBM_UNLOCK; + ldbm_datum_free( ldbm, *dbcp ); + + if ( d.dptr != NULL ) { + *dbcp = ldbm_datum_dup( ldbm, d ); + } else { + free( dbcp ); + } + return d; } diff --git a/libraries/libldbm/libldbm.dsp b/libraries/libldbm/libldbm.dsp new file mode 100644 index 0000000000..5c2a9e94d2 --- /dev/null +++ b/libraries/libldbm/libldbm.dsp @@ -0,0 +1,137 @@ +# Microsoft Developer Studio Project File - Name="libldbm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libldbm - Win32 Single Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libldbm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libldbm.mak" CFG="libldbm - Win32 Single Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libldbm - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Single Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "libldbm - Win32 Single Release" (based on\ + "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "libldbm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\libldbm" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Release\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\libldbm" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\Debug\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libldbm_" +# PROP BASE Intermediate_Dir "libldbm_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\libldbm" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Debug\oldbm32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\oldbm32.lib" + +!ELSEIF "$(CFG)" == "libldbm - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "libldbm0" +# PROP BASE Intermediate_Dir "libldbm0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\libldbm" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo /out:"..\Release\oldbm32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\oldbm32.lib" + +!ENDIF + +# Begin Target + +# Name "libldbm - Win32 Release" +# Name "libldbm - Win32 Debug" +# Name "libldbm - Win32 Single Debug" +# Name "libldbm - Win32 Single Release" +# Begin Source File + +SOURCE=.\ldbm.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\ldbm.h +# End Source File +# End Target +# End Project diff --git a/libraries/libldif/Makefile.in b/libraries/libldif/Makefile.in index 020e16d816..c15f30be93 100644 --- a/libraries/libldif/Makefile.in +++ b/libraries/libldif/Makefile.in @@ -1,4 +1,6 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## Makefile for -lldif ## @@ -10,3 +12,6 @@ OBJS = line64.o fetch.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries +NT_DYN_LIB_DEFS = -DLIBLDAP_DECL=dllimport -DLIBLBER_DECL=dllimport +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) + diff --git a/libraries/libldif/fetch.c b/libraries/libldif/fetch.c index 94d0861455..4dc179bbc5 100644 --- a/libraries/libldif/fetch.c +++ b/libraries/libldif/fetch.c @@ -1,7 +1,7 @@ /* line64.c - routines for dealing with the slapd line format */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/libraries/libldif/libldif.dsp b/libraries/libldif/libldif.dsp index f72025a241..112f5658f1 100644 --- a/libraries/libldif/libldif.dsp +++ b/libraries/libldif/libldif.dsp @@ -38,9 +38,10 @@ CPP=cl.exe # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\Release" -# PROP Intermediate_Dir "Release\libldif" +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\libldif" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -48,7 +49,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Release\oldif32.lib" +# ADD LIB32 /nologo /out:"..\..\Release\oldif32.lib" !ELSEIF "$(CFG)" == "libldif - Win32 Debug" @@ -59,9 +60,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\Debug" -# PROP Intermediate_Dir "Debug\libldif" +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\libldif" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -69,7 +71,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Debug\oldif32.lib" +# ADD LIB32 /nologo /out:"..\..\Debug\oldif32.lib" !ELSEIF "$(CFG)" == "libldif - Win32 Single Debug" @@ -80,9 +82,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\SDebug" -# PROP Intermediate_Dir "SDebug\libldif" +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\libldif" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -90,7 +93,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Debug\oldif32.lib" -# ADD LIB32 /nologo /out:"..\SDebug\oldif32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\oldif32.lib" !ELSEIF "$(CFG)" == "libldif - Win32 Single Release" @@ -101,9 +104,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\SRelease" -# PROP Intermediate_Dir "SRelease\libldif" +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\libldif" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -111,7 +115,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Release\oldif32.lib" -# ADD LIB32 /nologo /out:"..\SRelease\oldif32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\oldif32.lib" !ENDIF diff --git a/libraries/libldif/line64.c b/libraries/libldif/line64.c index f2a8e995ed..7ee83d8e6a 100644 --- a/libraries/libldif/line64.c +++ b/libraries/libldif/line64.c @@ -1,7 +1,7 @@ /* line64.c - routines for dealing with the slapd line format */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -135,6 +135,13 @@ ldif_parse_line( s++; } + /* check for continued line markers that should be deleted */ + for ( p = s, d = s; *p; p++ ) { + if ( *p != CONTINUED_LINE_MARKER ) + *d++ = *p; + } + *d = '\0'; + /* if no value is present, error out */ if ( *s == '\0' ) { ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, @@ -145,13 +152,6 @@ ldif_parse_line( goto done; } - /* check for continued line markers that should be deleted */ - for ( p = s, d = s; *p; p++ ) { - if ( *p != CONTINUED_LINE_MARKER ) - *d++ = *p; - } - *d = '\0'; - if ( b64 ) { char *byte = s; @@ -223,14 +223,17 @@ done: } if( !url && value != NULL ) { - value = ber_strdup( value ); - if( value == NULL ) { + p = ber_memalloc( vlen + 1 ); + if( p == NULL ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, "ldif_parse_line: value malloc failed\n"); ber_memfree( type ); ber_memfree( freeme ); return( -1 ); } + memcpy( p, value, vlen ); + p[vlen] = '\0'; + value = p; } ber_memfree( freeme ); @@ -349,6 +352,11 @@ ldif_sput( } #endif + if( vlen == 0 ) { + *(*out)++ = '\n'; + return; + } + switch( type ) { case LDIF_PUT_NOVALUE: *(*out)++ = '\n'; @@ -395,18 +403,18 @@ ldif_sput( *(*out)++ = ' '; len++; - if( vlen == 0 ) { - *(*out)++ = '\n'; - return; - } - stop = (const unsigned char *) (val + vlen); if ( type == LDIF_PUT_VALUE && isgraph( val[0] ) && val[0] != ':' && val[0] != '<' && isgraph( val[vlen-1] ) +#ifndef LDAP_BINARY_DEBUG + && strstr( name, ";binary" ) == NULL +#endif +#ifndef LDAP_PASSWD_DEBUG && strcasecmp( name, "userPassword" ) != 0 /* encode userPassword */ && strcasecmp( name, "2.5.4.35" ) != 0 /* encode userPassword */ +#endif ) { int b64 = 0; diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in index 31e3aa9d8d..87192d2970 100644 --- a/libraries/liblutil/Makefile.in +++ b/libraries/liblutil/Makefile.in @@ -1,15 +1,39 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## -## Makefile for -lutil +## Makefile for -llutil ## LIBRARY = liblutil.a -SRCS = base64.c debug.c detach.c \ - md5.c passwd.c sha1.c getpass.c lockf.c utils.c sockpair.c -OBJS = base64.o debug.o detach.o \ + +NT_SRCS = ntservice.c +NT_OBJS = ntservice.o slapdmsg.res + +UNIX_SRCS = detach.c +UNIX_OBJS = detach.o + +SRCS = base64.c debug.c entropy.c \ + md5.c passwd.c sha1.c getpass.c lockf.c utils.c sockpair.c \ + @LIBSRCS@ $(@PLAT@_SRCS) + +OBJS = base64.o debug.o entropy.o \ md5.o passwd.o sha1.o getpass.o lockf.o utils.o sockpair.o \ - @LIBOBJS@ + @LIBOBJS@ $(@PLAT@_OBJS) LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries +NT_DYN_LIB_DEFS = -DLIBLDAP_DECL=dllimport +CPPFLAGS = $(@PLAT@_@LIB_LINKAGE@_LIB_DEFS) + +# These rules are for a Mingw32 build, specifically. +# It's ok for them to be here because the clean rule is harmless, and +# slapdmsg.res won't get built unless it's declared in OBJS. + +slapdmsg.res: slapdmsg.rc slapdmsg.bin + windres $< -O coff -o $@ + +clean-local: + $(RM) *.res + diff --git a/libraries/liblutil/authpasswd.c b/libraries/liblutil/authpasswd.c new file mode 100644 index 0000000000..1fc4d74c71 --- /dev/null +++ b/libraries/liblutil/authpasswd.c @@ -0,0 +1,929 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * lutil_authpassword(authpasswd, cred) + * + * Returns true if user supplied credentials (cred) matches + * the stored authentication password (authpasswd). + * + * Due to the use of the crypt(3) function + * this routine is NOT thread-safe. + */ + +#include "portable.h" + +#include +#include +#include + +#ifdef SLAPD_KPASSWD +# include +# include +#endif + +#include + +#include +#include + +#ifdef HAVE_SHADOW_H +# include +#endif +#ifdef HAVE_PWD_H +# include +#endif + +#include + +#include "lutil_md5.h" +#include "lutil_sha1.h" +#include "lutil.h" + +static const unsigned char crypt64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; + +struct pw_scheme; + +typedef int (*PASSWD_CHK_FUNC)( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *salt, + const struct berval *cred ); + +typedef int (*PASSWD_HASH_FUNC) ( + const struct pw_scheme *scheme, + const struct berval *cred, + const struct berval *salt, + struct berval **passwd_out, + struct berval **salt_out ); + +/* password check routines */ +static int chk_md5( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *salt, + const struct berval *cred ); + +static int chk_sha1( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *salt, + const struct berval *cred ); + +static int chk_crypt( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *salt, + const struct berval *cred ); + +static int chk_ext( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *salt, + const struct berval *cred ); + +static int chk_ext_kerberos( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +static int chk_ext_unix( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + + +/* password hash routines */ +static int *hash_sha1( + const struct pw_scheme *scheme, + const struct berval *cred, + const struct berval *salt, + struct berval **passwd_out, + struct berval **salt_out ); + +static int *hash_md5( + const struct pw_scheme *scheme, + const struct berval *cred, + const struct berval *salt, + struct berval **passwd_out, + struct berval **salt_out ); + +static int *hash_crypt( + const struct pw_scheme *scheme, + const struct berval *cred, + const struct berval *salt, + struct berval **passwd_out, + struct berval **salt_out ); + + +struct pw_scheme { + struct berval name; + PASSWD_CHK_FUNC chk_fn; + PASSWD_HASH_FUNC hash_fn; + int saltbytes; +}; + +static const struct pw_scheme pw_schemes[] = +{ + { {sizeof("SHA1")-1, "SHA1"}, chk_sha1, 0 /* hash_sha1 */, 4 }, + { {sizeof("MD5")-1, "MD5"}, chk_md5, 0 /* hash_md5 */, 4 }, + +#ifdef SLAPD_CRYPT + { {sizeof("CRYPT")-1, "CRYPT"}, chk_crypt, hash_crypt, 2 }, +#endif + +#ifdef EXT_PASSWD + { {sizeof("EXTERNAL")-1, "EXTERNAL"}, chk_ext, NULL, 0 }, +#endif + + { {0, NULL}, NULL, NULL, 0 } +}; + +#ifdef EXT_PASSWD +struct ext_scheme { + struct berval name; + EXT_CHK_FUNC chk_fn; +}; + +static const struct ext_scheme ext_schemes[] = +{ + { {0, NULL}, NULL, NULL, 0 } +}; +#endif + +static const struct pw_scheme *get_scheme( + const char *scheme ) +{ + int i; + + if( scheme == NULL || *scheme == '\0' ) return NULL; + + for( i=0; pw_schemes[i].name.bv_val; i++) { + if( pw_schemes[i].name.bv_len == 0 ) continue; + + if( strncasecmp( scheme, + pw_schemes[i].name.bv_val, + pw_schemes[i].name.bv_len) == 0 ) + { + return &pw_schemes[i]; + } + } + + return NULL; +} + +int lutil_authpasswd_scheme( + const char *scheme ) +{ + return get_scheme( scheme ) != NULL; +} + + +static int is_allowed_scheme( + const char* scheme, + const char** schemes ) +{ + int i; + + if( scheme == NULL || *scheme == '\0' ) return 1; + + for( i=0; schemes[i] != NULL; i++ ) { + if( strcasecmp( scheme, schemes[i] ) == 0 ) { + return 1; + } + } + return 0; +} + +static int parse_authpasswd( + char **scheme, + struct berval *salt, + struct berval *passwd ) +{ + *scheme = NULL; + return -1; +} + +/* + * Return 0 if creds are good. + */ +int +lutil_authpasswd( + const struct berval *value, /* stored authpasswd */ + const struct berval *cred, /* user cred */ + const char **schemes ) +{ + char *scheme; + struct berval salt, passwd; + const struct pw_scheme *pws; + int rc = -1; + + if (cred == NULL || cred->bv_len == 0 || + value == NULL || value->bv_len == 0 ) + { + return -1; + } + + rc = parse_authpasswd( &scheme, &salt, &passwd ); + + if( rc != 0 ) return -1; + + if( !is_allowed_scheme( scheme, schemes ) ) { + goto done; + } + + pws = get_scheme( scheme ); + + if( pws == NULL || !pws->chk_fn ) { + goto done; + }; + + rc = (pws->chk_fn)( pws, &salt, &passwd, cred ); + +done: + if( scheme != NULL ) { + ber_memfree( scheme ); + ber_memfree( salt.bv_val ); + ber_memfree( passwd.bv_val ); + } + + return rc ? -1 : 0; +} + +struct berval * lutil_authpasswd_generate( ber_len_t len ) +{ + struct berval *pw; + + if( len < 1 ) return NULL; + + pw = ber_memalloc( sizeof( struct berval ) ); + if( pw == NULL ) return NULL; + + pw->bv_len = len; + pw->bv_val = ber_memalloc( len + 1 ); + + if( pw->bv_val == NULL ) { + ber_memfree( pw ); + return NULL; + } + + if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) { + ber_bvfree( pw ); + return NULL; + } + + for( len = 0; len < pw->bv_len; len++ ) { + pw->bv_val[len] = crypt64[ + pw->bv_val[len] % (sizeof(crypt64)-1) ]; + } + + pw->bv_val[len] = '\0'; + + return pw; +} + +int lutil_authpasswd_hash( + const struct berval * cred, + struct berval ** passwd_out, + struct berval ** salt_out, + const char * method ) +{ + const struct pw_scheme *sc; + int rc; + + if( passwd_out == NULL ) return -1; + + sc = get_scheme( method ); + if( sc == NULL || !sc->hash_fn ) return -1; + + if( sc->saltbytes && salt_out != NULL ) { + struct berval salt; + salt.bv_val = ber_memalloc( sc->saltbytes ); + + if( salt.bv_val == NULL ) { + return -1; + } + salt.bv_len = sc->saltbytes; + + if( lutil_entropy( salt.bv_val, salt.bv_len ) < 0 ) { + ber_memfree( salt.bv_val ); + return -1; + } + + rc = (sc->hash_fn)( sc, cred, &salt, passwd_out, NULL ); + ber_memfree( salt.bv_val ); + + } else if ( sc->saltbytes ) { + /* wants salt, disallow */ + return -1; + + } else { + rc = (sc->hash_fn)( sc, cred, NULL, passwd_out, salt_out ); + } + + return rc; +} + +static struct berval * base64( + const struct berval *value ) +{ + int rc; + struct berval *b64; + + assert( value != NULL ); + + if( value == NULL || value->bv_len == 0 ) return NULL; + + b64 = ber_memalloc( sizeof(struct berval) ); + if( b64 == NULL ) return NULL; + + b64->bv_len = LUTIL_BASE64_ENCODE_LEN( value->bv_len ); + b64->bv_val = ber_memalloc( b64->bv_len + 1 ); + + if( b64->bv_val == NULL ) { + ber_memfree( b64 ); + return NULL; + } + + rc = lutil_b64_ntop( + value->bv_val, value->bv_len, + b64->bv_val, b64->bv_len ); + + b64->bv_val[b64->bv_len] = '\0'; + + if( rc < 0 ) { + ber_bvfree( b64 ); + return NULL; + } + + return b64; +} + +/* PASSWORD CHECK ROUTINES */ + +static int chk_sha1( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * salt, + const struct berval * cred ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + int rc; + unsigned char *orig_pass = NULL; + unsigned char *orig_salt = NULL; + int saltlen; + + if( passwd == NULL || passwd->bv_len == 0 ) { + return 1; + } + + /* decode base64 password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) { + rc = -1; + goto done; + } + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + + if( rc < 0 ) { + goto done; + } + + /* decode base64 salt */ + if( salt != NULL && salt->bv_len > 0 ) { + orig_salt = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) ); + + if( orig_salt == NULL ) { + rc = -1; + goto done; + } + + saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len); + + if( saltlen < 0 ) { + goto done; + } + } + + /* hash credentials with salt */ + lutil_SHA1Init(&SHA1context); + lutil_SHA1Update(&SHA1context, + (const unsigned char *) cred->bv_val, cred->bv_len); + if( orig_salt != NULL ) { + lutil_SHA1Update(&SHA1context, + orig_salt, saltlen ); + } + lutil_SHA1Final(SHA1digest, &SHA1context); + + /* compare */ + rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); + +done: + ber_memfree(orig_pass); + ber_memfree(orig_salt); + return rc; +} + +static int chk_md5( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * salt, + const struct berval * cred ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + int rc; + unsigned char *orig_pass = NULL; + unsigned char *orig_salt = NULL; + int saltlen; + + if( passwd == NULL || passwd->bv_len == 0 ) { + return 1; + } + + /* decode base64 password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) { + rc = -1; + goto done; + } + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + + if( rc < 0 ) { + goto done; + } + + /* decode base64 salt */ + if( salt != NULL && salt->bv_len > 0 ) { + orig_salt = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) ); + + if( orig_salt == NULL ) { + rc = -1; + goto done; + } + + saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len); + + if( saltlen < 0 ) { + goto done; + } + } + + /* hash credentials with salt */ + lutil_MD5Init(&MD5context); + lutil_MD5Update(&MD5context, + (const unsigned char *) cred->bv_val, cred->bv_len); + if( orig_salt != NULL ) { + lutil_MD5Update(&MD5context, + orig_salt, saltlen ); + } + lutil_MD5Final(MD5digest, &MD5context); + + /* compare */ + rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); + +done: + ber_memfree(orig_pass); + ber_memfree(orig_salt); + return rc; +} + +#ifdef SLAPD_KPASSWD +static int chk_kerberos( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred, + const struct berval * salt ) +{ + int i; + int rtn; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( cred->bv_val[i] != '\0' ) { + return 1; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return 1; /* passwd must behave like a string */ + } + + rtn = 1; + +#ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */ + { +/* Portions: + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + krb5_context context; + krb5_error_code ret; + krb5_creds creds; + krb5_get_init_creds_opt get_options; + krb5_verify_init_creds_opt verify_options; + krb5_principal client, server; +#ifdef notdef + krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP}; +#endif + + ret = krb5_init_context( &context ); + if (ret) { + return 1; + } + +#ifdef notdef + krb5_get_init_creds_opt_set_preauth_list(&get_options, + pre_auth_types, 1); +#endif + + krb5_get_init_creds_opt_init( &get_options ); + + krb5_verify_init_creds_opt_init( &verify_options ); + + ret = krb5_parse_name( context, passwd->bv_val, &client ); + + if (ret) { + krb5_free_context( context ); + return 1; + } + + ret = krb5_get_init_creds_password( context, + &creds, client, cred->bv_val, NULL, + NULL, 0, NULL, &get_options ); + + if (ret) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } + + { + char host[MAXHOSTNAMELEN]; + + if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } + + ret = krb5_sname_to_principal( context, + host, "ldap", KRB5_NT_SRV_HST, &server ); + } + + if (ret) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } + + ret = krb5_verify_init_creds( context, + &creds, server, NULL, NULL, &verify_options ); + + krb5_free_principal( context, client ); + krb5_free_principal( context, server ); + krb5_free_creds_contents( context, &creds ); + krb5_free_context( context ); + + rtn = !!ret; + } +#elif defined(HAVE_KRB4) + { + /* Borrowed from Heimdal kpopper */ +/* Portions: + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + + int status; + char lrealm[REALM_SZ]; + char tkt[MAXHOSTNAMELEN]; + + status = krb_get_lrealm(lrealm,1); + if (status == KFAILURE) { + return 1; + } + + snprintf(tkt, sizeof(tkt), "%s_slapd.%u", + TKT_ROOT, (unsigned)getpid()); + krb_set_tkt_string (tkt); + + status = krb_verify_user( passwd->bv_val, "", lrealm, + cred->bv_val, 1, "ldap"); + + dest_tkt(); /* no point in keeping the tickets */ + + return status == KFAILURE; + } +#endif + + return rtn; +} +#endif /* SLAPD_KPASSWD */ + +#ifdef SLAPD_CRYPT +static int chk_crypt( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + char *cr; + int i; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( cred->bv_val[i] != '\0' ) { + return 1; /* cred must behave like a string */ + } + + if( passwd->bv_len < 2 ) { + return 1; /* passwd must be at least two characters long */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return 1; /* passwd must behave like a string */ + } + + cr = crypt( cred->bv_val, passwd->bv_val ); + + if( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + return 1; + } + + return strcmp( passwd->bv_val, cr ); +} + +# if defined( HAVE_GETSPNAM ) \ + || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) ) +static int chk_unix( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + int i; + char *pw,*cr; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + if( cred->bv_val[i] != '\0' ) { + return 1; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return 1; /* passwd must behave like a string */ + } + +# ifdef HAVE_GETSPNAM + { + struct spwd *spwd = getspnam(passwd->bv_val); + + if(spwd == NULL) { + return 1; /* not found */ + } + + pw = spwd->sp_pwdp; + } + +# else + { + struct passwd *pwd = getpwnam(passwd->bv_val); + + if(pwd == NULL) { + return 1; /* not found */ + } + + pw = pwd->pw_passwd; + } +# endif + + if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) { + /* password must must be at least two characters long */ + return 1; + } + + cr = crypt(cred->bv_val, pw); + + if( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + return 1; + } + + return strcmp(pw, cr); + +} +# endif +#endif + +/* PASSWORD GENERATION ROUTINES */ + +#ifdef SLAPD_GENERATE + +static struct berval *hash_ssha1( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + unsigned char saltdata[4]; + struct berval digest; + struct berval salt; + + digest.bv_val = SHA1digest; + digest.bv_len = sizeof(SHA1digest); + salt.bv_val = saltdata; + salt.bv_len = sizeof(saltdata); + + if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) { + return NULL; + } + + lutil_SHA1Init( &SHA1context ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)passwd->bv_val, passwd->bv_len ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)salt.bv_val, salt.bv_len ); + lutil_SHA1Final( SHA1digest, &SHA1context ); + + return pw_string64( scheme, &digest, &salt); +} + +static struct berval *hash_sha1( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + struct berval digest; + digest.bv_val = SHA1digest; + digest.bv_len = sizeof(SHA1digest); + + lutil_SHA1Init( &SHA1context ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)passwd->bv_val, passwd->bv_len ); + lutil_SHA1Final( SHA1digest, &SHA1context ); + + return pw_string64( scheme, &digest, NULL); +} + +static struct berval *hash_smd5( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + unsigned char saltdata[4]; + struct berval digest; + struct berval salt; + + digest.bv_val = MD5digest; + digest.bv_len = sizeof(MD5digest); + salt.bv_val = saltdata; + salt.bv_len = sizeof(saltdata); + + if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) { + return NULL; + } + + lutil_MD5Init( &MD5context ); + lutil_MD5Update( &MD5context, + (const unsigned char *) passwd->bv_val, passwd->bv_len ); + lutil_MD5Update( &MD5context, + (const unsigned char *) salt.bv_val, salt.bv_len ); + lutil_MD5Final( MD5digest, &MD5context ); + + return pw_string64( scheme, &digest, &salt ); +} + +static struct berval *hash_md5( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + + struct berval digest; + + digest.bv_val = MD5digest; + digest.bv_len = sizeof(MD5digest); + + lutil_MD5Init( &MD5context ); + lutil_MD5Update( &MD5context, + (const unsigned char *) passwd->bv_val, passwd->bv_len ); + lutil_MD5Final( MD5digest, &MD5context ); + + return pw_string64( scheme, &digest, NULL ); +; +} + +#ifdef SLAPD_CRYPT +static struct berval *hash_crypt( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + struct berval hash; + unsigned char salt[3]; + int i; + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return NULL; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return NULL; /* passwd must behave like a string */ + } + + if( lutil_entropy( salt, sizeof(salt)) < 0 ) { + return NULL; + } + + salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ]; + salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ]; + salt[2] = '\0'; + + hash.bv_val = crypt( passwd->bv_val, salt ); + + if( hash.bv_val == NULL ) return NULL; + + hash.bv_len = strlen( hash.bv_val ); + + if( hash.bv_len == 0 ) { + return NULL; + } + + return pw_string( scheme, &hash ); +} +#endif +#endif \ No newline at end of file diff --git a/libraries/liblutil/base64.c b/libraries/liblutil/base64.c index d4e107b621..1ebd409afb 100644 --- a/libraries/liblutil/base64.c +++ b/libraries/liblutil/base64.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* diff --git a/libraries/liblutil/debug.c b/libraries/liblutil/debug.c index a6fc5064d2..7cf7f64dfe 100644 --- a/libraries/liblutil/debug.c +++ b/libraries/liblutil/debug.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -29,12 +29,14 @@ #include "ldap_log.h" #include "ldap_defaults.h" +#include "lber.h" static FILE *log_file; int lutil_debug_file( FILE *file ) { log_file = file; + ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file ); return 0; } @@ -57,9 +59,10 @@ void (lutil_debug)( int level, int debug, const char *fmt, ... ) if ( log_file == NULL ) return; + + ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file ); } #endif - va_start( vl, fmt ); #ifdef HAVE_VSNPRINTF diff --git a/libraries/liblutil/detach.c b/libraries/liblutil/detach.c index c4f2aa4478..022c2dbd78 100644 --- a/libraries/liblutil/detach.c +++ b/libraries/liblutil/detach.c @@ -72,21 +72,37 @@ lutil_detach( int debug, int do_close ) break; } - if ( do_close ) - for ( i = 3; i < nbits; i++ ) - close( i ); - - (void) chdir( "/" ); - if ( (sd = open( "/dev/null", O_RDWR )) == -1 ) { - perror( "/dev/null" ); - exit( EXIT_FAILURE ); + perror("/dev/null"); } - for ( i = 0; i < 3; i++ ) - if ( sd != i && isatty( i ) ) - (void) dup2( sd, i ); - if ( sd > 2 ) - close( sd ); + + /* close stdin, stdout, stderr */ + close( STDIN_FILENO ); + close( STDOUT_FILENO ); + close( STDERR_FILENO ); + + /* redirect stdin, stdout, stderr to /dev/null */ + dup2( sd, STDIN_FILENO ); + dup2( sd, STDOUT_FILENO ); + dup2( sd, STDERR_FILENO ); + + close( sd ); + + if ( do_close ) { + /* close everything else */ + for ( i = 0; i < nbits; i++ ) { + if( i != STDIN_FILENO && + i != STDOUT_FILENO && + i != STDERR_FILENO ) + { + close( i ); + } + } + } + +#ifdef CHDIR_TO_ROOT + (void) chdir( "/" ); +#endif #ifdef HAVE_SETSID (void) setsid(); diff --git a/libraries/liblutil/entropy.c b/libraries/liblutil/entropy.c new file mode 100644 index 0000000000..1759f7dee1 --- /dev/null +++ b/libraries/liblutil/entropy.c @@ -0,0 +1,151 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include +#include + +#ifdef HAVE_WINCRYPT_H +#include +#endif +#ifdef HAVE_PROCESS_H +#include +#endif + +#include + +#include +#include + +/* + * lutil_entropy() provides nbytes of entropy in buf. + * Quality offerred is suitable for one-time uses, such as "once" keys. + * Values may not be suitable for multi-time uses. + * + * Note: Callers are encouraged to provide additional bytes of + * of entropy in the buf argument. This information is used in + * fallback mode to improve the quality of bytes returned. + * + * This routinue should be extended to support additional sources + * of entropy. + */ +int lutil_entropy( char *buf, ber_len_t nbytes ) +{ + if( nbytes == 0 ) return 0; + +#ifdef URANDOM_DEVICE + /* Linux and *BSD offer a urandom device */ + { + int rc, fd; + + fd = open( URANDOM_DEVICE, O_RDONLY ); + + if( fd < 0 ) return -1; + + rc = read( fd, buf, nbytes ); + close(fd); + + /* should return nbytes */ + if( rc < nbytes ) return -1; + + return 0; + } +#elif PROV_RSA_FULL + { + /* Not used since _WIN32_WINNT not set... */ + HCRYPTPROV hProv = 0; + + /* Get handle to user default provider */ + if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { + return -1; + } + + /* Generate random initialization vector */ + if(!CryptGenRandom(hProv, (DWORD) nbytes, (BYTE *) buf)) { + return -1; + } + + /* Release provider handle */ + if(hProv != 0) CryptReleaseContext(hProv, 0); + + return 0; + } +#else + { + /* based upon Phil Karn's "practical randomness" idea + * but implementation 100% OpenLDAP. So don't blame Phil. + * + * Worse case is that this is a MD5 hash of a counter, if + * MD5 is a strong cryptographic hash, this should be fairly + * resistant to attack + */ + + /* + * the caller may need to provide external synchronization OR + * provide entropy (in buf) to ensure quality results as + * access to this counter may not be atomic. + */ + static int counter = 0; + ber_len_t n; + + struct rdata_s { + int counter; + + char *buf; + struct rdata_s *stack; + + pid_t pid; + +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; +#else + time_t time; +#endif + + unsigned long junk; /* purposely not initialized */ + } rdata; + + /* make sure rdata differs for each process */ + rdata.pid = getpid(); + + /* make sure rdata differs for each program */ + rdata.buf = buf; + rdata.stack = &rdata; + + for( n = 0; n < nbytes; n += 16 ) { + struct lutil_MD5Context ctx; + char digest[16]; + + /* poor resolution */ +#ifdef HAVE_GETTIMEOFDAY + (void) gettimeofday( &rdata.tv, NULL ); +#else + (void) time( &rdata.time ); +#endif + + /* make sure rdata differs */ + rdata.counter = ++counter; + rdata.pid++; + rdata.junk++; + + lutil_MD5Init( &ctx ); + lutil_MD5Update( &ctx, (char *) &rdata, sizeof( rdata ) ); + + /* allow caller to provided additional entropy */ + lutil_MD5Update( &ctx, (char *) &buf, nbytes ); + + lutil_MD5Final( digest, &ctx ); + + memcpy( &buf[n], digest, + nbytes - n >= 16 ? 16 : nbytes - n ); + } + + return 0; + } +#endif + return -1; +} diff --git a/libraries/liblutil/getopt.c b/libraries/liblutil/getopt.c index 3b0ca476a5..c85305a8ea 100644 --- a/libraries/liblutil/getopt.c +++ b/libraries/liblutil/getopt.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -59,6 +59,7 @@ int getopt (int argc, char * const argv [], const char * opts) printf("DF_TRACE_DEBUG: int getopt () in getopt.c\n"); #endif if (sp == 1) + { if (optind >= argc || argv[optind][0] != sw || argv[optind][1] == eos) return EOF; @@ -67,6 +68,7 @@ printf("DF_TRACE_DEBUG: int getopt () in getopt.c\n"); optind++; return EOF; } + } c = argv[optind][sp]; optopt = (int) c; if (c == arg || (cp = strchr(opts,c)) == NULL) diff --git a/libraries/liblutil/getpass.c b/libraries/liblutil/getpass.c index ce8f6de8c8..7da409108e 100644 --- a/libraries/liblutil/getpass.c +++ b/libraries/liblutil/getpass.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -17,8 +17,6 @@ #include "portable.h" -#ifndef HAVE_GETPASS - #include #include @@ -30,6 +28,8 @@ #include #include +#ifdef NEED_GETPASSPHRASE + #ifdef HAVE_FCNTL_H #include #endif @@ -44,16 +44,19 @@ #include "ldap_defaults.h" char * -getpass( const char *prompt ) +lutil_getpass( const char *prompt ) { #if !defined(HAVE_POSIX_TERMIOS) && !defined(HAVE_SGTTY_H) static char buf[256]; int i, c; + if( prompt == NULL ) prompt = "Password: "; + #ifdef DEBUG if (debug & D_TRACE) printf("->getpass(%s)\n", prompt); #endif + printf("%s", prompt); i = 0; while ( (c = getch()) != EOF && c != '\n' && c != '\r' ) @@ -73,6 +76,8 @@ getpass( const char *prompt ) FILE *fi; RETSIGTYPE (*sig)( int sig ); + if( prompt == NULL ) prompt = "Password: "; + #ifdef DEBUG if (debug & D_TRACE) printf("->getpass(%s)\n", prompt); @@ -155,4 +160,4 @@ getpass( const char *prompt ) #endif } -#endif /* !HAVE_GETPASS */ +#endif /* !NEED_GETPASSPHRASE */ diff --git a/libraries/liblutil/liblutil.dsp b/libraries/liblutil/liblutil.dsp index 54800a3eca..121921e985 100644 --- a/libraries/liblutil/liblutil.dsp +++ b/libraries/liblutil/liblutil.dsp @@ -39,9 +39,10 @@ CPP=cl.exe # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\Release" -# PROP Intermediate_Dir "Release\liblutil" +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\liblutil" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -49,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Release\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\Release\olutil32.lib" !ELSEIF "$(CFG)" == "liblutil - Win32 Debug" @@ -60,9 +61,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\Debug" -# PROP Intermediate_Dir "Debug\liblutil" +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\liblutil" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -70,7 +72,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\Debug\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\Debug\olutil32.lib" !ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug" @@ -81,9 +83,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\SDebug" -# PROP Intermediate_Dir "SDebug\liblutil" +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\liblutil" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -91,7 +94,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Debug\olutil32.lib" -# ADD LIB32 /nologo /out:"..\SDebug\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\SDebug\olutil32.lib" !ELSEIF "$(CFG)" == "liblutil - Win32 Single Release" @@ -102,9 +105,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\SRelease" -# PROP Intermediate_Dir "SRelease\liblutil" +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\liblutil" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -112,7 +116,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo /out:"..\Release\olutil32.lib" -# ADD LIB32 /nologo /out:"..\SRelease\olutil32.lib" +# ADD LIB32 /nologo /out:"..\..\SRelease\olutil32.lib" !ENDIF @@ -124,6 +128,10 @@ LIB32=link.exe -lib # Name "liblutil - Win32 Single Release" # Begin Source File +SOURCE=.\authpasswd.c +# End Source File +# Begin Source File + SOURCE=.\base64.c # End Source File # Begin Source File @@ -136,6 +144,10 @@ SOURCE=.\debug.c # End Source File # Begin Source File +SOURCE=.\entropy.c +# End Source File +# Begin Source File + SOURCE="..\..\include\getopt-compat.h" # End Source File # Begin Source File @@ -176,10 +188,6 @@ SOURCE=.\md5.c # End Source File # Begin Source File -SOURCE=.\nt_err.c -# End Source File -# Begin Source File - SOURCE=.\ntservice.c # End Source File # Begin Source File @@ -201,7 +209,7 @@ SOURCE=.\slapdmsg.mc !IF "$(CFG)" == "liblutil - Win32 Release" # Begin Custom Build - Building slapd message file -IntDir=.\Release\liblutil +IntDir=.\..\..\Release\liblutil InputPath=.\slapdmsg.mc "slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" @@ -214,7 +222,7 @@ InputPath=.\slapdmsg.mc !ELSEIF "$(CFG)" == "liblutil - Win32 Debug" # Begin Custom Build - Building slapd message file -IntDir=.\Debug\liblutil +IntDir=.\..\..\Debug\liblutil InputPath=.\slapdmsg.mc "slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" @@ -227,7 +235,7 @@ InputPath=.\slapdmsg.mc !ELSEIF "$(CFG)" == "liblutil - Win32 Single Debug" # Begin Custom Build - Building slapd message file -IntDir=.\SDebug\liblutil +IntDir=.\..\..\SDebug\liblutil InputPath=.\slapdmsg.mc "slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" @@ -240,7 +248,7 @@ InputPath=.\slapdmsg.mc !ELSEIF "$(CFG)" == "liblutil - Win32 Single Release" # Begin Custom Build - Building slapd message file -IntDir=.\SRelease\liblutil +IntDir=.\..\..\SRelease\liblutil InputPath=.\slapdmsg.mc "slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" diff --git a/libraries/liblutil/lockf.c b/libraries/liblutil/lockf.c index a3424ba146..7ba5c0ea50 100644 --- a/libraries/liblutil/lockf.c +++ b/libraries/liblutil/lockf.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA + * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -79,7 +79,7 @@ int lutil_unlockf ( int fd ) { int lutil_lockf ( int fd ) { struct flock file_lock; - memset( &file_lock, 0, sizeof( file_lock ) ); + memset( &file_lock, '\0', sizeof( file_lock ) ); file_lock.l_type = F_WRLCK; file_lock.l_whence = SEEK_SET; file_lock.l_start = 0; @@ -92,7 +92,7 @@ int lutil_lockf ( int fd ) { int lutil_unlockf ( int fd ) { struct flock file_lock; - memset( &file_lock, 0, sizeof( file_lock ) ); + memset( &file_lock, '\0', sizeof( file_lock ) ); file_lock.l_type = F_UNLCK; file_lock.l_whence = SEEK_SET; file_lock.l_start = 0; diff --git a/libraries/liblutil/md5.c b/libraries/liblutil/md5.c index 6758de0240..9ce509f8ff 100644 --- a/libraries/liblutil/md5.c +++ b/libraries/liblutil/md5.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -44,12 +44,12 @@ #include /* Little-endian byte-swapping routines. Note that these do not - depend on the size of datatypes such as uint32, nor do they require + depend on the size of datatypes such as ber_uint_t, nor do they require us to detect the endianness of the machine we are running on. It is possible they should be macros for speed, but I would be surprised if they were a performance bottleneck for MD5. */ -static uint32 +static ber_uint_t getu32( const unsigned char *addr ) { return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) @@ -57,7 +57,7 @@ getu32( const unsigned char *addr ) } static void -putu32( uint32 data, unsigned char *addr ) +putu32( ber_uint_t data, unsigned char *addr ) { addr[0] = (unsigned char)data; addr[1] = (unsigned char)(data >> 8); @@ -89,15 +89,15 @@ void lutil_MD5Update( struct lutil_MD5Context *ctx, const unsigned char *buf, - unsigned int len + ber_len_t len ) { - uint32 t; + ber_uint_t t; /* Update bitcount */ t = ctx->bits[0]; - if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t) + if ((ctx->bits[0] = (t + ((ber_uint_t)len << 3)) & 0xffffffff) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; @@ -157,14 +157,14 @@ lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx ) /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); + memset(p, '\0', count); lutil_MD5Transform(ctx->buf, ctx->in); /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); + memset(ctx->in, '\0', 56); } else { /* Pad block to 56 bytes */ - memset(p, 0, count-8); + memset(p, '\0', count-8); } /* Append length in bits and transform */ @@ -176,7 +176,7 @@ lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx ) putu32(ctx->buf[1], digest + 4); putu32(ctx->buf[2], digest + 8); putu32(ctx->buf[3], digest + 12); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + memset(ctx, '\0', sizeof(ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 @@ -199,10 +199,10 @@ lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx ) * the data and converts bytes into longwords for this routine. */ void -lutil_MD5Transform( uint32 *buf, const unsigned char *inraw ) +lutil_MD5Transform( ber_uint_t *buf, const unsigned char *inraw ) { - register uint32 a, b, c, d; - uint32 in[16]; + register ber_uint_t a, b, c, d; + ber_uint_t in[16]; int i; for (i = 0; i < 16; ++i) @@ -297,7 +297,7 @@ int main (int argc, char **argv ) { struct lutil_MD5Context context; - unsigned char checksum[16]; + unsigned char checksum[LUTIL_MD5_BYTES]; int i; int j; @@ -312,7 +312,7 @@ main (int argc, char **argv ) lutil_MD5Init (&context); lutil_MD5Update (&context, argv[j], strlen (argv[j])); lutil_MD5Final (checksum, &context); - for (i = 0; i < 16; i++) + for (i = 0; i < LUTIL_MD5_BYTES; i++) { printf ("%02x", (unsigned int) checksum[i]); } diff --git a/libraries/liblutil/ntservice.c b/libraries/liblutil/ntservice.c index e1554a5cb4..657974ae7c 100644 --- a/libraries/liblutil/ntservice.c +++ b/libraries/liblutil/ntservice.c @@ -1,11 +1,18 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ -/* ntservice.c */ + +/* + * NT Service manager utilities for OpenLDAP services + * these should NOT be slapd specific, but are + */ + #include "portable.h" +#ifdef HAVE_NT_SERVICE_MANAGER + #include #include @@ -41,10 +48,10 @@ ldap_pvt_thread_t start_status_tid, stop_status_tid; void (*stopfunc)(int); -/* in nt_err.c */ -char *GetLastErrorString( void ); +static char *GetLastErrorString( void ); -int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) +int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName, + LPCTSTR lpszBinaryPathName, BOOL auto_start) { HKEY hKey; DWORD dwValue, dwDisposition; @@ -56,10 +63,10 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) if ((schService = CreateService( schSCManager, lpszServiceName, - TEXT("OpenLDAP Directory Service"), - SC_MANAGER_CREATE_SERVICE, + lpszDisplayName, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, + auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL)) != NULL) @@ -76,13 +83,13 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) { - fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS) { - fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } @@ -90,7 +97,7 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) dwValue = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS) { - fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); RegCloseKey(hKey); return(0); } @@ -99,13 +106,13 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) } else { - fprintf( stderr, "CreateService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "CreateService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); CloseServiceHandle(schSCManager); return(0); } } else - fprintf( stderr, "OpenSCManager() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); return(0); } @@ -125,20 +132,20 @@ int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) CloseServiceHandle(schSCManager); return(1); } else { - fprintf( stderr, "DeleteService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "DeleteService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); fprintf( stderr, "The %s service has not been removed.\n", lpszBinaryPathName); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return(0); } } else { - fprintf( stderr, "OpenService() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "OpenService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); CloseServiceHandle(schSCManager); return(0); } } else - fprintf( stderr, "OpenSCManager() failed. GetLastError=%d (%s)\n", GetLastError(), GetLastErrorString() ); + fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); return(0); } @@ -291,7 +298,7 @@ void *getRegParam( char *svc, char *value ) DWORD valLen = sizeof( vValue ); if ( svc != NULL ) - sprintf ( path, "SOFTWARE\\OpenLDAP\\%s\\Parameters", svc ); + sprintf ( path, "SOFTWARE\\%s", svc ); else strcpy (path, "SOFTWARE\\OpenLDAP\\Parameters" ); @@ -330,12 +337,12 @@ void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *ur Inserts[i] = (char *)malloc( 20 ); itoa( slap_debug, Inserts[i++], 10 ); - Inserts[i++] = ldap_pvt_strdup( configfile ); - Inserts[i++] = ldap_pvt_strdup( urls ? urls : "ldap:///" ); - Inserts[i++] = ldap_pvt_strdup( is_NT_Service ? "svc" : "cmd" ); + Inserts[i++] = strdup( configfile ); + Inserts[i++] = strdup( urls ? urls : "ldap:///" ); + Inserts[i++] = strdup( is_NT_Service ? "svc" : "cmd" ); ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, - MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL ); + MSG_SLAPD_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL ); for ( j = 0; j < i; j++ ) ldap_memfree( Inserts[j] ); @@ -425,3 +432,22 @@ void ReportSlapdShutdownComplete( ) SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); } } + +static char *GetErrorString( int err ) +{ + static char msgBuf[1024]; + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + msgBuf, 1024, NULL ); + + return msgBuf; +} + +static char *GetLastErrorString( void ) +{ + return GetErrorString( GetLastError() ); +} +#endif diff --git a/libraries/liblutil/passwd.c b/libraries/liblutil/passwd.c index d350770ef9..becde0e6c5 100644 --- a/libraries/liblutil/passwd.c +++ b/libraries/liblutil/passwd.c @@ -1,13 +1,16 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* - * lutil_password(credentials, password) + * int lutil_passwd( + * const struct berval *passwd, + * const struct berval *cred, + * const char **schemes ) * - * Returns true if user supplied credentials matches - * the stored password. + * Returns true if user supplied credentials (cred) matches + * the stored password (passwd). * * Due to the use of the crypt(3) function * this routine is NOT thread-safe. @@ -15,14 +18,23 @@ #include "portable.h" +#include #include - #include -#include -#include "lutil_md5.h" -#include "lutil_sha1.h" -#include "lutil.h" +#ifdef SLAPD_SPASSWD +# include +#endif + +#ifdef SLAPD_KPASSWD +# include +# include +#endif + +#include + +#include +#include #ifdef HAVE_SHADOW_H # include @@ -30,41 +42,206 @@ #ifdef HAVE_PWD_H # include #endif +#ifdef HAVE_AIX_SECURITY +# include +#endif + +#include + +#include "lutil_md5.h" +#include "lutil_sha1.h" +#include "lutil.h" + +static const unsigned char crypt64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; + +struct pw_scheme; + +typedef int (*PASSWD_CHK_FUNC)( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +typedef struct berval * (*PASSWD_HASH_FUNC) ( + const struct pw_scheme *scheme, + const struct berval *passwd ); + +struct pw_scheme { + struct berval name; + PASSWD_CHK_FUNC chk_fn; + PASSWD_HASH_FUNC hash_fn; +}; + +/* password check routines */ +static int chk_md5( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +static int chk_smd5( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +static int chk_ssha1( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +static int chk_sha1( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +#ifdef SLAPD_SPASSWD +static int chk_sasl( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); +#endif + +#ifdef SLAPD_KPASSWD +static int chk_kerberos( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); +#endif + +#ifdef SLAPD_CRYPT +static int chk_crypt( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); + +#if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +static int chk_unix( + const struct pw_scheme *scheme, + const struct berval *passwd, + const struct berval *cred ); +#endif +#endif + + +/* password hash routines */ +static struct berval *hash_sha1( + const struct pw_scheme *scheme, + const struct berval *passwd ); + +static struct berval *hash_ssha1( + const struct pw_scheme *scheme, + const struct berval *passwd ); + +static struct berval *hash_smd5( + const struct pw_scheme *scheme, + const struct berval *passwd ); + +static struct berval *hash_md5( + const struct pw_scheme *scheme, + const struct berval *passwd ); + +#ifdef SLAPD_CRYPT +static struct berval *hash_crypt( + const struct pw_scheme *scheme, + const struct berval *passwd ); +#endif + -static int supported_hash( - const char* method, - const char** methods ) +static const struct pw_scheme pw_schemes[] = +{ + { {sizeof("{SSHA}")-1, "{SSHA}"}, chk_ssha1, hash_ssha1 }, + { {sizeof("{SHA}")-1, "{SHA}"}, chk_sha1, hash_sha1 }, + + { {sizeof("{SMD5}")-1, "{SMD5}"}, chk_smd5, hash_smd5 }, + { {sizeof("{MD5}")-1, "{MD5}"}, chk_md5, hash_md5 }, + +#ifdef SLAPD_SPASSWD + { {sizeof("{SASL}")-1, "{SASL}"}, chk_sasl, NULL }, +#endif + +#ifdef SLAPD_KPASSWD + { {sizeof("{KERBEROS}")-1, "{KERBEROS}"}, chk_kerberos, NULL }, +#endif + +#ifdef SLAPD_CRYPT + { {sizeof("{CRYPT}")-1, "{CRYPT}"}, chk_crypt, hash_crypt }, +# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) + { {sizeof("{UNIX}")-1, "{UNIX}"}, chk_unix, NULL }, +# endif +#endif + +#ifdef SLAPD_CLEARTEXT + /* psuedo scheme */ + { {0, "{CLEARTEXT}"}, NULL, NULL }, +#endif + + { {0, NULL}, NULL, NULL } +}; + +static const struct pw_scheme *get_scheme( + const char* scheme ) { int i; - if(methods == NULL) { - return 1; + for( i=0; pw_schemes[i].name.bv_val; i++) { + if( pw_schemes[i].name.bv_len == 0 ) continue; + + if( strncasecmp(scheme, pw_schemes[i].name.bv_val, + pw_schemes[i].name.bv_len) == 0 ) + { + return &pw_schemes[i]; + } } - for(i=0; methods[i] != NULL; i++) { - if(strcasecmp(method, methods[i]) == 0) { + return NULL; +} + +int lutil_passwd_scheme( + const char* scheme ) +{ + if( scheme == NULL ) { + return 0; + } + + return get_scheme(scheme) != NULL; +} + + +static int is_allowed_scheme( + const char* scheme, + const char** schemes ) +{ + int i; + + if( schemes == NULL ) return 1; + + for( i=0; schemes[i] != NULL; i++ ) { + if( strcasecmp( scheme, schemes[i] ) == 0 ) { return 1; } } - return 0; } -static const char *passwd_hash( - const char* passwd, - const char* method, - const char** methods ) +static struct berval *passwd_scheme( + const struct pw_scheme *scheme, + const struct berval * passwd, + const char** allowed ) { - int len; - - if( !supported_hash( method, methods ) ) { + if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) { return NULL; } - len = strlen(method); + if( passwd->bv_len >= scheme->name.bv_len ) { + if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) { + struct berval *bv = ber_memalloc( sizeof(struct berval) ); - if( strncasecmp( passwd, method, len ) == 0 ) { - return &passwd[len]; + if( bv == NULL ) return NULL; + + bv->bv_val = &passwd->bv_val[scheme->name.bv_len]; + bv->bv_len = passwd->bv_len - scheme->name.bv_len; + + return bv; + } } return NULL; @@ -75,144 +252,796 @@ static const char *passwd_hash( */ int lutil_passwd( - const char *cred, - const char *passwd, - const char **methods) + const struct berval *passwd, /* stored passwd */ + const struct berval *cred, /* user cred */ + const char **schemes ) { - const char *p; + int i; - if (cred == NULL || passwd == NULL) { + if (cred == NULL || cred->bv_len == 0 || + passwd == NULL || passwd->bv_len == 0 ) + { return -1; } - if ((p = passwd_hash( passwd, "{MD5}", methods )) != NULL ) { - lutil_MD5_CTX MD5context; - unsigned char MD5digest[16]; - char base64digest[25]; /* ceiling(sizeof(input)/3) * 4 + 1 */ + for( i=0; pw_schemes[i].name.bv_val != NULL; i++ ) { + if( pw_schemes[i].chk_fn ) { + struct berval *p = passwd_scheme( &pw_schemes[i], + passwd, schemes ); - lutil_MD5Init(&MD5context); - lutil_MD5Update(&MD5context, - (const unsigned char *)cred, strlen(cred)); - lutil_MD5Final(MD5digest, &MD5context); + if( p != NULL ) { + int rc = (pw_schemes[i].chk_fn)( &pw_schemes[i], p, cred ); - if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest), - base64digest, sizeof(base64digest)) < 0) - { - return ( 1 ); + /* only free the berval structure as the bv_val points + * into passwd->bv_val + */ + ber_memfree( p ); + + return rc; + } } + } + +#ifdef SLAPD_CLEARTEXT + if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) { + return passwd->bv_len == cred->bv_len + ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len ) + : 1; + } +#endif + return 1; +} - return( strcmp(p, base64digest) ); +struct berval * lutil_passwd_generate( ber_len_t len ) +{ + struct berval *pw; - } else if ((p = passwd_hash( passwd, "{SHA}", methods )) != NULL ) { - lutil_SHA1_CTX SHA1context; - unsigned char SHA1digest[20]; - char base64digest[29]; /* ceiling(sizeof(input)/3) * 4 + 1 */ + if( len < 1 ) return NULL; - lutil_SHA1Init(&SHA1context); - lutil_SHA1Update(&SHA1context, - (const unsigned char *) cred, strlen(cred)); - lutil_SHA1Final(SHA1digest, &SHA1context); + pw = ber_memalloc( sizeof( struct berval ) ); + if( pw == NULL ) return NULL; - if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest), - base64digest, sizeof(base64digest)) < 0) - { - return ( 1 ); + pw->bv_len = len; + pw->bv_val = ber_memalloc( len + 1 ); + + if( pw->bv_val == NULL ) { + ber_memfree( pw ); + return NULL; + } + + if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) { + ber_bvfree( pw ); + return NULL; + } + + for( len = 0; len < pw->bv_len; len++ ) { + pw->bv_val[len] = crypt64[ + pw->bv_val[len] % (sizeof(crypt64)-1) ]; + } + + pw->bv_val[len] = '\0'; + + return pw; +} + +struct berval * lutil_passwd_hash( + const struct berval * passwd, + const char * method ) +{ + const struct pw_scheme *sc = get_scheme( method ); + + if( sc == NULL ) return NULL; + if( ! sc->hash_fn ) return NULL; + + return (sc->hash_fn)( sc, passwd ); +} + +static struct berval * pw_string( + const struct pw_scheme *sc, + const struct berval *passwd ) +{ + struct berval *pw = ber_memalloc( sizeof( struct berval ) ); + if( pw == NULL ) return NULL; + + pw->bv_len = sc->name.bv_len + passwd->bv_len; + pw->bv_val = ber_memalloc( pw->bv_len + 1 ); + + if( pw->bv_val == NULL ) { + ber_memfree( pw ); + return NULL; + } + + memcpy( pw->bv_val, sc->name.bv_val, sc->name.bv_len ); + memcpy( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len ); + + pw->bv_val[pw->bv_len] = '\0'; + return pw; +} + +static struct berval * pw_string64( + const struct pw_scheme *sc, + const struct berval *hash, + const struct berval *salt ) +{ + int rc; + struct berval string; + struct berval *b64 = ber_memalloc( sizeof(struct berval) ); + size_t b64len; + + if( b64 == NULL ) return NULL; + + if( salt ) { + /* need to base64 combined string */ + string.bv_len = hash->bv_len + salt->bv_len; + string.bv_val = ber_memalloc( string.bv_len + 1 ); + + if( string.bv_val == NULL ) { + ber_memfree( b64 ); + return NULL; } - return( strcmp(p, base64digest) ); + memcpy( string.bv_val, hash->bv_val, + hash->bv_len ); + memcpy( &string.bv_val[hash->bv_len], salt->bv_val, + salt->bv_len ); + string.bv_val[string.bv_len] = '\0'; + + } else { + string = *hash; + } + + b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1; + b64->bv_len = b64len + sc->name.bv_len; + b64->bv_val = ber_memalloc( b64->bv_len + 1 ); + + if( b64->bv_val == NULL ) { + if( salt ) ber_memfree( string.bv_val ); + ber_memfree( b64 ); + return NULL; + } + + memcpy(b64->bv_val, sc->name.bv_val, sc->name.bv_len); + + rc = lutil_b64_ntop( + string.bv_val, string.bv_len, + &b64->bv_val[sc->name.bv_len], b64len ); + + if( salt ) ber_memfree( string.bv_val ); + + if( rc < 0 ) { + ber_bvfree( b64 ); + return NULL; + } + + /* recompute length */ + b64->bv_len = sc->name.bv_len + rc; + assert( strlen(b64->bv_val) == b64->bv_len ); + return b64; +} - } else if ((p = passwd_hash( passwd, "{SSHA}", methods )) != NULL ) { - lutil_SHA1_CTX SHA1context; - unsigned char SHA1digest[20]; - int pw_len = strlen(p); - int rc; - unsigned char *orig_pass = NULL; +/* PASSWORD CHECK ROUTINES */ + +static int chk_ssha1( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + int rc; + unsigned char *orig_pass = NULL; - /* base64 un-encode password */ - orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1)); - if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0) - { - free(orig_pass); - return ( 1 ); - } + /* decode base64 password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) return -1; + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + + if(rc < 0) { + ber_memfree(orig_pass); + return -1; + } + + /* hash credentials with salt */ + lutil_SHA1Init(&SHA1context); + lutil_SHA1Update(&SHA1context, + (const unsigned char *) cred->bv_val, cred->bv_len); + lutil_SHA1Update(&SHA1context, + (const unsigned char *) &orig_pass[sizeof(SHA1digest)], + rc - sizeof(SHA1digest)); + lutil_SHA1Final(SHA1digest, &SHA1context); + + /* compare */ + rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); + ber_memfree(orig_pass); + return rc ? 1 : 0; +} + +static int chk_sha1( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + int rc; + unsigned char *orig_pass = NULL; - /* hash credentials with salt */ - lutil_SHA1Init(&SHA1context); - lutil_SHA1Update(&SHA1context, - (const unsigned char *) cred, strlen(cred)); - lutil_SHA1Update(&SHA1context, - (const unsigned char *) orig_pass + sizeof(SHA1digest), - rc - sizeof(SHA1digest)); - lutil_SHA1Final(SHA1digest, &SHA1context); + /* base64 un-encode password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) return -1; + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + + if( rc != sizeof(SHA1digest) ) { + ber_memfree(orig_pass); + return -1; + } + + /* hash credentials with salt */ + lutil_SHA1Init(&SHA1context); + lutil_SHA1Update(&SHA1context, + (const unsigned char *) cred->bv_val, cred->bv_len); + lutil_SHA1Final(SHA1digest, &SHA1context); - /* compare */ - rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); - free(orig_pass); - return(rc); - - } else if ((p = passwd_hash( passwd, "{SMD5}", methods )) != NULL ) { - lutil_MD5_CTX MD5context; - unsigned char MD5digest[16]; - int pw_len = strlen(p); - int rc; - unsigned char *orig_pass = NULL; - - /* base64 un-encode password */ - orig_pass = (unsigned char *)malloc((size_t)(pw_len * 0.75 + 1)); - if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0) + /* compare */ + rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); + ber_memfree(orig_pass); + return rc ? 1 : 0; +} + +static int chk_smd5( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + int rc; + unsigned char *orig_pass = NULL; + + /* base64 un-encode password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) return -1; + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + if ( rc < 0 ) { + ber_memfree(orig_pass); + return -1; + } + + /* hash credentials with salt */ + lutil_MD5Init(&MD5context); + lutil_MD5Update(&MD5context, + (const unsigned char *) cred->bv_val, cred->bv_len ); + lutil_MD5Update(&MD5context, + (const unsigned char *) &orig_pass[sizeof(MD5digest)], + rc - sizeof(MD5digest)); + lutil_MD5Final(MD5digest, &MD5context); + + /* compare */ + rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); + ber_memfree(orig_pass); + return rc ? 1 : 0; +} + +static int chk_md5( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + int rc; + unsigned char *orig_pass = NULL; + + /* base64 un-encode password */ + orig_pass = (unsigned char *) ber_memalloc( (size_t) ( + LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) ); + + if( orig_pass == NULL ) return -1; + + rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len); + if ( rc != sizeof(MD5digest) ) { + ber_memfree(orig_pass); + return -1; + } + + /* hash credentials with salt */ + lutil_MD5Init(&MD5context); + lutil_MD5Update(&MD5context, + (const unsigned char *) cred->bv_val, cred->bv_len ); + lutil_MD5Final(MD5digest, &MD5context); + + /* compare */ + rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); + ber_memfree(orig_pass); + return rc ? 1 : 0; +} + +#ifdef SLAPD_SPASSWD +#ifdef HAVE_CYRUS_SASL +sasl_conn_t *lutil_passwd_sasl_conn = NULL; +#endif + +static int chk_sasl( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + int i; + int rtn; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( cred->bv_val[i] != '\0' ) { + return 1; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return 1; /* passwd must behave like a string */ + } + + rtn = 1; + +#ifdef HAVE_CYRUS_SASL + if( lutil_passwd_sasl_conn != NULL ) { + const char *errstr = NULL; + int sc; + + sc = sasl_checkpass( lutil_passwd_sasl_conn, + passwd->bv_val, passwd->bv_len, + cred->bv_val, cred->bv_len, + &errstr ); + + rtn = ( sc != SASL_OK ); + } +#endif + + return rtn; +} +#endif + +#ifdef SLAPD_KPASSWD +static int chk_kerberos( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + int i; + int rtn; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( cred->bv_val[i] != '\0' ) { + return 1; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return 1; /* passwd must behave like a string */ + } + + rtn = 1; + +#ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */ + { +/* Portions: + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + krb5_context context; + krb5_error_code ret; + krb5_creds creds; + krb5_get_init_creds_opt get_options; + krb5_verify_init_creds_opt verify_options; + krb5_principal client, server; +#ifdef notdef + krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP}; +#endif + + ret = krb5_init_context( &context ); + if (ret) { + return 1; + } + +#ifdef notdef + krb5_get_init_creds_opt_set_preauth_list(&get_options, + pre_auth_types, 1); +#endif + + krb5_get_init_creds_opt_init( &get_options ); + + krb5_verify_init_creds_opt_init( &verify_options ); + + ret = krb5_parse_name( context, passwd->bv_val, &client ); + + if (ret) { + krb5_free_context( context ); + return 1; + } + + ret = krb5_get_init_creds_password( context, + &creds, client, cred->bv_val, NULL, + NULL, 0, NULL, &get_options ); + + if (ret) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } + { - free(orig_pass); - return ( 1 ); + char host[MAXHOSTNAMELEN]; + + if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } + + ret = krb5_sname_to_principal( context, + host, "ldap", KRB5_NT_SRV_HST, &server ); } - /* hash credentials with salt */ - lutil_MD5Init(&MD5context); - lutil_MD5Update(&MD5context, - (const unsigned char *) cred, strlen(cred)); - lutil_MD5Update(&MD5context, - (const unsigned char *) orig_pass + sizeof(MD5digest), - rc - sizeof(MD5digest)); - lutil_MD5Final(MD5digest, &MD5context); + if (ret) { + krb5_free_principal( context, client ); + krb5_free_context( context ); + return 1; + } - /* compare */ - rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); - free(orig_pass); - return ( rc ); + ret = krb5_verify_init_creds( context, + &creds, server, NULL, NULL, &verify_options ); + + krb5_free_principal( context, client ); + krb5_free_principal( context, server ); + krb5_free_creds_contents( context, &creds ); + krb5_free_context( context ); + + rtn = !!ret; + } +#elif defined(HAVE_KRB4) + { + /* Borrowed from Heimdal kpopper */ +/* Portions: + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + + int status; + char lrealm[REALM_SZ]; + char tkt[MAXHOSTNAMELEN]; + + status = krb_get_lrealm(lrealm,1); + if (status == KFAILURE) { + return 1; + } + + snprintf(tkt, sizeof(tkt), "%s_slapd.%u", + TKT_ROOT, (unsigned)getpid()); + krb_set_tkt_string (tkt); + + status = krb_verify_user( passwd->bv_val, "", lrealm, + cred->bv_val, 1, "ldap"); + + dest_tkt(); /* no point in keeping the tickets */ + + return status == KFAILURE; + } +#endif + + return rtn; +} +#endif /* SLAPD_KPASSWD */ #ifdef SLAPD_CRYPT - } else if ((p = passwd_hash( passwd, "{CRYPT}", methods )) != NULL ) { - return( strcmp(p, crypt(cred, p)) ); +static int chk_crypt( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + char *cr; + int i; -# if defined( HAVE_GETSPNAM ) \ - || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) ) - } else if ((p = passwd_hash( passwd, "{UNIX}", methods )) != NULL ) { + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return 1; /* NUL character in password */ + } + } -# ifdef HAVE_GETSPNAM - struct spwd *spwd = getspnam(p); + if( cred->bv_val[i] != '\0' ) { + return -1; /* cred must behave like a string */ + } + + if( passwd->bv_len < 2 ) { + return -1; /* passwd must be at least two characters long */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return -1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return -1; /* passwd must behave like a string */ + } + + cr = crypt( cred->bv_val, passwd->bv_val ); + + if( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + return -1; + } + + return strcmp( passwd->bv_val, cr ) ? 1 : 0; +} + +# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +static int chk_unix( + const struct pw_scheme *sc, + const struct berval * passwd, + const struct berval * cred ) +{ + int i; + char *pw,*cr; - if(spwd == NULL) { - return 1; /* not found */ + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return -1; /* NUL character in password */ } + } + if( cred->bv_val[i] != '\0' ) { + return -1; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return -1; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return -1; /* passwd must behave like a string */ + } - return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp)); -# else - struct passwd *pwd = getpwnam(p); + { + struct passwd *pwd = getpwnam(passwd->bv_val); if(pwd == NULL) { - return 1; /* not found */ + return -1; /* not found */ } - return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd)); + pw = pwd->pw_passwd; + } +# ifdef HAVE_GETSPNAM + { + struct spwd *spwd = getspnam(passwd->bv_val); + + if(spwd != NULL) { + pw = spwd->sp_pwdp; + } + } # endif +# ifdef HAVE_AIX_SECURITY + { + struct userpw *upw = getuserpw(passwd->bv_val); + + if (upw != NULL) { + pw = upw->upw_passwd; + } + } +# endif + + if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) { + /* password must must be at least two characters long */ + return -1; + } + + cr = crypt(cred->bv_val, pw); + + if( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + return -1; + } + + return strcmp(pw, cr) ? 1 : 0; + +} # endif #endif + +/* PASSWORD GENERATION ROUTINES */ + +static struct berval *hash_ssha1( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + unsigned char saltdata[4]; + struct berval digest; + struct berval salt; + + digest.bv_val = SHA1digest; + digest.bv_len = sizeof(SHA1digest); + salt.bv_val = saltdata; + salt.bv_len = sizeof(saltdata); + + if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) { + return NULL; } -#ifdef SLAPD_CLEARTEXT - return supported_hash("{CLEARTEXT}", methods ) && - strcmp(passwd, cred) != 0; -#else - return( 1 ); -#endif + lutil_SHA1Init( &SHA1context ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)passwd->bv_val, passwd->bv_len ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)salt.bv_val, salt.bv_len ); + lutil_SHA1Final( SHA1digest, &SHA1context ); + + return pw_string64( scheme, &digest, &salt); +} + +static struct berval *hash_sha1( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[LUTIL_SHA1_BYTES]; + struct berval digest; + digest.bv_val = SHA1digest; + digest.bv_len = sizeof(SHA1digest); + + lutil_SHA1Init( &SHA1context ); + lutil_SHA1Update( &SHA1context, + (const unsigned char *)passwd->bv_val, passwd->bv_len ); + lutil_SHA1Final( SHA1digest, &SHA1context ); + + return pw_string64( scheme, &digest, NULL); +} + +static struct berval *hash_smd5( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + unsigned char saltdata[4]; + struct berval digest; + struct berval salt; + + digest.bv_val = MD5digest; + digest.bv_len = sizeof(MD5digest); + salt.bv_val = saltdata; + salt.bv_len = sizeof(saltdata); + + if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) { + return NULL; + } + + lutil_MD5Init( &MD5context ); + lutil_MD5Update( &MD5context, + (const unsigned char *) passwd->bv_val, passwd->bv_len ); + lutil_MD5Update( &MD5context, + (const unsigned char *) salt.bv_val, salt.bv_len ); + lutil_MD5Final( MD5digest, &MD5context ); + + return pw_string64( scheme, &digest, &salt ); +} + +static struct berval *hash_md5( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + lutil_MD5_CTX MD5context; + unsigned char MD5digest[LUTIL_MD5_BYTES]; + + struct berval digest; + + digest.bv_val = MD5digest; + digest.bv_len = sizeof(MD5digest); + + lutil_MD5Init( &MD5context ); + lutil_MD5Update( &MD5context, + (const unsigned char *) passwd->bv_val, passwd->bv_len ); + lutil_MD5Final( MD5digest, &MD5context ); + return pw_string64( scheme, &digest, NULL ); +; } + +#ifdef SLAPD_CRYPT +static struct berval *hash_crypt( + const struct pw_scheme *scheme, + const struct berval *passwd ) +{ + struct berval hash; + unsigned char salt[3]; + int i; + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return NULL; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return NULL; /* passwd must behave like a string */ + } + + if( lutil_entropy( salt, sizeof(salt)) < 0 ) { + return NULL; + } + + salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ]; + salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ]; + salt[2] = '\0'; + + hash.bv_val = crypt( passwd->bv_val, salt ); + + if( hash.bv_val == NULL ) return NULL; + + hash.bv_len = strlen( hash.bv_val ); + + if( hash.bv_len == 0 ) { + return NULL; + } + + return pw_string( scheme, &hash ); +} +#endif diff --git a/libraries/liblutil/passwd.dsp b/libraries/liblutil/passwd.dsp new file mode 100644 index 0000000000..e5aa45b472 --- /dev/null +++ b/libraries/liblutil/passwd.dsp @@ -0,0 +1,201 @@ +# Microsoft Developer Studio Project File - Name="passwd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=passwd - Win32 DLL Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "passwd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "passwd.mak" CFG="passwd - Win32 DLL Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "passwd - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "passwd - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "passwd - Win32 Single Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "passwd - Win32 Single Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "passwd - Win32 DLL Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "passwd - Win32 DLL Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "passwd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\Release" +# PROP Intermediate_Dir "..\..\Release\passwd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ELSEIF "$(CFG)" == "passwd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "passwd___" +# PROP BASE Intermediate_Dir "passwd___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\Debug" +# PROP Intermediate_Dir "..\..\Debug\passwd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "passwd - Win32 Single Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "passwd___" +# PROP BASE Intermediate_Dir "passwd___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\SDebug" +# PROP Intermediate_Dir "..\..\SDebug\passwd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug" + +!ELSEIF "$(CFG)" == "passwd - Win32 Single Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "passwd__0" +# PROP BASE Intermediate_Dir "passwd__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\SRelease" +# PROP Intermediate_Dir "..\..\SRelease\passwd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 olber32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease" + +!ELSEIF "$(CFG)" == "passwd - Win32 DLL Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "passwd___" +# PROP BASE Intermediate_Dir "passwd___" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\DLLDebug" +# PROP Intermediate_Dir "..\..\DLLDebug\passwd" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug" + +!ELSEIF "$(CFG)" == "passwd - Win32 DLL Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "passwd__0" +# PROP BASE Intermediate_Dir "passwd__0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "passwd__0" +# PROP Intermediate_Dir "passwd__0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" +# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release" + +!ENDIF + +# Begin Target + +# Name "passwd - Win32 Release" +# Name "passwd - Win32 Debug" +# Name "passwd - Win32 Single Debug" +# Name "passwd - Win32 Single Release" +# Name "passwd - Win32 DLL Debug" +# Name "passwd - Win32 DLL Release" +# Begin Source File + +SOURCE=.\ptest.c +# End Source File +# End Target +# End Project diff --git a/libraries/liblutil/passwd.dsw b/libraries/liblutil/passwd.dsw new file mode 100644 index 0000000000..4746b7401d --- /dev/null +++ b/libraries/liblutil/passwd.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "passwd"=.\passwd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name liblber + End Project Dependency +}}} + +############################################################################### + +Project: "liblber"=.\liblber.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/libraries/liblutil/ptest.c b/libraries/liblutil/ptest.c new file mode 100644 index 0000000000..dc972b071f --- /dev/null +++ b/libraries/liblutil/ptest.c @@ -0,0 +1,105 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "lutil.h" + +// #define SLAP_AUTHPASSWD 1 + +/* + * Password Test Program + */ + +char *hash[] = { +#ifdef SLAP_AUTHPASSWD + "SHA1", "MD5", +#else +#ifdef SLAPD_CRYPT + "{CRYPT}", +#endif + "{SSHA}", "{SMD5}", + "{SHA}", "{MD5}", + "{BOGUS}", +#endif + NULL +}; + +static struct berval pw[] = { + { sizeof("secret")-1, "secret" }, + { sizeof("binary\0secret")-1, "binary\0secret" }, + { 0, NULL } +}; + +int +main( int argc, char *argv[] ) +{ + int i, j, rc; + struct berval *passwd; +#ifdef SLAP_AUTHPASSWD + struct berval *salt; +#endif + struct berval bad; + bad.bv_val = "bad password"; + bad.bv_len = sizeof("bad password")-1; + + for( i= 0; hash[i]; i++ ) { + for( j = 0; pw[j].bv_len; j++ ) { +#ifdef SLAP_AUTHPASSWD + rc = lutil_authpasswd_hash( &pw[j], + &passwd, &salt, hash[i] ); + + if( rc ) +#else + passwd = lutil_passwd_hash( &pw[j], hash[i] ); + + if( passwd == NULL ) +#endif + { + printf("%s generate fail: %s (%d)\n", + hash[i], pw[j].bv_val, pw[j].bv_len ); + continue; + } + + +#ifdef SLAP_AUTHPASSWD + rc = lutil_authpasswd( &pw[j], passwd, salt, NULL ); +#else + rc = lutil_passwd( passwd, &pw[j], NULL ); +#endif + + printf("%s (%d): %s (%d)\t(%d) %s\n", + pw[j].bv_val, pw[j].bv_len, passwd->bv_val, passwd->bv_len, + rc, rc == 0 ? "OKAY" : "BAD" ); + +#ifdef SLAP_AUTHPASSWD + rc = lutil_authpasswd( passwd, salt, &bad, NULL ); +#else + rc = lutil_passwd( passwd, &bad, NULL ); +#endif + + printf("%s (%d): %s (%d)\t(%d) %s\n", + bad.bv_val, bad.bv_len, passwd->bv_val, passwd->bv_len, + rc, rc != 0 ? "OKAY" : "BAD" ); + } + + printf("\n"); + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/libraries/liblutil/sha1.c b/libraries/liblutil/sha1.c index f8c38a1a66..b3e608b606 100644 --- a/libraries/liblutil/sha1.c +++ b/libraries/liblutil/sha1.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Acquired from: @@ -20,6 +20,9 @@ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ +/* + * This code assumes uint32 is 32 bits and char is 8 bits + */ #include "portable.h" #include @@ -27,12 +30,11 @@ /* include socket.h to get sys/types.h and/or winsock2.h */ #include -#if defined(HAVE_SYS_PARAM_H) -#include -#endif +#include #include "lutil_sha1.h" +/* undefining this will cause pointer alignment errors */ #define SHA1HANDSOFF /* Copies data before messing with it. */ #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) @@ -67,13 +69,11 @@ lutil_SHA1Transform( uint32 *state, const unsigned char *buffer ) { uint32 a, b, c, d, e; - /* Assumes u_int is 32 bits and char 8 bits. - * I don't know why uint32 isn't used (or what the difference is). */ #ifdef SHA1HANDSOFF - u_int block[16]; + uint32 block[16]; (void)memcpy(block, buffer, 64); #else - u_int *block = (u_int *)buffer; + uint32 *block = (u_int32 *) buffer; #endif /* Copy context->state[] to working vars */ diff --git a/libraries/liblutil/slapdmsg.bin b/libraries/liblutil/slapdmsg.bin new file mode 100644 index 0000000000000000000000000000000000000000..89a6c4a5c19c8dae62aeae75e857b5b7164066f8 GIT binary patch literal 140 zcmZQ%00LG92Sy+k05U^>*uNk(&&S0vKq1)2F~CKkIJKxOGdWeExFoTtBsE1(Atg1b zG(9J^EH%eg)lf$vIX^EgEi)(8R@F#Hp|mKc*jCk8M #include +#include #include #include @@ -17,11 +18,11 @@ char* lutil_progname( const char* name, int argc, char *argv[] ) char *progname; if(argc == 0) { - return strdup( name ); + return ber_strdup( name ); } progname = strrchr ( argv[0], *LDAP_DIRSEP ); - progname = strdup( progname ? &progname[1] : argv[0] ); + progname = ber_strdup( progname ? &progname[1] : argv[0] ); return progname; } diff --git a/servers/Makefile.in b/servers/Makefile.in index 9cf821cda5..f44196330a 100644 --- a/servers/Makefile.in +++ b/servers/Makefile.in @@ -1,5 +1,5 @@ # $OpenLDAP$ -## Copyright 1998 The OpenLDAP Foundation, All Rights Reserved. +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. ## COPYING RESTRICTIONS APPLY, see COPYRIGHT file ## ## servers Makefile.in for OpenLDAP diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 8752f3f40c..8d618e927b 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -5,36 +5,46 @@ PROGRAMS=slapd XPROGRAMS=sslapd libbackends.a .backend XSRCS=version.c + +NT_SRCS = nt_svc.c +NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res + SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \ attr.c entry.c config.c backend.c result.c operation.c \ dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \ value.c ava.c bind.c unbind.c abandon.c filterentry.c \ phonetic.c acl.c str2filter.c aclparse.c init.c user.c \ - repl.c lock.c controls.c extended.c \ - schema.c schemaparse.c monitor.c configinfo.c \ - root_dse.c sasl.c module.c suffixalias.c + repl.c lock.c controls.c extended.c kerberos.c passwd.c \ + schema.c schema_check.c schema_init.c schema_prep.c \ + schemaparse.c ad.c at.c mr.c syntax.c oc.c \ + monitor.c configinfo.c starttls.c index.c \ + root_dse.c sasl.c module.c suffixalias.c $(@PLAT@_SRCS) + OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ attr.o entry.o config.o backend.o result.o operation.o \ dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \ value.o ava.o bind.o unbind.o abandon.o filterentry.o \ phonetic.o acl.o str2filter.o aclparse.o init.o user.o \ - repl.o lock.o controls.o extended.o \ - schema.o schemaparse.o monitor.o configinfo.o \ - root_dse.o sasl.o module.o suffixalias.o + repl.o lock.o controls.o extended.o kerberos.o passwd.o \ + schema.o schema_check.o schema_init.o schema_prep.o \ + schemaparse.o ad.o at.o mr.o syntax.o oc.o \ + monitor.o configinfo.o starttls.o index.o \ + root_dse.o sasl.o module.o suffixalias.o $(@PLAT@_OBJS) LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries SLAP_DIR= SLAPD_MODULES=@SLAPD_MODULES_LIST@ + XDEFS = $(MODULES_CPPFLAGS) XLDFLAGS = $(MODULES_LDFLAGS) $(SLAPD_MODULES) # $(LTHREAD_LIBS) must be last -XLIBS = libbackends.a -lavl -lldbm -lldif -lldap_r -llber -llutil +XLIBS = libbackends.a -lavl -lldbm -lldif -llutil -lldap_r -llber XXLIBS = $(LDBM_LIBS) $(SLAPD_LIBS) \ - $(PERL_LDFLAGS) $(SECURITY_LIBS) \ - $(LDIF_LIBS) $(LUTIL_LIBS) + $(SECURITY_LIBS) \ + $(LDIF_LIBS) $(LUTIL_LIBS) XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS) BUILD_OPT = "--enable-slapd" @@ -42,18 +52,118 @@ BUILD_SRV = @BUILD_SLAPD@ all-local-srv: all-cffiles -slapd: libbackends.a version.o - $(LTLINK) -o $@ $(OBJS) version.o $(LIBS) +NT_DYN_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport + +DEFINES = $(@PLAT@_@LIB_LINKAGE@_DEFS) + +# The tricky part about building slapd in NT is that it will export symbols +# like a DLL. The symbols that it exports should be representative of all +# of the static symbols that it knows about. + +NT_EXP = slapd.exp +NT_IMPLIB = libslapd.a +NT_DUMMY = symdummy.o + +# Add extra def targets here +EXTRA_DEFS = + +# NT needs this if libltdl is built statically. You'll have to fix the path +# to point to where libltdl was built, then put ltdl.def in EXTRA_DEFS +ltdl.def: ../../../libtool/libltdl/*.o + dlltool --export-all-symbols --output-def $@ $^ + +DYNAMIC_DEFS = liblber.def libldap_r.def + +STATIC_DEFS = libavl.def libldbm.def libldif.def liblutil.def slapd.def \ + $(EXTRA_DEFS) + +libavl.def: $(LDAP_LIBDIR)/libavl/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +liblber.def: $(LDAP_LIBDIR)/liblber/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +libldap_r.def: $(LDAP_LIBDIR)/libldap_r/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +libldbm.def: $(LDAP_LIBDIR)/libldbm/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +libldif.def: $(LDAP_LIBDIR)/libldif/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +liblutil.def: $(LDAP_LIBDIR)/liblutil/*.o + dlltool --export-all-symbols --output-def $@ `ls $^ | grep -v test` + +slapd.def: $(OBJS) version.o + dlltool --export-all-symbols --exclude-symbols main,ServiceMain@8 --output-def $@ `ls $^ | grep -v test` + +# We don't want to include symbols from dynamic libraries. +all.def: $(STATIC_DEFS) $(DYNAMIC_DEFS) + cat $(STATIC_DEFS) | grep " @ " | sed -e 's/ @ [0-9]*//' > $@ + if [ "@LIB_LINKAGE@" != "DYN" ] ; \ + then \ + cat $(DYNAMIC_DEFS) | grep " @ " | sed -e 's/ @ [0-9]*//' >> $@; \ + fi + echo EXPORTS > tmp.def + sort $@ >> tmp.def + rm -f $@ + dlltool --input-def tmp.def --output-def $@ + rm -f tmp.def + +DUMMYTMP = symdummytmp.c + +symdummy.c: all.def $(ALL_DEFS) + rm -f $@ + echo "static void never_called() {" > $(DUMMYTMP) + cat $< | grep " @ " | while read line; \ + do \ + set dummy $$line; \ + case $$# in \ + 5) \ + echo "int $$2();" >> $@; \ + echo "$$2();" >> $(DUMMYTMP); \ + ;; \ + 6) \ + echo "extern int $$2;" >> $@; \ + echo "$$2 = 0;" >> $(DUMMYTMP); \ + ;; \ + esac; \ + done + echo "" >> $@ + echo "}" >> $(DUMMYTMP) + cat $(DUMMYTMP) >> $@ + rm -f $(DUMMYTMP) + +symdummy.o: symdummy.c + $(CC) $(CFLAGS) -c $< + +SLAPD_OBJS = $(OBJS) version.o symdummy.o + +slapd.exp: libbackends.a all.def $(SLAPD_OBJS) + $(LTLINK) -o slapd $(SLAPD_OBJS) $(LIBS) $(WRAP_LIBS) -Wl,--base-file,slapd.base + rm -f slapd.exe + dlltool --dllname slapd.exe --input-def all.def --base-file slapd.base --output-exp $@ + $(LTLINK) -o slapd $(SLAPD_OBJS) $(LIBS) $(WRAP_LIBS) $@ -Wl,--base-file,slapd.base + rm -f slapd.exe + dlltool --dllname slapd.exe --input-def all.def --base-file slapd.base --output-exp $@ + +libslapd.a: all.def + dlltool --dllname slapd.exe --input-def $< --output-lib $@ + +slapd: libbackends.a version.o $(@PLAT@_EXP) $(@PLAT@_DUMMY) + $(LTLINK) -o $@ $(@PLAT@_EXP) $(@PLAT@_DUMMY) $(OBJS) version.o $(LIBS) $(WRAP_LIBS) (cd tools; $(MAKE) $(MFLAGS) all) sslapd: version.o - $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS) + $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS) $(WRAP_LIBS) -.backend: FORCE +.backend: $(@PLAT@_IMPLIB) FORCE @for i in back-*; do \ if [ -d $$i ]; then \ echo " "; echo " cd $$i; $(MAKE) $(MFLAGS) all"; \ ( cd $$i; $(MAKE) $(MFLAGS) all ); \ + if test $$? != 0 ; then exit 1; fi ; \ fi; \ done; \ echo " " @@ -70,7 +180,7 @@ libbackends.a: .backend mv $$j $${pre}$$j; \ done; \ $(AR) ruv libbackends.a *.o 2>&1 | grep -v truncated; \ - $(RM) *.o __.SYMDEF; \ + $(RM) *.o __.SYMDEF ________64ELEL_ ; \ echo "added backend library $$i"; \ ); \ done @@ -81,7 +191,7 @@ libbackends.a: .backend fi @ls -l libbackends.a -version.c: libbackends.a $(OBJS) $(SLAPD_LIBDEPEND) +version.c: $(OBJS) $(SLAPD_LIBDEPEND) @-$(RM) $@ $(MKVERSION) -s -n Versionstr slapd > $@ @@ -90,14 +200,20 @@ depend-local-srv: FORCE if [ -d $$i ]; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) depend"; \ ( cd $$i; $(MAKE) $(MFLAGS) depend ); \ + if test $$? != 0 ; then exit 1; fi ; \ fi; \ done + @echo "" + +clean-local: + rm -f *.exp *.def *.base *.a *.objs symdummy.c clean-local-srv: FORCE @for i in back-* shell-backends tools; do \ if [ -d $$i ]; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \ ( cd $$i; $(MAKE) $(MFLAGS) clean ); \ + if test $$? != 0 ; then exit 1; fi ; \ fi; \ done rm -f *.tmp all-cffiles @@ -110,53 +226,57 @@ veryclean-local-srv: FORCE fi; \ done -install-local-srv: install-slapd install-conf install-tools +install-local-srv: install-slapd install-conf install-schema install-tools install-slapd: FORCE - @-$(MKDIR) $(libexecdir) - @-$(MKDIR) $(localstatedir) - $(LTINSTALL) $(INSTALLFLAGS) -m 755 slapd $(libexecdir) + -$(MKDIR) $(DESTDIR)$(libexecdir) + -$(MKDIR) $(DESTDIR)$(localstatedir) + $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 \ + slapd$(EXEEXT) $(DESTDIR)$(libexecdir) @if [ ! -z "$(SLAPD_MODULES)" ]; then \ for i in back-* shell-backends tools; do \ if [ -d $$i ]; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) install"; \ ( cd $$i; $(MAKE) $(MFLAGS) install ); \ + if test $$? != 0 ; then exit 1; fi ; \ fi; \ done; \ fi - -CFFILES=slapd.conf slapd.at.conf slapd.oc.conf - all-cffiles: slapd - @for i in $(CFFILES); do \ - tmpcf=$$i.tmp; \ - $(SED) -e 's;%SYSCONFDIR%;$(sysconfdir);' \ - -e 's;%LOCALSTATEDIR%;$(localstatedir);' \ - $(srcdir)/$$i > $$tmpcf ; \ - done + $(SED) -e 's;%SYSCONFDIR%;$(sysconfdir);' \ + -e 's;%LOCALSTATEDIR%;$(localstatedir);' \ + -e 's;%MODULEDIR%;$(moduledir);' \ + $(srcdir)/slapd.conf > slapd.conf.tmp ; \ touch all-cffiles -install-conf: FORCE - @-$(MKDIR) $(sysconfdir) - @for i in $(CFFILES); do \ - tmpcf=$$i.tmp ; \ - if test $$i = slapd.conf ; then \ - mode=600 ; \ - else \ - mode=644 ; \ - fi ; \ - if test ! -f $(sysconfdir)/$$i; then \ +install-schema: FORCE + @-$(MKDIR) $(DESTDIR)$(sysconfdir)/schema + @cd $(srcdir) ; \ + for i in schema/*.schema ; do \ + if test ! -f $(DESTDIR)$(sysconfdir)/$$i; then \ echo "installing $$i in $(sysconfdir)"; \ - echo "$(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i"; \ - $(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i; \ + echo $(INSTALL) $(INSTALLFLAGS) -m 444 $$i $(DESTDIR)$(sysconfdir)/$$i; \ + $(INSTALL) $(INSTALLFLAGS) -m 444 $$i $(DESTDIR)$(sysconfdir)/$$i; \ else \ - echo "PRESERVING EXISTING CONFIGURATION FILE $(sysconfdir)/$$i" ; \ + echo "PRESERVING EXISTING SCHEMA FILE $(DESTDIR)$(sysconfdir)/$$i"; \ fi; \ - $(INSTALL) $(INSTALLFLAGS) -m $$mode $$tmpcf $(sysconfdir)/$$i.default ; \ + $(INSTALL) $(INSTALLFLAGS) $$i $(DESTDIR)$(sysconfdir)/$$i.default ; \ done +install-conf: FORCE + @-$(MKDIR) $(DESTDIR)$(sysconfdir) + @-$(INSTALL) -m 700 -d $(DESTDIR)$(localstatedir)/openldap-ldbm + $(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf.default + if test ! -f $(DESTDIR)$(sysconfdir)/$$cf; then \ + echo "installing $$cf in $(sysconfdir)"; \ + echo "$(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf"; \ + $(INSTALL) $(INSTALLFLAGS) -m 600 slapd.conf.tmp $(DESTDIR)$(sysconfdir)/slapd.conf; \ + else \ + echo "PRESERVING EXISTING CONFIGURATION FILE $(DESTDIR)$(sysconfdir)/slapd.conf" ; \ + fi + install-tools: FORCE - @-$(MKDIR) $(sbindir) + @-$(MKDIR) $(DESTDIR)$(sbindir) (cd tools; $(MAKE) $(MFLAGS) install) diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c index 3340bc70f7..78c14be6ba 100644 --- a/servers/slapd/abandon.c +++ b/servers/slapd/abandon.c @@ -1,7 +1,7 @@ /* abandon.c - decode and handle an ldap abandon operation */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 99b4283266..d93d1c3ef4 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -1,7 +1,7 @@ /* acl.c - routines to parse and check acl's */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -15,25 +15,55 @@ #include "slap.h" +static AccessControl * acl_get( + AccessControl *ac, int *count, + Backend *be, Operation *op, + Entry *e, + AttributeDescription *desc, + int nmatches, regmatch_t *matches ); + +static slap_control_t acl_mask( + AccessControl *ac, slap_access_mask_t *mask, + Backend *be, Connection *conn, Operation *op, + Entry *e, + AttributeDescription *desc, + struct berval *val, + regmatch_t *matches ); + #ifdef SLAPD_ACI_ENABLED -int aci_access_allowed (struct berval *aci, char *attr, Backend *be, Entry *e, - Operation *op, int access, char *edn, regmatch_t *matches); +static int aci_mask( + Backend *be, + Connection *conn, + Operation *op, + Entry *e, + AttributeDescription *desc, + struct berval *val, + struct berval *aci, + regmatch_t *matches, + slap_access_t *grant, + slap_access_t *deny ); #endif -static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches); -static void string_expand(char *newbuf, int bufsiz, char *pattern, - char *match, regmatch_t *matches); +static int regex_matches( + char *pat, char *str, char *buf, regmatch_t *matches); +static void string_expand( + char *newbuf, int bufsiz, char *pattern, + char *match, regmatch_t *matches); /* * access_allowed - check whether op->o_ndn is allowed the requested access * to entry e, attribute attr, value val. if val is null, access to - * the whole attribute is assumed (all values). this routine finds - * the applicable acl and calls acl_access_allowed() to make the - * decision. + * the whole attribute is assumed (all values). * - * returns 0 access NOT allowed - * 1 access allowed + * This routine loops through all access controls and calls + * acl_mask() on each applicable access control. + * The loop exits when a definitive answer is reached or + * or no more controls remain. + * + * returns: + * 0 access denied + * 1 access granted */ int @@ -42,168 +72,259 @@ access_allowed( Connection *conn, Operation *op, Entry *e, - char *attr, + AttributeDescription *desc, struct berval *val, - int access -) + slap_access_t access ) { - int rc; + int count; AccessControl *a; - char *edn; +#ifdef LDAP_DEBUG + char accessmaskbuf[ACCESSMASK_MAXLEN]; +#endif + slap_access_mask_t mask; + slap_control_t control; + + const char *attr = desc ? desc->ad_cname->bv_val : NULL; regmatch_t matches[MAXREMATCHES]; - int i; - int n; - if ( be == NULL ) { - return( 0 ); - } + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: %s access to \"%s\" \"%s\" requested\n", + access2str( access ), + e->e_dn, attr ); - edn = e->e_ndn; + assert( be != NULL ); + assert( e != NULL ); + assert( attr != NULL ); + assert( access > ACL_NONE ); - Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n", - e->e_dn, attr, 0 ); + /* grant database root access */ + if ( be != NULL && be_isroot( be, op->o_ndn ) ) { + Debug( LDAP_DEBUG_ACL, + "<= root access granted\n", + 0, 0, 0 ); + return 1; + } - /* the lastmod attributes are ignored by ACL checking */ - if ( oc_check_no_usermod_attr( attr ) ) { - Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", + /* + * no-user-modification operational attributes are ignored + * by ACL_WRITE checking as any found here are not provided + * by the user + */ + if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type ) ) + { + Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:" + " %s access granted\n", attr, 0, 0 ); - return(1); + return 1; } - memset(matches, 0, sizeof(matches)); + /* use backend default access if no backend acls */ + if( be != NULL && be->be_acl == NULL ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: backend default %s access %s to \"%s\"\n", + access2str( access ), + be->be_dfltaccess >= access ? "granted" : "denied", op->o_dn ); + + return be->be_dfltaccess >= access; + +#ifdef notdef + /* be is always non-NULL */ + /* use global default access if no global acls */ + } else if ( be == NULL && global_acl == NULL ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: global default %s access %s to \"%s\"\n", + access2str( access ), + global_default_access >= access ? "granted" : "denied", op->o_dn ); + + return global_default_access >= access; +#endif + } + + ACL_INIT(mask); + memset(matches, '\0', sizeof(matches)); + + control = ACL_BREAK; + a = NULL; + count = 0; - a = acl_get_applicable( be, op, e, attr, MAXREMATCHES, matches ); + while( a = acl_get( a, &count, be, op, e, desc, MAXREMATCHES, matches ) ) + { + int i; - if (a) { for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) { - Debug( LDAP_DEBUG_ARGS, "=> match[%d]: %d %d ", i, + Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i, (int)matches[i].rm_so, (int)matches[i].rm_eo ); if( matches[i].rm_so <= matches[0].rm_eo ) { + int n; for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) { - Debug( LDAP_DEBUG_ARGS, "%c", edn[n], 0, 0 ); + Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 ); } } Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); } + + control = acl_mask( a, &mask, be, conn, op, + e, desc, val, matches ); + + if ( control != ACL_BREAK ) { + break; + } + + memset(matches, '\0', sizeof(matches)); } - rc = acl_access_allowed( a, attr, be, conn, e, val, op, access, edn, matches ); + if ( ACL_IS_INVALID( mask ) ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: \"%s\" (%s) invalid!\n", + e->e_dn, attr, 0 ); + ACL_INIT( mask ); - Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n", - e->e_dn, attr, 0); + } else if ( control == ACL_BREAK ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: no more rules\n", 0, 0, 0); + ACL_INIT( mask ); + } + + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: %s access %s by %s\n", + access2str( access ), + ACL_GRANT(mask, access) ? "granted" : "denied", + accessmask2str( mask, accessmaskbuf ) ); - return( rc ); + return ACL_GRANT(mask, access); } /* - * acl_get_applicable - return the acl applicable to entry e, attribute + * acl_get - return the acl applicable to entry e, attribute * attr. the acl returned is suitable for use in subsequent calls to * acl_access_allowed(). */ -AccessControl * -acl_get_applicable( +static AccessControl * +acl_get( + AccessControl *a, + int *count, Backend *be, - Operation *op, + Operation *op, Entry *e, - char *attr, + AttributeDescription *desc, int nmatch, - regmatch_t *matches -) + regmatch_t *matches ) { - int i; - AccessControl *a; - char *edn; + const char *attr; + int dnlen, patlen; - Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n", - e->e_dn, attr, 0 ); + assert( e != NULL ); + assert( count != NULL ); - if ( be_isroot( be, op->o_ndn ) ) { - Debug( LDAP_DEBUG_ACL, - "<= acl_get: no acl applicable to database root\n", 0, 0, - 0 ); - return( NULL ); - } + attr = desc ? desc->ad_cname->bv_val : NULL; - edn = e->e_ndn; + if( a == NULL ) { + if( be == NULL ) { + a = global_acl; + } else { + a = be->be_acl; + } - Debug( LDAP_DEBUG_ARGS, "=> acl_get: edn %s\n", edn, 0, 0 ); + assert( a != NULL ); - /* check for a backend-specific acl that matches the entry */ - for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) { - if (a->acl_dn_pat != NULL) { - Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n", - i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub); + } else { + a = a->acl_next; + } - if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) { - continue; + dnlen = strlen(e->e_ndn); - } else { - Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n", - i, 0, 0); - } - } + for ( ; a != NULL; a = a->acl_next ) { + (*count) ++; - if ( a->acl_filter != NULL ) { - if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) { - continue; - } - } + if (a->acl_dn_pat != NULL) { + if ( a->acl_dn_style == ACL_STYLE_REGEX ) { + Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n", + *count, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub ); - Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0); + if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0)) + continue; - if ( attr == NULL || a->acl_attrs == NULL || - charray_inlist( a->acl_attrs, attr ) ) - { - Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] backend acl %s attr: %s\n", - i, e->e_dn, attr ); - return( a ); - } - matches[0].rm_so = matches[0].rm_eo = -1; - } + } else { + Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n", + *count, a->acl_dn_pat, 0 ); - /* check for a global acl that matches the entry */ - for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) { - if (a->acl_dn_pat != NULL) { - Debug( LDAP_DEBUG_TRACE, "=> dn pat: [%d] %s nsub: %d\n", - i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub); + patlen = strlen( a->acl_dn_pat ); + if ( dnlen < patlen ) + continue; - if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) { - continue; + if ( a->acl_dn_style == ACL_STYLE_BASE ) { + /* base dn -- entire object DN must match */ + if ( dnlen != patlen ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_ONE ) { + char *rdn; + int rdnlen = -1; + + if ( dnlen <= patlen ) + continue; + + if ( e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + + rdn = dn_rdn( NULL, e->e_ndn ); + if ( rdn != NULL ) { + rdnlen = strlen( rdn ); + ch_free( rdn ); + } + if ( rdnlen != dnlen - patlen - 1 ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) { + if ( dnlen > patlen && e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + + } else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) { + if ( dnlen <= patlen ) + continue; + if ( e->e_ndn[dnlen - patlen - 1] != ',' ) + continue; + } - } else { - Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n", - i, 0, 0); + if ( strcmp( a->acl_dn_pat, e->e_ndn + dnlen - patlen ) != 0 ) + continue; } + + Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] matched\n", + *count, 0, 0 ); } if ( a->acl_filter != NULL ) { - if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) { + ber_int_t rc = test_filter( NULL, NULL, NULL, e, a->acl_filter ); + if ( rc != LDAP_COMPARE_TRUE ) { continue; } } - Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 0); + Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] check attr %s\n", + *count, attr, 0); if ( attr == NULL || a->acl_attrs == NULL || - charray_inlist( a->acl_attrs, attr ) ) + ad_inlist( desc, a->acl_attrs ) ) { - Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] global acl %s attr: %s\n", - i, e->e_dn, attr ); - return( a ); + Debug( LDAP_DEBUG_ACL, + "<= acl_get: [%d] acl %s attr: %s\n", + *count, e->e_dn, attr ); + return a; } - matches[0].rm_so = matches[0].rm_eo = -1; } - Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 ); return( NULL ); } + /* - * acl_access_allowed - check whether the given acl allows dn the + * acl_mask - modifies mask based upon the given acl and the * requested access to entry e, attribute attr, value val. if val * is null, access to the whole attribute is assumed (all values). * @@ -211,152 +332,242 @@ acl_get_applicable( * 1 access allowed */ -int -acl_access_allowed( +static slap_control_t +acl_mask( AccessControl *a, - char *attr, + slap_access_mask_t *mask, Backend *be, - Connection *conn, + Connection *conn, + Operation *op, Entry *e, + AttributeDescription *desc, struct berval *val, - Operation *op, - int access, - char *edn, regmatch_t *matches ) { - int i; + int i, odnlen, patlen; Access *b; - int default_access; +#ifdef LDAP_DEBUG + char accessmaskbuf[ACCESSMASK_MAXLEN]; +#endif + const char *attr = desc ? desc->ad_cname->bv_val : NULL; - Debug( LDAP_DEBUG_ACL, - "\n=> acl_access_allowed: %s access to entry \"%s\"\n", - access2str( access ), e->e_dn, 0 ); + assert( a != NULL ); + assert( mask != NULL ); Debug( LDAP_DEBUG_ACL, - "\n=> acl_access_allowed: %s access to value \"%s\" by \"%s\"\n", - access2str( access ), - val ? val->bv_val : "any", - op->o_ndn ? op->o_ndn : "" ); + "=> acl_mask: access to entry \"%s\", attr \"%s\" requested\n", + e->e_dn, attr, 0 ); - if ( be_isroot( be, op->o_ndn ) ) { - Debug( LDAP_DEBUG_ACL, - "<= acl_access_allowed: granted to database root\n", - 0, 0, 0 ); - return( 1 ); - } + Debug( LDAP_DEBUG_ACL, + "=> acl_mask: to value \"%s\" by \"%s\", (%s) \n", + val ? val->bv_val : "*", + op->o_ndn ? op->o_ndn : "", + accessmask2str( *mask, accessmaskbuf ) ); - default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access; + for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) { + slap_access_mask_t oldmask, modmask; - if ( a == NULL ) { - Debug( LDAP_DEBUG_ACL, - "<= acl_access_allowed: %s by default (no matching to)\n", - default_access >= access ? "granted" : "denied", 0, 0 ); - return( default_access >= access ); - } + ACL_INVALIDATE( modmask ); - for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) { /* AND clauses */ if ( b->a_dn_pat != NULL ) { - Debug( LDAP_DEBUG_TRACE, "<= check a_dn_pat: %s\n", + Debug( LDAP_DEBUG_ACL, "<= check a_dn_pat: %s\n", b->a_dn_pat, 0, 0); /* * if access applies to the entry itself, and the * user is bound as somebody in the same namespace as * the entry, OR the given dn matches the dn pattern */ - if ( strcasecmp( b->a_dn_pat, "anonymous" ) == 0 ) { + if ( strcmp( b->a_dn_pat, "anonymous" ) == 0 ) { if (op->o_ndn != NULL && op->o_ndn[0] != '\0' ) { continue; } - } else if ( strcasecmp( b->a_dn_pat, "self" ) == 0 ) { + } else if ( strcmp( b->a_dn_pat, "users" ) == 0 ) { + if (op->o_ndn == NULL || op->o_ndn[0] == '\0' ) { + continue; + } + + } else if ( strcmp( b->a_dn_pat, "self" ) == 0 ) { if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) { continue; } - if ( e->e_dn == NULL || strcmp( edn, op->o_ndn ) != 0 ) { + if ( e->e_dn == NULL || strcmp( e->e_ndn, op->o_ndn ) != 0 ) { continue; } - } else if ( strcmp( b->a_dn_pat, ".*" ) != 0 && - !regex_matches( b->a_dn_pat, op->o_ndn, edn, matches ) ) - { - continue; + } else if ( b->a_dn_style == ACL_STYLE_REGEX ) { + if ( strcmp( b->a_dn_pat, "*" ) != 0 ) { + int ret = regex_matches( b->a_dn_pat, + op->o_ndn, e->e_ndn, matches ); + + if( ret == 0 ) { + continue; + } + } + + } else { + if ( e->e_dn == NULL ) + continue; + + patlen = strlen( b->a_dn_pat ); + odnlen = strlen( op->o_ndn ); + if ( odnlen < patlen ) + continue; + + if ( b->a_dn_style == ACL_STYLE_BASE ) { + /* base dn -- entire object DN must match */ + if ( odnlen != patlen ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_ONE ) { + char *rdn; + int rdnlen = -1; + + if ( odnlen <= patlen ) + continue; + + if ( op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; + + rdn = dn_rdn( NULL, op->o_ndn ); + if ( rdn != NULL ) { + rdnlen = strlen( rdn ); + ch_free( rdn ); + } + if ( rdnlen != odnlen - patlen - 1 ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_SUBTREE ) { + if ( odnlen > patlen && op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; + + } else if ( b->a_dn_style == ACL_STYLE_CHILDREN ) { + if ( odnlen <= patlen ) + continue; + if ( op->o_ndn[odnlen - patlen - 1] != ',' ) + continue; + } + + if ( strcmp( b->a_dn_pat, op->o_ndn + odnlen - patlen ) != 0 ) + continue; + } } if ( b->a_sockurl_pat != NULL ) { - Debug( LDAP_DEBUG_ARGS, "<= check a_sockurl_pat: %s\n", + Debug( LDAP_DEBUG_ACL, "<= check a_sockurl_pat: %s\n", b->a_sockurl_pat, 0, 0 ); - if ( strcmp( b->a_sockurl_pat, ".*" ) != 0 && - !regex_matches( b->a_sockurl_pat, conn->c_listener_url, - edn, matches ) ) - { - continue; + if ( strcmp( b->a_sockurl_pat, "*" ) != 0) { + if ( b->a_sockurl_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_sockurl_pat, conn->c_listener_url, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_sockurl_pat, conn->c_listener_url ) == 0 ) + continue; + } } } if ( b->a_domain_pat != NULL ) { - Debug( LDAP_DEBUG_ARGS, "<= check a_domain_pat: %s\n", + Debug( LDAP_DEBUG_ACL, "<= check a_domain_pat: %s\n", b->a_domain_pat, 0, 0 ); - if ( strcmp( b->a_domain_pat, ".*" ) != 0 && - !regex_matches( b->a_domain_pat, conn->c_peer_domain, - edn, matches ) ) - { - continue; + if ( strcmp( b->a_domain_pat, "*" ) != 0) { + if ( b->a_domain_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_domain_pat, conn->c_peer_domain, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_domain_pat, conn->c_peer_domain ) == 0 ) + continue; + } } } if ( b->a_peername_pat != NULL ) { - Debug( LDAP_DEBUG_ARGS, "<= check a_peername_path: %s\n", + Debug( LDAP_DEBUG_ACL, "<= check a_peername_path: %s\n", b->a_peername_pat, 0, 0 ); - if ( strcmp( b->a_peername_pat, ".*" ) != 0 && - !regex_matches( b->a_peername_pat, conn->c_peer_name, - edn, matches ) ) - { - continue; + if ( strcmp( b->a_peername_pat, "*" ) != 0) { + if ( b->a_peername_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_peername_pat, conn->c_peer_name, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_peername_pat, conn->c_peer_name ) == 0 ) + continue; + } } } if ( b->a_sockname_pat != NULL ) { - Debug( LDAP_DEBUG_ARGS, "<= check a_sockname_path: %s\n", + Debug( LDAP_DEBUG_ACL, "<= check a_sockname_path: %s\n", b->a_sockname_pat, 0, 0 ); - if ( strcmp( b->a_sockname_pat, ".*" ) != 0 && - !regex_matches( b->a_sockname_pat, conn->c_sock_name, - edn, matches ) ) - { - continue; + if ( strcmp( b->a_sockname_pat, "*" ) != 0) { + if ( b->a_sockname_style == ACL_STYLE_REGEX) { + if (!regex_matches( b->a_sockname_pat, conn->c_sock_name, + e->e_ndn, matches ) ) + { + continue; + } + } else { + if ( strcasecmp( b->a_sockname_pat, conn->c_sock_name ) == 0 ) + continue; + } } } if ( b->a_dn_at != NULL && op->o_ndn != NULL ) { Attribute *at; struct berval bv; + int match; + const char *text; + const char *desc = b->a_dn_at->ad_cname->bv_val; - Debug( LDAP_DEBUG_ARGS, "<= check a_dn_at: %s\n", - b->a_dn_at, 0, 0); + Debug( LDAP_DEBUG_ACL, "<= check a_dn_at: %s\n", + desc, 0, 0); bv.bv_val = op->o_ndn; bv.bv_len = strlen( bv.bv_val ); - /* see if asker is listed in dnattr */ - if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL && - value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 ) + /* see if asker is listed in dnattr */ + for( at = attrs_find( e->e_attrs, b->a_dn_at ); + at == NULL; + at = attrs_find( e->e_attrs->a_next, b->a_dn_at ) ) { - if ( ACL_IS_SELF(b->a_access) && - (val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) ) + if( value_find( b->a_dn_at, at->a_vals, &bv ) == 0 ) { + /* found it */ + match = 1; + break; + } + } + + if( match ) { + if ( b->a_dn_self && (val == NULL + || value_match( &match, b->a_dn_at, + b->a_dn_at->ad_type->sat_equality, val, &bv, &text ) ) + != LDAP_SUCCESS + || match ) { continue; } - - /* asker not listed in dnattr - check for self access */ - } else if ( ! ACL_IS_SELF(b->a_access) || val == NULL || - value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) + } else if ( ! b->a_dn_self || val == NULL + || value_match( &match, b->a_dn_at, + b->a_dn_at->ad_type->sat_equality, val, &bv, &text ) + != LDAP_SUCCESS + || match ) { continue; } @@ -370,10 +581,15 @@ acl_access_allowed( * the values in the attribute group */ /* see if asker is listed in dnattr */ - string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches); - if ( dn_normalize_case(buf) == NULL ) { - /* did not expand to a valid dn */ - continue; + if ( b->a_group_style != ACL_STYLE_REGEX ) { + string_expand(buf, sizeof(buf), b->a_group_pat, e->e_ndn, matches); + if ( dn_normalize(buf) == NULL ) { + /* did not expand to a valid dn */ + continue; + } + } else { + strncpy( buf, b->a_group_pat, sizeof(buf) - 1 ); + buf[sizeof(buf) - 1] = 0; } if (backend_group(be, e, buf, op->o_ndn, @@ -384,12 +600,13 @@ acl_access_allowed( } #ifdef SLAPD_ACI_ENABLED - if ( b->a_aci_at != NULL ) { + if ( b->a_aci_at != NULL ) { Attribute *at; + slap_access_t grant, deny, tgrant, tdeny; /* this case works different from the others above. * since aci's themselves give permissions, we need - * to first check b->a_access, the ACL's access level. + * to first check b->a_mask, the ACL's access level. */ if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) { @@ -400,10 +617,10 @@ acl_access_allowed( continue; } - /* first check if the right being requested is - * higher than allowed by the ACL clause. + /* first check if the right being requested + * is allowed by the ACL clause. */ - if ( ! ACL_GRANT( b->a_access, access ) ) { + if ( ! ACL_GRANT( b->a_mask, *mask ) ) { continue; } @@ -413,44 +630,115 @@ acl_access_allowed( continue; } + /* start out with nothing granted, nothing denied */ + ACL_INIT(tgrant); + ACL_INIT(tdeny); + /* the aci is an multi-valued attribute. The * rights are determined by OR'ing the individual * rights given by the acis. */ for ( i = 0; at->a_vals[i] != NULL; i++ ) { - if ( aci_access_allowed( at->a_vals[i], attr, be, e, op, access, edn, matches ) ) { - Debug( LDAP_DEBUG_ACL, - "<= acl_access_allowed: matched by clause #%d access granted\n", - i, 0, 0 ); - return(1); + if (aci_mask( be, conn, op, + e, desc, val, at->a_vals[i], + matches, &grant, &deny ) != 0) + { + tgrant |= grant; + tdeny |= deny; } } - continue; - } + + /* remove anything that the ACL clause does not allow */ + tgrant &= b->a_mask & ACL_PRIV_MASK; + tdeny &= ACL_PRIV_MASK; + + /* see if we have anything to contribute */ + if( ACL_IS_INVALID(tgrant) && ACL_IS_INVALID(tdeny) ) { + continue; + } + + /* this could be improved by changing acl_mask so that it can deal with + * by clauses that return grant/deny pairs. Right now, it does either + * additive or subtractive rights, but not both at the same time. So, + * we need to combine the grant/deny pair into a single rights mask in + * a smart way: if either grant or deny is "empty", then we use the + * opposite as is, otherwise we remove any denied rights from the grant + * rights mask and construct an additive mask. + */ + if (ACL_IS_INVALID(tdeny)) { + modmask = tgrant | ACL_PRIV_ADDITIVE; + + } else if (ACL_IS_INVALID(tgrant)) { + modmask = tdeny | ACL_PRIV_SUBSTRACTIVE; + + } else { + modmask = (tgrant & ~tdeny) | ACL_PRIV_ADDITIVE; + } + + } else #endif + { + modmask = b->a_mask; + } + + + Debug( LDAP_DEBUG_ACL, + "<= acl_mask: [%d] applying %s (%s)\n", + i, accessmask2str( modmask, accessmaskbuf ), + b->a_type == ACL_CONTINUE + ? "continue" + : b->a_type == ACL_BREAK + ? "break" + : "stop" ); + + /* save old mask */ + oldmask = *mask; + + if( ACL_IS_ADDITIVE(modmask) ) { + /* add privs */ + ACL_PRIV_SET( *mask, modmask ); + + /* cleanup */ + ACL_PRIV_CLR( *mask, ~ACL_PRIV_MASK ); + + } else if( ACL_IS_SUBTRACTIVE(modmask) ) { + /* substract privs */ + ACL_PRIV_CLR( *mask, modmask ); + + /* cleanup */ + ACL_PRIV_CLR( *mask, ~ACL_PRIV_MASK ); + + } else { + /* assign privs */ + *mask = modmask; + } Debug( LDAP_DEBUG_ACL, - "<= acl_access_allowed: matched by clause #%d access %s\n", - i, - ACL_GRANT(b->a_access, access) ? "granted" : "denied", - 0 ); + "<= acl_mask: [%d] mask: %s\n", + i, accessmask2str(*mask, accessmaskbuf), 0 ); + + if( b->a_type == ACL_CONTINUE ) { + continue; + + } else if ( b->a_type == ACL_BREAK ) { + return ACL_BREAK; - return ACL_GRANT(b->a_access, access ); + } else { + return ACL_STOP; + } } Debug( LDAP_DEBUG_ACL, - "<= acl_access_allowed: %s by default (no matching by)\n", - default_access >= access ? "granted" : "denied", 0, 0 ); - - return( default_access >= access ); + "<= acl_mask: no more clauses, returning %s (stop)\n", + accessmask2str(*mask, accessmaskbuf), 0, 0 ); + return ACL_STOP; } /* * acl_check_modlist - check access control on the given entry to see if * it allows the given modifications by the user associated with op. - * returns LDAP_SUCCESS mods allowed ok - * anything else mods not allowed - return is an error - * code indicating the problem + * returns 1 if mods allowed ok + * 0 mods not allowed */ int @@ -459,67 +747,97 @@ acl_check_modlist( Connection *conn, Operation *op, Entry *e, - LDAPModList *mlist + Modifications *mlist ) { int i; - AccessControl *a; - char *edn = e->e_ndn; - for ( ; mlist != NULL; mlist = mlist->ml_next ) { - regmatch_t matches[MAXREMATCHES]; + assert( be != NULL ); + + /* short circuit root database access */ + if ( be_isroot( be, op->o_ndn ) ) { + Debug( LDAP_DEBUG_ACL, + "<= acl_access_allowed: granted to database root\n", + 0, 0, 0 ); + return 1; + } + + /* use backend default access if no backend acls */ + if( be != NULL && be->be_acl == NULL ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: backend default %s access %s to \"%s\"\n", + access2str( ACL_WRITE ), + be->be_dfltaccess >= ACL_WRITE ? "granted" : "denied", op->o_dn ); + + return be->be_dfltaccess >= ACL_WRITE; + +#ifdef notdef + /* be is always non-NULL */ + /* use global default access if no global acls */ + } else if ( be == NULL && global_acl == NULL ) { + Debug( LDAP_DEBUG_ACL, + "=> access_allowed: global default %s access %s to \"%s\"\n", + access2str( ACL_WRITE ), + global_default_access >= ACL_WRITE ? "granted" : "denied", op->o_dn ); + + return global_default_access >= ACL_WRITE; +#endif + } - /* the lastmod attributes are ignored by ACL checking */ - if ( oc_check_no_usermod_attr( mlist->ml_type ) ) { - Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", - mlist->ml_type, 0, 0 ); + for ( ; mlist != NULL; mlist = mlist->sml_next ) { + /* + * no-user-modification operational attributes are ignored + * by ACL_WRITE checking as any found here are not provided + * by the user + */ + if ( is_at_no_user_mod( mlist->sml_desc->ad_type ) ) { + Debug( LDAP_DEBUG_ACL, "acl: no-user-mod %s:" + " modify access granted\n", + mlist->sml_desc->ad_cname->bv_val, 0, 0 ); continue; } - a = acl_get_applicable( be, op, e, mlist->ml_type, - MAXREMATCHES, matches ); - - switch ( mlist->ml_op & ~LDAP_MOD_BVALUES ) { + switch ( mlist->sml_op ) { case LDAP_MOD_REPLACE: case LDAP_MOD_ADD: - if ( mlist->ml_bvalues == NULL ) { + if ( mlist->sml_bvalues == NULL ) { break; } - for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) { - if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i], - op, ACL_WRITE, edn, matches) ) + for ( i = 0; mlist->sml_bvalues[i] != NULL; i++ ) { + if ( ! access_allowed( be, conn, op, e, + mlist->sml_desc, mlist->sml_bvalues[i], ACL_WRITE ) ) { - return( LDAP_INSUFFICIENT_ACCESS ); + return( 0 ); } } break; case LDAP_MOD_DELETE: - if ( mlist->ml_bvalues == NULL ) { - if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, - NULL, op, ACL_WRITE, edn, matches) ) + if ( mlist->sml_bvalues == NULL ) { + if ( ! access_allowed( be, conn, op, e, + mlist->sml_desc, NULL, ACL_WRITE ) ) { - return( LDAP_INSUFFICIENT_ACCESS ); + return( 0 ); } break; } - for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) { - if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i], - op, ACL_WRITE, edn, matches) ) + for ( i = 0; mlist->sml_bvalues[i] != NULL; i++ ) { + if ( ! access_allowed( be, conn, op, e, + mlist->sml_desc, mlist->sml_bvalues[i], ACL_WRITE ) ) { - return( LDAP_INSUFFICIENT_ACCESS ); + return( 0 ); } } break; } } - return( LDAP_SUCCESS ); + return( 1 ); } #ifdef SLAPD_ACI_ENABLED static char * -aci_bvstrdup (struct berval *bv) +aci_bvstrdup( struct berval *bv ) { char *s; @@ -532,7 +850,9 @@ aci_bvstrdup (struct berval *bv) } static int -aci_strbvcmp (char *s, struct berval *bv) +aci_strbvcmp( + const char *s, + struct berval *bv ) { int res, len; @@ -540,15 +860,19 @@ aci_strbvcmp (char *s, struct berval *bv) if (res) return(res); len = strlen(s); - if (len > bv->bv_len) + if (len > (int)bv->bv_len) return(1); - if (len < bv->bv_len) + if (len < (int)bv->bv_len) return(-1); return(0); } static int -aci_get_part (struct berval *list, int ix, char sep, struct berval *bv) +aci_get_part( + struct berval *list, + int ix, + char sep, + struct berval *bv ) { int len; char *p; @@ -583,17 +907,20 @@ aci_get_part (struct berval *list, int ix, char sep, struct berval *bv) } static int -aci_list_has_right (struct berval *list, int access, int action) +aci_list_map_rights( + struct berval *list ) { struct berval bv; - int i, right; + slap_access_t mask; + int i; + ACL_INIT(mask); for (i = 0; aci_get_part(list, i, ',', &bv) >= 0; i++) { if (bv.bv_len <= 0) continue; switch (*bv.bv_val) { case 'c': - right = ACL_COMPARE; + ACL_PRIV_SET(mask, ACL_PRIV_COMPARE); break; case 's': /* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt defines @@ -601,192 +928,228 @@ aci_list_has_right (struct berval *list, int access, int action) * that the right 's' means "search". The latter definition * is used here. */ - right = ACL_SEARCH; + ACL_PRIV_SET(mask, ACL_PRIV_SEARCH); break; case 'r': - right = ACL_READ; + ACL_PRIV_SET(mask, ACL_PRIV_READ); break; case 'w': - right = ACL_WRITE; + ACL_PRIV_SET(mask, ACL_PRIV_WRITE); break; case 'x': /* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not * define any equivalent to the AUTH right, so I've just used * 'x' for now. */ - right = ACL_AUTH; + ACL_PRIV_SET(mask, ACL_PRIV_AUTH); break; default: - right = 0; break; } -#ifdef SLAPD_ACI_DISCRETE_RIGHTS - if (right & access) { - return(action); - } - } - return(!action); -#else - if (action != 0) { - /* check granted */ - if (ACL_GRANT(right, access)) - return(1); - } else { - /* check denied */ - if (right <= access) - return(1); - } + } - return(0); -#endif + return(mask); } static int -aci_list_has_attr (struct berval *list, char *attr) +aci_list_has_attr( + struct berval *list, + const char *attr, + struct berval *val ) { - struct berval bv; + struct berval bv, left, right; int i; for (i = 0; aci_get_part(list, i, ',', &bv) >= 0; i++) { - if (aci_strbvcmp(attr, &bv) == 0) { - return(1); + if (aci_get_part(&bv, 0, '=', &left) < 0 + || aci_get_part(&bv, 1, '=', &right) < 0) + { + if (aci_strbvcmp(attr, &bv) == 0) + return(1); + } else if (val == NULL) { + if (aci_strbvcmp(attr, &left) == 0) + return(1); + } else { + if (aci_strbvcmp(attr, &left) == 0) { + /* this is experimental code that implements a + * simple (prefix) match of the attribute value. + * the ACI draft does not provide for aci's that + * apply to specific values, but it would be + * nice to have. If the part of an aci's + * rights list is of the form =, + * that means the aci applies only to attrs with + * the given value. Furthermore, if the attr is + * of the form =*, then is + * treated as a prefix, and the aci applies to + * any value with that prefix. + * + * Ideally, this would allow r.e. matches. + */ + if (aci_get_part(&right, 0, '*', &left) < 0 + || right.bv_len <= left.bv_len) + { + if (aci_strbvcmp(val->bv_val, &right) == 0) + return(1); + } else if (val->bv_len >= left.bv_len) { + if (strncasecmp( val->bv_val, left.bv_val, left.bv_len ) == 0) + return(1); + } + } } } return(0); } -static int -aci_list_has_attr_right (struct berval *list, char *attr, int access, int action) +static slap_access_t +aci_list_get_attr_rights( + struct berval *list, + const char *attr, + struct berval *val ) { struct berval bv; - int i, found; + slap_access_t mask; + int i; /* loop through each rights/attr pair, skip first part (action) */ - found = -1; + ACL_INIT(mask); for (i = 1; aci_get_part(list, i + 1, ';', &bv) >= 0; i += 2) { - if (aci_list_has_attr(&bv, attr) == 0) + if (aci_list_has_attr(&bv, attr, val) == 0) continue; - found = 0; if (aci_get_part(list, i, ';', &bv) < 0) continue; - if (aci_list_has_right(&bv, access, action) != 0) - return(1); + mask |= aci_list_map_rights(&bv); } - return(found); + return(mask); } static int -aci_list_has_permission (struct berval *list, char *attr, int access) +aci_list_get_rights( + struct berval *list, + const char *attr, + struct berval *val, + slap_access_t *grant, + slap_access_t *deny ) { struct berval perm, actn; - int i, action, specific, general; + slap_access_t *mask; + int i, found; if (attr == NULL || *attr == 0 || strcasecmp(attr, "entry") == 0) { attr = "[entry]"; } + found = 0; + ACL_INIT(*grant); + ACL_INIT(*deny); /* loop through each permissions clause */ for (i = 0; aci_get_part(list, i, '$', &perm) >= 0; i++) { if (aci_get_part(&perm, 0, ';', &actn) < 0) continue; if (aci_strbvcmp( "grant", &actn ) == 0) { - action = 1; + mask = grant; } else if (aci_strbvcmp( "deny", &actn ) == 0) { - action = 0; + mask = deny; } else { continue; } - specific = aci_list_has_attr_right(&perm, attr, access, action); - if (specific >= 0) - return(specific); - - general = aci_list_has_attr_right(&perm, "[all]", access, action); - if (general >= 0) - return(general); + found = 1; + *mask |= aci_list_get_attr_rights(&perm, attr, val); + *mask |= aci_list_get_attr_rights(&perm, "[all]", NULL); } - return(0); + return(found); } static int aci_group_member ( struct berval *subj, - char *grpoc, - char *grpat, + const char *defgrpoc, + const char *defgrpat, Backend *be, Entry *e, Operation *op, - char *edn, regmatch_t *matches ) { struct berval bv; - char *subjdn, *grpdn; - int rc = 0; + char *subjdn, *grpdn = NULL; + char *grpoc; + char *grpat; + ObjectClass *grp_oc = NULL; + AttributeDescription *grp_ad = NULL; + char *text; + int rc; /* format of string is "group/objectClassValue/groupAttrName" */ - if (aci_get_part(subj, 0, '/', &bv) < 0) + if (aci_get_part(subj, 0, '/', &bv) < 0) { return(0); + } + subjdn = aci_bvstrdup(&bv); - if (subjdn == NULL) + if (subjdn == NULL) { return(0); + } - if (aci_get_part(subj, 1, '/', &bv) < 0) - grpoc = ch_strdup(grpoc); - else + if (aci_get_part(subj, 1, '/', &bv) < 0) { + grpoc = ch_strdup( defgrpoc ); + } else { grpoc = aci_bvstrdup(&bv); + } - if (aci_get_part(subj, 2, '/', &bv) < 0) - grpat = ch_strdup(grpat); - else + if (aci_get_part(subj, 2, '/', &bv) < 0) { + grpat = ch_strdup( defgrpat ); + } else { grpat = aci_bvstrdup(&bv); + } + + rc = slap_str2ad( grpat, &grp_ad, &text ); + if( rc != LDAP_SUCCESS ) { + rc = 0; + goto done; + } + rc = 0; grpdn = (char *)ch_malloc(1024); - if (grpoc != NULL && grpat != NULL && grpdn != NULL) { - string_expand(grpdn, 1024, subjdn, edn, matches); - if ( dn_normalize_case(grpdn) != NULL ) { - rc = (backend_group(be, e, grpdn, op->o_ndn, grpoc, grpat) == 0); + + if (grp_oc != NULL && grp_ad != NULL && grpdn != NULL) { + string_expand(grpdn, 1024, subjdn, e->e_ndn, matches); + if ( dn_normalize(grpdn) != NULL ) { + rc = (backend_group(be, e, grpdn, op->o_ndn, grp_oc, grp_ad) == 0); } - ch_free(grpdn); } - if (grpat != NULL) - ch_free(grpat); - if (grpoc != NULL) - ch_free(grpoc); + +done: + if( grp_ad != NULL ) ad_free( grp_ad, 1 ); + ch_free(grpdn); + ch_free(grpat); + ch_free(grpoc); ch_free(subjdn); return(rc); } -int -aci_access_allowed ( - struct berval *aci, - char *attr, +static int +aci_mask( Backend *be, - Entry *e, + Connection *conn, Operation *op, - int access, - char *edn, - regmatch_t *matches + Entry *e, + AttributeDescription *desc, + struct berval *val, + struct berval *aci, + regmatch_t *matches, + slap_access_t *grant, + slap_access_t *deny ) { struct berval bv, perms, sdn; char *subjdn; int rc; - - Debug( LDAP_DEBUG_ACL, - "\n=> aci_access_allowed: %s access to entry \"%s\"\n", - access2str( access ), e->e_dn, 0 ); - - Debug( LDAP_DEBUG_ACL, - "\n=> aci_access_allowed: %s access to attribute \"%s\" by \"%s\"\n", - access2str( access ), - attr, - op->o_ndn ? op->o_ndn : "" ); + char *attr = desc->ad_cname->bv_val; /* parse an aci of the form: oid#scope#action;rights;attr;rights;attr$action;rights;attr;rights;attr#dnType#subjectDN - See draft-ietf-ldapext-aci-model-0.3.txt section 9.1 for + See draft-ietf-ldapext-aci-model-04.txt section 9.1 for a full description of the format for this attribute. For now, this routine only supports scope=entry. @@ -796,6 +1159,10 @@ aci_access_allowed ( if (aci_get_part(aci, 4, '#', NULL) < 0) return(0); + /* check that the aci family is supported */ + if (aci_get_part(aci, 0, '#', &bv) < 0) + return(0); + /* check that the scope is "entry" */ if (aci_get_part(aci, 1, '#', &bv) < 0 || aci_strbvcmp( "entry", &bv ) != 0) @@ -808,7 +1175,7 @@ aci_access_allowed ( return(0); /* check if any permissions allow desired access */ - if (aci_list_has_permission(&perms, attr, access) == 0) + if (aci_list_get_rights(&perms, attr, val, grant, deny) == 0) return(0); /* see if we have a DN match */ @@ -817,31 +1184,67 @@ aci_access_allowed ( if (aci_get_part(aci, 4, '#', &sdn) < 0) return(0); + if (aci_strbvcmp( "access-id", &bv ) == 0) { subjdn = aci_bvstrdup(&sdn); if (subjdn == NULL) return(0); - rc = 0; - if (dn_normalize_case(subjdn) != NULL) - rc = (strcasecmp(op->o_ndn, subjdn) == 0); + rc = 1; + if ( dn_normalize(subjdn) != NULL ) + if (strcasecmp(op->o_ndn, subjdn) != 0) + rc = 0; ch_free(subjdn); return(rc); } if (aci_strbvcmp( "self", &bv ) == 0) { - return(strcasecmp(op->o_ndn, edn) == 0); - } + if (strcasecmp(op->o_ndn, e->e_ndn) == 0) + return(1); - if (aci_strbvcmp( "group", &bv ) == 0) { - return(aci_group_member(&sdn, "groupOfNames", "member", be, e, op, edn, matches)); - } + } else if (aci_strbvcmp( "dnattr", &bv ) == 0) { + char *dnattr = aci_bvstrdup(&sdn); + Attribute *at; + AttributeDescription *ad = NULL; + const char *text; + + rc = slap_str2ad( dnattr, &ad, &text ); + ch_free( dnattr ); + + if( rc != LDAP_SUCCESS ) { + return 0; + } + + rc = 0; + + bv.bv_val = op->o_ndn; + bv.bv_len = strlen( bv.bv_val ); + + for(at = attrs_find( e->e_attrs, ad ); + at != NULL; + at = attrs_find( at->a_next, ad ) ) + { + if (value_find( ad, at->a_vals, &bv) == 0 ) { + rc = 1; + break; + } + } + + ad_free( ad, 1 ); + return rc; - if (aci_strbvcmp( "role", &bv ) == 0) { - return(aci_group_member(&sdn, "organizationalRole", "roleOccupant", be, e, op, edn, matches)); + + } else if (aci_strbvcmp( "group", &bv ) == 0) { + if (aci_group_member(&sdn, SLAPD_GROUP_CLASS, SLAPD_GROUP_ATTR, be, e, op, matches)) + return(1); + + } else if (aci_strbvcmp( "role", &bv ) == 0) { + if (aci_group_member(&sdn, SLAPD_ROLE_CLASS, SLAPD_ROLE_ATTR, be, e, op, matches)) + return(1); } return(0); } + #endif /* SLAPD_ACI_ENABLED */ static void @@ -859,6 +1262,7 @@ string_expand( size = 0; newbuf[0] = '\0'; + bufsiz--; /* leave space for lone $ */ flag = 0; for ( dp = newbuf, sp = pat; size < bufsiz && *sp ; sp++) { @@ -892,6 +1296,13 @@ string_expand( } } } + + if (flag) { + /* must have ended with a single $ */ + *dp++ = '$'; + size++; + } + *dp = '\0'; Debug( LDAP_DEBUG_TRACE, "=> string_expand: pattern: %s\n", pat, 0, 0 ); diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index a134506908..8d64d9aad8 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -1,7 +1,7 @@ -/* acl.c - routines to parse and check acl's */ +/* aclparse.c - routines to parse and check acl's */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -18,11 +18,11 @@ #include "slap.h" static void split(char *line, int splitchar, char **left, char **right); -static void acl_append(AccessControl **l, AccessControl *a); static void access_append(Access **l, Access *a); static void acl_usage(void) LDAP_GCCATTR((noreturn)); + #ifdef LDAP_DEBUG -static void print_acl(AccessControl *a); +static void print_acl(Backend *be, AccessControl *a); static void print_access(Access *b); #endif @@ -92,9 +92,11 @@ parse_acl( ) { int i; - char *left, *right; + char *left, *right, *style; AccessControl *a; Access *b; + int rc; + const char *text; a = NULL; for ( i = 1; i < argc; i++ ) { @@ -119,11 +121,21 @@ parse_acl( } if ( strcasecmp( argv[i], "*" ) == 0 ) { - a->acl_dn_pat = ch_strdup( ".*" ); + if( a->acl_dn_pat != NULL ) { + fprintf( stderr, + "%s: line %d: dn pattern" + " already specified in to clause.\n", + fname, lineno ); + acl_usage(); + } + + a->acl_dn_pat = ch_strdup( "*" ); continue; } split( argv[i], '=', &left, &right ); + split( left, '.', &left, &style ); + if ( right == NULL || *right == '\0' ) { fprintf( stderr, "%s: line %d: missing \"=\" in (or value after) \"%s\" in to clause\n", @@ -131,6 +143,58 @@ parse_acl( acl_usage(); } + if ( strcasecmp( left, "dn" ) == 0 ) { + if( a->acl_dn_pat != NULL ) { + fprintf( stderr, + "%s: line %d: dn pattern" + " already specified in to clause.\n", + fname, lineno ); + acl_usage(); + } + + if ( style == NULL || *style == '\0' + || strcasecmp( style, "regex" ) == 0 ) + { + a->acl_dn_style = ACL_STYLE_REGEX; + if ( strcmp(right, "*") == 0 + || strcmp(right, ".*") == 0 + || strcmp(right, ".*$") == 0 + || strcmp(right, "^.*") == 0 + || strcmp(right, "^.*$$") == 0 + || strcmp(right, ".*$$") == 0 + || strcmp(right, "^.*$$") == 0 ) + { + a->acl_dn_pat = ch_strdup( "*" ); + + } else { + a->acl_dn_pat = ch_strdup( right ); + } + } else if ( strcasecmp( style, "base" ) == 0 ) { + a->acl_dn_style = ACL_STYLE_BASE; + a->acl_dn_pat = ch_strdup( right ); + + } else if ( strcasecmp( style, "one" ) == 0 ) { + a->acl_dn_style = ACL_STYLE_ONE; + a->acl_dn_pat = ch_strdup( right ); + + } else if ( strcasecmp( style, "subtree" ) == 0 ) { + a->acl_dn_style = ACL_STYLE_SUBTREE; + a->acl_dn_pat = ch_strdup( right ); + + } else if ( strcasecmp( style, "children" ) == 0 ) { + a->acl_dn_style = ACL_STYLE_CHILDREN; + a->acl_dn_pat = ch_strdup( right ); + + } else { + fprintf( stderr, + "%s: line %d: unknown dn style \"%s\" in to clause\n", + fname, lineno, style ); + acl_usage(); + } + + continue; + } + if ( strcasecmp( left, "filter" ) == 0 ) { if ( (a->acl_filter = str2filter( right )) == NULL ) { @@ -140,9 +204,6 @@ parse_acl( acl_usage(); } - } else if ( strcasecmp( left, "dn" ) == 0 ) { - a->acl_dn_pat = ch_strdup( right ); - } else if ( strncasecmp( left, "attr", 4 ) == 0 ) { char **alist; @@ -158,16 +219,27 @@ parse_acl( } } - if ( a->acl_dn_pat != NULL ) { - int e = regcomp( &a->acl_dn_re, a->acl_dn_pat, - REG_EXTENDED | REG_ICASE ); - if ( e ) { - char buf[512]; - regerror( e, &a->acl_dn_re, buf, sizeof(buf) ); - fprintf( stderr, - "%s: line %d: regular expression \"%s\" bad because of %s\n", - fname, lineno, right, buf ); - acl_usage(); + if ( a->acl_dn_pat != NULL && strcmp(a->acl_dn_pat, "*") == 0) { + free( a->acl_dn_pat ); + a->acl_dn_pat = NULL; + } + + if( a->acl_dn_pat != NULL ) { + if ( a->acl_dn_style != ACL_STYLE_REGEX ) + { + dn_normalize(a->acl_dn_pat); + + } else { + int e = regcomp( &a->acl_dn_re, a->acl_dn_pat, + REG_EXTENDED | REG_ICASE ); + if ( e ) { + char buf[512]; + regerror( e, &a->acl_dn_re, buf, sizeof(buf) ); + fprintf( stderr, + "%s: line %d: regular expression \"%s\" bad because of %s\n", + fname, lineno, right, buf ); + acl_usage(); + } } } @@ -179,12 +251,15 @@ parse_acl( fname, lineno ); acl_usage(); } + /* * by clause consists of and */ b = (Access *) ch_calloc( 1, sizeof(Access) ); + ACL_INVALIDATE( b->a_mask ); + if ( ++i == argc ) { fprintf( stderr, "%s: line %d: premature eol: expecting \n", @@ -195,17 +270,91 @@ parse_acl( /* get */ for ( ; i < argc; i++ ) { char *pat; + slap_style_t sty = ACL_STYLE_REGEX; + split( argv[i], '=', &left, &right ); + split( left, '.', &left, &style ); + if ( style == NULL || *style == '\0' + || strcasecmp( style, "regex" ) == 0 ) + { + sty = ACL_STYLE_REGEX; + } else if ( strcasecmp( style, "exact" ) == 0 ) { + sty = ACL_STYLE_BASE; + } else if ( strcasecmp( style, "base" ) == 0 ) { + sty = ACL_STYLE_BASE; + } else if ( strcasecmp( style, "one" ) == 0 ) { + sty = ACL_STYLE_ONE; + } else if ( strcasecmp( style, "subtree" ) == 0 ) { + sty = ACL_STYLE_SUBTREE; + } else if ( strcasecmp( style, "children" ) == 0 ) { + sty = ACL_STYLE_CHILDREN; + } else { + fprintf( stderr, + "%s: line %d: unknown style \"%s\" in by clause\n", + fname, lineno, style ); + acl_usage(); + } if ( strcasecmp( argv[i], "*" ) == 0 ) { - pat = ch_strdup( ".*" ); + pat = ch_strdup( "*" ); + } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) { pat = ch_strdup( "anonymous" ); + } else if ( strcasecmp( argv[i], "self" ) == 0 ) { pat = ch_strdup( "self" ); + + } else if ( strcasecmp( argv[i], "users" ) == 0 ) { + pat = ch_strdup( "users" ); + } else if ( strcasecmp( left, "dn" ) == 0 ) { - regtest(fname, lineno, right); - pat = ch_strdup( right ); + if ( sty == ACL_STYLE_REGEX ) { + b->a_dn_style = ACL_STYLE_REGEX; + if( right == NULL ) { + /* no '=' */ + pat = ch_strdup( "users" ); + + } else if (*right == '\0' ) { + /* dn="" */ + pat = ch_strdup( "anonymous" ); + + } else if ( strcmp( right, "*" ) == 0 ) { + /* dn=* */ + /* any or users? users for now */ + pat = ch_strdup( "users" ); + + } else if ( strcmp( right, ".+" ) == 0 + || strcmp( right, "^.+" ) == 0 + || strcmp( right, ".+$" ) == 0 + || strcmp( right, "^.+$" ) == 0 + || strcmp( right, ".+$$" ) == 0 + || strcmp( right, "^.+$$" ) == 0 ) + { + pat = ch_strdup( "users" ); + + } else if ( strcmp( right, ".*" ) == 0 + || strcmp( right, "^.*" ) == 0 + || strcmp( right, ".*$" ) == 0 + || strcmp( right, "^.*$" ) == 0 + || strcmp( right, ".*$$" ) == 0 + || strcmp( right, "^.*$$" ) == 0 ) + { + pat = ch_strdup( "*" ); + + } else { + regtest(fname, lineno, right); + pat = ch_strdup( right ); + } + } else if ( right == NULL || *right == '\0' ) { + fprintf( stderr, + "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n", + fname, lineno, left ); + acl_usage(); + + } else { + pat = ch_strdup( right ); + } + } else { pat = NULL; } @@ -219,21 +368,51 @@ parse_acl( } b->a_dn_pat = pat; + b->a_dn_style = sty; + if ( sty != ACL_STYLE_REGEX ) + dn_normalize(pat); continue; } if ( strcasecmp( left, "dnattr" ) == 0 ) { - if( b->a_dn_pat != NULL ) { + if( b->a_dn_at != NULL ) { fprintf( stderr, - "%s: line %d: dnaddr already specified.\n", + "%s: line %d: dnattr already specified.\n", fname, lineno ); acl_usage(); } - b->a_dn_at = ch_strdup( right ); + rc = slap_str2ad( right, &b->a_dn_at, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: dnattr \"%s\": %s\n", + fname, lineno, right, text ); + acl_usage(); + } + + + if( !is_at_syntax( b->a_dn_at->ad_type, + SLAPD_DN_SYNTAX ) ) + { + fprintf( stderr, + "%s: line %d: dnattr \"%s\": " + "inappropriate syntax: %s\n", + fname, lineno, right, + b->a_dn_at->ad_type->sat_syntax_oid ); + acl_usage(); + } + continue; } + if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) { + fprintf( stderr, + "%s: line %d: inappropriate style \"%s\" in by clause\n", + fname, lineno, style ); + acl_usage(); + } + if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) { char *name = NULL; char *value = NULL; @@ -248,28 +427,119 @@ parse_acl( /* format of string is "group/objectClassValue/groupAttrName" */ if ((value = strchr(left, '/')) != NULL) { *value++ = '\0'; - if (value && *value + if (*value && (name = strchr(value, '/')) != NULL) { *name++ = '\0'; } } - regtest(fname, lineno, right); - b->a_group_pat = ch_strdup( right ); + b->a_group_style = sty; + if (sty == ACL_STYLE_REGEX) { + regtest(fname, lineno, right); + b->a_group_pat = ch_strdup( right ); + } else { + b->a_group_pat = ch_strdup( right ); + dn_normalize(b->a_group_pat); + } if (value && *value) { - b->a_group_oc = ch_strdup(value); + b->a_group_oc = oc_find( value ); *--value = '/'; + + if( b->a_group_oc == NULL ) { + fprintf( stderr, + "%s: line %d: group objectclass " + "\"%s\" unknown\n", + fname, lineno, value ); + acl_usage(); + } } else { - b->a_group_oc = ch_strdup("groupOfNames"); + b->a_group_oc = oc_find(SLAPD_GROUP_CLASS); + + if( b->a_group_oc == NULL ) { + fprintf( stderr, + "%s: line %d: group default objectclass " + "\"%s\" unknown\n", + fname, lineno, SLAPD_GROUP_CLASS ); + acl_usage(); + } + } - if (name && *name) { - b->a_group_at = ch_strdup(name); - *--name = '/'; +#if 0 + if( is_object_subclass( b->a_group_oc, + slap_schema.si_oc_referral ) ) + { + fprintf( stderr, + "%s: line %d: group objectclass \"%s\" " + "is subclass of referral\n", + fname, lineno, value ); + acl_usage(); + } - } else { - b->a_group_at = ch_strdup("member"); + if( is_object_subclass( b->a_group_oc, + slap_schema.si_oc_alias ) ) + { + fprintf( stderr, + "%s: line %d: group objectclass \"%s\" " + "is subclass of alias\n", + fname, lineno, value ); + acl_usage(); + } +#endif + + if (name && *name) { + rc = slap_str2ad( right, &b->a_group_at, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: group \"%s\": %s\n", + fname, lineno, right, text ); + acl_usage(); + } + *--name = '/'; + } else { + rc = slap_str2ad( SLAPD_GROUP_ATTR, &b->a_group_at, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: group \"%s\": %s\n", + fname, lineno, SLAPD_GROUP_ATTR, text ); + acl_usage(); + } + } + + if( !is_at_syntax( b->a_group_at->ad_type, + SLAPD_DN_SYNTAX ) ) + { + fprintf( stderr, + "%s: line %d: group \"%s\": inappropriate syntax: %s\n", + fname, lineno, right, + b->a_group_at->ad_type->sat_syntax_oid ); + acl_usage(); + } + + + { + int rc; + struct berval val; + struct berval *vals[2]; + + val.bv_val = b->a_group_oc->soc_oid; + val.bv_len = strlen(val.bv_val); + vals[0] = &val; + vals[1] = NULL; + + + rc = oc_check_allowed( b->a_group_at->ad_type, vals ); + + if( rc != 0 ) { + fprintf( stderr, + "%s: line %d: group: \"%s\" not allowed by \"%s\"\n", + fname, lineno, + b->a_group_at->ad_cname->bv_val, + b->a_group_oc->soc_oid ); + acl_usage(); } } continue; @@ -283,7 +553,10 @@ parse_acl( acl_usage(); } - regtest(fname, lineno, right); + b->a_peername_style = sty; + if (sty == ACL_STYLE_REGEX) { + regtest(fname, lineno, right); + } b->a_peername_pat = ch_strdup( right ); continue; } @@ -296,7 +569,10 @@ parse_acl( acl_usage(); } - regtest(fname, lineno, right); + b->a_sockname_style = sty; + if (sty == ACL_STYLE_REGEX) { + regtest(fname, lineno, right); + } b->a_sockname_pat = ch_strdup( right ); continue; } @@ -309,7 +585,10 @@ parse_acl( acl_usage(); } - regtest(fname, lineno, right); + b->a_domain_style = sty; + if (sty == ACL_STYLE_REGEX) { + regtest(fname, lineno, right); + } b->a_domain_pat = ch_strdup( right ); continue; } @@ -322,7 +601,10 @@ parse_acl( acl_usage(); } - regtest(fname, lineno, right); + b->a_sockurl_style = sty; + if (sty == ACL_STYLE_REGEX) { + regtest(fname, lineno, right); + } b->a_sockurl_pat = ch_strdup( right ); continue; } @@ -336,24 +618,127 @@ parse_acl( acl_usage(); } - if ( right != NULL && *right != '\0' ) - b->a_aci_at = ch_strdup( right ); - else - b->a_aci_at = ch_strdup( SLAPD_ACI_DEFAULT_ATTR ); + if ( right != NULL && *right != '\0' ) { + rc = slap_str2ad( right, &b->a_aci_at, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: aci \"%s\": %s\n", + fname, lineno, right, text ); + acl_usage(); + } + + } else { + rc = slap_str2ad( SLAPD_ACI_ATTR, &b->a_aci_at, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: aci \"%s\": %s\n", + fname, lineno, SLAPD_ACI_ATTR, text ); + acl_usage(); + } + } + + if( !is_at_syntax( b->a_aci_at->ad_type, + SLAPD_ACI_SYNTAX) ) + { + fprintf( stderr, + "%s: line %d: aci \"%s\": inappropriate syntax: %s\n", + fname, lineno, right, + b->a_aci_at->ad_type->sat_syntax_oid ); + acl_usage(); + } + continue; } -#endif +#endif /* SLAPD_ACI_ENABLED */ - /* get */ - if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) { - fprintf( stderr, - "%s: line %d: expecting got \"%s\"\n", - fname, lineno, left ); - acl_usage(); + if( right != NULL ) { + /* unsplit */ + right[-1] = '='; } - access_append( &a->acl_access, b ); break; } + + if( i == argc || ( strcasecmp( left, "stop" ) == 0 )) { + /* out of arguments or plain stop */ + + ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE); + b->a_type = ACL_STOP; + + access_append( &a->acl_access, b ); + continue; + } + + if( strcasecmp( left, "continue" ) == 0 ) { + /* plain continue */ + + ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE); + b->a_type = ACL_CONTINUE; + + access_append( &a->acl_access, b ); + continue; + } + + if( strcasecmp( left, "break" ) == 0 ) { + /* plain continue */ + + ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE); + b->a_type = ACL_BREAK; + + access_append( &a->acl_access, b ); + continue; + } + + if ( strcasecmp( left, "by" ) == 0 ) { + /* we've gone too far */ + --i; + ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE); + b->a_type = ACL_STOP; + + access_append( &a->acl_access, b ); + continue; + } + + /* get */ + if( strncasecmp( left, "self", 4 ) == 0 ) { + b->a_dn_self = 1; + ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( &left[4] ) ); + + } else { + ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( left ) ); + } + + if( ACL_IS_INVALID( b->a_mask ) ) { + fprintf( stderr, + "%s: line %d: expecting got \"%s\"\n", + fname, lineno, left ); + acl_usage(); + } + + b->a_type = ACL_STOP; + + if( ++i == argc ) { + /* out of arguments or plain stop */ + access_append( &a->acl_access, b ); + continue; + } + + if( strcasecmp( argv[i], "continue" ) == 0 ) { + /* plain continue */ + b->a_type = ACL_CONTINUE; + + } else if( strcasecmp( argv[i], "break" ) == 0 ) { + /* plain continue */ + b->a_type = ACL_BREAK; + + } else if ( strcasecmp( argv[i], "stop" ) != 0 ) { + /* gone to far */ + i--; + } + + access_append( &a->acl_access, b ); + } else { fprintf( stderr, "%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n", @@ -369,10 +754,9 @@ parse_acl( fname, lineno ); } else { - #ifdef LDAP_DEBUG - if (ldap_debug & LDAP_DEBUG_ACL) - print_acl(a); + if (ldap_debug & LDAP_DEBUG_ACL) + print_acl(be, a); #endif if ( a->acl_access == NULL ) { @@ -390,76 +774,175 @@ parse_acl( } char * -access2str( int access ) +accessmask2str( slap_access_mask_t mask, char *buf ) { - static char buf[12]; + int none=1; - if ( ACL_IS_SELF( access ) ) { - strcpy( buf, "self" ); - } else { - buf[0] = '\0'; + assert( buf != NULL ); + + if ( ACL_IS_INVALID( mask ) ) { + return "invalid"; + } + + buf[0] = '\0'; + + if ( ACL_IS_LEVEL( mask ) ) { + if ( ACL_LVL_IS_NONE(mask) ) { + strcat( buf, "none" ); + + } else if ( ACL_LVL_IS_AUTH(mask) ) { + strcat( buf, "auth" ); + + } else if ( ACL_LVL_IS_COMPARE(mask) ) { + strcat( buf, "compare" ); + + } else if ( ACL_LVL_IS_SEARCH(mask) ) { + strcat( buf, "search" ); + + } else if ( ACL_LVL_IS_READ(mask) ) { + strcat( buf, "read" ); + + } else if ( ACL_LVL_IS_WRITE(mask) ) { + strcat( buf, "write" ); + } else { + strcat( buf, "unknown" ); + } + + strcat(buf, " ("); } - if ( ACL_IS_NONE(access) ) { - strcat( buf, "none" ); - } else if ( ACL_IS_AUTH(access) ) { - strcat( buf, "auth" ); - } else if ( ACL_IS_COMPARE(access) ) { - strcat( buf, "compare" ); - } else if ( ACL_IS_SEARCH(access) ) { - strcat( buf, "search" ); - } else if ( ACL_IS_READ(access) ) { - strcat( buf, "read" ); - } else if ( ACL_IS_WRITE(access) ) { - strcat( buf, "write" ); + if( ACL_IS_ADDITIVE( mask ) ) { + strcat( buf, "+" ); + + } else if( ACL_IS_SUBTRACTIVE( mask ) ) { + strcat( buf, "-" ); } else { - strcat( buf, "unknown" ); + strcat( buf, "=" ); + } + + if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) { + none = 0; + strcat( buf, "w" ); + } + + if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) { + none = 0; + strcat( buf, "r" ); + } + + if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) { + none = 0; + strcat( buf, "s" ); + } + + if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) { + none = 0; + strcat( buf, "c" ); + } + + if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) { + none = 0; + strcat( buf, "x" ); + } + + if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) { + none = 0; + strcat( buf, "n" ); + } + + if ( none ) { + strcat( buf, "0" ); } - return( buf ); + if ( ACL_IS_LEVEL( mask ) ) { + strcat(buf, ")"); + } + return buf; } -int -str2access( char *str ) +slap_access_mask_t +str2accessmask( const char *str ) { - int access; + slap_access_mask_t mask; + + if( !isalpha(str[0]) ) { + int i; + + if ( str[0] == '=' ) { + ACL_INIT(mask); + + } else if( str[0] == '+' ) { + ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE); + + } else if( str[0] == '-' ) { + ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE); + + } else { + ACL_INVALIDATE(mask); + return mask; + } + + for( i=1; str[i] != '\0'; i++ ) { + if( TOLOWER(str[i]) == 'w' ) { + ACL_PRIV_SET(mask, ACL_PRIV_WRITE); - ACL_CLR(access); + } else if( TOLOWER(str[i]) == 'r' ) { + ACL_PRIV_SET(mask, ACL_PRIV_READ); - if ( strncasecmp( str, "self", 4 ) == 0 ) { - ACL_SET_SELF(access); - str += 4; + } else if( TOLOWER(str[i]) == 's' ) { + ACL_PRIV_SET(mask, ACL_PRIV_SEARCH); + + } else if( TOLOWER(str[i]) == 'c' ) { + ACL_PRIV_SET(mask, ACL_PRIV_COMPARE); + + } else if( TOLOWER(str[i]) == 'x' ) { + ACL_PRIV_SET(mask, ACL_PRIV_AUTH); + + } else if( str[i] != '0' ) { + ACL_INVALIDATE(mask); + return mask; + } + } + + return mask; } if ( strcasecmp( str, "none" ) == 0 ) { - ACL_SET_NONE(access); + ACL_LVL_ASSIGN_NONE(mask); + } else if ( strcasecmp( str, "auth" ) == 0 ) { - ACL_SET_AUTH(access); + ACL_LVL_ASSIGN_AUTH(mask); + } else if ( strcasecmp( str, "compare" ) == 0 ) { - ACL_SET_COMPARE(access); + ACL_LVL_ASSIGN_COMPARE(mask); + } else if ( strcasecmp( str, "search" ) == 0 ) { - ACL_SET_SEARCH(access); + ACL_LVL_ASSIGN_SEARCH(mask); + } else if ( strcasecmp( str, "read" ) == 0 ) { - ACL_SET_READ(access); + ACL_LVL_ASSIGN_READ(mask); + } else if ( strcasecmp( str, "write" ) == 0 ) { - ACL_SET_WRITE(access); + ACL_LVL_ASSIGN_WRITE(mask); + } else { - ACL_SET_INVALID(access); + ACL_INVALIDATE( mask ); } - return( access ); + return mask; } static void acl_usage( void ) { fprintf( stderr, "\n" - " ::= access to [ by ]+ \n" + " ::= access to " + "[ by ]+ \n" " ::= * | [dn=] [filter=] [attrs=]\n" " ::= | , \n" " ::= | entry | children\n" - " ::= [ * | anonymous | self | dn= ]\n" + " ::= [ * | anonymous | users | self | dn= ]\n" "\t[dnattr=]\n" "\t[group[/[/]]=]\n" "\t[peername=] [sockname=]\n" @@ -467,7 +950,10 @@ acl_usage( void ) #ifdef SLAPD_ACI_ENABLED "\t[aci=]\n" #endif - " ::= [self]{none|auth|compare|search|read|write}\n" + " ::= [self]{|}\n" + " ::= none | auth | compare | search | read | write\n" + " ::= {=|+|-}{w|r|s|c|x}+\n" + " ::= [ stop | continue | break ]\n" ); exit( EXIT_FAILURE ); } @@ -495,7 +981,7 @@ access_append( Access **l, Access *a ) *l = a; } -static void +void acl_append( AccessControl **l, AccessControl *a ) { for ( ; *l != NULL; l = &(*l)->acl_next ) @@ -504,37 +990,100 @@ acl_append( AccessControl **l, AccessControl *a ) *l = a; } +char * +access2str( slap_access_t access ) +{ + if ( access == ACL_NONE ) { + return "none"; + + } else if ( access == ACL_AUTH ) { + return "auth"; + + } else if ( access == ACL_COMPARE ) { + return "compare"; + + } else if ( access == ACL_SEARCH ) { + return "search"; + + } else if ( access == ACL_READ ) { + return "read"; + + } else if ( access == ACL_WRITE ) { + return "write"; + } + + return "unknown"; +} + +slap_access_t +str2access( const char *str ) +{ + if ( strcasecmp( str, "none" ) == 0 ) { + return ACL_NONE; + + } else if ( strcasecmp( str, "auth" ) == 0 ) { + return ACL_AUTH; + + } else if ( strcasecmp( str, "compare" ) == 0 ) { + return ACL_COMPARE; + + } else if ( strcasecmp( str, "search" ) == 0 ) { + return ACL_SEARCH; + + } else if ( strcasecmp( str, "read" ) == 0 ) { + return ACL_READ; + + } else if ( strcasecmp( str, "write" ) == 0 ) { + return ACL_WRITE; + } + + return( ACL_INVALID_ACCESS ); +} + #ifdef LDAP_DEBUG +static char *style_strings[5] = { + "regex", + "base", + "one", + "subtree", + "children" + }; + + static void print_access( Access *b ) { + char maskbuf[ACCESSMASK_MAXLEN]; + fprintf( stderr, "\tby" ); if ( b->a_dn_pat != NULL ) { - if( strcmp(b->a_dn_pat, "anonymous") == 0 ) { - fprintf( stderr, " anonymous" ); - - } else if( strcmp(b->a_dn_pat, "self") == 0 ) { - fprintf( stderr, " self" ); + if( strcmp(b->a_dn_pat, "*") == 0 + || strcmp(b->a_dn_pat, "users") == 0 + || strcmp(b->a_dn_pat, "anonymous") == 0 + || strcmp(b->a_dn_pat, "self") == 0 ) + { + fprintf( stderr, " %s", b->a_dn_pat ); } else { - fprintf( stderr, " dn=%s", b->a_dn_pat ); + fprintf( stderr, " dn.%s=%s", style_strings[b->a_dn_style], b->a_dn_pat ); } } if ( b->a_dn_at != NULL ) { - fprintf( stderr, " dnattr=%s", b->a_dn_at ); + fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname->bv_val ); } if ( b->a_group_pat != NULL ) { - fprintf( stderr, " group: %s", b->a_group_pat ); + fprintf( stderr, " group=%s", b->a_group_pat ); if ( b->a_group_oc ) { - fprintf( stderr, " objectClass: %s", b->a_group_oc ); + fprintf( stderr, " objectClass: %s", + b->a_group_oc->soc_oclass.oc_oid ); if ( b->a_group_at ) { - fprintf( stderr, " attributeType: %s", b->a_group_at ); + fprintf( stderr, " attributeType: %s", b->a_group_at->ad_cname->bv_val ); } } } @@ -542,6 +1091,7 @@ print_access( Access *b ) if ( b->a_peername_pat != NULL ) { fprintf( stderr, " peername=%s", b->a_peername_pat ); } + if ( b->a_sockname_pat != NULL ) { fprintf( stderr, " sockname=%s", b->a_sockname_pat ); } @@ -556,35 +1106,55 @@ print_access( Access *b ) #ifdef SLAPD_ACI_ENABLED if ( b->a_aci_at != NULL ) { - fprintf( stderr, " aci=%s", b->a_aci_at ); + fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname->bv_val ); } #endif + fprintf( stderr, " %s%s", + b->a_dn_self ? "self" : "", + accessmask2str( b->a_mask, maskbuf ) ); + + if( b->a_type == ACL_BREAK ) { + fprintf( stderr, " break" ); + + } else if( b->a_type == ACL_CONTINUE ) { + fprintf( stderr, " continue" ); + + } else if( b->a_type != ACL_STOP ) { + fprintf( stderr, " unknown-control" ); + } + fprintf( stderr, "\n" ); } + static void -print_acl( AccessControl *a ) +print_acl( Backend *be, AccessControl *a ) { - int i; + int to = 0; Access *b; - if ( a == NULL ) { - fprintf( stderr, "NULL\n" ); + fprintf( stderr, "%s ACL: access to", + be == NULL ? "Global" : "Backend" ); + + if ( a->acl_dn_pat != NULL ) { + to++; + fprintf( stderr, " dn.%s=%s\n", + style_strings[a->acl_dn_style], a->acl_dn_pat ); } - fprintf( stderr, "ACL: access to" ); + if ( a->acl_filter != NULL ) { - fprintf( stderr," filter=" ); + to++; + fprintf( stderr, " filter=" ); filter_print( a->acl_filter ); + fprintf( stderr, "\n" ); } - if ( a->acl_dn_pat != NULL ) { - fprintf( stderr, " dn=" ); - fprintf( stderr, a->acl_dn_pat ); - } + if ( a->acl_attrs != NULL ) { - int first = 1; + int i, first = 1; + to++; - fprintf( stderr, "\n attrs=" ); + fprintf( stderr, " attrs=" ); for ( i = 0; a->acl_attrs[i] != NULL; i++ ) { if ( ! first ) { fprintf( stderr, "," ); @@ -592,11 +1162,17 @@ print_acl( AccessControl *a ) fprintf( stderr, a->acl_attrs[i] ); first = 0; } + fprintf( stderr, "\n" ); } - fprintf( stderr, "\n" ); + + if( !to ) { + fprintf( stderr, " *\n" ); + } + for ( b = a->acl_access; b != NULL; b = b->a_next ) { print_access( b ); } + fprintf( stderr, "\n" ); } diff --git a/servers/slapd/ad.c b/servers/slapd/ad.c new file mode 100644 index 0000000000..9a844259a8 --- /dev/null +++ b/servers/slapd/ad.c @@ -0,0 +1,245 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* ad.c - routines for dealing with attribute descriptions */ + +#include "portable.h" + +#include + +#include +#include +#include +#include +#include + +#include "ldap_pvt.h" +#include "slap.h" + +AttributeDescription *ad_dup( + AttributeDescription *desc ) +{ + AttributeDescription *ad; + + if( desc == NULL ) { + return NULL; + } + + ad = (AttributeDescription *) ch_malloc( sizeof(AttributeDescription) ); + + *ad = *desc; + + if( ad->ad_cname != NULL ) { + ad->ad_cname = ber_bvdup( ad->ad_cname ); + } + + if( ad->ad_lang != NULL ) { + ad->ad_lang = ch_strdup( ad->ad_lang ); + } + + return ad; +} + +void +ad_free( AttributeDescription *ad, int freeit ) +{ + if( ad == NULL ) return; + + if( ad->ad_cname != NULL ) { + ber_bvfree( ad->ad_cname ); + } + + free( ad->ad_lang ); + + if( freeit ) free( ad ); +} + +static int ad_keystring( + struct berval *bv ) +{ + ber_len_t i; + + if( !AD_CHAR( bv->bv_val[0] ) ) { + return 1; + } + + for( i=1; ibv_len; i++ ) { + if( !AD_CHAR( bv->bv_val[i] ) ) { + return 1; + } + } + return 0; +} + +int slap_str2ad( + const char *str, + AttributeDescription **ad, + const char **text ) +{ + struct berval bv; + bv.bv_val = (char *) str; + bv.bv_len = strlen( str ); + + return slap_bv2ad( &bv, ad, text ); +} + +int slap_bv2ad( + struct berval *bv, + AttributeDescription **ad, + const char **text ) +{ + int rtn = LDAP_UNDEFINED_TYPE; + int i; + AttributeDescription desc; + char **tokens; + + assert( ad != NULL ); + assert( *ad == NULL ); /* temporary */ + + if( bv == NULL || bv->bv_len == 0 ) { + *text = "empty attribute description"; + return rtn; + } + + /* make sure description is IA5 */ + if( ad_keystring( bv ) ) { + *text = "attribute description contains inappropriate characters"; + return rtn; + } + + tokens = str2charray( bv->bv_val, ";"); + + if( tokens == NULL || *tokens == NULL ) { + *text = "no attribute type"; + goto done; + } + + desc.ad_type = at_find( *tokens ); + + if( desc.ad_type == NULL ) { + *text = "attribute type undefined"; + goto done; + } + + desc.ad_flags = SLAP_DESC_NONE; + desc.ad_lang = NULL; + + for( i=1; tokens[i] != NULL; i++ ) { + if( strcasecmp( tokens[i], "binary" ) == 0 ) { + if( slap_ad_is_binary( &desc ) ) { + *text = "option \"binary\" specified multiple times"; + goto done; + } + + if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) { + /* not stored in binary, disallow option */ + *text = "option \"binary\" with type not supported"; + goto done; + } + + desc.ad_flags |= SLAP_DESC_BINARY; + + } else if ( strncasecmp( tokens[i], "lang-", + sizeof("lang-")-1 ) == 0 && tokens[i][sizeof("lang-")-1] ) + { + if( desc.ad_lang != NULL ) { + *text = "multiple language tag options specified"; + goto done; + } + + desc.ad_lang = tokens[i]; + + /* normalize to all lower case, it's easy */ + ldap_pvt_str2lower( desc.ad_lang ); + + } else { + *text = "unrecognized option"; + goto done; + } + } + + desc.ad_cname = ch_malloc( sizeof( struct berval ) ); + + desc.ad_cname->bv_len = strlen( desc.ad_type->sat_cname ); + if( slap_ad_is_binary( &desc ) ) { + desc.ad_cname->bv_len += sizeof("binary"); + } + if( desc.ad_lang != NULL ) { + desc.ad_cname->bv_len += 1 + strlen( desc.ad_lang ); + } + + desc.ad_cname->bv_val = ch_malloc( desc.ad_cname->bv_len + 1 ); + + strcpy( desc.ad_cname->bv_val, desc.ad_type->sat_cname ); + if( slap_ad_is_binary( &desc ) ) { + strcat( desc.ad_cname->bv_val, ";binary" ); + } + + if( desc.ad_lang != NULL ) { + strcat( desc.ad_cname->bv_val, ";" ); + strcat( desc.ad_cname->bv_val, desc.ad_lang ); + } + + if( *ad == NULL ) { + *ad = ch_malloc( sizeof( AttributeDescription ) ); + } + + **ad = desc; + + rtn = LDAP_SUCCESS; + +done: + charray_free( tokens ); + return rtn; +} + +int is_ad_subtype( + AttributeDescription *sub, + AttributeDescription *super +) +{ + if( !is_at_subtype( sub->ad_type, super->ad_type ) ) { + return 0; + } + + if( super->ad_flags && ( super->ad_flags == sub->ad_flags )) { + return 0; + } + + if( super->ad_lang != NULL && ( sub->ad_lang == NULL + || strcasecmp( super->ad_lang, sub->ad_lang ))) + { + return 0; + } + + return 1; +} + + +int ad_inlist( + AttributeDescription *desc, + char **attrs ) +{ + int i; + for( i=0; attrs[i] != NULL; i++ ) { + AttributeDescription *ad = NULL; + const char *text; + int rc; + + rc = slap_str2ad( attrs[i], &ad, &text ); + + if( rc != LDAP_SUCCESS ) continue; + + rc = is_ad_subtype( desc, ad ); + + ad_free( ad, 1 ); + + if( rc ) return 1; + } + + return 0; +} + + diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 388ad9d629..1b7333f5cf 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* @@ -23,9 +23,13 @@ #include #include +#include "ldap_pvt.h" #include "slap.h" -static int add_created_attrs(Operation *op, Entry *e); +static int slap_mods2entry( + Modifications *mods, + Entry **e, + const char **text ); int do_add( Connection *conn, Operation *op ) @@ -36,17 +40,14 @@ do_add( Connection *conn, Operation *op ) ber_tag_t tag; Entry *e; Backend *be; + LDAPModList *modlist = NULL; + LDAPModList **modtail = &modlist; + Modifications *mods = NULL; + const char *text; int rc = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 ); - if( op->o_bind_in_progress ) { - Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress", NULL, NULL ); - return LDAP_SASL_BIND_IN_PROGRESS; - } - /* * Parse the add request. It looks like this: * @@ -69,7 +70,7 @@ do_add( Connection *conn, Operation *op ) ndn = ch_strdup( dn ); - if ( dn_normalize_case( ndn ) == NULL ) { + if ( dn_normalize( ndn ) == NULL ) { Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn, 0, 0 ); send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, NULL, "invalid DN", NULL, NULL ); @@ -82,54 +83,64 @@ do_add( Connection *conn, Operation *op ) e->e_dn = dn; e->e_ndn = ndn; + e->e_attrs = NULL; e->e_private = NULL; Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 ); /* get the attrs */ - e->e_attrs = NULL; for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - char *type; - struct berval **vals; + tag = ber_next_element( ber, &len, last ) ) + { + LDAPModList *mod = (LDAPModList *) ch_malloc( sizeof(LDAPModList) ); + mod->ml_op = LDAP_MOD_ADD; + mod->ml_next = NULL; + + rc = ber_scanf( ber, "{a{V}}", &mod->ml_type, &mod->ml_bvalues ); - if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) { + if ( rc == LBER_ERROR ) { + Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 ); send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); - entry_free( e ); - return -1; + rc = -1; + free( mod ); + goto done; } - if ( vals == NULL ) { - Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type, - 0, 0 ); - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - NULL, "no values for type", NULL, NULL ); - free( type ); - entry_free( e ); - return LDAP_PROTOCOL_ERROR; + if ( mod->ml_bvalues == NULL ) { + Debug( LDAP_DEBUG_ANY, "no values for type %s\n", + mod->ml_type, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, + NULL, "no values for attribute type", NULL, NULL ); + free( mod->ml_type ); + free( mod ); + goto done; } - attr_merge( e, type, vals ); - - free( type ); - ber_bvecfree( vals ); + *modtail = mod; + modtail = &mod->ml_next; } if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) { - entry_free( e ); Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); - return -1; + rc = -1; + goto done; } if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { - entry_free( e ); Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 ); - return rc; + goto done; } + if ( modlist == NULL ) + { + send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, + NULL, "no attributes provided", NULL, NULL ); + goto done; + } + Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d ADD dn=\"%s\"\n", op->o_connid, op->o_opid, e->e_ndn, 0, 0 ); @@ -140,19 +151,26 @@ do_add( Connection *conn, Operation *op ) */ be = select_backend( e->e_ndn ); if ( be == NULL ) { - entry_free( e ); - send_ldap_result( conn, op, LDAP_REFERRAL, NULL, - NULL, default_referral, NULL ); - return rc; + send_ldap_result( conn, op, rc = LDAP_REFERRAL, + NULL, NULL, default_referral, NULL ); + goto done; + } + + /* make sure this backend recongizes critical controls */ + rc = backend_check_controls( be, conn, op, &text ) ; + + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + goto done; } if ( global_readonly || be->be_readonly ) { Debug( LDAP_DEBUG_ANY, "do_add: database is read-only\n", 0, 0, 0 ); - entry_free( e ); - send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, - NULL, "database is read-only", NULL, NULL ); - return LDAP_UNWILLING_TO_PERFORM; + send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, + NULL, "directory is read-only", NULL, NULL ); + goto done; } /* @@ -172,22 +190,43 @@ do_add( Connection *conn, Operation *op ) strcmp( be->be_update_ndn, op->o_ndn ) == 0 ) #endif { + int update = be->be_update_ndn != NULL; + + rc = slap_modlist2mods( modlist, update, &mods, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + goto done; + } + #ifndef SLAPD_MULTIMASTER if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED && - global_lastmod == ON)) && be->be_update_ndn == NULL ) + global_lastmod == ON)) && !update ) #endif { - rc = add_created_attrs( op, e ); - + Modifications **modstail; + for( modstail = &mods; + *modstail != NULL; + modstail = &(*modstail)->sml_next ) + { + assert( (*modstail)->sml_op == LDAP_MOD_ADD ); + assert( (*modstail)->sml_desc != NULL ); + } + rc = slap_mods_opattrs( op, modstail, &text ); if( rc != LDAP_SUCCESS ) { - entry_free( e ); send_ldap_result( conn, op, rc, - NULL, "no-user-modification attribute type", - NULL, NULL ); - return rc; + NULL, text, NULL, NULL ); + goto done; } } + rc = slap_mods2entry( mods, &e, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + goto done; + } + if ( (*be->be_add)( be, conn, op, e ) == 0 ) { #ifdef SLAPD_MULTIMASTER if (be->be_update_ndn == NULL || @@ -197,70 +236,71 @@ do_add( Connection *conn, Operation *op ) replog( be, op, e->e_dn, e ); } be_entry_release_w( be, e ); + e = NULL; } #ifndef SLAPD_MULTIMASTER } else { - entry_free( e ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL, be->be_update_refs ? be->be_update_refs : default_referral, NULL ); #endif } } else { - Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 ); - entry_free( e ); + Debug( LDAP_DEBUG_ARGS, " do_add: no backend support\n", 0, 0, 0 ); send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "Function not implemented", NULL, NULL ); + NULL, "operation not supported within namingContext", NULL, NULL ); + } + +done: + if( modlist != NULL ) { + slap_modlist_free( modlist ); + } + if( mods != NULL ) { + slap_mods_free( mods ); + } + if( e != NULL ) { + entry_free( e ); } return rc; } -static int -add_created_attrs( Operation *op, Entry *e ) +static int slap_mods2entry( + Modifications *mods, + Entry **e, + const char **text ) { - char buf[22]; - struct berval bv; - struct berval *bvals[2]; - Attribute *a; - struct tm *ltm; - time_t currenttime; - - Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 ); - - bvals[0] = &bv; - bvals[1] = NULL; - - /* return error on any attempts by the user to add these attrs */ - for ( a = e->e_attrs; a != NULL; a = a->a_next ) { - if ( oc_check_no_usermod_attr( a->a_type ) ) { - return LDAP_CONSTRAINT_VIOLATION; + Attribute **tail = &(*e)->e_attrs; + assert( *tail == NULL ); + + for( ; mods != NULL; mods = mods->sml_next ) { + Attribute *attr; + + assert( mods->sml_op == LDAP_MOD_ADD ); + assert( mods->sml_desc != NULL ); + + attr = attr_find( (*e)->e_attrs, mods->sml_desc ); + + if( attr != NULL ) { + *text = "attribute provided more than once"; + return LDAP_OPERATIONS_ERROR; } - } - if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) { - bv.bv_val = ""; - bv.bv_len = strlen( bv.bv_val ); - } else { - bv.bv_val = op->o_dn; - bv.bv_len = strlen( bv.bv_val ); - } - attr_merge( e, "creatorsname", bvals ); + attr = ch_calloc( 1, sizeof(Attribute) ); - currenttime = slap_get_time(); - ldap_pvt_thread_mutex_lock( &gmtime_mutex ); -#ifndef LDAP_LOCALTIME - ltm = gmtime( ¤ttime ); - strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm ); -#else - ltm = localtime( ¤ttime ); - strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm ); -#endif - ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); + /* move ad to attr structure */ + attr->a_desc = mods->sml_desc; + mods->sml_desc = NULL; - bv.bv_val = buf; - bv.bv_len = strlen( bv.bv_val ); - attr_merge( e, "createtimestamp", bvals ); + /* move values to attr structure */ + /* should check for duplicates */ + attr->a_vals = mods->sml_bvalues; + mods->sml_bvalues = NULL; + + *tail = attr; + tail = &attr->a_next; + } return LDAP_SUCCESS; } + diff --git a/servers/slapd/at.c b/servers/slapd/at.c new file mode 100644 index 0000000000..4ad381d9ff --- /dev/null +++ b/servers/slapd/at.c @@ -0,0 +1,386 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* at.c - routines for dealing with attribute types */ + +#include "portable.h" + +#include + +#include +#include +#include +#include +#include + +#include "ldap_pvt.h" +#include "slap.h" + + +int is_at_syntax( + AttributeType *at, + const char *oid ) +{ + for( ; at != NULL; at = at->sat_sup ) { + if( at->sat_syntax_oid ) { + return ( strcmp( at->sat_syntax_oid, oid ) == 0 ); + } + } + + return 0; +} + +int is_at_subtype( + AttributeType *sub, + AttributeType *sup ) +{ + for( ; sub != NULL; sub = sub->sat_sup ) { + if( sub == sup ) return 1; + } + + return 0; +} + +struct aindexrec { + char *air_name; + AttributeType *air_at; +}; + +static Avlnode *attr_index = NULL; +static AttributeType *attr_list = NULL; + +static int +attr_index_cmp( + struct aindexrec *air1, + struct aindexrec *air2 +) +{ + return (strcasecmp( air1->air_name, air2->air_name )); +} + +static int +attr_index_name_cmp( + const char *type, + struct aindexrec *air +) +{ + return (strcasecmp( type, air->air_name )); +} + +AttributeType * +at_find( + const char *name +) +{ + struct aindexrec *air; + char *tmpname; + + { + tmpname = (char *)name; + } + + if ( (air = (struct aindexrec *) avl_find( attr_index, tmpname, + (AVL_CMP) attr_index_name_cmp )) != NULL ) { + if ( tmpname != name ) + ldap_memfree( tmpname ); + return( air->air_at ); + } + + if ( tmpname != name ) + ldap_memfree( tmpname ); + return( NULL ); +} + +int +at_append_to_list( + AttributeType *sat, + AttributeType ***listp +) +{ + AttributeType **list; + AttributeType **list1; + int size; + + list = *listp; + if ( !list ) { + size = 2; + list = calloc(size, sizeof(AttributeType *)); + if ( !list ) { + return -1; + } + } else { + size = 0; + list1 = *listp; + while ( *list1 ) { + size++; + list1++; + } + size += 2; + list1 = realloc(list, size*sizeof(AttributeType *)); + if ( !list1 ) { + return -1; + } + list = list1; + } + list[size-2] = sat; + list[size-1] = NULL; + *listp = list; + return 0; +} + +int +at_delete_from_list( + int pos, + AttributeType ***listp +) +{ + AttributeType **list; + AttributeType **list1; + int i; + int j; + + if ( pos < 0 ) { + return -2; + } + list = *listp; + for ( i=0; list[i]; i++ ) + ; + if ( pos >= i ) { + return -2; + } + for ( i=pos, j=pos+1; list[j]; i++, j++ ) { + list[i] = list[j]; + } + list[i] = NULL; + /* Tell the runtime this can be shrinked */ + list1 = realloc(list, (i+1)*sizeof(AttributeType **)); + if ( !list1 ) { + return -1; + } + *listp = list1; + return 0; +} + +int +at_find_in_list( + AttributeType *sat, + AttributeType **list +) +{ + int i; + + if ( !list ) { + return -1; + } + for ( i=0; list[i]; i++ ) { + if ( sat == list[i] ) { + return i; + } + } + return -1; +} + +static int +at_insert( + AttributeType *sat, + const char **err +) +{ + AttributeType **atp; + struct aindexrec *air; + char **names; + + atp = &attr_list; + while ( *atp != NULL ) { + atp = &(*atp)->sat_next; + } + *atp = sat; + + if ( sat->sat_oid ) { + air = (struct aindexrec *) + ch_calloc( 1, sizeof(struct aindexrec) ); + air->air_name = sat->sat_oid; + air->air_at = sat; + if ( avl_insert( &attr_index, (caddr_t) air, + (AVL_CMP) attr_index_cmp, + (AVL_DUP) avl_dup_error ) ) { + *err = sat->sat_oid; + ldap_memfree(air); + return SLAP_SCHERR_DUP_ATTR; + } + /* FIX: temporal consistency check */ + at_find(air->air_name); + } + + if ( (names = sat->sat_names) ) { + while ( *names ) { + air = (struct aindexrec *) + ch_calloc( 1, sizeof(struct aindexrec) ); + air->air_name = ch_strdup(*names); + air->air_at = sat; + if ( avl_insert( &attr_index, (caddr_t) air, + (AVL_CMP) attr_index_cmp, + (AVL_DUP) avl_dup_error ) ) { + *err = *names; + ldap_memfree(air->air_name); + ldap_memfree(air); + return SLAP_SCHERR_DUP_ATTR; + } + /* FIX: temporal consistency check */ + at_find(air->air_name); + names++; + } + } + + return 0; +} + +int +at_add( + LDAP_ATTRIBUTE_TYPE *at, + const char **err +) +{ + AttributeType *sat; + MatchingRule *mr; + Syntax *syn; + int code; + char *cname; + + if ( at->at_names && at->at_names[0] ) { + cname = at->at_names[0]; + } else if ( at->at_oid ) { + cname = at->at_oid; + } else { + cname = ""; + return SLAP_SCHERR_ATTR_INCOMPLETE; + } + sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) ); + memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE)); + + sat->sat_cname = cname; + + if ( at->at_sup_oid ) { + AttributeType *supsat = at_find(at->at_sup_oid); + + if ( (supsat == NULL ) ) { + *err = at->at_sup_oid; + return SLAP_SCHERR_ATTR_NOT_FOUND; + } + + sat->sat_sup = supsat; + + if ( at_append_to_list(sat, &supsat->sat_subtypes) ) { + *err = cname; + return SLAP_SCHERR_OUTOFMEM; + } + } + + /* + * Inherit definitions from superiors. We only check the + * direct superior since that one has already inherited from + * its own superiorss + */ + if ( sat->sat_sup ) { + sat->sat_syntax = sat->sat_sup->sat_syntax; + sat->sat_equality = sat->sat_sup->sat_equality; + sat->sat_ordering = sat->sat_sup->sat_ordering; + sat->sat_substr = sat->sat_sup->sat_substr; + } + + if ( at->at_syntax_oid ) { + if ( (syn = syn_find(sat->sat_syntax_oid)) ) { + sat->sat_syntax = syn; + } else { + *err = sat->sat_syntax_oid; + return SLAP_SCHERR_SYN_NOT_FOUND; + } + + + } else if ( sat->sat_syntax == NULL ) { + return SLAP_SCHERR_ATTR_INCOMPLETE; + } + + if ( sat->sat_equality_oid ) { + if ( (mr = mr_find(sat->sat_equality_oid)) ) { + sat->sat_equality = mr; + } else { + *err = sat->sat_equality_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + + } + + if ( sat->sat_ordering_oid ) { + if ( (mr = mr_find(sat->sat_ordering_oid)) ) { + sat->sat_ordering = mr; + } else { + *err = sat->sat_ordering_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + } + + if ( sat->sat_substr_oid ) { + if ( (mr = mr_find(sat->sat_substr_oid)) ) { + sat->sat_substr = mr; + } else { + *err = sat->sat_substr_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + } + + code = at_insert(sat,err); + return code; +} + +#ifdef LDAP_DEBUG +static int +at_index_printnode( struct aindexrec *air ) +{ + + printf("%s = %s\n", + air->air_name, + ldap_attributetype2str(&air->air_at->sat_atype) ); + return( 0 ); +} + +static void +at_index_print( void ) +{ + printf("Printing attribute type index:\n"); + (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode, + 0, -1, AVL_INORDER ); +} +#endif + +#if defined( SLAPD_SCHEMA_DN ) +int +at_schema_info( Entry *e ) +{ + struct berval val; + struct berval *vals[2]; + AttributeType *at; + + AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes; + + vals[0] = &val; + vals[1] = NULL; + + for ( at = attr_list; at; at = at->sat_next ) { + val.bv_val = ldap_attributetype2str( &at->sat_atype ); + if ( val.bv_val == NULL ) { + return -1; + } + val.bv_len = strlen( val.bv_val ); +#if 0 + Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n", + (long) val.bv_len, val.bv_val, 0 ); +#endif + attr_merge( e, ad_attributeTypes, vals ); + ldap_memfree( val.bv_val ); + } + return 0; +} +#endif diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c index 8a5f5358cb..f4aa43308d 100644 --- a/servers/slapd/attr.c +++ b/servers/slapd/attr.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* attr.c - routines for dealing with attributes */ @@ -19,10 +19,6 @@ #include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #include "ldap_pvt.h" #include "slap.h" @@ -33,7 +29,7 @@ static void at_index_print( void ); void attr_free( Attribute *a ) { - free( a->a_type ); + ad_free( a->a_desc, 1 ); ber_bvecfree( a->a_vals ); free( a ); } @@ -78,8 +74,7 @@ Attribute *attr_dup( Attribute *a ) tmp->a_vals = NULL; } - tmp->a_type = ch_strdup( a->a_type ); - tmp->a_syntax = a->a_syntax; + tmp->a_desc = ad_dup( a->a_desc ); tmp->a_next = NULL; return tmp; @@ -103,56 +98,7 @@ Attribute *attrs_dup( Attribute *a ) return tmp; } -/* - * attr_normalize - normalize an attribute name (make it all lowercase) - */ - -char * -attr_normalize( char *s ) -{ - assert( s != NULL ); - - return( ldap_pvt_str2lower( s ) ); -} - -/* - * attr_merge_fast - merge the given type and value with the list of - * attributes in attrs. called from str2entry(), where we can make some - * assumptions to make things faster. - * returns 0 everything went ok - * -1 trouble - */ - -int -attr_merge_fast( - Entry *e, - char *type, - struct berval **vals, - int nvals, - int naddvals, - int *maxvals, - Attribute ***a -) -{ - if ( *a == NULL ) { - for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) { - if ( strcasecmp( (**a)->a_type, type ) == 0 ) { - break; - } - } - } - - if ( **a == NULL ) { - **a = (Attribute *) ch_malloc( sizeof(Attribute) ); - (**a)->a_type = attr_normalize( ch_strdup( type ) ); - (**a)->a_vals = NULL; - (**a)->a_syntax = attr_syntax( type ); - (**a)->a_next = NULL; - } - return( value_add_fast( &(**a)->a_vals, vals, nvals, naddvals, - maxvals ) ); -} /* * attr_merge - merge the given type and value with the list of @@ -164,23 +110,22 @@ attr_merge_fast( int attr_merge( Entry *e, - char *type, - struct berval **vals -) + AttributeDescription *desc, + struct berval **vals ) { Attribute **a; for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) { - if ( strcasecmp( (*a)->a_type, type ) == 0 ) { + if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) + { break; } } if ( *a == NULL ) { *a = (Attribute *) ch_malloc( sizeof(Attribute) ); - (*a)->a_type = attr_normalize( ch_strdup( type ) ); + (*a)->a_desc = ad_dup( desc ); (*a)->a_vals = NULL; - (*a)->a_syntax = attr_syntax( type ); (*a)->a_next = NULL; } @@ -188,17 +133,18 @@ attr_merge( } /* - * attr_find - find and return attribute type in list a + * attrs_find - find attribute(s) by AttributeDescription + * returns next attribute which is subtype of provided description. */ Attribute * -attr_find( +attrs_find( Attribute *a, - const char *type + AttributeDescription *desc ) { for ( ; a != NULL; a = a->a_next ) { - if ( strcasecmp( a->a_type, type ) == 0 ) { + if ( is_ad_subtype( a->a_desc, desc ) ) { return( a ); } } @@ -207,523 +153,51 @@ attr_find( } /* - * attr_delete - delete the attribute type in list pointed to by attrs - * return 0 deleted ok - * 1 not found in list a - * -1 something bad happened + * attr_find - find attribute by type */ -int -attr_delete( - Attribute **attrs, - const char *type +Attribute * +attr_find( + Attribute *a, + AttributeDescription *desc ) { - Attribute **a; - Attribute *save; - - for ( a = attrs; *a != NULL; a = &(*a)->a_next ) { - if ( strcasecmp( (*a)->a_type, type ) == 0 ) { - break; + for ( ; a != NULL; a = a->a_next ) { + if ( ad_cmp( a->a_desc, desc ) == 0 ) + { + return( a ); } } - if ( *a == NULL ) { - return( 1 ); - } - - save = *a; - *a = (*a)->a_next; - attr_free( save ); - - return( 0 ); -} - -#define DEFAULT_SYNTAX SYNTAX_CIS - -/* - * attr_syntax - return the syntax of attribute type - */ - -int -attr_syntax( char *type ) -{ - AttributeType *sat; - - sat = at_find(type); - if ( sat ) { - return( sat->sat_syntax_compat ); - } - - return( DEFAULT_SYNTAX ); + return( NULL ); } /* - * attr_syntax_config - process an attribute syntax config line + * attr_delete - delete the attribute type in list pointed to by attrs + * return 0 deleted ok + * 1 not found in list a + * -1 something bad happened */ -void -attr_syntax_config( - const char *fname, - int lineno, - int argc, - char **argv -) -{ - char *save; - LDAP_ATTRIBUTE_TYPE *at; - int lasti; - int code; - const char *err; - - if ( argc < 2 ) { - Debug( LDAP_DEBUG_ANY, -"%s: line %d: missing name in \"attribute + \" (ignored)\n", - fname, lineno, 0 ); - return; - } - - at = (LDAP_ATTRIBUTE_TYPE *) - ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) ); - - lasti = argc - 1; - if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 || - strcasecmp( argv[lasti], "cis" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15"; - at->at_equality_oid = "2.5.13.2"; - at->at_ordering_oid = "2.5.13.3"; - at->at_substr_oid = "2.5.13.4"; - } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 || - strcasecmp( argv[lasti], "tel" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50"; - at->at_equality_oid = "2.5.13.20"; - at->at_substr_oid = "2.5.13.21"; - } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12"; - at->at_equality_oid = "2.5.13.1"; - } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 || - strcasecmp( argv[lasti], "ces" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15"; - at->at_equality_oid = "2.5.13.5"; - at->at_ordering_oid = "2.5.13.6"; - at->at_substr_oid = "2.5.13.7"; - } else if ( strcasecmp( argv[lasti], "binary" ) == 0 || - strcasecmp( argv[lasti], "bin" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5"; - /* There is no match for binary syntax. Really */ - } else { - Debug( LDAP_DEBUG_ANY, - "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n", - fname, lineno, argv[lasti] ); - Debug( LDAP_DEBUG_ANY, - "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n", - 0, 0, 0 ); - free( (AttributeType *) at ); - return; - } - - save = argv[lasti]; - argv[lasti] = NULL; - at->at_names = charray_dup( argv ); - argv[lasti] = save; - - code = at_add( at, &err ); - if ( code ) { - fprintf( stderr, "%s: line %d: %s %s\n", - fname, lineno, scherr2str(code), err); - exit( EXIT_FAILURE ); - } - ldap_memfree(at); -} - -int -at_fake_if_needed( - char *name -) -{ - char *argv[3]; - - if ( at_find( name ) ) { - return 0; - } else { - argv[0] = name; - argv[1] = "cis"; - argv[2] = NULL; - attr_syntax_config( "implicit", 0, 2, argv ); - return 0; - } -} - -struct aindexrec { - char *air_name; - AttributeType *air_at; -}; - -static Avlnode *attr_index = NULL; -static AttributeType *attr_list = NULL; - -static int -attr_index_cmp( - struct aindexrec *air1, - struct aindexrec *air2 -) -{ - return (strcasecmp( air1->air_name, air2->air_name )); -} - -static int -attr_index_name_cmp( - char *type, - struct aindexrec *air -) -{ - return (strcasecmp( type, air->air_name )); -} - -AttributeType * -at_find( - const char *name -) -{ - struct aindexrec *air = NULL; - - if ( (air = (struct aindexrec *) avl_find( attr_index, name, - (AVL_CMP) attr_index_name_cmp )) != NULL ) { - return( air->air_at ); - } - return( NULL ); -} - -int -at_append_to_list( - AttributeType *sat, - AttributeType ***listp -) -{ - AttributeType **list; - AttributeType **list1; - int size; - - list = *listp; - if ( !list ) { - size = 2; - list = calloc(size, sizeof(AttributeType *)); - if ( !list ) { - return -1; - } - } else { - size = 0; - list1 = *listp; - while ( *list1 ) { - size++; - list1++; - } - size += 2; - list1 = realloc(list, size*sizeof(AttributeType *)); - if ( !list1 ) { - return -1; - } - list = list1; - } - list[size-2] = sat; - list[size-1] = NULL; - *listp = list; - return 0; -} - -int -at_delete_from_list( - int pos, - AttributeType ***listp -) -{ - AttributeType **list; - AttributeType **list1; - int i; - int j; - - if ( pos < 0 ) { - return -2; - } - list = *listp; - for ( i=0; list[i]; i++ ) - ; - if ( pos >= i ) { - return -2; - } - for ( i=pos, j=pos+1; list[j]; i++, j++ ) { - list[i] = list[j]; - } - list[i] = NULL; - /* Tell the runtime this can be shrinked */ - list1 = realloc(list, (i+1)*sizeof(AttributeType **)); - if ( !list1 ) { - return -1; - } - *listp = list1; - return 0; -} - -int -at_find_in_list( - AttributeType *sat, - AttributeType **list -) -{ - int i; - - if ( !list ) { - return -1; - } - for ( i=0; list[i]; i++ ) { - if ( sat == list[i] ) { - return i; - } - } - return -1; -} - -static int -at_insert( - AttributeType *sat, - const char **err -) -{ - AttributeType **atp; - struct aindexrec *air; - char **names; - - atp = &attr_list; - while ( *atp != NULL ) { - atp = &(*atp)->sat_next; - } - *atp = sat; - - if ( sat->sat_oid ) { - air = (struct aindexrec *) - ch_calloc( 1, sizeof(struct aindexrec) ); - air->air_name = sat->sat_oid; - air->air_at = sat; - if ( avl_insert( &attr_index, (caddr_t) air, - (AVL_CMP) attr_index_cmp, - (AVL_DUP) avl_dup_error ) ) { - *err = sat->sat_oid; - ldap_memfree(air); - return SLAP_SCHERR_DUP_ATTR; - } - /* FIX: temporal consistency check */ - at_find(air->air_name); - } - if ( (names = sat->sat_names) ) { - while ( *names ) { - air = (struct aindexrec *) - ch_calloc( 1, sizeof(struct aindexrec) ); - air->air_name = ch_strdup(*names); - air->air_at = sat; - if ( avl_insert( &attr_index, (caddr_t) air, - (AVL_CMP) attr_index_cmp, - (AVL_DUP) avl_dup_error ) ) { - *err = *names; - ldap_memfree(air); - return SLAP_SCHERR_DUP_ATTR; - } - /* FIX: temporal consistency check */ - at_find(air->air_name); - names++; - } - } - - return 0; -} - int -at_add( - LDAP_ATTRIBUTE_TYPE *at, - const char **err +attr_delete( + Attribute **attrs, + AttributeDescription *desc ) { - AttributeType *sat; - AttributeType *sat1; - MatchingRule *mr; - Syntax *syn; - int code; - char *errattr; - - if ( at->at_names && at->at_names[0] ) { - errattr = at->at_names[0]; - } else if ( at->at_oid ) { - errattr = at->at_oid; - } else { - errattr = ""; - return SLAP_SCHERR_ATTR_INCOMPLETE; - } - sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) ); - memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE)); - if ( at->at_sup_oid ) { - if ( (sat1 = at_find(at->at_sup_oid)) ) { - sat->sat_sup = sat1; - if ( at_append_to_list(sat, &sat1->sat_subtypes) ) { - *err = errattr; - return SLAP_SCHERR_OUTOFMEM; - } - } else { - *err = at->at_sup_oid; - return SLAP_SCHERR_ATTR_NOT_FOUND; - } - } - - if ( at->at_syntax_oid ) { - if ( (syn = syn_find(sat->sat_syntax_oid)) ) { - sat->sat_syntax = syn; - } else { - *err = sat->sat_syntax_oid; - return SLAP_SCHERR_SYN_NOT_FOUND; - } - if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.15") ) { - if ( at->at_equality_oid && - !strcmp(at->at_equality_oid, "2.5.13.5") ) { - sat->sat_syntax_compat = SYNTAX_CES; - } else { - sat->sat_syntax_compat = SYNTAX_CIS; - } - } else if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.50") ) { - sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL; - } else if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.12") ) { - sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN; - } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) { - sat->sat_syntax_compat = SYNTAX_BIN; - } else { - sat->sat_syntax_compat = DEFAULT_SYNTAX; - } - } else { - sat->sat_syntax_compat = DEFAULT_SYNTAX; - } - - if ( sat->sat_equality_oid ) { - if ( (mr = mr_find(sat->sat_equality_oid)) ) { - sat->sat_equality = mr; - } else { - *err = sat->sat_equality_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - } - if ( sat->sat_ordering_oid ) { - if ( (mr = mr_find(sat->sat_ordering_oid)) ) { - sat->sat_ordering = mr; - } else { - *err = sat->sat_ordering_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - } - if ( sat->sat_substr_oid ) { - if ( (mr = mr_find(sat->sat_substr_oid)) ) { - sat->sat_substr = mr; - } else { - *err = sat->sat_substr_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - } - - /* - * Now inherit definitions from superiors. We only check the - * direct superior since that one has already inherited from - * its own superiorss - */ - if ( sat->sat_sup ) { - if ( !sat->sat_syntax ) { - sat->sat_syntax = sat->sat_sup->sat_syntax; - sat->sat_syntax_len = sat->sat_sup->sat_syntax_len; - } - if ( !sat->sat_equality ) { - sat->sat_equality = sat->sat_sup->sat_equality; - } - if ( !sat->sat_ordering ) { - sat->sat_ordering = sat->sat_sup->sat_ordering; - } - if ( !sat->sat_substr ) { - sat->sat_substr = sat->sat_sup->sat_substr; - } - } - code = at_insert(sat,err); - return code; -} - - -char * -at_canonical_name( char * a_type ) -{ - AttributeType *atp; - - if ( (atp=at_find(a_type)) == NULL ) { - - return a_type; - - } else if ( atp->sat_names - && atp->sat_names[0] - && (*(atp->sat_names[0]) != '\0') ) { - - return atp->sat_names[0]; - - } else if (atp->sat_oid && (*atp->sat_oid != '\0')) { - - return atp->sat_oid; - - } else { - - return a_type; - - } - -}/* char * at_canonica_name() */ - + Attribute **a; -#if defined( SLAPD_SCHEMA_DN ) + for ( a = attrs; *a != NULL; a = &(*a)->a_next ) { + if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) + { + Attribute *save = *a; + *a = (*a)->a_next; + attr_free( save ); -int -at_schema_info( Entry *e ) -{ - struct berval val; - struct berval *vals[2]; - AttributeType *at; - - vals[0] = &val; - vals[1] = NULL; - - for ( at = attr_list; at; at = at->sat_next ) { - val.bv_val = ldap_attributetype2str( &at->sat_atype ); - if ( val.bv_val ) { - val.bv_len = strlen( val.bv_val ); - Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n", - (long) val.bv_len, val.bv_val, 0 ); - attr_merge( e, "attributeTypes", vals ); - ldap_memfree( val.bv_val ); - } else { - return -1; + return LDAP_SUCCESS; } } - return 0; -} -#endif - -#ifdef LDAP_DEBUG -static int -at_index_printnode( struct aindexrec *air ) -{ - - printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) ); - return( 0 ); -} - -static void -at_index_print( void ) -{ - printf("Printing attribute type index:\n"); - (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode, - 0, -1, AVL_INORDER ); + return LDAP_NO_SUCH_ATTRIBUTE; } -#endif diff --git a/servers/slapd/ava.c b/servers/slapd/ava.c index b3f314050a..4b797978fa 100644 --- a/servers/slapd/ava.c +++ b/servers/slapd/ava.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* ava.c - routines for dealing with attribute value assertions */ @@ -14,33 +14,66 @@ #include "slap.h" + +void +ava_free( + AttributeAssertion *ava, + int freeit +) +{ + ad_free( ava->aa_desc, 1 ); + ber_bvfree( ava->aa_value ); + if ( freeit ) { + ch_free( (char *) ava ); + } +} + int get_ava( BerElement *ber, - Ava *ava + AttributeAssertion **ava, + unsigned usage, + const char **text ) { - if ( ber_scanf( ber, "{ao}", &ava->ava_type, &ava->ava_value ) - == LBER_ERROR ) { + int rc; + struct berval type, value, *nvalue; + AttributeAssertion *aa; + + rc = ber_scanf( ber, "{oo}", &type, &value ); + + if( rc == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, " get_ava ber_scanf\n", 0, 0, 0 ); - return( -1 ); + *text = "Error decoding attribute value assertion"; + return SLAPD_DISCONNECT; } - attr_normalize( ava->ava_type ); - value_normalize( ava->ava_value.bv_val, attr_syntax( ava->ava_type ) ); - return( LDAP_SUCCESS ); -} + aa = ch_malloc( sizeof( AttributeAssertion ) ); + aa->aa_desc = NULL; + aa->aa_value = NULL; -void -ava_free( - Ava *ava, - int freeit -) -{ - free( (char *) ava->ava_type ); - free( (char *) ava->ava_value.bv_val ); - if ( freeit ) { - free( (char *) ava ); + rc = slap_bv2ad( &type, &aa->aa_desc, text ); + + if( rc != LDAP_SUCCESS ) { + ch_free( type.bv_val ); + ch_free( value.bv_val ); + ch_free( aa ); + return rc; + } + + rc = value_normalize( aa->aa_desc, usage, &value, &nvalue, text ); + ch_free( value.bv_val ); + + if( rc != LDAP_SUCCESS ) { + ch_free( type.bv_val ); + ad_free( aa->aa_desc, 1 ); + ch_free( aa ); + return rc; } + + aa->aa_value = nvalue; + *ava = aa; + + return LDAP_SUCCESS; } diff --git a/servers/slapd/back-bdb2/Makefile.in b/servers/slapd/back-bdb2/Makefile.in deleted file mode 100644 index fd25b63bcb..0000000000 --- a/servers/slapd/back-bdb2/Makefile.in +++ /dev/null @@ -1,31 +0,0 @@ -# $OpenLDAP$ - -SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c id2entry.c \ - index.c id2children.c nextid.c abandon.c compare.c group.c \ - modify.c modrdn.c delete.c init.c config.c bind.c attr.c \ - filterindex.c unbind.c kerberos.c close.c alias.c startup.c \ - timing.c porter.c txn.c tools.c -OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \ - index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \ - modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \ - filterindex.lo unbind.lo kerberos.lo close.lo alias.lo startup.lo \ - timing.lo porter.lo txn.lo tools.lo - -LDAP_INCDIR= ../../../include -LDAP_LIBDIR= ../../../libraries - -BUILD_OPT = "--enable-bdb2" -BUILD_MOD = @BUILD_BDB2@ -LINKAGE = @BUILD_BDB2_DYNAMIC@ - -LIBBASE = back_bdb2 - -XINCPATH = -I.. -I$(srcdir)/.. -XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) - -all-local-lib: ../.backend - -../.backend: lib$(LIBBASE).a - @touch $@ - diff --git a/servers/slapd/back-bdb2/abandon.c b/servers/slapd/back-bdb2/abandon.c deleted file mode 100644 index a062487393..0000000000 --- a/servers/slapd/back-bdb2/abandon.c +++ /dev/null @@ -1,47 +0,0 @@ -/* abandon.c - ldbm backend abandon routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - - -/*ARGSUSED*/ -static int -bdb2i_back_abandon_internal( - BackendDB *be, - Connection *c, - Operation *o, - int msgid ) -{ - return 0; -} - - -int -bdb2_back_abandon( - BackendDB *be, - Connection *conn, - Operation *op, - int msgid ) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_abandon_internal( be, conn, op, msgid ); - - bdb2i_stop_timing( be->bd_info, time1, "ABND", conn, op ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/add.c b/servers/slapd/back-bdb2/add.c deleted file mode 100644 index b72dc51512..0000000000 --- a/servers/slapd/back-bdb2/add.c +++ /dev/null @@ -1,325 +0,0 @@ -/* add.c - ldap bdb2 back-end add routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static DB_LOCK lock; - - -static int -bdb2i_back_add_internal( - BackendDB *be, - Connection *conn, - Operation *op, - Entry *e -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char *pdn; - Entry *p = NULL; - int rc; - struct timeval time1; - - Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0); - - if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) { - entry_free( e ); - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, - NULL, NULL, NULL, NULL ); - return( -1 ); - } - - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { - Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", - 0, 0, 0 ); - - entry_free( e ); - send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL, NULL ); - return( -1 ); - } - - /* - * Get the parent dn and see if the corresponding entry exists. - * If the parent does not exist, only allow the "root" user to - * add the entry. - */ - - pdn = dn_parent( be, e->e_ndn ); - - if( pdn != NULL && *pdn != '\0' ) { - Entry *matched = NULL; - - assert( *pdn != '\0' ); - - /* get parent with writer lock */ - if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) { - char *matched_dn; - struct berval **refs; - - if( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - - bdb2i_cache_return_entry_w( &li->li_cache, matched ); - - } else { - matched_dn = NULL; - refs = default_referral; - } - - Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", - 0, 0, 0 ); - - send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, - matched_dn, NULL, NULL, NULL ); - - if ( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - entry_free( e ); - free( pdn ); - return -1; - } - - free(pdn); - - if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) - { - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - - Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - - entry_free( e ); - return -1; - } - - - if ( is_entry_alias( p ) ) { - /* parent is an alias, don't allow add */ - - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - - Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, - NULL, NULL, NULL, NULL ); - - entry_free( e ); - return -1; - } - - if ( is_entry_referral( p ) ) { - /* parent is an referral, don't allow add */ - char *matched_dn = ch_strdup( matched->e_dn ); - struct berval **refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - - Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - free( matched_dn ); - entry_free( e ); - return -1; - } - - } else { - if(pdn != NULL) { - assert( *pdn == '\0' ); - free(pdn); - } - - /* no parent, must be adding entry to root */ - if ( !be_isroot( be, op->o_ndn ) && !be_issuffix(be, "") ) { - Debug( LDAP_DEBUG_TRACE, "%s add denied\n", - pdn == NULL ? "suffix" : "entry at root", - 0, 0 ); - - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - - entry_free( e ); - return -1; - } - } - - e->e_id = bdb2i_next_id( be ); - - /* - * Try to add the entry to the cache, assign it a new dnid. - */ - bdb2i_start_timing( be->bd_info, &time1 ); - - rc = bdb2i_cache_add_entry_rw( &li->li_cache, e, CACHE_WRITE_LOCK ); - - bdb2i_stop_timing( be->bd_info, time1, "ADD-CACHE", conn, op ); - - if ( rc != 0 ) { - if( p != NULL) { - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - } - - Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, - 0 ); - - /* free the entry */ - entry_free( e ); - - send_ldap_result( conn, op, - rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - return( -1 ); - } - - rc = -1; - - /* - * Add the entry to the attribute indexes, then add it to - * the id2entry and dn2id index. - */ - - bdb2i_start_timing( be->bd_info, &time1 ); - - /* attribute indexes */ - if ( bdb2i_index_add_entry( be, e ) != 0 ) { - Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op ); - - goto return_results; - } - - bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op ); - - bdb2i_start_timing( be->bd_info, &time1 ); - - /* dn2id index */ - if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { - Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op ); - - goto return_results; - } - - bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op ); - - bdb2i_start_timing( be->bd_info, &time1 ); - - /* id2entry index */ - if ( bdb2i_id2entry_add( be, e ) != 0 ) { - Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0, - 0, 0 ); - (void) bdb2i_dn2id_delete( be, e->e_ndn, e->e_id ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op ); - - goto return_results; - } - - bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op ); - - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - rc = 0; - -return_results:; - if (p != NULL) { - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - } - - if ( rc ) { - /* free entry and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, e ); - } - - return( rc ); -} - - -int -bdb2_back_add( - BackendDB *be, - Connection *conn, - Operation *op, - Entry *e -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_w( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( -1 ); - } - - /* check, if a new default attribute index will be created, - in which case we have to open the index file BEFORE TP */ - switch ( slapMode & SLAP_MODE ) { - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - bdb2i_check_default_attr_index_add( li, e ); - break; - } - - ret = bdb2i_back_add_internal( be, conn, op, e ); - - /* if the operation was successful, we will delay the unlock */ - if ( ret ) - (void) bdb2i_leave_backend_w( lock ); - - bdb2i_stop_timing( be->bd_info, time1, "ADD", conn, op ); - - return( ret ); -} - - -int -bdb2i_release_add_lock( void ) -{ - (void) bdb2i_leave_backend_w( lock ); - return 0; -} - - diff --git a/servers/slapd/back-bdb2/alias.c b/servers/slapd/back-bdb2/alias.c deleted file mode 100644 index 3de54b9bf0..0000000000 --- a/servers/slapd/back-bdb2/alias.c +++ /dev/null @@ -1,285 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ - -#include "portable.h" - -#include -#include -#include -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static char* get_alias_dn( - Entry *e, - int *err, - char **errmsg ); - -static char* new_superior( - char *dn, - char *oldSup, - char *newSup ); - -static int dnlist_subordinate( - char** dnlist, - char *dn ); - -Entry *bdb2i_deref_r( - Backend* be, - Entry* alias, - char* dn, - int* err, - Entry** matched, - char** text ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *entry; - Entry *sup; - unsigned depth; - char **dnlist; - - assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) ); - - *matched = NULL; - *err = LDAP_SUCCESS; - *text = NULL; - - if( alias == NULL ) { - dn = ch_strdup( dn ); - entry = bdb2i_dn2entry_r( be, dn, &sup ); - - } else { - dn = ch_strdup( alias->e_ndn ); - entry = alias; - sup = NULL; - } - - dnlist = NULL; - charray_add( &dnlist, dn ); - - for( depth=0 ; ; depth++ ) { - if( entry != NULL ) { - Entry *newe; - char *aliasDN; - - /* have entry, may be an alias */ - - if( !is_entry_alias( entry ) ) { - /* entry is not an alias */ - break; - } - - /* entry is alias */ - if( depth > be->be_max_deref_depth ) { - *matched = entry; - entry = NULL; - *err = LDAP_ALIAS_DEREF_PROBLEM; - *text = "maximum deref depth exceeded"; - break; - } - - /* deref entry */ - aliasDN = get_alias_dn( entry, err, text ); - - if( aliasDN == NULL ) { - *matched = entry; - entry = NULL; - break; - } - - /* check if aliasDN is a subordinate of any DN in our list */ - if( dnlist_subordinate( dnlist, aliasDN ) ) { - *matched = entry; - entry = NULL; - *err = LDAP_ALIAS_PROBLEM; - *text = "circular alias"; - break; - } - - /* attempt to dereference alias */ - - newe = bdb2i_dn2entry_r( be, aliasDN, &sup ); - - if( newe != NULL ) { - free( dn ); - bdb2i_cache_return_entry_r(&li->li_cache, entry ); - entry = newe; - dn = ch_strdup( entry->e_ndn ); - charray_add( &dnlist, dn ); - continue; - - } - - if ( sup != NULL ) { - bdb2i_cache_return_entry_r(&li->li_cache, entry ); - entry = NULL; - continue; - } - - /* no newe and no superior, we're done */ - break; - - } else if( sup != NULL ) { - /* have superior, may be an alias */ - Entry *newe; - Entry *newSup; - char *supDN; - char *aliasDN; - - if( !is_entry_alias( sup ) ) { - /* entry is not an alias */ - *matched = sup; - sup = NULL; - break; - } - - /* entry is alias */ - if( depth > be->be_max_deref_depth ) { - *matched = sup; - entry = NULL; - *err = LDAP_ALIAS_DEREF_PROBLEM; - *text = "maximum deref depth exceeded"; - break; - } - - /* deref entry */ - supDN = get_alias_dn( sup, err, text ); - - if( supDN == NULL ) { - *matched = sup; - break; - } - - aliasDN = new_superior( dn, sup->e_ndn, supDN ); - - if( aliasDN == NULL ) { - free(aliasDN); - *matched = sup; - *err = LDAP_ALIAS_PROBLEM; - *text = "superior alias problem"; - break; - } - - /* check if aliasDN is a subordinate of any DN in our list */ - if( dnlist_subordinate( dnlist, aliasDN ) ) { - free(aliasDN); - *matched = entry; - entry = NULL; - *err = LDAP_ALIAS_PROBLEM; - *text = "subordinate circular alias"; - break; - } - - /* attempt to dereference alias */ - newe = bdb2i_dn2entry_r( be, aliasDN, &newSup ); - - if( newe != NULL ) { - free(aliasDN); - free( dn ); - bdb2i_cache_return_entry_r(&li->li_cache, sup ); - entry = newe; - dn = ch_strdup( entry->e_ndn ); - charray_add( &dnlist, dn ); - continue; - - } - - if ( newSup != NULL ) { - free( dn ); - bdb2i_cache_return_entry_r(&li->li_cache, sup ); - sup = newSup; - dn = aliasDN; - continue; - } - - break; - - } else { - /* no newe and no superior, we're done */ - break; - } - } - - free( dn ); - return entry; -} - - -static char* get_alias_dn( - Entry *e, - int *err, - char **errmsg ) -{ - Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" ); - - if( a == NULL ) { - /* - * there was an aliasedobjectname defined but no data. - */ - *err = LDAP_ALIAS_PROBLEM; - *errmsg = "alias missing aliasedObjectName attribute"; - return NULL; - } - - /* - * aliasedObjectName should be SINGLE-VALUED with a single value. - */ - if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val == NULL ) { - /* - * there was an aliasedobjectname defined but no data. - */ - *err = LDAP_ALIAS_PROBLEM; - *errmsg = "alias missing aliasedObjectName value"; - return NULL; - } - - if( a->a_vals[1] != NULL ) { - *err = LDAP_ALIAS_PROBLEM; - *errmsg = "alias has multivalued aliasedObjectName"; - return NULL; - } - - return a->a_vals[0]->bv_val; -} - -static char* new_superior( - char *dn, - char *oldSup, - char *newSup ) -{ - char *newDN; - size_t dnlen, olen, nlen; - assert( dn && oldSup && newSup ); - - dnlen = strlen( dn ); - olen = strlen( oldSup ); - nlen = strlen( newSup ); - - newDN = ch_malloc( dnlen - olen + nlen + 1 ); - - memcpy( newDN, dn, dnlen - olen ); - memcpy( &newDN[dnlen - olen], newSup, nlen ); - newDN[dnlen - olen + nlen] = '\0'; - - return newDN; -} - -static int dnlist_subordinate( - char** dnlist, - char *dn ) -{ - int i; - assert( dnlist ); - - for( i = 0; dnlist[i] != NULL; i++ ) { - if( dn_issuffix( dnlist[i], dn ) ) { - return 1; - } - } - - return 0; -} - diff --git a/servers/slapd/back-bdb2/attr.c b/servers/slapd/back-bdb2/attr.c deleted file mode 100644 index 7fa5988865..0000000000 --- a/servers/slapd/back-bdb2/attr.c +++ /dev/null @@ -1,174 +0,0 @@ -/* attr.c - backend routines for dealing with attributes */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static int -ainfo_type_cmp( - char *type, - struct attrinfo *a -) -{ - return( strcasecmp( type, a->ai_type ) ); -} - -static int -ainfo_cmp( - struct attrinfo *a, - struct attrinfo *b -) -{ - return( strcasecmp( a->ai_type, b->ai_type ) ); -} - -/* - * Called when a duplicate "index" line is encountered. - * - * returns 1 => original from init code, indexmask updated - * 2 => original not from init code, warn the user - */ - -static int -ainfo_dup( - struct attrinfo *a, - struct attrinfo *b -) -{ - /* - * if the duplicate definition is because we initialized the attr, - * just add what came from the config file. otherwise, complain. - */ - if ( a->ai_indexmask & INDEX_FROMINIT ) { - a->ai_indexmask |= b->ai_indexmask; - - return( 1 ); - } - - return( 2 ); -} - -void -bdb2i_attr_masks( - struct ldbminfo *li, - char *type, - int *indexmask, - int *syntaxmask -) -{ - struct attrinfo *a; - - *indexmask = 0; - *syntaxmask = 0; - if ( (a = (struct attrinfo *) avl_find( li->li_attrs, type, - (AVL_CMP) ainfo_type_cmp )) == NULL ) { - if ( (a = (struct attrinfo *) avl_find( li->li_attrs, "default", - (AVL_CMP) ainfo_type_cmp )) == NULL ) { - return; - } - } - *indexmask = a->ai_indexmask; - if ( strcasecmp( a->ai_type, "default" ) == 0 ) { - *syntaxmask = attr_syntax( type ); - } else { - *syntaxmask = a->ai_syntaxmask; - } -} - - -/* BDB2 changed */ -void -bdb2i_attr_index_config( - struct ldbminfo *li, - const char *fname, - int lineno, - int argc, - char **argv, - int init -) -{ - int i, j; - char **attrs, **indexes; - struct attrinfo *a; - - attrs = str2charray( argv[0], "," ); - if ( argc > 1 ) { - indexes = str2charray( argv[1], "," ); - } - for ( i = 0; attrs[i] != NULL; i++ ) { - a = (struct attrinfo *) ch_malloc( sizeof(struct attrinfo) ); - a->ai_type = ch_strdup( attrs[i] ); - a->ai_syntaxmask = attr_syntax( a->ai_type ); - if ( argc == 1 ) { - a->ai_indexmask = (INDEX_PRESENCE | INDEX_EQUALITY | - INDEX_APPROX | INDEX_SUB); - } else { - a->ai_indexmask = 0; - for ( j = 0; indexes[j] != NULL; j++ ) { - if ( strncasecmp( indexes[j], "pres", 4 ) - == 0 ) { - a->ai_indexmask |= INDEX_PRESENCE; - } else if ( strncasecmp( indexes[j], "eq", 2 ) - == 0 ) { - a->ai_indexmask |= INDEX_EQUALITY; - } else if ( strncasecmp( indexes[j], "approx", - 6 ) == 0 ) { - a->ai_indexmask |= INDEX_APPROX; - } else if ( strncasecmp( indexes[j], "sub", 3 ) - == 0 ) { - a->ai_indexmask |= INDEX_SUB; - } else if ( strncasecmp( indexes[j], "none", 4 ) - == 0 ) { - if ( a->ai_indexmask != 0 ) { - fprintf( stderr, -"%s: line %d: index type \"none\" cannot be combined with other types\n", - fname, lineno ); - } - a->ai_indexmask = 0; - } else { - fprintf( stderr, - "%s: line %d: unknown index type \"%s\" (ignored)\n", - fname, lineno, indexes[j] ); - fprintf( stderr, - "valid index types are \"pres\", \"eq\", \"approx\", or \"sub\"\n" ); - } - } - } - if ( init ) { - a->ai_indexmask |= INDEX_FROMINIT; - } else { - if ( a->ai_indexmask ) - bdb2i_txn_attr_config( li, a->ai_type, 0 ); - } - - switch (avl_insert( &li->li_attrs, (caddr_t) a, - (AVL_CMP) ainfo_cmp, (AVL_DUP) ainfo_dup )) - { - case 1: /* duplicate - updating init version */ - free( a->ai_type ); - free( (char *) a ); - break; - - case 2: /* user duplicate - ignore and warn */ - fprintf( stderr, - "%s: line %d: duplicate index definition for attr \"%s\" (ignored)\n", - fname, lineno, a->ai_type ); - free( a->ai_type ); - free( (char *) a ); - break; - - default:; /* inserted ok */ - /* FALL */ - } - } - charray_free( attrs ); - if ( argc > 1 ) - charray_free( indexes ); -} diff --git a/servers/slapd/back-bdb2/back-bdb2.h b/servers/slapd/back-bdb2/back-bdb2.h deleted file mode 100644 index 4ebc54422c..0000000000 --- a/servers/slapd/back-bdb2/back-bdb2.h +++ /dev/null @@ -1,207 +0,0 @@ -/* back-bdb2.h - ldap bdb2 back-end header file */ -/* $OpenLDAP$ */ - -#ifndef _BACK_BDB2_H_ -#define _BACK_BDB2_H_ - -#include "ldbm.h" -#include "db.h" - -LDAP_BEGIN_DECL - -#define DEFAULT_CACHE_SIZE 1000 - -/* since DEFAULT_DB_PAGE_SIZE is 1K, we have 128K, - which is suggested by Sleepycat */ -#define DEFAULT_DBCACHE_SIZE (128 * DEFAULT_DB_PAGE_SIZE) - -#define DEFAULT_DB_DIRECTORY "/usr/tmp" -#define DEFAULT_DB_HOME "/usr/tmp" -#define DEFAULT_MODE 0600 - -#define SUBLEN 3 - -#define DN_BASE_PREFIX '=' -#define DN_ONE_PREFIX '@' -#define DN_SUBTREE_PREFIX '?' - -#define SLAPD_FILTER_DN_ONE ((ber_tag_t) -2) -#define SLAPD_FILTER_DN_SUBTREE ((ber_tag_t) -3) - - -#define BDB2_SUFFIX ".bdb2" - - -/* - * there is a single index for each attribute. these prefixes ensure - * that there is no collision among keys. - */ -#define EQ_PREFIX '=' /* prefix for equality keys */ -#define APPROX_PREFIX '~' /* prefix for approx keys */ -#define SUB_PREFIX '*' /* prefix for substring keys */ -#define CONT_PREFIX '\\' /* prefix for continuation keys */ - -/* allow 3 characters per byte + PREFIX + EOS */ -#define CONT_SIZE ( sizeof(long)*3 + 1 + 1 ) - - -#define UNKNOWN_PREFIX '?' /* prefix for unknown keys */ - -#define DEFAULT_BLOCKSIZE 8192 - -/* - * This structure represents an id block on disk and an id list - * in core. - * - * The fields have the following meanings: - * - * b_nmax maximum number of ids in this block. if this is == ALLIDSBLOCK, - * then this block represents all ids. - * b_nids current number of ids in use in this block. if this - * is == INDBLOCK, then this block is an indirect block - * containing a list of other blocks containing actual ids. - * the list is terminated by an id of NOID. - * b_ids a list of the actual ids themselves - */ - -typedef ID ID_BLOCK; - -#define ID_BLOCK_NMAX_OFFSET 0 -#define ID_BLOCK_NIDS_OFFSET 1 -#define ID_BLOCK_IDS_OFFSET 2 - -/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */ - -#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET]) -#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET]) -#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)]) - -#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID) - -#define ID_BLOCK_ALLIDS_VALUE 0 -#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE) - -#define ID_BLOCK_INDIRECT_VALUE 0 -#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE) - -/* for the in-core cache of entries */ -struct cache { - int c_maxsize; - int c_cursize; - Avlnode *c_dntree; - Avlnode *c_idtree; - Entry *c_lruhead; /* lru - add accessed entries here */ - Entry *c_lrutail; /* lru - rem lru entries from here */ - ldap_pvt_thread_mutex_t c_mutex; -}; - -#define CACHE_READ_LOCK 0 -#define CACHE_WRITE_LOCK 1 - -/* for the cache of open index files (re-used for txn) */ -struct dbcache { - int dbc_refcnt; - int dbc_maxids; - int dbc_maxindirect; - long dbc_blksize; - char *dbc_name; - LDBM dbc_db; - - struct dbcache *next; -}; - -typedef struct dbcache BDB2_TXN_FILES; -typedef struct dbcache DBCache; - - -/* for the cache of attribute information (which are indexed, etc.) */ -struct attrinfo { - char *ai_type; /* type name (cn, sn, ...) */ - int ai_indexmask; /* how the attr is indexed */ -#define INDEX_PRESENCE 0x0001 -#define INDEX_EQUALITY 0x0002 -#define INDEX_APPROX 0x0004 -#define INDEX_SUB 0x0008 -#define INDEX_UNKNOWN 0x0010 -#define INDEX_FROMINIT 0x1000 - int ai_syntaxmask; /* what kind of syntax */ -/* ...from slap.h... -#define SYNTAX_CIS 0x01 -#define SYNTAX_CES 0x02 -#define SYNTAX_BIN 0x04 - ... etc. ... -*/ -}; - -/* TP stuff */ - -typedef struct _bdb2_txn_head { - - /* log size and timer to control checkpoints */ - u_int32_t txn_log; - u_int32_t txn_time; - - /* a list of all DB files in use */ - BDB2_TXN_FILES *dbFiles; - - /* we have five fixed files */ -#define BDB2_DB_DN_FILE 0 -#define BDB2_DB_DN2ID_FILE 1 -#define BDB2_DB_ID2ENTRY_FILE 2 -#define BDB2_DB_ID2CHILDREN_FILE 3 -#define BDB2_DB_OC_IDX_FILE 4 - - /* a database handle for the NEXTID file - (must be opened like all DB files at startup - and closed on shutdown */ - LDBM nextidFile; - - /* is the default attribute index set to non-none */ - int withDefIDX; -#define BDB2_WITH_DEF_IDX 1 - - /* a handle for the backend's environment */ - DB_ENV **dbenvH; - -} BDB2_TXN_HEAD; - - -/* end of TP stuff */ - - -/* the private description of a backend type */ -struct ldbtype { - char *lty_dbhome; - size_t lty_mpsize; - int lty_betiming; -}; - -#define with_timing(bi) (((struct ldbtype *) \ - (bi)->bi_private)->lty_betiming == 1) - -/* The DB environment */ -extern DB_ENV bdb2i_dbEnv; - - -/* the private description of a database */ -struct ldbminfo { - ID li_nextid; - char *li_nextid_file; - int li_mode; - char *li_directory; - struct cache li_cache; - Avlnode *li_attrs; - int li_dbcachesize; - int li_dbcachewsync; - - /* a list of all files of the database */ - BDB2_TXN_HEAD li_txn_head; - -}; - - -#include "proto-back-bdb2.h" - -LDAP_END_DECL - -#endif /* _back_bdb2_h_ */ diff --git a/servers/slapd/back-bdb2/bind.c b/servers/slapd/back-bdb2/bind.c deleted file mode 100644 index e022a5533b..0000000000 --- a/servers/slapd/back-bdb2/bind.c +++ /dev/null @@ -1,347 +0,0 @@ -/* bind.c - bdb2 backend bind and unbind routines */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -#include - -#ifdef HAVE_KERBEROS -extern int bdb2i_krbv4_ldap_auth(); -#endif - -static int -crypted_value_find( - struct berval **vals, - struct berval *v, - int syntax, - int normalize, - struct berval *cred -) -{ - int i; - for ( i = 0; vals[i] != NULL; i++ ) { - if ( syntax != SYNTAX_BIN ) { - int result; - -#ifdef SLAPD_CRYPT - ldap_pvt_thread_mutex_lock( &crypt_mutex ); -#endif - - result = lutil_passwd( - (char*) cred->bv_val, - (char*) vals[i]->bv_val, - NULL ); - -#ifdef SLAPD_CRYPT - ldap_pvt_thread_mutex_unlock( &crypt_mutex ); -#endif - - return result; - - } else { - if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) { - return( 0 ); - } - } - } - - return( 1 ); -} - -static int -bdb2i_back_bind_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - int method, - char *mech, - struct berval *cred, - char** edn -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *e; - Attribute *a; - int rc; - Entry *matched; -#ifdef HAVE_KERBEROS - char krbname[MAX_K_NAME_SZ + 1]; - AUTH_DAT ad; -#endif - - Debug(LDAP_DEBUG_ARGS, "==> bdb2_back_bind: dn: %s\n", dn, 0, 0); - - *edn = NULL; - - /* get entry with reader lock */ - if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - /* allow noauth binds */ - rc = 1; - if ( method == LDAP_AUTH_SIMPLE ) { - if( cred->bv_len == 0 ) { - /* SUCCESS */ - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - - } else if ( be_isroot_pw( be, dn, cred ) ) { - /* front end will send result */ - *edn = ch_strdup( be_root_dn( be ) ); - rc = 0; - - } else { - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - } - - } else if ( method == LDAP_AUTH_SASL ) { - if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) { - /* insert DIGEST calls here */ - send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, NULL, NULL, NULL ); - } - - } else { - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - rc = 1; - } - - if ( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - return( rc ); - } - - *edn = ch_strdup( e->e_dn ); - - /* check for deleted */ - - if ( ! access_allowed( be, conn, op, e, - "entry", NULL, ACL_AUTH ) ) - { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - rc = 1; - goto return_results; - } - - if ( is_entry_alias( e ) ) { - /* entry is a alias, don't allow bind */ - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, - NULL, NULL, NULL, NULL ); - - rc = 1; - goto return_results; - } - - - if ( is_entry_referral( e ) ) { - /* entry is a referral, don't allow bind */ - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - - rc = 1; - goto return_results; - } - - switch ( method ) { - case LDAP_AUTH_SIMPLE: - if ( cred->bv_len == 0 ) { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - - /* stop front end from sending result */ - rc = 1; - goto return_results; - } - - /* check for root dn/passwd */ - if ( be_isroot_pw( be, dn, cred ) ) { - /* front end will send result */ - if( *edn != NULL ) free( *edn ); - *edn = ch_strdup( be_root_dn( be ) ); - rc = 0; - goto return_results; - } - - if ( ! access_allowed( be, conn, op, e, - "userpassword", NULL, ACL_AUTH ) ) - { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL); - rc = 1; - goto return_results; - } - - if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) { - send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, - NULL, NULL, NULL, NULL); - - /* stop front end from sending result */ - rc = 1; - goto return_results; - } - - if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 ) - { - send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL, NULL); - /* stop front end from sending result */ - rc = 1; - goto return_results; - } - rc = 0; - break; - -#ifdef HAVE_KERBEROS - case LDAP_AUTH_KRBV41: - if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { - send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL, NULL); - rc = 1; - goto return_results; - } - - if ( ! access_allowed( be, conn, op, e, - "krbname", NULL, ACL_AUTH ) ) - { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL); - rc = 1; - goto return_results; - } - - sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "." - : "", ad.pinst, ad.prealm ); - - if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) { - /* - * no krbName values present: check against DN - */ - if ( strcasecmp( dn, krbname ) == 0 ) { - rc = 0; /* XXX wild ass guess */ - break; - } - send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, - NULL, NULL, NULL, NULL); - rc = 1; - goto return_results; - } else { /* look for krbName match */ - struct berval krbval; - - krbval.bv_val = krbname; - krbval.bv_len = strlen( krbname ); - - if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) { - send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, - NULL, NULL, NULL, NULL); - rc = 1; - goto return_results; - } - } - rc = 0; - break; - - case LDAP_AUTH_KRBV42: - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - /* stop front end from sending result */ - rc = 1; - goto return_results; -#endif - - case LDAP_AUTH_SASL: - /* insert sasl code here */ - - default: - send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED, - NULL, "auth method not supported", NULL, NULL ); - rc = 1; - goto return_results; - } - -return_results:; - /* free entry and reader lock */ - bdb2i_cache_return_entry_r( &li->li_cache, e ); - - /* front end with send result on success (rc==0) */ - return( rc ); -} - - -int -bdb2_back_bind( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - int method, - char *mech, - struct berval *cred, - char** edn -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_r( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( 1 ); - } - - ret = bdb2i_back_bind_internal( be, conn, op, dn, method, mech, cred, edn ); - - (void) bdb2i_leave_backend_r( lock ); - - bdb2i_stop_timing( be->bd_info, time1, "BIND", conn, op ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/cache.c b/servers/slapd/back-bdb2/cache.c deleted file mode 100644 index 4c44dbcc46..0000000000 --- a/servers/slapd/back-bdb2/cache.c +++ /dev/null @@ -1,590 +0,0 @@ -/* cache.c - routines to maintain an in-core cache of entries */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include - -#include "slap.h" - -#include "back-bdb2.h" - -/* LDBM backend specific entry info -- visible only to the cache */ -struct ldbm_entry_info { - /* - * These items are specific to the LDBM backend and should - * be hidden. - */ - int lei_state; /* for the cache */ -#define CACHE_ENTRY_UNDEFINED 0 -#define CACHE_ENTRY_CREATING 1 -#define CACHE_ENTRY_READY 2 -#define CACHE_ENTRY_DELETED 3 - - int lei_refcnt; /* # threads ref'ing this entry */ - Entry *lei_lrunext; /* for cache lru list */ - Entry *lei_lruprev; -}; -#define LEI(e) ((struct ldbm_entry_info *) ((e)->e_private)) - -static int cache_delete_entry_internal(struct cache *cache, Entry *e); -#ifdef LDAP_DEBUG -static void lru_print(struct cache *cache); -#endif - -static int -cache_entry_private_init( Entry*e ) -{ - assert( e->e_private == NULL ); - - if( e->e_private != NULL ) { - /* this should never happen */ - return 1; - } - - e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info)); - - return 0; -} - -static int -cache_entry_private_destroy( Entry*e ) -{ - assert( e->e_private ); - - free( e->e_private ); - e->e_private = NULL; - return 0; -} - -void -bdb2i_cache_return_entry_rw( struct cache *cache, Entry *e, int rw ) -{ - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - assert( e->e_private ); - - LEI(e)->lei_refcnt--; - - if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_return_entry_%s( %ld ): created (%d)\n", - rw ? "w" : "r", e->e_id, LEI(e)->lei_refcnt ); - - LEI(e)->lei_state = CACHE_ENTRY_READY; - - } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) { - if( LEI(e)->lei_refcnt > 0 ) { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_return_entry_%s( %ld ): delete pending (%d)\n", - rw ? "w" : "r", e->e_id, LEI(e)->lei_refcnt ); - - } else { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_return_entry_%s( %ld ): deleted (%d)\n", - rw ? "w" : "r", e->e_id, LEI(e)->lei_refcnt ); - - cache_entry_private_destroy( e ); - entry_free( e ); - } - - } else { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_return_entry_%s( %ld ): returned (%d)\n", - rw ? "w" : "r", e->e_id, LEI(e)->lei_refcnt); - } - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); -} - -#define LRU_DELETE( cache, e ) { \ - if ( LEI(e)->lei_lruprev != NULL ) { \ - LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \ - } else { \ - (cache)->c_lruhead = LEI(e)->lei_lrunext; \ - } \ - if ( LEI(e)->lei_lrunext != NULL ) { \ - LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \ - } else { \ - (cache)->c_lrutail = LEI(e)->lei_lruprev; \ - } \ -} - -#define LRU_ADD( cache, e ) { \ - LEI(e)->lei_lrunext = (cache)->c_lruhead; \ - if ( LEI(e)->lei_lrunext != NULL ) { \ - LEI(LEI(e)->lei_lrunext)->lei_lruprev = (e); \ - } \ - (cache)->c_lruhead = (e); \ - LEI(e)->lei_lruprev = NULL; \ - if ( (cache)->c_lrutail == NULL ) { \ - (cache)->c_lrutail = (e); \ - } \ -} - -/* - * bdb2i_cache_add_entry_rw - create and lock an entry in the cache - * returns: 0 entry has been created and locked - * 1 entry already existed - * -1 something bad happened - */ -int -bdb2i_cache_add_entry_rw( - struct cache *cache, - Entry *e, - int rw -) -{ - int i; - Entry *ee; - - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - assert( e->e_private == NULL ); - - if( cache_entry_private_init(e) != 0 ) { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - Debug( LDAP_DEBUG_ANY, - "====> bdb2i_cache_add_entry( %ld ): \"%s\": private init failed!\n", - e->e_id, e->e_dn, 0 ); - - return( -1 ); - } - - if ( avl_insert( &cache->c_dntree, (caddr_t) e, - (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 ) - { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_add_entry( %ld ): \"%s\": already in dn cache\n", - e->e_id, e->e_dn, 0 ); - - cache_entry_private_destroy(e); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( 1 ); - } - - /* id tree */ - if ( avl_insert( &cache->c_idtree, (caddr_t) e, - (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 ) - { - Debug( LDAP_DEBUG_ANY, - "====> bdb2i_cache_add_entry( %ld ): \"%s\": already in id cache\n", - e->e_id, e->e_dn, 0 ); - - /* delete from dn tree inserted above */ - if ( avl_delete( &cache->c_dntree, (caddr_t) e, - (AVL_CMP) entry_dn_cmp ) == NULL ) - { - Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", - 0, 0, 0 ); - } - - cache_entry_private_destroy(e); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( -1 ); - } - - /* put the entry into 'CREATING' state */ - /* will be marked after when entry is returned */ - LEI(e)->lei_state = CACHE_ENTRY_CREATING; - LEI(e)->lei_refcnt = 1; - - /* lru */ - LRU_ADD( cache, e ); - if ( ++cache->c_cursize > cache->c_maxsize ) { - /* - * find the lru entry not currently in use and delete it. - * in case a lot of entries are in use, only look at the - * first 10 on the tail of the list. - */ - i = 0; - while ( cache->c_lrutail != NULL && - LEI(cache->c_lrutail)->lei_refcnt != 0 && - i < 10 ) - { - /* move this in-use entry to the front of the q */ - ee = cache->c_lrutail; - LRU_DELETE( cache, ee ); - LRU_ADD( cache, ee ); - i++; - } - - /* - * found at least one to delete - try to get back under - * the max cache size. - */ - while ( cache->c_lrutail != NULL && - LEI(cache->c_lrutail)->lei_refcnt == 0 && - cache->c_cursize > cache->c_maxsize ) - { - e = cache->c_lrutail; - - /* delete from cache and lru q */ - cache_delete_entry_internal( cache, e ); - cache_entry_private_destroy( e ); - entry_free( e ); - } - } - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( 0 ); -} - -/* - * cache_update_entry - update a LOCKED entry which has been deleted. - * returns: 0 entry has been created and locked - * 1 entry already existed - * -1 something bad happened - */ -int -bdb2i_cache_update_entry( - struct cache *cache, - Entry *e -) -{ - int i; - Entry *ee; - - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - assert( e->e_private ); - - if ( avl_insert( &cache->c_dntree, (caddr_t) e, - (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 ) - { - Debug( LDAP_DEBUG_TRACE, - "====> bdb2i_cache_add_entry( %ld ): \"%s\": already in dn cache\n", - e->e_id, e->e_dn, 0 ); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( 1 ); - } - - /* id tree */ - if ( avl_insert( &cache->c_idtree, (caddr_t) e, - (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 ) - { - Debug( LDAP_DEBUG_ANY, - "====> bdb2i_cache_update_entry( %ld ): \"%s\": already in id cache\n", - e->e_id, e->e_dn, 0 ); - - /* delete from dn tree inserted above */ - if ( avl_delete( &cache->c_dntree, (caddr_t) e, - (AVL_CMP) entry_dn_cmp ) == NULL ) - { - Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", - 0, 0, 0 ); - } - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( -1 ); - } - - /* put the entry into 'CREATING' state */ - /* will be marked after when entry is returned */ - LEI(e)->lei_state = CACHE_ENTRY_CREATING; - - /* lru */ - LRU_ADD( cache, e ); - if ( ++cache->c_cursize > cache->c_maxsize ) { - /* - * find the lru entry not currently in use and delete it. - * in case a lot of entries are in use, only look at the - * first 10 on the tail of the list. - */ - i = 0; - while ( cache->c_lrutail != NULL && - LEI(cache->c_lrutail)->lei_refcnt != 0 && - i < 10 ) - { - /* move this in-use entry to the front of the q */ - ee = cache->c_lrutail; - LRU_DELETE( cache, ee ); - LRU_ADD( cache, ee ); - i++; - } - - /* - * found at least one to delete - try to get back under - * the max cache size. - */ - while ( cache->c_lrutail != NULL && - LEI(cache->c_lrutail)->lei_refcnt == 0 && - cache->c_cursize > cache->c_maxsize ) - { - e = cache->c_lrutail; - - /* delete from cache and lru q */ - cache_delete_entry_internal( cache, e ); - cache_entry_private_destroy( e ); - entry_free( e ); - } - } - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( 0 ); -} - -/* - * bdb2i_cache_find_entry_dn2id - find an entry in the cache, given dn - */ - -ID -bdb2i_cache_find_entry_dn2id( - BackendDB *be, - struct cache *cache, - const char *dn -) -{ - Entry e, *ep; - ID id; - int count = 0; - - e.e_dn = (char *) dn; - e.e_ndn = ch_strdup( dn ); - (void) dn_normalize_case( e.e_ndn ); - -try_again: - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e, - (AVL_CMP) entry_dn_cmp )) != NULL ) - { - int state; - count++; - - /* - * ep now points to an unlocked entry - * we do not need to lock the entry if we only - * check the state, refcnt, LRU, and id. - */ - - assert( ep->e_private ); - - /* save id */ - id = ep->e_id; - state = LEI(ep)->lei_state; - - /* - * entry is deleted or not fully created yet - */ - if ( state != CACHE_ENTRY_READY ) { - assert(state != CACHE_ENTRY_UNDEFINED); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - Debug(LDAP_DEBUG_TRACE, - "====> bdb2i_cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n", - dn, id, state); - - ldap_pvt_thread_yield(); - goto try_again; - } - - /* lru */ - LRU_DELETE( cache, ep ); - LRU_ADD( cache, ep ); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - Debug(LDAP_DEBUG_TRACE, - "====> bdb2i_cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n", - dn, id, count); - - } else { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - id = NOID; - } - - free(e.e_ndn); - - return( id ); -} - -/* - * cache_find_entry_id - find an entry in the cache, given id - */ - -Entry * -bdb2i_cache_find_entry_id( - struct cache *cache, - ID id, - int rw -) -{ - Entry e; - Entry *ep; - int count=0; - - e.e_id = id; - -try_again: - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e, - (AVL_CMP) entry_id_cmp )) != NULL ) - { - int state; - - assert( ep->e_private ); - - state = LEI(ep)->lei_state; - - /* - * entry is deleted or not fully created yet - */ - if ( state != CACHE_ENTRY_READY ) { - ID ep_id = ep->e_id; - - assert(state != CACHE_ENTRY_UNDEFINED); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - Debug(LDAP_DEBUG_TRACE, - "====> bdb2i_cache_find_entry_id( %ld ): %ld (not ready) %d\n", - id, ep_id, state); - - ldap_pvt_thread_yield(); - goto try_again; - } - - /* lru */ - LRU_DELETE( cache, ep ); - LRU_ADD( cache, ep ); - - LEI(ep)->lei_refcnt++; - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - Debug(LDAP_DEBUG_TRACE, - "====> bdb2i_cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n", - id, ep->e_dn, count); - - return( ep ); - } - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - - return( NULL ); -} - -/* - * cache_delete_entry - delete the entry e from the cache. the caller - * should have obtained e (increasing its ref count) via a call to one - * of the cache_find_* routines. the caller should *not* call the - * cache_return_entry() routine prior to calling cache_delete_entry(). - * it performs this function. - * - * returns: 0 e was deleted ok - * 1 e was not in the cache - * -1 something bad happened - */ -int -bdb2i_cache_delete_entry( - struct cache *cache, - Entry *e -) -{ - int rc; - - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); - - assert( e->e_private ); - - Debug( LDAP_DEBUG_TRACE, "====> bdb2i_cache_delete_entry( %ld )\n", - e->e_id, 0, 0 ); - - rc = cache_delete_entry_internal( cache, e ); - - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); - return( rc ); -} - -static int -cache_delete_entry_internal( - struct cache *cache, - Entry *e -) -{ - int rc = 0; /* return code */ - - /* dn tree */ - if ( avl_delete( &cache->c_dntree, (caddr_t) e, (AVL_CMP) entry_dn_cmp ) - == NULL ) - { - rc = -1; - } - - /* id tree */ - if ( avl_delete( &cache->c_idtree, (caddr_t) e, (AVL_CMP) entry_id_cmp ) - == NULL ) - { - rc = -1; - } - - if (rc != 0) { - return rc; - } - - /* lru */ - LRU_DELETE( cache, e ); - cache->c_cursize--; - - /* - * flag entry to be freed later by a call to cache_return_entry() - */ - LEI(e)->lei_state = CACHE_ENTRY_DELETED; - - return( 0 ); -} - -#ifdef LDAP_DEBUG - -static void -lru_print( struct cache *cache ) -{ - Entry *e; - - fprintf( stderr, "LRU queue (head to tail):\n" ); - for ( e = cache->c_lruhead; e != NULL; e = LEI(e)->lei_lrunext ) { - fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n", - e->e_dn, e->e_id, LEI(e)->lei_refcnt ); - } - fprintf( stderr, "LRU queue (tail to head):\n" ); - for ( e = cache->c_lrutail; e != NULL; e = LEI(e)->lei_lruprev ) { - fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n", - e->e_dn, e->e_id, LEI(e)->lei_refcnt ); - } -} - -#endif - diff --git a/servers/slapd/back-bdb2/close.c b/servers/slapd/back-bdb2/close.c deleted file mode 100644 index 98d68c7c68..0000000000 --- a/servers/slapd/back-bdb2/close.c +++ /dev/null @@ -1,62 +0,0 @@ -/* close.c - close bdb2 backend database */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include - -#include "slap.h" -#include "back-bdb2.h" - -static int -bdb2i_back_db_close_internal( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - DB_LOCK lock; - - /* since close will probably write the NEXTID file, - wee need transaction control */ - if ( bdb2i_enter_backend_w( &lock ) != 0 ) { - return( -1 ); - } - - if ( li->li_nextid != NOID ) { - Debug( LDAP_DEBUG_TRACE, "bdb2 backend saving nextid\n", 0, 0, 0 ); - if ( bdb2i_next_id_save( be ) < 0 ) { - Debug( LDAP_DEBUG_ANY, "bdb2 backend nextid save failed!\n", - 0, 0, 0 ); - } - } - - /* before closing all files, leave the backend (thus commiting - all writes) and set a last checkpoint */ - (void) bdb2i_leave_backend_w( lock ); - (void) bdb2i_set_txn_checkpoint( bdb2i_dbEnv.tx_info, 1 ); - - /* close all DB files */ - Debug( LDAP_DEBUG_TRACE, "bdb2 backend closing DB files\n", 0, 0, 0 ); - bdb2i_txn_close_files( be ); - Debug( LDAP_DEBUG_TRACE, "bdb2 backend done closing DB files\n", 0, 0, 0 ); - - return 0; -} - - -int -bdb2_back_db_close( BackendDB *be ) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_db_close_internal( be ); - - bdb2i_stop_timing( be->bd_info, time1, "CLOSE", NULL, NULL ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/compare.c b/servers/slapd/back-bdb2/compare.c deleted file mode 100644 index 46093d61a6..0000000000 --- a/servers/slapd/back-bdb2/compare.c +++ /dev/null @@ -1,136 +0,0 @@ -/* compare.c - bdb2 backend compare routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static int -bdb2i_back_compare_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - Ava *ava -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *matched; - Entry *e; - Attribute *a; - int rc; - int manageDSAit = get_manageDSAit( op ); - - /* get entry with reader lock */ - if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - if( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - return( 1 ); - } - - if (!manageDSAit && is_entry_referral( e ) ) { - /* entry is a referral, don't allow add */ - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - - rc = 1; - goto return_results; - } - - if ( ! access_allowed( be, conn, op, e, - ava->ava_type, &ava->ava_value, ACL_COMPARE ) ) - { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - rc = 1; - goto return_results; - } - - if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) { - send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, - NULL, NULL, NULL, NULL ); - rc = 1; - goto return_results; - } - - if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) - send_ldap_result( conn, op, LDAP_COMPARE_TRUE, - NULL, NULL, NULL, NULL ); - else - send_ldap_result( conn, op, LDAP_COMPARE_FALSE, - NULL, NULL, NULL, NULL ); - - rc = 0; - -return_results:; - bdb2i_cache_return_entry_r( &li->li_cache, e ); - return( rc ); -} - - -int -bdb2_back_compare( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - Ava *ava -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_r( &lock ) != 0 ) { - - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( 1 ); - - } - - ret = bdb2i_back_compare_internal( be, conn, op, dn, ava ); - (void) bdb2i_leave_backend_r( lock ); - bdb2i_stop_timing( be->bd_info, time1, "CMP", conn, op ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/config.c b/servers/slapd/back-bdb2/config.c deleted file mode 100644 index 87d739204a..0000000000 --- a/servers/slapd/back-bdb2/config.c +++ /dev/null @@ -1,202 +0,0 @@ -/* config.c - bdb2 backend configuration file routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static int -bdb2i_back_config_internal( - BackendInfo *bi, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - struct ldbtype *lty = (struct ldbtype *) bi->bi_private; - - if ( lty == NULL ) { - fprintf( stderr, "%s: line %d: ldbm backend type info is null!\n", - fname, lineno ); - return( 1 ); - } - - /* directory where DB control files live */ - if ( strcasecmp( argv[0], "home" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing dir in \"home

\" line\n", - fname, lineno ); - return( 1 ); - } - lty->lty_dbhome = ch_strdup( argv[1] ); - - /* size of the DB memory pool */ - } else if ( strcasecmp( argv[0], "mpoolsize" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing size in \"mpoolsize \" line\n", - fname, lineno ); - return( 1 ); - } - lty->lty_mpsize = (size_t) atoi( argv[1] ); - /* we should at least have the suggested 128k */ - if ( lty->lty_mpsize < DEFAULT_DBCACHE_SIZE ) - lty->lty_mpsize = DEFAULT_DBCACHE_SIZE; - - /* anything else */ - } else { - fprintf( stderr, -"%s: line %d: unknown directive \"%s\" in ldbm backend definition (ignored)\n", - fname, lineno, argv[0] ); - } - - return 0; -} - - -int -bdb2_back_config( - BackendInfo *bi, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( bi, &time1 ); - - ret = bdb2i_back_config_internal( bi, fname, lineno, argc, argv ); - bdb2i_stop_timing( bi, time1, "BE-CONFIG", NULL, NULL ); - - return( ret ); -} - - -static int -bdb2i_back_db_config_internal( - BackendDB *be, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - if ( li == NULL ) { - fprintf( stderr, "%s: line %d: ldbm database info is null!\n", - fname, lineno ); - return( 1 ); - } - - /* directory where database files live */ - if ( strcasecmp( argv[0], "directory" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing dir in \"directory \" line\n", - fname, lineno ); - return( 1 ); - } - li->li_directory = ch_strdup( argv[1] ); - - li->li_nextid_file = - ch_malloc( strlen(li->li_directory) + sizeof("/NEXTID") + 1 ); - - strcpy(li->li_nextid_file, li->li_directory); - strcat(li->li_nextid_file, "/NEXTID"); - - /* mode with which to create new database files */ - } else if ( strcasecmp( argv[0], "mode" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing mode in \"mode \" line\n", - fname, lineno ); - return( 1 ); - } - li->li_mode = strtol( argv[1], NULL, 0 ); - - /* attribute to index */ - } else if ( strcasecmp( argv[0], "index" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, -"%s: line %d: missing attr in \"index [pres,eq,approx,sub]\" line\n", - fname, lineno ); - return( 1 ); - } else if ( argc > 3 ) { - fprintf( stderr, -"%s: line %d: extra junk after \"index [pres,eq,approx,sub]\" line (ignored)\n", - fname, lineno ); - } - bdb2i_attr_index_config( li, fname, lineno, argc - 1, &argv[1], 0 ); - - /* size of the cache in entries */ - } else if ( strcasecmp( argv[0], "cachesize" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing size in \"cachesize \" line\n", - fname, lineno ); - return( 1 ); - } - li->li_cache.c_maxsize = atoi( argv[1] ); - - /* size of each dbcache in bytes */ - } else if ( strcasecmp( argv[0], "dbcachesize" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing size in \"dbcachesize \" line\n", - fname, lineno ); - return( 1 ); - } - li->li_dbcachesize = atoi( argv[1] ); - /* we should at least have the suggested 128k */ - if ( li->li_dbcachesize < DEFAULT_DBCACHE_SIZE ) - li->li_dbcachesize = DEFAULT_DBCACHE_SIZE; - - /* no write sync */ - } else if ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) { - li->li_dbcachewsync = 0; - - /* anything else */ - } else { - fprintf( stderr, -"%s: line %d: unknown directive \"%s\" in ldbm database definition (ignored)\n", - fname, lineno, argv[0] ); - } - - return 0; -} - - -int -bdb2_back_db_config( - BackendDB *be, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_db_config_internal( be, fname, lineno, argc, argv ); - - bdb2i_stop_timing( be->bd_info, time1, "DB-CONFIG", NULL, NULL ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/dbcache.c b/servers/slapd/back-bdb2/dbcache.c deleted file mode 100644 index 6a1a0ef3d8..0000000000 --- a/servers/slapd/back-bdb2/dbcache.c +++ /dev/null @@ -1,187 +0,0 @@ -/* ldbmcache.c - maintain a cache of open bdb2 files */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include -#include - -#include - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#include "slap.h" -#include "back-bdb2.h" - -struct dbcache * -bdb2i_cache_open( - BackendDB *be, - char *name, - char *suffix, - int flags -) -{ - /* all files are open, so return handle from file cache */ - switch ( slapMode & SLAP_MODE ) { - - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - char buf[MAXPATHLEN]; - - /* use short name */ - sprintf( buf, "%s%s", name, suffix ); - return( bdb2i_get_db_file_cache( li, buf )); - - } - break; - - default: - /* if not SERVER or TOOL, who else would ask? - NO ONE, so return error */ - - Debug( LDAP_DEBUG_ANY, - "bdb2i_cache_open: database user (%d) unknown -- cannot open \"%s%s\".\n", - slapMode, name, suffix ); - return( NULL ); - } -} - -void -bdb2i_cache_close( BackendDB *be, struct dbcache *db ) -{ - /* all files stay open until SERVER or TOOL shut down */ - switch ( slapMode & SLAP_MODE ) { - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - return; - - default: - /* if unknown user, complain */ - Debug( LDAP_DEBUG_ANY, - "bdb2i_cache_close: database user (%d) unknown -- ignored.\n", - slapMode, 0, 0 ); - return; - } -} - -void -bdb2i_cache_really_close( BackendDB *be, struct dbcache *db ) -{ - /* all files stay open until SERVER or TOOL shut down */ - switch ( slapMode & SLAP_MODE ) { - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - return; - - default: - /* if unknown user, complain */ - Debug( LDAP_DEBUG_ANY, - "bdb2i_cache_really_close: database user (%d) unknown -- ignored.\n", - slapMode, 0, 0 ); - return; - } -} - -void -bdb2i_cache_flush_all( BackendDB *be ) -{ - /* if SERVER or TOOL, syncing is done by TP, or during shutdown */ - switch ( slapMode & SLAP_MODE ) { - - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - return; - - default: - /* if unknown user, complain */ - Debug( LDAP_DEBUG_ANY, - "bdb2i_cache_flush_all: database user (%d) unknown -- ignored.\n", - slapMode, 0, 0 ); - return; - } -} - -Datum -bdb2i_cache_fetch( - struct dbcache *db, - Datum key -) -{ - Datum data; - - ldbm_datum_init( data ); - - data = bdb2i_db_fetch( db->dbc_db, key ); - - return( data ); -} - -int -bdb2i_cache_store( - struct dbcache *db, - Datum key, - Datum data, - int flags -) -{ - int rc; - struct timeval time1; - -#ifdef LDBM_DEBUG - Statslog( LDAP_DEBUG_STATS, - "=> bdb2i_cache_store(): key.dptr=%s, key.dsize=%d\n", - key.dptr, key.dsize, 0, 0, 0 ); - - Statslog( LDAP_DEBUG_STATS, - "=> bdb2i_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n", - key.dptr, data.dptr, 0, 0, 0 ); - - Statslog( LDAP_DEBUG_STATS, - "=> bdb2i_cache_store(): data.dptr=%s, data.dsize=%d\n", - data.dptr, data.dsize, 0, 0, 0 ); - - Statslog( LDAP_DEBUG_STATS, - "=> bdb2i_cache_store(): flags=0x%08x\n", - flags, 0, 0, 0, 0 ); -#endif /* LDBM_DEBUG */ - - if ( slapMode & SLAP_TIMED_MODE ) - bdb2i_uncond_start_timing( &time1 ); - - rc = bdb2i_db_store( db->dbc_db, key, data, flags ); - - if ( slapMode & SLAP_TIMED_MODE ) { - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - - *buf2 = '\0'; - if ( !( strcasecmp( db->dbc_name, "dn.bdb2" ))) - sprintf( buf2, " [%s]", key.dptr ); - sprintf( buf, "ADD-BDB2( %s%s )", db->dbc_name, buf2 ); - bdb2i_uncond_stop_timing( time1, buf, - NULL, NULL, LDAP_DEBUG_TRACE ); - } - - return( rc ); -} - -int -bdb2i_cache_delete( - struct dbcache *db, - Datum key -) -{ - int rc; - - rc = bdb2i_db_delete( db->dbc_db, key ); - - return( rc ); -} diff --git a/servers/slapd/back-bdb2/delete.c b/servers/slapd/back-bdb2/delete.c deleted file mode 100644 index eee7b6d914..0000000000 --- a/servers/slapd/back-bdb2/delete.c +++ /dev/null @@ -1,199 +0,0 @@ -/* delete.c - bdb2 backend delete routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static int -bdb2i_back_delete_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *matched = NULL; - char *pdn = NULL; - Entry *e, *p = NULL; - int rc = -1, manageDSAit; - - Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0); - - /* get entry with writer lock */ - if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n", - dn, 0, 0); - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - if( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - return( -1 ); - } - - if (!manageDSAit && is_entry_referral( e ) ) { - /* entry is a referral, don't allow add */ - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - goto return_results; - } - - - if ( bdb2i_has_children( be, e ) ) { - Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n", - dn, 0, 0); - send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, - NULL, NULL, NULL, NULL ); - goto return_results; - } - -#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL - if ( ! access_allowed( be, conn, op, e, - "entry", NULL, ACL_WRITE ) ) - { - Debug(LDAP_DEBUG_ARGS, - "<=- bdb2i_back_delete: insufficient access %s\n", - dn, 0, 0); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } -#endif - - /* find parent's entry */ - if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) { - if( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL) { - Debug( LDAP_DEBUG_TRACE, - "<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - /* check parent for "children" acl */ - if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) - { - Debug( LDAP_DEBUG_TRACE, - "<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - } else { - /* no parent, must be root to delete */ - if( ! be_isroot( be, op->o_ndn ) ) { - Debug( LDAP_DEBUG_TRACE, - "<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - } - - /* delete from dn2id mapping */ - if ( bdb2i_dn2id_delete( be, e->e_ndn, e->e_id ) != 0 ) { - Debug(LDAP_DEBUG_ARGS, - "<=- bdb2i_back_delete: operations error %s\n", - dn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - /* delete from disk and cache */ - if ( bdb2i_id2entry_delete( be, e ) != 0 ) { - Debug(LDAP_DEBUG_ARGS, - "<=- bdb2i_back_delete: operations error %s\n", - dn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - rc = 0; - -return_results:; - if ( pdn != NULL ) free(pdn); - - if( p != NULL ) { - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - - } - - /* free entry and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, e ); - - if ( matched != NULL ) free(matched); - - return rc; -} - - -int -bdb2_back_delete( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_w( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( -1 ); - } - - ret = bdb2i_back_delete_internal( be, conn, op, dn ); - (void) bdb2i_leave_backend_w( lock ); - bdb2i_stop_timing( be->bd_info, time1, "DEL", conn, op ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/dn2id.c b/servers/slapd/back-bdb2/dn2id.c deleted file mode 100644 index 1d4599a826..0000000000 --- a/servers/slapd/back-bdb2/dn2id.c +++ /dev/null @@ -1,307 +0,0 @@ -/* dn2id.c - routines to deal with the dn2id index */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -int -bdb2i_dn2id_add( - BackendDB *be, - const char *dn, - ID id -) -{ - int rc, flags; - struct dbcache *db; - Datum key, data; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_add( \"%s\", %ld )\n", dn, id, 0 ); - - if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n", - BDB2_SUFFIX, 0, 0 ); - return( -1 ); - } - - ldbm_datum_init( key ); - key.dsize = strlen( dn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn ); - - ldbm_datum_init( data ); - data.dptr = (char *) &id; - data.dsize = sizeof(ID); - - flags = LDBM_INSERT; - if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; - - rc = bdb2i_cache_store( db, key, data, flags ); - - free( key.dptr ); - - if ( rc != -1 ) { - char *pdn = dn_parent( NULL, dn ); - - if( pdn != NULL ) { - ldbm_datum_init( key ); - key.dsize = strlen( pdn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn ); - rc = bdb2i_idl_insert_key( be, db, key, id ); - free( key.dptr ); - free( pdn ); - } - } - - if ( rc != -1 ) { - char **subtree = dn_subtree( NULL, dn ); - - if( subtree != NULL ) { - int i; - for( i=0; subtree[i] != NULL; i++ ) { - ldbm_datum_init( key ); - key.dsize = strlen( subtree[i] ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_SUBTREE_PREFIX, subtree[i] ); - - rc = bdb2i_idl_insert_key( be, db, key, id ); - - free( key.dptr ); - } - - charray_free( subtree ); - } - } - - bdb2i_cache_close( be, db ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_add %d\n", rc, 0, 0 ); - return( rc ); -} - -ID -bdb2i_dn2id( - BackendDB *be, - const char *dn -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct dbcache *db; - ID id; - Datum key, data; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id( \"%s\" )\n", dn, 0, 0 ); - - /* first check the cache */ - if ( (id = bdb2i_cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) { - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld (in cache)\n", id, - 0, 0 ); - return( id ); - } - - if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "<= bdb2i_dn2id could not open dn2id%s\n", - BDB2_SUFFIX, 0, 0 ); - return( NOID ); - } - - ldbm_datum_init( key ); - - key.dsize = strlen( dn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn ); - - data = bdb2i_cache_fetch( db, key ); - - bdb2i_cache_close( be, db ); - - free( key.dptr ); - - if ( data.dptr == NULL ) { - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id NOID\n", 0, 0, 0 ); - return( NOID ); - } - - (void) memcpy( (char *) &id, data.dptr, sizeof(ID) ); - - ldbm_datum_free( db->dbc_db, data ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld\n", id, 0, 0 ); - return( id ); -} - -ID_BLOCK * -bdb2i_dn2idl( - BackendDB *be, - const char *dn, - int prefix ) -{ - struct dbcache *db; - Datum key; - ID_BLOCK *idl; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2idl( \"%c%s\" )\n", prefix, dn, 0 ); - - if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= bdb2i_dn2idl could not open dn2id%s\n", BDB2_SUFFIX, - 0, 0 ); - return( NULL ); - } - - ldbm_datum_init( key ); - - key.dsize = strlen( dn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", prefix, dn ); - - idl = bdb2i_idl_fetch( be, db, key ); - - free( key.dptr ); - - bdb2i_cache_close( be, db ); - - return( idl ); -} - -int -bdb2i_dn2id_delete( - BackendDB *be, - const char *dn, - ID id -) -{ - struct dbcache *db; - Datum key; - int rc; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_delete( \"%s\", %ld )\n", - dn, id, 0 ); - - if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= bdb2i_dn2id_delete could not open dn2id%s\n", BDB2_SUFFIX, - 0, 0 ); - return( -1 ); - } - - { - char *pdn = dn_parent( NULL, dn ); - - if( pdn != NULL ) { - ldbm_datum_init( key ); - key.dsize = strlen( pdn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn ); - (void) bdb2i_idl_delete_key( be, db, key, id ); - free( key.dptr ); - free( pdn ); - } - } - - { - char **subtree = dn_subtree( NULL, dn ); - - if( subtree != NULL ) { - int i; - for( i=0; subtree[i] != NULL; i++ ) { - ldbm_datum_init( key ); - key.dsize = strlen( subtree[i] ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_SUBTREE_PREFIX, subtree[i] ); - - (void) bdb2i_idl_delete_key( be, db, key, id ); - - free( key.dptr ); - } - - charray_free( subtree ); - } - } - - ldbm_datum_init( key ); - - key.dsize = strlen( dn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn ); - - rc = bdb2i_cache_delete( db, key ); - - free( key.dptr ); - - bdb2i_cache_close( be, db ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_delete %d\n", rc, 0, 0 ); - return( rc ); -} - -/* - * dn2entry - look up dn in the cache/indexes and return the corresponding - * entry. - */ - -Entry * -bdb2i_dn2entry_rw( - BackendDB *be, - const char *dn, - Entry **matched, - int rw -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id; - Entry *e = NULL; - char *pdn; - - Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n", - rw ? "w" : "r", dn, 0); - - if( matched != NULL ) { - /* caller cares about match */ - *matched = NULL; - } - - if ( (id = bdb2i_dn2id( be, dn )) != NOID && - (e = bdb2i_id2entry_rw( be, id, rw )) != NULL ) - { - return( e ); - } - - if ( id != NOID ) { - Debug(LDAP_DEBUG_ANY, - "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n", - rw ? "w" : "r", id, dn); - /* must have been deleted from underneath us */ - /* treat as if NOID was found */ - } - - /* caller doesn't care about match */ - if( matched == NULL ) return NULL; - - /* entry does not exist - see how much of the dn does exist */ - /* dn_parent checks returns NULL if dn is suffix */ - if ( (pdn = dn_parent( be, dn )) != NULL ) { - /* get entry with reader lock */ - if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) { - *matched = e; - } - free( pdn ); - } - - return( NULL ); -} - - diff --git a/servers/slapd/back-bdb2/entry.c b/servers/slapd/back-bdb2/entry.c deleted file mode 100644 index 9238b1c9b2..0000000000 --- a/servers/slapd/back-bdb2/entry.c +++ /dev/null @@ -1,30 +0,0 @@ -/* entry.c - ldbm backend entry_release routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - - -int -bdb2_back_entry_release_rw( - BackendDB *be, - Entry *e, - int rw -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - /* free entry and reader or writer lock */ - bdb2i_cache_return_entry_rw( &li->li_cache, e, rw ); - bdb2i_release_add_lock(); - - return 0; -} diff --git a/servers/slapd/back-bdb2/external.h b/servers/slapd/back-bdb2/external.h deleted file mode 100644 index 9af5a84ed6..0000000000 --- a/servers/slapd/back-bdb2/external.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenLDAP$ */ -#ifndef _BDB2_EXTERNAL_H -#define _BDB2_EXTERNAL_H - -LDAP_BEGIN_DECL - -extern int bdb2_back_initialize LDAP_P(( BackendInfo *bi )); -extern int bdb2_back_open LDAP_P(( BackendInfo *bi )); -extern int bdb2_back_close LDAP_P(( BackendInfo *bi )); -extern int bdb2_back_destroy LDAP_P(( BackendInfo *bi )); - -extern int bdb2_back_config LDAP_P(( BackendInfo *bt, - const char *fname, int lineno, int argc, char **argv )); - -extern int bdb2_back_db_init LDAP_P(( BackendDB *bd )); -extern int bdb2_back_db_open LDAP_P(( BackendDB *bd )); -extern int bdb2_back_db_close LDAP_P(( BackendDB *bd )); -extern int bdb2_back_db_destroy LDAP_P(( BackendDB *bd )); - -extern int bdb2_back_db_config LDAP_P(( BackendDB *bd, - const char *fname, int lineno, int argc, char **argv )); - -extern int bdb2_back_bind LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, int method, char* mech, - struct berval *cred, char** edn )); - -extern int bdb2_back_unbind LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op )); - -extern int bdb2_back_search LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter *filter, char *filterstr, char **attrs, int attrsonly )); - -extern int bdb2_back_compare LDAP_P((BackendDB *bd, - Connection *conn, Operation *op, - char *dn, Ava *ava )); - -extern int bdb2_back_modify LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, LDAPModList *ml )); - -extern int bdb2_back_modrdn LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, char*newrdn, int deleteoldrdn, - char *newSuperior )); - -extern int bdb2_back_add LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, Entry *e )); - -extern int bdb2_back_delete LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, char *dn )); - -extern int bdb2_back_abandon LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, int msgid )); - -extern int bdb2_back_group LDAP_P(( BackendDB *bd, - Entry *target, const char* gr_ndn, const char* op_ndn, - const char* objectclassValue, const char* groupattrName)); - -/* hooks for slap tools */ -extern int bdb2_tool_entry_open LDAP_P(( BackendDB *be, int mode )); -extern int bdb2_tool_entry_close LDAP_P(( BackendDB *be )); -extern ID bdb2_tool_entry_first LDAP_P(( BackendDB *be )); -extern ID bdb2_tool_entry_next LDAP_P(( BackendDB *be )); -extern Entry* bdb2_tool_entry_get LDAP_P(( BackendDB *be, ID id )); -extern ID bdb2_tool_entry_put LDAP_P(( BackendDB *be, Entry *e )); -extern int bdb2_tool_index_attr LDAP_P(( BackendDB *be, char* type )); -extern int bdb2_tool_index_change LDAP_P(( BackendDB *be, char* type, - struct berval **bv, ID id, int op )); -extern int bdb2_tool_sync LDAP_P(( BackendDB *be )); - -LDAP_END_DECL - -#endif /* _BDB2_EXTERNAL_H */ - diff --git a/servers/slapd/back-bdb2/filterindex.c b/servers/slapd/back-bdb2/filterindex.c deleted file mode 100644 index a9f7452cf4..0000000000 --- a/servers/slapd/back-bdb2/filterindex.c +++ /dev/null @@ -1,369 +0,0 @@ -/* filterindex.c - generate the list of candidate entries from a filter */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static ID_BLOCK *ava_candidates( BackendDB *be, Ava *ava, int type ); -static ID_BLOCK *presence_candidates( BackendDB *be, char *type ); -static ID_BLOCK *approx_candidates( BackendDB *be, Ava *ava ); -static ID_BLOCK *list_candidates( BackendDB *be, Filter *flist, int ftype ); -static ID_BLOCK *substring_candidates( BackendDB *be, Filter *f ); -static ID_BLOCK *substring_comp_candidates( BackendDB *be, char *type, char *val, int prepost ); - -/* - * test_filter - test a filter against a single entry. - * returns 0 filter matched - * -1 filter did not match - * >0 an ldap error code - */ - -ID_BLOCK * -bdb2i_filter_candidates( - BackendDB *be, - Filter *f -) -{ - ID_BLOCK *result, *tmp1, *tmp2; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_filter_candidates\n", 0, 0, 0 ); - - result = NULL; - switch ( f->f_choice ) { - case SLAPD_FILTER_DN_ONE: - Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 ); - result = bdb2i_dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX ); - break; - - case SLAPD_FILTER_DN_SUBTREE: - Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 ); - result = bdb2i_dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX ); - break; - - case LDAP_FILTER_EQUALITY: - Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_EQUALITY ); - break; - - case LDAP_FILTER_SUBSTRINGS: - Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 ); - result = substring_candidates( be, f ); - break; - - case LDAP_FILTER_GE: - Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_GE ); - break; - - case LDAP_FILTER_LE: - Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_LE ); - break; - - case LDAP_FILTER_PRESENT: - Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 ); - result = presence_candidates( be, f->f_type ); - break; - - case LDAP_FILTER_APPROX: - Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 ); - result = approx_candidates( be, &f->f_ava ); - break; - - case LDAP_FILTER_AND: - Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 ); - result = list_candidates( be, f->f_and, LDAP_FILTER_AND ); - break; - - case LDAP_FILTER_OR: - Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 ); - result = list_candidates( be, f->f_or, LDAP_FILTER_OR ); - break; - - case LDAP_FILTER_NOT: - Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 ); - tmp1 = bdb2i_idl_allids( be ); - tmp2 = bdb2i_filter_candidates( be, f->f_not ); - result = bdb2i_idl_notin( be, tmp1, tmp2 ); - bdb2i_idl_free( tmp2 ); - bdb2i_idl_free( tmp1 ); - break; - } - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_filter_candidates %ld\n", - result ? ID_BLOCK_NIDS(result) : 0, 0, 0 ); - return( result ); -} - -static ID_BLOCK * -ava_candidates( - BackendDB *be, - Ava *ava, - int type -) -{ - ID_BLOCK *idl; - - Debug( LDAP_DEBUG_TRACE, "=> ava_candidates 0x%x\n", type, 0, 0 ); - - switch ( type ) { - case LDAP_FILTER_EQUALITY: - idl = bdb2i_index_read( be, ava->ava_type, INDEX_EQUALITY, - ava->ava_value.bv_val ); - break; - - case LDAP_FILTER_GE: - idl = bdb2i_idl_allids( be ); - break; - - case LDAP_FILTER_LE: - idl = bdb2i_idl_allids( be ); - break; - } - - Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static ID_BLOCK * -presence_candidates( - BackendDB *be, - char *type -) -{ - ID_BLOCK *idl; - - Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 ); - - idl = bdb2i_index_read( be, type, 0, "*" ); - - Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static ID_BLOCK * -approx_candidates( - BackendDB *be, - Ava *ava -) -{ - char *w, *c; - ID_BLOCK *idl, *tmp; - - Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 ); - - idl = NULL; - for ( w = first_word( ava->ava_value.bv_val ); w != NULL; - w = next_word( w ) ) { - c = phonetic( w ); - if ( (tmp = bdb2i_index_read( be, ava->ava_type, INDEX_APPROX, c )) - == NULL ) { - free( c ); - bdb2i_idl_free( idl ); - Debug( LDAP_DEBUG_TRACE, "<= approx_candidates NULL\n", - 0, 0, 0 ); - return( NULL ); - } - free( c ); - - if ( idl == NULL ) { - idl = tmp; - } else { - idl = bdb2i_idl_intersection( be, idl, tmp ); - } - } - - Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static ID_BLOCK * -list_candidates( - BackendDB *be, - Filter *flist, - int ftype -) -{ - ID_BLOCK *idl, *tmp, *tmp2; - Filter *f; - - Debug( LDAP_DEBUG_TRACE, "=> list_candidates 0x%x\n", ftype, 0, 0 ); - - idl = NULL; - for ( f = flist; f != NULL; f = f->f_next ) { - if ( (tmp = bdb2i_filter_candidates( be, f )) == NULL && - ftype == LDAP_FILTER_AND ) { - Debug( LDAP_DEBUG_TRACE, - "<= list_candidates NULL\n", 0, 0, 0 ); - bdb2i_idl_free( idl ); - return( NULL ); - } - - tmp2 = idl; - if ( idl == NULL ) { - idl = tmp; - } else if ( ftype == LDAP_FILTER_AND ) { - idl = bdb2i_idl_intersection( be, idl, tmp ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - } else { - idl = bdb2i_idl_union( be, idl, tmp ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - } - } - - Debug( LDAP_DEBUG_TRACE, "<= list_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static ID_BLOCK * -substring_candidates( - BackendDB *be, - Filter *f -) -{ - int i; - ID_BLOCK *idl, *tmp, *tmp2; - - Debug( LDAP_DEBUG_TRACE, "=> substring_candidates\n", 0, 0, 0 ); - - idl = NULL; - - /* initial */ - if ( f->f_sub_initial != NULL ) { - if ( (int) strlen( f->f_sub_initial ) < SUBLEN - 1 ) { - idl = bdb2i_idl_allids( be ); - } else if ( (idl = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_initial, '^' )) == NULL ) { - return( NULL ); - } - } - - /* final */ - if ( f->f_sub_final != NULL ) { - if ( (int) strlen( f->f_sub_final ) < SUBLEN - 1 ) { - tmp = bdb2i_idl_allids( be ); - } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_final, '$' )) == NULL ) { - bdb2i_idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = bdb2i_idl_intersection( be, idl, tmp ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - } - } - - for ( i = 0; f->f_sub_any != NULL && f->f_sub_any[i] != NULL; i++ ) { - if ( (int) strlen( f->f_sub_any[i] ) < SUBLEN ) { - tmp = bdb2i_idl_allids( be ); - } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_any[i], 0 )) == NULL ) { - bdb2i_idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = bdb2i_idl_intersection( be, idl, tmp ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - } - } - - Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static ID_BLOCK * -substring_comp_candidates( - BackendDB *be, - char *type, - char *val, - int prepost -) -{ - int i, len; - ID_BLOCK *idl, *tmp, *tmp2; - char *p; - char buf[SUBLEN + 1]; - - Debug( LDAP_DEBUG_TRACE, "=> substring_comp_candidates\n", 0, 0, 0 ); - - len = strlen( val ); - idl = NULL; - - /* prepend ^ for initial substring */ - if ( prepost == '^' ) { - buf[0] = '^'; - for ( i = 0; i < SUBLEN - 1; i++ ) { - buf[i + 1] = val[i]; - } - buf[SUBLEN] = '\0'; - - if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) { - return( NULL ); - } - } else if ( prepost == '$' ) { - p = val + len - SUBLEN + 1; - for ( i = 0; i < SUBLEN - 1; i++ ) { - buf[i] = p[i]; - } - buf[SUBLEN - 1] = '$'; - buf[SUBLEN] = '\0'; - - if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) { - return( NULL ); - } - } - - for ( p = val; p < (val + len - SUBLEN + 1); p++ ) { - for ( i = 0; i < SUBLEN; i++ ) { - buf[i] = p[i]; - } - buf[SUBLEN] = '\0'; - - if ( (tmp = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) { - bdb2i_idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = bdb2i_idl_intersection( be, idl, tmp ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - } - - /* break if no candidates */ - if( idl == NULL ) { - break; - } - } - - Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} diff --git a/servers/slapd/back-bdb2/group.c b/servers/slapd/back-bdb2/group.c deleted file mode 100644 index 4bc4fc9a45..0000000000 --- a/servers/slapd/back-bdb2/group.c +++ /dev/null @@ -1,182 +0,0 @@ -/* group.c - bdb2 backend acl group routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - - -/* return 0 IFF op_dn is a value in member attribute - * of entry with gr_dn AND that entry has an objectClass - * value of groupOfNames - */ -static int -bdb2i_back_group_internal( - BackendDB *be, - Entry *target, - const char *gr_ndn, - const char *op_ndn, - const char *objectclassValue, - const char *groupattrName -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *e; - int rc = 1; - Attribute *attr; - struct berval bv; - - Debug( LDAP_DEBUG_ARGS, - "=> bdb2i_back_group: gr dn: \"%s\"\n", - gr_ndn, 0, 0 ); - Debug( LDAP_DEBUG_ARGS, - "=> bdb2i_back_group: op dn: \"%s\"\n", - op_ndn, 0, 0 ); - Debug( LDAP_DEBUG_ARGS, - "=> bdb2i_back_group: objectClass: \"%s\" attrName: \"%s\"\n", - objectclassValue, groupattrName, 0 ); - - Debug( LDAP_DEBUG_ARGS, - "=> bdb2i_back_group: tr dn: \"%s\"\n", - target->e_ndn, 0, 0 ); - - if (strcmp(target->e_ndn, gr_ndn) == 0) { - /* we already have a LOCKED copy of the entry */ - e = target; - Debug( LDAP_DEBUG_ARGS, - "=> bdb2i_back_group: target is group: \"%s\"\n", - gr_ndn, 0, 0 ); - - } else { - /* can we find group entry with reader lock */ - if ((e = bdb2i_dn2entry_r(be, gr_ndn, NULL )) == NULL) { - Debug( LDAP_DEBUG_ACL, - "=> bdb2i_back_group: cannot find group: \"%s\"\n", - gr_ndn, 0, 0 ); - return( 1 ); - } - - Debug( LDAP_DEBUG_ACL, - "=> bdb2i_back_group: found group: \"%s\"\n", - gr_ndn, 0, 0 ); - } - - /* find it's objectClass and member attribute values - * make sure this is a group entry - * finally test if we can find op_dn in the member attribute value list - */ - - rc = 1; - - if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 ); - goto return_results; - } - - bv.bv_val = "ALIAS"; - bv.bv_len = sizeof("ALIAS")-1; - - if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: group is an alias\n", 0, 0, 0 ); - goto return_results; - } - - bv.bv_val = "REFERRAL"; - bv.bv_len = sizeof("REFERRAL")-1; - - if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: group is a referral\n", 0, 0, 0 ); - goto return_results; - } - - bv.bv_val = (char *) objectclassValue; - bv.bv_len = strlen( bv.bv_val ); - - if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: failed to find %s in objectClass\n", - objectclassValue, 0, 0 ); - goto return_results; - } - - if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: failed to find %s\n", - groupattrName, 0, 0 ); - goto return_results; - } - - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: found objectClass %s and %s\n", - objectclassValue, groupattrName, 0 ); - - - bv.bv_val = (char *) op_ndn; - bv.bv_len = strlen( op_ndn ); - - if (value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) { - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n", - op_ndn, gr_ndn, groupattrName ); - goto return_results; - } - - Debug( LDAP_DEBUG_ACL, - "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n", - op_ndn, gr_ndn, groupattrName ); - rc = 0; - -return_results: - if( target != e ) { - /* free entry and reader lock */ - bdb2i_cache_return_entry_r( &li->li_cache, e ); - } - - Debug( LDAP_DEBUG_ARGS, "bdb2i_back_group: rc: %d\n", rc, 0, 0 ); - return(rc); -} - - -int -bdb2_back_group( - BackendDB *be, - Entry *target, - const char *gr_ndn, - const char *op_ndn, - const char *objectclassValue, - const char *groupattrName -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_r( &lock ) != 0 ) { - - return( 1 ); - - } - - ret = bdb2i_back_group_internal( be, target, gr_ndn, op_ndn, - objectclassValue, groupattrName ); - - (void) bdb2i_leave_backend_r( lock ); - bdb2i_stop_timing( be->bd_info, time1, "GRP", NULL, NULL ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/id2children.c b/servers/slapd/back-bdb2/id2children.c deleted file mode 100644 index 8db5c188b3..0000000000 --- a/servers/slapd/back-bdb2/id2children.c +++ /dev/null @@ -1,55 +0,0 @@ -/* id2children.c - routines to deal with the id2children index */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include -#include - -#include - -#include "slap.h" -#include "back-bdb2.h" - -int -bdb2i_has_children( - BackendDB *be, - Entry *p -) -{ - struct dbcache *db; - Datum key; - int rc = 0; - ID_BLOCK *idl; - - ldbm_datum_init( key ); - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_has_children( %ld )\n", p->e_id , 0, 0 ); - - if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, - LDBM_WRCREAT )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= bdb2i_has_children: could not open \"dn2id" BDB2_SUFFIX "\"\n", - 0, 0, 0 ); - return( 0 ); - } - - key.dsize = strlen( p->e_ndn ) + 2; - key.dptr = ch_malloc( key.dsize ); - sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, p->e_ndn ); - - idl = bdb2i_idl_fetch( be, db, key ); - - free( key.dptr ); - - bdb2i_cache_close( be, db ); - - if( idl != NULL ) { - bdb2i_idl_free( idl ); - rc = 1; - } - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_has_children( %ld ): %s\n", - p->e_id, rc ? "yes" : "no", 0 ); - return( rc ); -} diff --git a/servers/slapd/back-bdb2/id2entry.c b/servers/slapd/back-bdb2/id2entry.c deleted file mode 100644 index 1a151fb1d6..0000000000 --- a/servers/slapd/back-bdb2/id2entry.c +++ /dev/null @@ -1,179 +0,0 @@ -/* id2entry.c - routines to deal with the id2entry index */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include - -#include "slap.h" -#include "back-bdb2.h" - -/* - * This routine adds (or updates) an entry on disk. - * The cache should already be updated. - */ - -int -bdb2i_id2entry_add( BackendDB *be, Entry *e ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct dbcache *db; - Datum key, data; - int len, rc, flags; - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_add( %ld, \"%s\" )\n", e->e_id, - e->e_dn, 0 ); - - if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n", - BDB2_SUFFIX, 0, 0 ); - return( -1 ); - } - - key.dptr = (char *) &e->e_id; - key.dsize = sizeof(ID); - - ldap_pvt_thread_mutex_lock( &entry2str_mutex ); - data.dptr = entry2str( e, &len ); - data.dsize = len + 1; - - /* store it */ - flags = LDBM_REPLACE; - if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; - rc = bdb2i_cache_store( db, key, data, flags ); - - ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); - - bdb2i_cache_close( be, db ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_add %d\n", rc, 0, 0 ); - - return( rc ); -} - -int -bdb2i_id2entry_delete( BackendDB *be, Entry *e ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct dbcache *db; - Datum key; - int rc; - - Debug(LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_delete( %ld, \"%s\" )\n", e->e_id, - e->e_dn, 0 ); - -#ifdef notdef -#ifdef LDAP_DEBUG - /* check for writer lock */ - assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1); -#endif -#endif - - ldbm_datum_init( key ); - - if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n", - BDB2_SUFFIX, 0, 0 ); - return( -1 ); - } - - if ( bdb2i_cache_delete_entry( &li->li_cache, e ) != 0 ) { - Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n", - e->e_id, e->e_dn, 0 ); - } - - key.dptr = (char *) &e->e_id; - key.dsize = sizeof(ID); - - rc = bdb2i_cache_delete( db, key ); - - bdb2i_cache_close( be, db ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_delete %d\n", rc, 0, 0 ); - return( rc ); -} - -/* returns entry with reader/writer lock */ -Entry * -bdb2i_id2entry_rw( BackendDB *be, ID id, int rw ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct dbcache *db; - Datum key, data; - Entry *e; - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_%s( %ld )\n", - rw ? "w" : "r", id, 0 ); - - if ( (e = bdb2i_cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) { - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) 0x%lx (cache)\n", - rw ? "w" : "r", id, (unsigned long)e ); - return( e ); - } - - if ( (db = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n", - BDB2_SUFFIX, 0, 0 ); - return( NULL ); - } - - key.dptr = (char *) &id; - key.dsize = sizeof(ID); - - data = bdb2i_cache_fetch( db, key ); - - if ( data.dptr == NULL ) { - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) not found\n", - rw ? "w" : "r", id, 0 ); - bdb2i_cache_close( be, db ); - return( NULL ); - } - - e = str2entry( data.dptr ); - - ldbm_datum_free( db->dbc_db, data ); - bdb2i_cache_close( be, db ); - - if ( e == NULL ) { - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) (failed)\n", - rw ? "w" : "r", id, 0 ); - return( NULL ); - } - - e->e_id = id; - - if ( bdb2i_cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) { - entry_free( e ); - - /* see if it got added underneath us */ - if((e = bdb2i_cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) { - Debug( LDAP_DEBUG_TRACE, - "<= bdb2i_id2entry_%s( %ld ) 0x%lx (cache)\n", - rw ? "w" : "r", id, (unsigned long)e ); - return( e ); - } - - Debug( LDAP_DEBUG_TRACE, - "<= bdb2i_id2entry_%s( %ld ) (cache add failed)\n", - rw ? "w" : "r", id, 0 ); - return( NULL ); - } - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) 0x%lx (disk)\n", - rw ? "w" : "r", id, (unsigned long) e ); - - return( e ); -} - - diff --git a/servers/slapd/back-bdb2/idl.c b/servers/slapd/back-bdb2/idl.c deleted file mode 100644 index c062642d8e..0000000000 --- a/servers/slapd/back-bdb2/idl.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* idl.c - ldap id list handling routines */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static ID_BLOCK* idl_dup( ID_BLOCK *idl ); - -/* Allocate an ID_BLOCK with room for nids ids */ -ID_BLOCK * -bdb2i_idl_alloc( unsigned int nids ) -{ - ID_BLOCK *new; - - /* nmax + nids + space for the ids */ - new = (ID_BLOCK *) ch_calloc( (ID_BLOCK_IDS_OFFSET + nids), sizeof(ID) ); - ID_BLOCK_NMAX(new) = nids; - ID_BLOCK_NIDS(new) = 0; - - return( new ); -} - - -/* Allocate an empty ALLIDS ID_BLOCK */ -ID_BLOCK * -bdb2i_idl_allids( BackendDB *be ) -{ - ID_BLOCK *idl; - - idl = bdb2i_idl_alloc( 0 ); - ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE; - ID_BLOCK_NIDS(idl) = bdb2i_next_id_get( be ); - - return( idl ); -} - - -/* Free an ID_BLOCK */ -void -bdb2i_idl_free( ID_BLOCK *idl ) -{ - if ( idl == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "bdb2i_idl_free: called with NULL pointer\n", - 0, 0, 0 ); - return; - } - - free( (char *) idl ); -} - - -/* Fetch an single ID_BLOCK from the cache */ -static ID_BLOCK * -idl_fetch_one( - BackendDB *be, - struct dbcache *db, - Datum key -) -{ - Datum data; - ID_BLOCK *idl; - - ldbm_datum_init( data ); - - /* Debug( LDAP_DEBUG_TRACE, "=> idl_fetch_one\n", 0, 0, 0 ); */ - - data = bdb2i_cache_fetch( db, key ); - - if( data.dptr == NULL ) { - return NULL; - } - - idl = idl_dup( (ID_BLOCK *) data.dptr); - ldbm_datum_free( db->dbc_db, data ); - - return( idl ); -} - - -/* Fetch a set of ID_BLOCKs from the cache - * if not INDIRECT - * if block return is an ALLIDS block, - * return an new ALLIDS block - * otherwise - * return block - * construct super block from all blocks referenced by INDIRECT block - * return super block - */ -ID_BLOCK * -bdb2i_idl_fetch( - BackendDB *be, - struct dbcache *db, - Datum key -) -{ - Datum data; - ID_BLOCK *idl; - ID_BLOCK **tmp; - char *kstr; - int i, nids; - - idl = idl_fetch_one( be, db, key ); - - if ( idl == NULL ) { - return NULL; - } - - if ( ID_BLOCK_ALLIDS(idl) ) { - /* all ids block */ - /* make sure we have the current value of highest id */ - bdb2i_idl_free( idl ); - idl = bdb2i_idl_allids( be ); - - return( idl ); - } - - if ( ! ID_BLOCK_INDIRECT( idl ) ) { - /* regular block */ - return( idl ); - } - - /* - * this is an indirect block which points to other blocks. - * we need to read in all the blocks it points to and construct - * a big id list containing all the ids, which we will return. - */ - - /* count the number of blocks & allocate space for pointers to them */ - for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) - ; /* NULL */ - tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) ); - - /* read in all the blocks */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - nids = 0; - for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) { - ldbm_datum_init( data ); - - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i), key.dptr ); - data.dptr = kstr; - data.dsize = strlen( kstr ) + 1; - - if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "bdb2i_idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 ); - continue; - } - - nids += ID_BLOCK_NIDS(tmp[i]); - } - tmp[i] = NULL; - free( kstr ); - bdb2i_idl_free( idl ); - - /* allocate space for the big block */ - idl = bdb2i_idl_alloc( nids ); - ID_BLOCK_NIDS(idl) = nids; - nids = 0; - - /* copy in all the ids from the component blocks */ - for ( i = 0; tmp[i] != NULL; i++ ) { - if ( tmp[i] == NULL ) { - continue; - } - - SAFEMEMCPY( - (char *) &ID_BLOCK_ID(idl, nids), - (char *) &ID_BLOCK_ID(tmp[i], 0), - ID_BLOCK_NIDS(tmp[i]) * sizeof(ID) ); - nids += ID_BLOCK_NIDS(tmp[i]); - - bdb2i_idl_free( tmp[i] ); - } - free( (char *) tmp ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_idl_fetch %ld ids (%ld max)\n", - ID_BLOCK_NIDS(idl), ID_BLOCK_NMAX(idl), 0 ); - return( idl ); -} - - -/* store a single block */ -static int -idl_store( - BackendDB *be, - struct dbcache *db, - Datum key, - ID_BLOCK *idl -) -{ - int rc, flags; - Datum data; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - ldbm_datum_init( data ); - - /* Debug( LDAP_DEBUG_TRACE, "=> idl_store\n", 0, 0, 0 ); */ - - data.dptr = (char *) idl; - data.dsize = (ID_BLOCK_IDS_OFFSET + ID_BLOCK_NMAX(idl)) * sizeof(ID); - -#ifdef LDBM_DEBUG - Statslog( LDAP_DEBUG_STATS, "<= idl_store(): rc=%d\n", - rc, 0, 0, 0, 0 ); -#endif - - flags = LDBM_REPLACE; - if( li->li_dbcachewsync ) flags |= LDBM_SYNC; - rc = bdb2i_cache_store( db, key, data, flags ); - - /* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */ - return( rc ); -} - - -/* split the block at id - * locate ID greater than or equal to id. - */ -static void -idl_split_block( - ID_BLOCK *b, - ID id, - ID_BLOCK **right, - ID_BLOCK **left -) -{ - unsigned int nr, nl; - - /* find where to split the block *//* XXX linear search XXX */ - for ( nr = 0; nr < ID_BLOCK_NIDS(b) && id > ID_BLOCK_ID(b, nr); nr++ ) - ; /* NULL */ - - nl = ID_BLOCK_NIDS(b) - nr; - - *right = bdb2i_idl_alloc( nr == 0 ? 1 : nr ); - *left = bdb2i_idl_alloc( nl + (nr == 0 ? 0 : 1)); - - /* - * everything before the id being inserted in the first block - * unless there is nothing, in which case the id being inserted - * goes there. - */ - if ( nr == 0 ) { - ID_BLOCK_NIDS(*right) = 1; - ID_BLOCK_ID(*right, 0) = id; - } else { - SAFEMEMCPY( - (char *) &ID_BLOCK_ID(*right, 0), - (char *) &ID_BLOCK_ID(b, 0), - nr * sizeof(ID) ); - ID_BLOCK_NIDS(*right) = nr; - ID_BLOCK_ID(*left, 0) = id; - } - - /* the id being inserted & everything after in the second block */ - SAFEMEMCPY( - (char *) &ID_BLOCK_ID(*left, (nr == 0 ? 0 : 1)), - (char *) &ID_BLOCK_ID(b, nr), - nl * sizeof(ID) ); - ID_BLOCK_NIDS(*left) = nl + (nr == 0 ? 0 : 1); -} - - -/* - * idl_change_first - called when an indirect block's first key has - * changed, meaning it needs to be stored under a new key, and the - * header block pointing to it needs updating. - */ -static int -idl_change_first( - BackendDB *be, - struct dbcache *db, - Datum hkey, /* header block key */ - ID_BLOCK *h, /* header block */ - int pos, /* pos in h to update */ - Datum bkey, /* data block key */ - ID_BLOCK *b /* data block */ -) -{ - int rc; - - /* Debug( LDAP_DEBUG_TRACE, "=> idl_change_first\n", 0, 0, 0 ); */ - - /* delete old key block */ - if ( (rc = bdb2i_cache_delete( db, bkey )) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_delete of (%s) returns %d\n", bkey.dptr, rc, - 0 ); - return( rc ); - } - - /* write block with new key */ - sprintf( bkey.dptr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(b, 0), hkey.dptr ); - bkey.dsize = strlen( bkey.dptr ) + 1; - if ( (rc = idl_store( be, db, bkey, b )) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", bkey.dptr, rc, 0 ); - return( rc ); - } - - /* update + write indirect header block */ - ID_BLOCK_ID(h, pos) = ID_BLOCK_ID(b, 0); - if ( (rc = idl_store( be, db, hkey, h )) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", hkey.dptr, rc, 0 ); - return( rc ); - } - - return( 0 ); -} - - -int -bdb2i_idl_insert_key( - BackendDB *be, - struct dbcache *db, - Datum key, - ID id -) -{ - int i, j, first, rc; - ID_BLOCK *idl, *tmp, *tmp2, *tmp3; - char *kstr; - Datum k2; - - ldbm_datum_init( k2 ); - - if ( (idl = idl_fetch_one( be, db, key )) == NULL ) { -#ifdef LDBM_DEBUG - Statslog( LDAP_DEBUG_STATS, "=> bdb2i_idl_insert_key(): no key yet\n", - 0, 0, 0, 0, 0 ); -#endif - - idl = bdb2i_idl_alloc( 1 ); - ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)++) = id; - rc = idl_store( be, db, key, idl ); - - bdb2i_idl_free( idl ); - return( rc ); - } - - if ( ID_BLOCK_ALLIDS( idl ) ) { - /* ALLIDS */ - bdb2i_idl_free( idl ); - return 0; - } - - if ( ! ID_BLOCK_INDIRECT( idl ) ) { - /* regular block */ - switch ( bdb2i_idl_insert( &idl, id, db->dbc_maxids ) ) { - case 0: /* id inserted - store the updated block */ - case 1: - rc = idl_store( be, db, key, idl ); - break; - - case 2: /* id already there - nothing to do */ - rc = 0; - break; - - case 3: /* id not inserted - block must be split */ - /* check threshold for marking this an all-id block */ - if ( db->dbc_maxindirect < 2 ) { - bdb2i_idl_free( idl ); - idl = bdb2i_idl_allids( be ); - rc = idl_store( be, db, key, idl ); - break; - } - - idl_split_block( idl, id, &tmp, &tmp2 ); - bdb2i_idl_free( idl ); - - /* create the header indirect block */ - idl = bdb2i_idl_alloc( 3 ); - ID_BLOCK_NMAX(idl) = 3; - ID_BLOCK_NIDS(idl) = ID_BLOCK_INDIRECT_VALUE; - ID_BLOCK_ID(idl, 0) = ID_BLOCK_ID(tmp, 0); - ID_BLOCK_ID(idl, 1) = ID_BLOCK_ID(tmp2, 0); - ID_BLOCK_ID(idl, 2) = NOID; - - /* store it */ - rc = idl_store( be, db, key, idl ); - - /* store the first id block */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - rc = idl_store( be, db, k2, tmp ); - - /* store the second id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp2, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - rc = idl_store( be, db, k2, tmp2 ); - - free( kstr ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - break; - } - - bdb2i_idl_free( idl ); - return( rc ); - } - - /* - * this is an indirect block which points to other blocks. - * we need to read in the block into which the id should be - * inserted, then insert the id and store the block. we might - * have to split the block if it is full, which means we also - * need to write a new "header" block. - */ - - /* select the block to try inserting into *//* XXX linear search XXX */ - for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ ) - ; /* NULL */ - if ( i != 0 ) { - i--; - first = 0; - } else { - first = 1; - } - - /* get the block */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) { - Debug( LDAP_DEBUG_ANY, "nonexistent continuation block (%s)\n", - k2.dptr, 0, 0 ); - free( kstr ); - bdb2i_idl_free( idl ); - return( -1 ); - } - - /* insert the id */ - switch ( bdb2i_idl_insert( &tmp, id, db->dbc_maxids ) ) { - case 0: /* id inserted ok */ - if ( (rc = idl_store( be, db, k2, tmp )) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", k2.dptr, rc, 0 ); - } - break; - - case 1: /* id inserted - first id in block has changed */ - /* - * key for this block has changed, so we have to - * write the block under the new key, delete the - * old key block + update and write the indirect - * header block. - */ - - rc = idl_change_first( be, db, key, idl, i, k2, tmp ); - break; - - case 2: /* id not inserted - already there, do nothing */ - rc = 0; - break; - - case 3: /* id not inserted - block is full */ - /* - * first, see if it will fit in the next block, - * without splitting, unless we're trying to insert - * into the beginning of the first block. - */ - - /* is there a next block? */ - if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) { - /* read it in */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i + 1), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "idl_fetch_one (%s) returns NULL\n", - k2.dptr, 0, 0 ); - /* split the original block */ - goto split; - } - - switch ( (rc = bdb2i_idl_insert( &tmp2, id, - db->dbc_maxids )) ) { - case 1: /* id inserted first in block */ - rc = idl_change_first( be, db, key, idl, - i + 1, k2, tmp2 ); - /* FALL */ - - case 2: /* id already there - how? */ - case 0: /* id inserted */ - if ( rc == 2 ) { - Debug( LDAP_DEBUG_ANY, - "id %ld already in next block\n", - id, 0, 0 ); - } - free( kstr ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( tmp2 ); - bdb2i_idl_free( idl ); - return( 0 ); - - case 3: /* split the original block */ - break; - } - - bdb2i_idl_free( tmp2 ); - } - -split: - /* - * must split the block, write both new blocks + update - * and write the indirect header block. - */ - - rc = 0; /* optimistic */ - - - /* count how many indirect blocks *//* XXX linear count XXX */ - for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) - ; /* NULL */ - - /* check it against all-id thresholed */ - if ( j + 1 > db->dbc_maxindirect ) { - /* - * we've passed the all-id threshold, meaning - * that this set of blocks should be replaced - * by a single "all-id" block. our job: delete - * all the indirect blocks, and replace the header - * block by an all-id block. - */ - - /* delete all indirect blocks */ - for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) { - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, j), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - - rc = bdb2i_cache_delete( db, k2 ); - } - - /* store allid block in place of header block */ - bdb2i_idl_free( idl ); - idl = bdb2i_idl_allids( be ); - rc = idl_store( be, db, key, idl ); - - free( kstr ); - bdb2i_idl_free( idl ); - bdb2i_idl_free( tmp ); - return( rc ); - } - - idl_split_block( tmp, id, &tmp2, &tmp3 ); - bdb2i_idl_free( tmp ); - - /* create a new updated indirect header block */ - tmp = bdb2i_idl_alloc( ID_BLOCK_NMAX(idl) + 1 ); - ID_BLOCK_NIDS(tmp) = ID_BLOCK_INDIRECT_VALUE; - /* everything up to the split block */ - SAFEMEMCPY( - (char *) &ID_BLOCK_ID(tmp, 0), - (char *) &ID_BLOCK_ID(idl, 0), - i * sizeof(ID) ); - /* the two new blocks */ - ID_BLOCK_ID(tmp, i) = ID_BLOCK_ID(tmp2, 0); - ID_BLOCK_ID(tmp, i + 1) = ID_BLOCK_ID(tmp3, 0); - /* everything after the split block */ - SAFEMEMCPY( - (char *) &ID_BLOCK_ID(tmp, i + 2), - (char *) &ID_BLOCK_ID(idl, i + 1), - (ID_BLOCK_NMAX(idl) - i - 1) * sizeof(ID) ); - - /* store the header block */ - rc = idl_store( be, db, key, tmp ); - - /* store the first id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp2, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - rc = idl_store( be, db, k2, tmp2 ); - - /* store the second id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp3, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; - rc = idl_store( be, db, k2, tmp3 ); - - bdb2i_idl_free( tmp2 ); - bdb2i_idl_free( tmp3 ); - break; - } - - free( kstr ); - bdb2i_idl_free( tmp ); - bdb2i_idl_free( idl ); - return( rc ); -} - - -/* - * bdb2i_idl_insert - insert an id into an id list. - * - * returns - * 0 id inserted - * 1 id inserted, first id in block has changed - * 2 id not inserted, already there - * 3 id not inserted, block must be split - */ -int -bdb2i_idl_insert( ID_BLOCK **idl, ID id, unsigned int maxids ) -{ - unsigned int i; - - if ( ID_BLOCK_ALLIDS( *idl ) ) { - return( 2 ); /* already there */ - } - - /* is it already there? *//* XXX linear search XXX */ - for ( i = 0; i < ID_BLOCK_NIDS(*idl) && id > ID_BLOCK_ID(*idl, i); i++ ) { - ; /* NULL */ - } - if ( i < ID_BLOCK_NIDS(*idl) && ID_BLOCK_ID(*idl, i) == id ) { - return( 2 ); /* already there */ - } - - /* do we need to make room for it? */ - if ( ID_BLOCK_NIDS(*idl) == ID_BLOCK_NMAX(*idl) ) { - /* make room or indicate block needs splitting */ - if ( ID_BLOCK_NMAX(*idl) >= maxids ) { - return( 3 ); /* block needs splitting */ - } - - ID_BLOCK_NMAX(*idl) *= 2; - if ( ID_BLOCK_NMAX(*idl) > maxids ) { - ID_BLOCK_NMAX(*idl) = maxids; - } - *idl = (ID_BLOCK *) ch_realloc( (char *) *idl, - (ID_BLOCK_NMAX(*idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) ); - } - - /* make a slot for the new id */ - SAFEMEMCPY( &ID_BLOCK_ID(*idl, i+1), &ID_BLOCK_ID(*idl, i), - (ID_BLOCK_NIDS(*idl) - i) * sizeof(ID) ); - - ID_BLOCK_ID(*idl, i) = id; - ID_BLOCK_NIDS(*idl)++; - (void) memset( - (char *) &ID_BLOCK_ID((*idl), ID_BLOCK_NIDS(*idl)), - '\0', - (ID_BLOCK_NMAX(*idl) - ID_BLOCK_NIDS(*idl)) * sizeof(ID) ); - - return( i == 0 ? 1 : 0 ); /* inserted - first id changed or not */ -} - - -int -bdb2i_idl_delete_key ( - BackendDB *be, - struct dbcache *db, - Datum key, - ID id -) -{ - Datum data; - ID_BLOCK *idl, *tmp; - unsigned i; - int j, nids; - char *kstr; - - if ( (idl = idl_fetch_one( be, db, key ) ) == NULL ) - { - /* It wasn't found. Hmm... */ - return -1; - } - - if ( ID_BLOCK_ALLIDS( idl ) ) { - bdb2i_idl_free( idl ); - return 0; - } - - if ( ! ID_BLOCK_INDIRECT( idl ) ) { - for ( i=0; i < ID_BLOCK_NIDS(idl); i++ ) { - if ( ID_BLOCK_ID(idl, i) == id ) { - if( --ID_BLOCK_NIDS(idl) == 0 ) { - bdb2i_cache_delete( db, key ); - - } else { - SAFEMEMCPY ( - &ID_BLOCK_ID(idl, i), - &ID_BLOCK_ID(idl, i+1), - (ID_BLOCK_NIDS(idl)-i) * sizeof(ID) ); - - ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)) = NOID; - - idl_store( be, db, key, idl ); - } - - bdb2i_idl_free( idl ); - return 0; - } - /* We didn't find the ID. Hmmm... */ - } - bdb2i_idl_free( idl ); - return -1; - } - - /* We have to go through an indirect block and find the ID - in the list of IDL's - */ - for ( nids = 0; !ID_BLOCK_NOID(idl, nids); nids++ ) - ; /* NULL */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) - { - ldbm_datum_init( data ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, ID_BLOCK_ID(idl, j), key.dptr ); - data.dptr = kstr; - data.dsize = strlen( kstr ) + 1; - - if ( (tmp = idl_fetch_one( be, db, data )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "bdb2i_idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 ); - continue; - } - /* - Now try to find the ID in tmp - */ - for ( i=0; i < ID_BLOCK_NIDS(tmp); i++ ) - { - if ( ID_BLOCK_ID(tmp, i) == id ) - { - SAFEMEMCPY( - &ID_BLOCK_ID(tmp, i), - &ID_BLOCK_ID(tmp, i+1), - (ID_BLOCK_NIDS(tmp)-(i+1)) * sizeof(ID)); - ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp)-1 ) = NOID; - ID_BLOCK_NIDS(tmp)--; - - if ( ID_BLOCK_NIDS(tmp) ) { - idl_store ( be, db, data, tmp ); - - } else { - bdb2i_cache_delete( db, data ); - SAFEMEMCPY( - &ID_BLOCK_ID(idl, j), - &ID_BLOCK_ID(idl, j+1), - (nids-(j+1)) * sizeof(ID)); - ID_BLOCK_ID(idl, nids-1) = NOID; - nids--; - if ( ! nids ) - bdb2i_cache_delete( db, key ); - else - idl_store( be, db, key, idl ); - } - bdb2i_idl_free( tmp ); - free( kstr ); - bdb2i_idl_free( idl ); - return 0; - } - } - bdb2i_idl_free( tmp ); - } - free( kstr ); - bdb2i_idl_free( idl ); - return -1; -} - - -/* return a duplicate of a single ID_BLOCK */ -static ID_BLOCK * -idl_dup( ID_BLOCK *idl ) -{ - ID_BLOCK *new; - - if ( idl == NULL ) { - return( NULL ); - } - - new = bdb2i_idl_alloc( ID_BLOCK_NMAX(idl) ); - SAFEMEMCPY( - (char *) new, - (char *) idl, - (ID_BLOCK_NMAX(idl) + ID_BLOCK_IDS_OFFSET) * sizeof(ID) ); - - return( new ); -} - - -/* return the smaller ID_BLOCK */ -static ID_BLOCK * -idl_min( ID_BLOCK *a, ID_BLOCK *b ) -{ - return( ID_BLOCK_NIDS(a) > ID_BLOCK_NIDS(b) ? b : a ); -} - - -/* - * bdb2i_idl_intersection - return a intersection b - */ -ID_BLOCK * -bdb2i_idl_intersection( - BackendDB *be, - ID_BLOCK *a, - ID_BLOCK *b -) -{ - unsigned int ai, bi, ni; - ID_BLOCK *n; - - if ( a == NULL || b == NULL ) { - return( NULL ); - } - if ( ID_BLOCK_ALLIDS( a ) ) { - return( idl_dup( b ) ); - } - if ( ID_BLOCK_ALLIDS( b ) ) { - return( idl_dup( a ) ); - } - - n = idl_dup( idl_min( a, b ) ); - - for ( ni = 0, ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) { - for ( ; - bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai); - bi++ ) - { - ; /* NULL */ - } - - if ( bi == ID_BLOCK_NIDS(b) ) { - break; - } - - if ( ID_BLOCK_ID(b, bi) == ID_BLOCK_ID(a, ai) ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai); - } - } - - if ( ni == 0 ) { - bdb2i_idl_free( n ); - return( NULL ); - } - ID_BLOCK_NIDS(n) = ni; - - return( n ); -} - - -/* - * bdb2i_idl_union - return a union b - */ -ID_BLOCK * -bdb2i_idl_union( - BackendDB *be, - ID_BLOCK *a, - ID_BLOCK *b -) -{ - unsigned int ai, bi, ni; - ID_BLOCK *n; - - if ( a == NULL ) { - return( idl_dup( b ) ); - } - if ( b == NULL ) { - return( idl_dup( a ) ); - } - if ( ID_BLOCK_ALLIDS( a ) || ID_BLOCK_ALLIDS( b ) ) { - return( bdb2i_idl_allids( be ) ); - } - - if ( ID_BLOCK_NIDS(b) < ID_BLOCK_NIDS(a) ) { - n = a; - a = b; - b = n; - } - - n = bdb2i_idl_alloc( ID_BLOCK_NIDS(a) + ID_BLOCK_NIDS(b) ); - - for ( ni = 0, ai = 0, bi = 0; - ai < ID_BLOCK_NIDS(a) && bi < ID_BLOCK_NIDS(b); - ) - { - if ( ID_BLOCK_ID(a, ai) < ID_BLOCK_ID(b, bi) ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai++); - - } else if ( ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai) ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi++); - - } else { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai); - ai++, bi++; - } - } - - for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai); - } - for ( ; bi < ID_BLOCK_NIDS(b); bi++ ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(b, bi); - } - ID_BLOCK_NIDS(n) = ni; - - return( n ); -} - - -/* - * bdb2i_idl_notin - return a intersection ~b (or a minus b) - */ -ID_BLOCK * -bdb2i_idl_notin( - BackendDB *be, - ID_BLOCK *a, - ID_BLOCK *b -) -{ - unsigned int ni, ai, bi; - ID_BLOCK *n; - - if ( a == NULL ) { - return( NULL ); - } - if ( b == NULL || ID_BLOCK_ALLIDS( b )) { - return( idl_dup( a ) ); - } - - if ( ID_BLOCK_ALLIDS( a ) ) { - n = bdb2i_idl_alloc( SLAPD_LDBM_MIN_MAXIDS ); - ni = 0; - - for ( ai = 1, bi = 0; - ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n) && bi < ID_BLOCK_NMAX(b); - ai++ ) - { - if ( ID_BLOCK_ID(b, bi) == ai ) { - bi++; - } else { - ID_BLOCK_ID(n, ni++) = ai; - } - } - - for ( ; ai < ID_BLOCK_NIDS(a) && ni < ID_BLOCK_NMAX(n); ai++ ) { - ID_BLOCK_ID(n, ni++) = ai; - } - - if ( ni == ID_BLOCK_NMAX(n) ) { - bdb2i_idl_free( n ); - return( bdb2i_idl_allids( be ) ); - } else { - ID_BLOCK_NIDS(n) = ni; - return( n ); - } - } - - n = idl_dup( a ); - - ni = 0; - for ( ai = 0, bi = 0; ai < ID_BLOCK_NIDS(a); ai++ ) { - for ( ; - bi < ID_BLOCK_NIDS(b) && ID_BLOCK_ID(b, bi) < ID_BLOCK_ID(a, ai); - bi++ ) - { - ; /* NULL */ - } - - if ( bi == ID_BLOCK_NIDS(b) ) { - break; - } - - if ( ID_BLOCK_ID(b, bi) != ID_BLOCK_ID(a, ai) ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai); - } - } - - for ( ; ai < ID_BLOCK_NIDS(a); ai++ ) { - ID_BLOCK_ID(n, ni++) = ID_BLOCK_ID(a, ai); - } - ID_BLOCK_NIDS(n) = ni; - - return( n ); -} - - -/* return the first ID in the block - * if ALLIDS block - * NIDS > 1 return 1 - * otherwise return NOID - * otherwise return first ID - * - * cursor is set to 1 - */ -ID -bdb2i_idl_firstid( ID_BLOCK *idl, ID *cursor ) -{ - *cursor = 1; - - if ( idl == NULL || ID_BLOCK_NIDS(idl) == 0 ) { - return( NOID ); - } - - if ( ID_BLOCK_ALLIDS( idl ) ) { - return( ID_BLOCK_NIDS(idl) > 1 ? 1 : NOID ); - } - - return( ID_BLOCK_ID(idl, 0) ); -} - - -/* return next ID after id - * if ALLIDS block, cursor is id - * increment id - * if id < NIDS return id - * otherwise NOID. - * otherwise cursor is index into block - * if index < nids - * return id at index then increment - */ -ID -bdb2i_idl_nextid( ID_BLOCK *idl, ID *cursor ) -{ - if ( ID_BLOCK_ALLIDS( idl ) ) { - if( ++(*cursor) < ID_BLOCK_NIDS(idl) ) { - return *cursor; - } else { - return NOID; - } - } - - if ( *cursor < ID_BLOCK_NIDS(idl) ) { - return ID_BLOCK_ID(idl, (*cursor)++); - } - return NOID; -} diff --git a/servers/slapd/back-bdb2/index.c b/servers/slapd/back-bdb2/index.c deleted file mode 100644 index 6ef1ca2f73..0000000000 --- a/servers/slapd/back-bdb2/index.c +++ /dev/null @@ -1,379 +0,0 @@ -/* index.c - routines for dealing with attribute indexes */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static int add_value(BackendDB *be, struct dbcache *db, char *type, int indextype, char *val, ID id); -static int index2prefix(int indextype); - -int -bdb2i_index_add_entry( - BackendDB *be, - Entry *e -) -{ - Attribute *ap; - struct berval bv; - struct berval *bvals[2]; - - Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id, - e->e_dn, 0 ); - - /* - * dn index entry - make it look like an attribute so it works - * with bdb2i_index_add_values() call - */ - - bv.bv_val = ch_strdup( e->e_ndn ); - bv.bv_len = strlen( bv.bv_val ); - bvals[0] = &bv; - bvals[1] = NULL; - - /* add the dn to the indexes */ - { - char *dn = ch_strdup( "dn" ); - bdb2i_index_add_values( be, dn, bvals, e->e_id ); - free( dn ); - } - - free( bv.bv_val ); - - /* add each attribute to the indexes */ - for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) { - bdb2i_index_add_values( be, ap->a_type, ap->a_vals, e->e_id ); - } - - Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id, - e->e_ndn, 0 ); - return( 0 ); -} - -int -bdb2i_index_add_mods( - BackendDB *be, - LDAPModList *ml, - ID id -) -{ - int rc; - - for ( ; ml != NULL; ml = ml->ml_next ) { - LDAPMod *mod = &ml->ml_mod; - - switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) { - case LDAP_MOD_ADD: - case LDAP_MOD_REPLACE: - rc = bdb2i_index_add_values( be, mod->mod_type, - mod->mod_bvalues, id ); - break; - case LDAP_MOD_SOFTADD: - case LDAP_MOD_DELETE: - rc = 0; - break; - } - - if ( rc != 0 ) { - return( rc ); - } - } - - return( 0 ); -} - -ID_BLOCK * -bdb2i_index_read( - BackendDB *be, - char *type, - int indextype, - char *val -) -{ - struct dbcache *db; - Datum key; - ID_BLOCK *idl; - int indexmask, syntax; - char prefix; - char *realval, *tmpval; - char buf[BUFSIZ]; - - char *at_cn; - - ldbm_datum_init( key ); - - prefix = index2prefix( indextype ); - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_read( \"%c%s\" -> \"%s\" )\n", - prefix, type, val ); - - bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax ); - if ( ! (indextype & indexmask) ) { - idl = bdb2i_idl_allids( be ); - Debug( LDAP_DEBUG_TRACE, - "<= bdb2i_index_read %ld candidates (allids - not indexed)\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); - } - - attr_normalize( type ); - at_cn = at_canonical_name(type); - - if ( (db = bdb2i_cache_open( be, at_cn, BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= bdb2i_index_read NULL (could not open %s%s)\n", at_cn, - BDB2_SUFFIX, 0 ); - return( NULL ); - } - - realval = val; - tmpval = NULL; - if ( prefix != UNKNOWN_PREFIX ) { - unsigned int len = strlen( val ); - - if ( (len + 2) < sizeof(buf) ) { - realval = buf; - } else { - /* value + prefix + null */ - tmpval = (char *) ch_malloc( len + 2 ); - realval = tmpval; - } - - realval[0] = prefix; - strcpy( &realval[1], val ); - } - - key.dptr = realval; - key.dsize = strlen( realval ) + 1; - - idl = bdb2i_idl_fetch( be, db, key ); - if ( tmpval != NULL ) { - free( tmpval ); - } - - bdb2i_cache_close( be, db ); - - Debug( LDAP_DEBUG_TRACE, "<= bdb2i_index_read %ld candidates\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} - -static int -add_value( - BackendDB *be, - struct dbcache *db, - char *type, - int indextype, - char *val, - ID id -) -{ - int rc; - Datum key; - char *tmpval = NULL; - char *realval = val; - char buf[BUFSIZ]; - - char prefix = index2prefix( indextype ); - - ldbm_datum_init( key ); - - Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 ); - - if ( prefix != UNKNOWN_PREFIX ) { - unsigned int len = strlen( val ); - - if ( (len + 2) < sizeof(buf) ) { - realval = buf; - } else { - /* value + prefix + null */ - tmpval = (char *) ch_malloc( len + 2 ); - realval = tmpval; - } - realval[0] = prefix; - strcpy( &realval[1], val ); - } - - key.dptr = realval; - key.dsize = strlen( realval ) + 1; - - rc = bdb2i_idl_insert_key( be, db, key, id ); - - if ( tmpval != NULL ) { - free( tmpval ); - } - - ldap_pvt_thread_yield(); - - /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */ - return( rc ); -} - -int -bdb2i_index_add_values( - BackendDB *be, - char *type, - struct berval **vals, - ID id -) -{ - char *val, *p, *code, *w; - unsigned i, j, len; - int indexmask, syntax; - char buf[SUBLEN + 1]; - char vbuf[BUFSIZ]; - char *bigbuf; - struct dbcache *db; - - char *at_cn; - - if( vals == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "=> bdb2i_index_add_values( \"%s\", NULL, %ld )\n", - type, id, 0 ); - return 0; - } - - Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_add_values( \"%s\", %ld )\n", - type, id, 0 ); - attr_normalize( type ); - bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax ); - if ( indexmask == 0 ) { - return( 0 ); - } - at_cn = at_canonical_name(type); - - if ( (db = bdb2i_cache_open( be, at_cn, BDB2_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= bdb2i_index_add_values -1 (could not open/create %s%s)\n", - at_cn, BDB2_SUFFIX, 0 ); - return( -1 ); - } - - for ( i = 0; vals[i] != NULL; i++ ) { - /* - * presence index entry - */ - if ( indexmask & INDEX_PRESENCE ) { - add_value( be, db, at_cn, INDEX_PRESENCE, "*", id ); - } - - Debug( LDAP_DEBUG_TRACE, "*** bdb2i_index_add_values syntax 0x%x syntax bin 0x%x\n", - syntax, SYNTAX_BIN, 0 ); - if ( syntax & SYNTAX_BIN ) { - bdb2i_cache_close( be, db ); - return( 0 ); - } - - bigbuf = NULL; - len = vals[i]->bv_len; - - /* value + null */ - if ( len + 2 > sizeof(vbuf) ) { - bigbuf = (char *) ch_malloc( len + 1 ); - val = bigbuf; - } else { - val = vbuf; - } - (void) memcpy( val, vals[i]->bv_val, len ); - val[len] = '\0'; - - value_normalize( val, syntax ); - - /* value_normalize could change the length of val */ - len = strlen( val ); - - /* - * equality index entry - */ - if ( indexmask & INDEX_EQUALITY ) { - add_value( be, db, at_cn, INDEX_EQUALITY, val, id ); - } - - /* - * approximate index entry - */ - if ( indexmask & INDEX_APPROX ) { - for ( w = first_word( val ); w != NULL; - w = next_word( w ) ) { - if ( (code = phonetic( w )) != NULL ) { - add_value( be, db, at_cn, INDEX_APPROX, - code, id ); - free( code ); - } - } - } - - /* - * substrings index entry - */ - if ( indexmask & INDEX_SUB ) { - /* leading and trailing */ - if ( len > SUBLEN - 2 ) { - buf[0] = '^'; - for ( j = 0; j < SUBLEN - 1; j++ ) { - buf[j + 1] = val[j]; - } - buf[SUBLEN] = '\0'; - - add_value( be, db, at_cn, INDEX_SUB, buf, id ); - - p = val + len - SUBLEN + 1; - for ( j = 0; j < SUBLEN - 1; j++ ) { - buf[j] = p[j]; - } - buf[SUBLEN - 1] = '$'; - buf[SUBLEN] = '\0'; - - add_value( be, db, at_cn, INDEX_SUB, buf, id ); - } - - /* any */ - for ( p = val; p < (val + len - SUBLEN + 1); p++ ) { - for ( j = 0; j < SUBLEN; j++ ) { - buf[j] = p[j]; - } - buf[SUBLEN] = '\0'; - - add_value( be, db, at_cn, INDEX_SUB, buf, id ); - } - } - - if ( bigbuf != NULL ) { - free( bigbuf ); - } - } - bdb2i_cache_close( be, db ); - - return( 0 ); -} - -static int -index2prefix( int indextype ) -{ - int prefix; - - switch ( indextype ) { - case INDEX_EQUALITY: - prefix = EQ_PREFIX; - break; - case INDEX_APPROX: - prefix = APPROX_PREFIX; - break; - case INDEX_SUB: - prefix = SUB_PREFIX; - break; - default: - prefix = UNKNOWN_PREFIX; - break; - } - - return( prefix ); -} diff --git a/servers/slapd/back-bdb2/init.c b/servers/slapd/back-bdb2/init.c deleted file mode 100644 index 0eb5080460..0000000000 --- a/servers/slapd/back-bdb2/init.c +++ /dev/null @@ -1,240 +0,0 @@ -/* init.c - initialize bdb2 backend */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -#ifdef SLAPD_BDB2_DYNAMIC - -int back_bdb2_LTX_init_module(int argc, char *argv[]) { - BackendInfo bi; - - memset( &bi, 0, sizeof(bi) ); - bi.bi_type = "bdb2"; - bi.bi_init = bdb2_back_initialize; - - backend_add(&bi); - return 0; -} - -#endif /* SLAPD_BDB2_DYNAMIC */ - -static int -bdb2i_back_init_private( - BackendInfo *bi -) -{ - struct ldbtype *bt; - - /* allocate backend-type-specific stuff */ - bt = (struct ldbtype *) ch_calloc( 1, sizeof(struct ldbtype) ); - - bt->lty_dbhome = DEFAULT_DB_HOME; - bt->lty_mpsize = DEFAULT_DBCACHE_SIZE; - - if ( slapMode & SLAP_TIMED_MODE ) - bt->lty_betiming = 1; - - bi->bi_private = bt; - - return 0; -} - - -int -bdb2_back_initialize( - BackendInfo *bi -) -{ - int ret; - - bi->bi_open = bdb2_back_open; - bi->bi_config = bdb2_back_config; - bi->bi_close = bdb2_back_close; - bi->bi_destroy = bdb2_back_destroy; - - bi->bi_db_init = bdb2_back_db_init; - bi->bi_db_config = bdb2_back_db_config; - bi->bi_db_open = bdb2_back_db_open; - bi->bi_db_close = bdb2_back_db_close; - bi->bi_db_destroy = bdb2_back_db_destroy; - - bi->bi_op_bind = bdb2_back_bind; - bi->bi_op_unbind = bdb2_back_unbind; - bi->bi_op_search = bdb2_back_search; - bi->bi_op_compare = bdb2_back_compare; - bi->bi_op_modify = bdb2_back_modify; - bi->bi_op_modrdn = bdb2_back_modrdn; - bi->bi_op_add = bdb2_back_add; - bi->bi_op_delete = bdb2_back_delete; - bi->bi_op_abandon = bdb2_back_abandon; - - bi->bi_entry_release_rw = bdb2_back_entry_release_rw; - bi->bi_acl_group = bdb2_back_group; - - /* - * hooks for slap tools - */ - bi->bi_tool_entry_open = bdb2_tool_entry_open; - bi->bi_tool_entry_close = bdb2_tool_entry_close; - bi->bi_tool_entry_first = bdb2_tool_entry_first; - bi->bi_tool_entry_next = bdb2_tool_entry_next; - bi->bi_tool_entry_get = bdb2_tool_entry_get; - bi->bi_tool_entry_put = bdb2_tool_entry_put; - bi->bi_tool_index_attr = bdb2_tool_index_attr; - bi->bi_tool_index_change = bdb2_tool_index_change; - bi->bi_tool_sync = bdb2_tool_sync; - - bi->bi_connection_init = 0; - bi->bi_connection_destroy = 0; - - ret = bdb2i_back_init_private( bi ); - - Debug( LDAP_DEBUG_TRACE, "bdb2_back_initialize: done (%d).\n", ret, 0, 0 ); - - return( ret ); -} - -int -bdb2_back_destroy( - BackendInfo *bi -) -{ - return 0; -} - -int -bdb2_back_open( - BackendInfo *bi -) -{ - static int initialized = 0; - int rc; - - if ( initialized++ ) { - - Debug( LDAP_DEBUG_TRACE, - "bdb2_back_open: backend already initialized.\n", 0, 0, 0 ); - return 0; - - } - - /* initialize the underlying database system */ - rc = bdb2i_back_startup( bi ); - - return rc; -} - -int -bdb2_back_close( - BackendInfo *bi -) -{ - int rc; - - /* close the underlying database system */ - rc = bdb2i_back_shutdown( bi ); - - return rc; -} - -/* BDB2 changed */ -static int -bdb2i_back_db_init_internal( - BackendDB *be -) -{ - struct ldbminfo *li; - char *argv[ 4 ]; - - /* allocate backend-database-specific stuff */ - li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) ); - - /* arrange to read nextid later (on first request for it) */ - li->li_nextid = NOID; -#if SLAPD_NEXTID_CHUNK > 1 - li->li_nextid_wrote = NOID; -#endif - - /* default cache size */ - li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE; - - /* default database cache size */ - li->li_dbcachesize = DEFAULT_DBCACHE_SIZE; - - /* default cache mode is sync on write */ - li->li_dbcachewsync = 1; - - /* default file creation mode */ - li->li_mode = DEFAULT_MODE; - - /* default database directory */ - li->li_directory = DEFAULT_DB_DIRECTORY; - - argv[ 0 ] = "objectclass"; - argv[ 1 ] = "pres,eq"; - argv[ 2 ] = NULL; - bdb2i_attr_index_config( li, "ldbm objectclass initialization", - 0, 2, argv, 1 ); - - /* initialize the cache mutex */ - ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex ); - - /* initialize the TP file head */ - if ( bdb2i_txn_head_init( &li->li_txn_head ) != 0 ) - return 1; - - be->be_private = li; - - return 0; -} - - -int -bdb2_back_db_init( - BackendDB *be -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_db_init_internal( be ); - bdb2i_stop_timing( be->bd_info, time1, "DB-INIT", NULL, NULL ); - - return( ret ); -} - - -int -bdb2_back_db_open( - BackendDB *be -) -{ - int rc; - - rc = bdb2_back_db_startup( be ); - - return( rc ); -} - -int -bdb2_back_db_destroy( - BackendDB *be -) -{ - /* should free/destroy every in be_private */ - free( be->be_private ); - be->be_private = NULL; - return 0; -} - - diff --git a/servers/slapd/back-bdb2/kerberos.c b/servers/slapd/back-bdb2/kerberos.c deleted file mode 100644 index 61a9db0763..0000000000 --- a/servers/slapd/back-bdb2/kerberos.c +++ /dev/null @@ -1,49 +0,0 @@ -/* kerberos.c - bdb2 backend kerberos bind routines */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#ifdef HAVE_KERBEROS - -#include - -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -#define LDAP_KRB_PRINCIPAL "ldapserver" - -extern char *ldap_srvtab; -extern Attribute *attr_find(); - -bdb2i_krbv4_ldap_auth( - BackendDB *be, - struct berval *cred, - AUTH_DAT *ad -) -{ - KTEXT_ST k; - KTEXT ktxt = &k; - char instance[INST_SZ]; - int err; - - Debug( LDAP_DEBUG_TRACE, "=> kerberosv4_ldap_auth\n", 0, 0, 0 ); - - SAFEMEMCPY( ktxt->dat, cred->bv_val, cred->bv_len ); - ktxt->length = cred->bv_len; - - strcpy( instance, "*" ); - if ( (err = krb_rd_req( ktxt, LDAP_KRB_PRINCIPAL, instance, 0L, ad, - ldap_srvtab )) != KSUCCESS ) { - Debug( LDAP_DEBUG_ANY, "krb_rd_req failed (%s)\n", - krb_err_txt[err], 0, 0 ); - return( LDAP_INVALID_CREDENTIALS ); - } - - return( LDAP_SUCCESS ); -} - -#endif /* kerberos */ diff --git a/servers/slapd/back-bdb2/modify.c b/servers/slapd/back-bdb2/modify.c deleted file mode 100644 index 817d3ba26f..0000000000 --- a/servers/slapd/back-bdb2/modify.c +++ /dev/null @@ -1,323 +0,0 @@ -/* modify.c - bdb2 backend modify routine */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -int -bdb2i_back_modify_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - LDAPModList *modlist, - Entry *e -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - LDAPModList *ml; - int err; - - Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0); - - if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) { - send_ldap_result( conn, op, err, - NULL, NULL, NULL, NULL ); - goto error_return; - } - - for ( ml = modlist; ml != NULL; ml = ml->ml_next ) { - LDAPMod *mod = &ml->ml_mod; - - switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) { - case LDAP_MOD_ADD: - err = bdb2i_add_values( e, mod, op->o_ndn ); - break; - - case LDAP_MOD_DELETE: - err = bdb2i_delete_values( e, mod, op->o_ndn ); - break; - - case LDAP_MOD_REPLACE: - err = bdb2i_replace_values( e, mod, op->o_ndn ); - break; - - case LDAP_MOD_SOFTADD: - /* Avoid problems in index_add_mods() - * We need to add index if necessary. - */ - mod->mod_op = LDAP_MOD_ADD; - if ( (err = bdb2i_add_values( e, mod, op->o_ndn )) - == LDAP_TYPE_OR_VALUE_EXISTS ) { - - err = LDAP_SUCCESS; - mod->mod_op = LDAP_MOD_SOFTADD; - - } - break; - } - - if ( err != LDAP_SUCCESS ) { - /* unlock entry, delete from cache */ - send_ldap_result( conn, op, err, - NULL, NULL, NULL, NULL ); - goto error_return; - } - } - - /* check that the entry still obeys the schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { - Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL, NULL ); - goto error_return; - } - - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - goto error_return; - } - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - - /* modify indexes */ - if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto error_return; - } - - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - goto error_return; - } - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - - /* change the entry itself */ - if ( bdb2i_id2entry_add( be, e ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto error_return; - } - - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - return( 0 ); - -error_return:; - return( -1 ); -} - - -int -bdb2_back_modify( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - LDAPModList *modlist -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret, manageDSAit; - Entry *matched; - Entry *e; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_w( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( -1 ); - } - - /* check, if a new default attribute index will be created, - in which case we have to open the index file BEFORE TP */ - switch ( slapMode & SLAP_MODE ) { - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - bdb2i_check_default_attr_index_mod( li, modlist ); - break; - } - - if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - if( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - ret = -1; - goto done; - } - - if (!manageDSAit && is_entry_referral( e ) ) { - /* entry is a referral, don't allow add */ - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); - - bdb2i_cache_return_entry_w( &li->li_cache, e ); - - ber_bvecfree( refs ); - - ret = -1; - goto done; - } - - ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e ); - bdb2i_cache_return_entry_w( &li->li_cache, e ); - -done: - (void) bdb2i_leave_backend_w( lock ); - bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op ); - - return( ret ); -} - - -int -bdb2i_add_values( - Entry *e, - LDAPMod *mod, - char *dn -) -{ - int i; - Attribute *a; - - /* check if the values we're adding already exist */ - if ( (a = attr_find( e->e_attrs, mod->mod_type )) != NULL ) { - for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) { - if ( value_find( a->a_vals, mod->mod_bvalues[i], - a->a_syntax, 3 ) == 0 ) { - return( LDAP_TYPE_OR_VALUE_EXISTS ); - } - } - } - - /* no - add them */ - if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) { - return( LDAP_CONSTRAINT_VIOLATION ); - } - - return( LDAP_SUCCESS ); -} - -int -bdb2i_delete_values( - Entry *e, - LDAPMod *mod, - char *dn -) -{ - int i, j, k, found; - Attribute *a; - - /* delete the entire attribute */ - if ( mod->mod_bvalues == NULL ) { - Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", - mod->mod_type, 0, 0 ); - return( attr_delete( &e->e_attrs, mod->mod_type ) ? - LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS ); - } - - /* delete specific values - find the attribute first */ - if ( (a = attr_find( e->e_attrs, mod->mod_type )) == NULL ) { - Debug( LDAP_DEBUG_ARGS, "could not find attribute %s\n", - mod->mod_type, 0, 0 ); - return( LDAP_NO_SUCH_ATTRIBUTE ); - } - - /* find each value to delete */ - for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) { - found = 0; - for ( j = 0; a->a_vals[j] != NULL; j++ ) { - if ( value_cmp( mod->mod_bvalues[i], a->a_vals[j], - a->a_syntax, 3 ) != 0 ) { - continue; - } - found = 1; - - /* found a matching value - delete it */ - ber_bvfree( a->a_vals[j] ); - for ( k = j + 1; a->a_vals[k] != NULL; k++ ) { - a->a_vals[k - 1] = a->a_vals[k]; - } - a->a_vals[k - 1] = NULL; - - /* delete the entire attribute, if no values remain */ - if ( a->a_vals[0] == NULL) { - Debug( LDAP_DEBUG_ARGS, - "removing entire attribute %s\n", - mod->mod_type, 0, 0 ); - if ( attr_delete( &e->e_attrs, mod->mod_type ) ) { - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - - break; - } - - /* looked through them all w/o finding it */ - if ( ! found ) { - Debug( LDAP_DEBUG_ARGS, - "could not find value for attr %s\n", - mod->mod_type, 0, 0 ); - return( LDAP_NO_SUCH_ATTRIBUTE ); - } - } - - return( LDAP_SUCCESS ); -} - -int -bdb2i_replace_values( - Entry *e, - LDAPMod *mod, - char *dn -) -{ - (void) attr_delete( &e->e_attrs, mod->mod_type ); - - if ( mod->mod_bvalues != NULL && - attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) - { - return( LDAP_CONSTRAINT_VIOLATION ); - } - - return( LDAP_SUCCESS ); -} diff --git a/servers/slapd/back-bdb2/modrdn.c b/servers/slapd/back-bdb2/modrdn.c deleted file mode 100644 index 47c260fed7..0000000000 --- a/servers/slapd/back-bdb2/modrdn.c +++ /dev/null @@ -1,510 +0,0 @@ -/* modrdn.c - bdb2 backend modrdn routine */ -/* $OpenLDAP$ */ - -/* - * LDAP v3 newSuperior support. - * - * Copyright 1999, Juan C. Gomez, All rights reserved. - * This software is not subject to any license of Silicon Graphics - * Inc. or Purdue University. - * - * Redistribution and use in source and binary forms are permitted - * without restriction or fee of any kind as long as this notice - * is preserved. - * - */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static int -bdb2i_back_modrdn_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - char *newrdn, - int deleteoldrdn, - char *newSuperior -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Entry *matched = NULL; - char *p_dn = NULL, *p_ndn = NULL; - char *new_dn = NULL, *new_ndn = NULL; - char sep[2]; - Entry *e, *p = NULL; - int rc = -1, manageDSAit; - /* Added to support LDAP v2 correctly (deleteoldrdn thing) */ - char *new_rdn_val = NULL; /* Val of new rdn */ - char *new_rdn_type = NULL; /* Type of new rdn */ - char *old_rdn = NULL; /* Old rdn's attr type & val */ - char *old_rdn_type = NULL; /* Type of old rdn attr. */ - char *old_rdn_val = NULL; /* Old rdn attribute value */ - struct berval add_bv; /* Stores new rdn att */ - struct berval *add_bvals[2]; /* Stores new rdn att */ - struct berval del_bv; /* Stores old rdn att */ - struct berval *del_bvals[2]; /* Stores old rdn att */ - LDAPModList mod[2]; /* Used to delete old rdn */ - /* Added to support newSuperior */ - Entry *np = NULL; /* newSuperior Entry */ - char *np_dn = NULL; /* newSuperior dn */ - char *np_ndn = NULL; /* newSuperior ndn */ - char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */ - - Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n", - (newSuperior ? newSuperior : "NULL"), - 0, 0 ); - - /* get entry with writer lock */ - if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - if( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - return( -1 ); - } - - if (!manageDSAit && is_entry_referral( e ) ) { - /* entry is a referral, don't allow add */ - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - - goto return_results; - } - -#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL - /* check parent for "children" acl */ - if ( ! access_allowed( be, conn, op, e, - "entry", NULL, ACL_WRITE ) ) - { - Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } -#endif - - if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) { - /* parent + rdn + separator(s) + null */ - if( (p = bdb2i_dn2entry_w( be, p_ndn, &matched )) == NULL) { - Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", - 0, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - /* check parent for "children" acl */ - if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) - { - Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, - 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - p_dn = dn_parent( be, e->e_dn ); - - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n", - p_dn, 0, 0 ); - - - } else { - /* no parent, modrdn entry directly under root */ - if( ! be_isroot( be, op->o_ndn ) ) { - Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", - 0, 0, 0); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: no parent!, working on root\n", - 0, 0, 0 ); - - } - - new_parent_dn = p_dn; /* New Parent unless newSuperior given */ - - if ( (np_dn = newSuperior) != NULL) { - - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: new parent requested...\n", - 0, 0, 0 ); - - np_ndn = ch_strdup( np_dn ); - (void) dn_normalize_case( np_ndn ); - - /* newSuperior == oldParent?, if so ==> ERROR */ - - /* newSuperior == entry being moved?, if so ==> ERROR */ - - /* Get Entry with dn=newSuperior. Does newSuperior exist? */ - - if( (np = bdb2i_dn2entry_w( be, np_ndn, &matched )) == NULL) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: newSup(ndn=%s) not here!\n", - np_ndn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: wr to new parent OK np=%p, id=%d\n", - np, np->e_id, 0 ); - - /* check newSuperior for "children" acl */ - if ( !access_allowed( be, conn, op, np, "children", NULL, - ACL_WRITE ) ) - { - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: no wr to newSup children\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: wr to new parent's children OK\n", - 0, 0 , 0 ); - - - new_parent_dn = np_dn; - - } - - /* Build target dn and make sure target entry doesn't exist already. */ - - build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn ); - - - new_ndn = ch_strdup( new_dn ); - (void) dn_normalize_case( new_ndn ); - - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n", - new_ndn, 0, 0 ); - - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - goto return_results; - } - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - - if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) { - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - /* Get attribute type and attribute value of our new rdn, we will - * need to add that to our new entry - */ - - if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out type of newrdn\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - } - - if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out val of newrdn\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - } - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: new_rdn_val=%s, new_rdn_type=%s\n", - new_rdn_val, new_rdn_type, 0 ); - - /* Retrieve the old rdn from the entry's dn */ - - if ( (old_rdn = dn_rdn( be, dn )) == NULL ) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out old_rdn from dn\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - } - - if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out the old_rdn type\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - } - - if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) { - - /* Not a big deal but we may say something */ - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n", - old_rdn_type, new_rdn_type, 0 ); - - } - -#ifdef DNS_DN - if ( dn_type( old_rdn ) == DN_X500 ) { -#endif - - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n", - 0, 0, 0 ); - - /* Add new attribute value to the entry. - */ - - add_bvals[0] = &add_bv; /* Array of bervals */ - add_bvals[1] = NULL; - - add_bv.bv_val = new_rdn_val; - add_bv.bv_len = strlen(new_rdn_val); - - mod[0].ml_type = new_rdn_type; - mod[0].ml_bvalues = add_bvals; - mod[0].ml_op = LDAP_MOD_SOFTADD; - mod[0].ml_next = NULL; - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: adding new rdn attr val =%s\n", - new_rdn_val, 0, 0 ); - - /* Remove old rdn value if required */ - - if (deleteoldrdn) { - - del_bvals[0] = &del_bv; /* Array of bervals */ - del_bvals[1] = NULL; - /* Get value of old rdn */ - - if ((old_rdn_val = rdn_attr_value( old_rdn )) - == NULL) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - - } - - /* Remove old value of rdn as an attribute. */ - - del_bv.bv_val = old_rdn_val; - del_bv.bv_len = strlen(old_rdn_val); - - mod[0].ml_next = &mod[1]; - mod[1].ml_type = old_rdn_type; - mod[1].ml_bvalues = del_bvals; - mod[1].ml_op = LDAP_MOD_DELETE; - mod[1].ml_next = NULL; - - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: removing old_rdn_val=%s\n", - old_rdn_val, 0, 0 ); - - }/* if (deleteoldrdn) */ - -#ifdef DNS_DN - } else { - - - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n", - 0, 0, 0 ); - /* XXXV3: not sure of what to do here */ - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: not fully implemented...\n", - 0, 0, 0 ); - - } -#endif - - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - goto return_results; - } - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - - /* delete old one */ - if ( bdb2i_dn2id_delete( be, e->e_ndn, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - (void) bdb2i_cache_delete_entry( &li->li_cache, e ); - - free( e->e_dn ); - free( e->e_ndn ); - e->e_dn = new_dn; - e->e_ndn = new_ndn; - new_dn = NULL; - new_ndn = NULL; - - /* add new one */ - if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - /* modify memory copy of entry */ - if ( bdb2i_back_modify_internal( be, conn, op, dn, &mod[0], e ) - != 0 ) { - - goto return_results; - - } - - (void) bdb2i_cache_update_entry( &li->li_cache, e ); - - /* NOTE: after this you must not free new_dn or new_ndn! - * They are used by cache. - */ - - /* id2entry index */ - if ( bdb2i_id2entry_add( be, e ) != 0 ) { - entry_free( e ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - } - - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - rc = 0; - -return_results: - if( new_dn != NULL ) free( new_dn ); - if( new_ndn != NULL ) free( new_ndn ); - - /* NOTE: - * new_dn and new_ndn are not deallocated because they are used by - * the cache entry. - */ - if( p_dn != NULL ) free( p_dn ); - if( p_ndn != NULL ) free( p_ndn ); - - /* LDAP v2 supporting correct attribute handling. */ - if( new_rdn_type != NULL ) free(new_rdn_type); - if( new_rdn_val != NULL ) free(new_rdn_val); - if( old_rdn != NULL ) free(old_rdn); - if( old_rdn_type != NULL ) free(old_rdn_type); - if( old_rdn_val != NULL ) free(old_rdn_val); - - /* LDAP v3 Support */ - if ( np_dn != NULL ) free( np_dn ); - if ( np_ndn != NULL ) free( np_ndn ); - - if( p != NULL ) { - /* free parent and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, p ); - - } - - /* free entry and writer lock */ - bdb2i_cache_return_entry_w( &li->li_cache, e ); - return( rc ); -} - - -int -bdb2_back_modrdn( - BackendDB *be, - Connection *conn, - Operation *op, - char *dn, - char *newrdn, - int deleteoldrdn, - char *newSuperior -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_w( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( -1 ); - - } - - ret = bdb2i_back_modrdn_internal( be, conn, op, dn, - newrdn, deleteoldrdn, - newSuperior ); - - (void) bdb2i_leave_backend_w( lock ); - bdb2i_stop_timing( be->bd_info, time1, "MODRDN", conn, op ); - - return( ret ); -} - - diff --git a/servers/slapd/back-bdb2/nextid.c b/servers/slapd/back-bdb2/nextid.c deleted file mode 100644 index c00c67d11d..0000000000 --- a/servers/slapd/back-bdb2/nextid.c +++ /dev/null @@ -1,74 +0,0 @@ -/* id.c - keep track of the next id to be given out */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#include "slap.h" -#include "back-bdb2.h" - -/* reading and writing NEXTID is handled in txn.c */ -#define next_id_read(be) bdb2i_get_nextid( (be) ) -#define next_id_write(be,id) bdb2i_put_nextid( (be), (id) ) - - -int -bdb2i_next_id_save( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id = bdb2i_next_id_get( be ); - int rc; - - rc = next_id_write( be, id ); - - return rc; -} - -ID -bdb2i_next_id( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id; - - /* first time in here since startup - try to read the nexid */ - if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); - - if ( li->li_nextid == NOID ) { - li->li_nextid = 1; - } - } - - id = li->li_nextid++; - - (void) next_id_write( be, li->li_nextid ); - - return( id ); -} - -ID -bdb2i_next_id_get( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id; - - /* first time in here since startup - try to read the nexid */ - if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); - - if ( li->li_nextid == NOID ) { - li->li_nextid = 1; - } - } - - id = li->li_nextid; - - return( id ); -} diff --git a/servers/slapd/back-bdb2/porter.c b/servers/slapd/back-bdb2/porter.c deleted file mode 100644 index 55f87a63d3..0000000000 --- a/servers/slapd/back-bdb2/porter.c +++ /dev/null @@ -1,143 +0,0 @@ -/* porter.c - port functions of the bdb2 backend */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include -#include - -#include - -#include "slap.h" -#include "back-bdb2.h" - -#define PORTER_OBJ "bdb2_backend" - - -int -bdb2i_enter_backend_rw( DB_LOCK *lock, int writer ) -{ - u_int32_t locker; - db_lockmode_t lock_type; - DBT lock_dbt; - int ret = 0; - - switch ( slapMode & SLAP_MODE ) { - - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - if ( ( ret = lock_id( bdb2i_dbEnv.lk_info, &locker )) != 0 ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_enter_backend(): unable to get locker id -- %s\n", - strerror( ret ), 0, 0 ); - return( ret ); - - } - - lock_type = writer ? DB_LOCK_WRITE : DB_LOCK_READ; - lock_dbt.data = PORTER_OBJ; - lock_dbt.size = strlen( PORTER_OBJ ); - - switch ( ( ret = lock_get( bdb2i_dbEnv.lk_info, locker, 0, - &lock_dbt, lock_type, lock ))) { - - case 0: - Debug( LDAP_DEBUG_TRACE, - "bdb2i_enter_backend() -- %s lock granted\n", - writer ? "write" : "read", 0, 0 ); - break; - - case DB_LOCK_NOTGRANTED: - Debug( LDAP_DEBUG_ANY, - "bdb2i_enter_backend() -- %s lock NOT granted\n", - writer ? "write" : "read", 0, 0 ); - break; - - case DB_LOCK_DEADLOCK: - Debug( LDAP_DEBUG_ANY, - "bdb2i_enter_backend() -- %s lock returned DEADLOCK\n", - writer ? "write" : "read", 0, 0 ); - break; - - default: - ret = errno; - Debug( LDAP_DEBUG_ANY, - "bdb2i_enter_backend() -- %s lock returned ERROR: %s\n", - writer ? "write" : "read", strerror( ret ), 0 ); - break; - - } - break; - } - - /* if we are a writer and we have the backend lock, - start transaction control */ - if ( writer && ( ret == 0 )) { - - ret = bdb2i_start_transction( bdb2i_dbEnv.tx_info ); - - } - - return( ret ); -} - - -int -bdb2i_leave_backend_rw( DB_LOCK lock, int writer ) -{ - /* since one or more error can occure, - we must have several return codes that are or'ed at the end */ - int ret_transaction = 0; - int ret_lock = 0; - - /* if we are a writer, finish the transaction */ - if ( writer ) { - - ret_transaction = bdb2i_finish_transaction(); - - } - - /* check whether checkpointing is needed */ - ret_transaction |= bdb2i_set_txn_checkpoint( bdb2i_dbEnv.tx_info, 0 ); - - /* now release the lock */ - switch ( slapMode & SLAP_MODE ) { - - case SLAP_SERVER_MODE: - case SLAP_TOOL_MODE: - switch( ( ret_lock = lock_put( bdb2i_dbEnv.lk_info, lock ))) { - - case 0: - Debug( LDAP_DEBUG_TRACE, - "bdb2i_leave_backend() -- %s lock released\n", - writer ? "write" : "read", 0, 0 ); - break; - - case DB_LOCK_NOTHELD: - Debug( LDAP_DEBUG_ANY, - "bdb2i_leave_backend() -- %s lock NOT held\n", - writer ? "write" : "read", 0, 0 ); - break; - - case DB_LOCK_DEADLOCK: - Debug( LDAP_DEBUG_ANY, - "bdb2i_leave_backend() -- %s lock returned DEADLOCK\n", - writer ? "write" : "read", 0, 0 ); - break; - - default: - ret_lock = errno; - Debug( LDAP_DEBUG_ANY, - "bdb2i_leave_backend() -- %s lock returned ERROR: %s\n", - writer ? "write" : "read", strerror( ret_lock ), 0 ); - break; - - } - break; - } - - return( ret_transaction | ret_lock ); -} - - diff --git a/servers/slapd/back-bdb2/proto-back-bdb2.h b/servers/slapd/back-bdb2/proto-back-bdb2.h deleted file mode 100644 index befba8b8ab..0000000000 --- a/servers/slapd/back-bdb2/proto-back-bdb2.h +++ /dev/null @@ -1,251 +0,0 @@ -/* $OpenLDAP$ */ -#ifndef _PROTO_BACK_BDB2 -#define _PROTO_BACK_BDB2 - -#include - -#include /* Needed in add.c compare.c struct timeval */ - -#include "external.h" - -LDAP_BEGIN_DECL - -/* - * add.c - */ -int bdb2i_release_add_lock LDAP_P(()); - -/* - * alias.c - */ - -Entry * bdb2i_deref_r LDAP_P(( - Backend *be, - Entry *e, - char *dn, - int *err, - Entry **matched, - char **text )); - -#define deref_entry_r( be, e, err, matched, text ) \ - bdb2i_deref_r( be, e, NULL, err, matched, text ) -#define deref_dn_r( be, dn, err, matched, text ) \ - bdb2i_deref_r( be, NULL, dn, err, matched, text ) - -/* - * attr.c - */ - -void bdb2i_attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask, - int *syntaxmask )); -void bdb2i_attr_index_config LDAP_P(( struct ldbminfo *li, - const char *fname, - int lineno, int argc, char **argv, int init )); - -/* - * cache.c - */ - -int bdb2i_cache_add_entry_rw LDAP_P(( struct cache *cache, Entry *e, int rw )); -int bdb2i_cache_update_entry LDAP_P(( struct cache *cache, Entry *e )); -void bdb2i_cache_return_entry_rw LDAP_P(( struct cache *cache, Entry *e, - int rw )); -#define bdb2i_cache_return_entry_r(c, e) bdb2i_cache_return_entry_rw((c), (e), 0) -#define bdb2i_cache_return_entry_w(c, e) bdb2i_cache_return_entry_rw((c), (e), 1) - -ID bdb2i_cache_find_entry_dn2id LDAP_P(( BackendDB *be, struct cache *cache, - const char *dn )); -Entry * bdb2i_cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw )); -int bdb2i_cache_delete_entry LDAP_P(( struct cache *cache, Entry *e )); - -/* - * dbcache.c - */ - -struct dbcache * bdb2i_cache_open LDAP_P(( BackendDB *be, char *name, char *suffix, - int flags )); -void bdb2i_cache_close LDAP_P(( BackendDB *be, struct dbcache *db )); -void bdb2i_cache_really_close LDAP_P(( BackendDB *be, struct dbcache *db )); -void bdb2i_cache_flush_all LDAP_P(( BackendDB *be )); -Datum bdb2i_cache_fetch LDAP_P(( struct dbcache *db, Datum key )); -int bdb2i_cache_store LDAP_P(( struct dbcache *db, Datum key, Datum data, int flags )); -int bdb2i_cache_delete LDAP_P(( struct dbcache *db, Datum key )); - -/* - * dn2id.c - */ - -int bdb2i_dn2id_add LDAP_P(( BackendDB *be, const char *dn, ID id )); -ID bdb2i_dn2id LDAP_P(( BackendDB *be, const char *dn )); -int bdb2i_dn2id_delete LDAP_P(( BackendDB *be, const char *dn, ID id )); - -ID_BLOCK * -bdb2i_dn2idl LDAP_P(( - BackendDB *be, - const char *dn, - int prefix )); - -Entry * bdb2i_dn2entry_rw LDAP_P(( - BackendDB *be, - const char *dn, - Entry **matched, - int rw )); - -#define bdb2i_dn2entry_r(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 0) -#define bdb2i_dn2entry_w(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 1) - -/* - * entry.c - */ -int bdb2_back_entry_release_rw LDAP_P(( BackendDB *be, Entry *e, int rw )); - -/* - * filterindex.c - */ - -ID_BLOCK * bdb2i_filter_candidates LDAP_P(( BackendDB *be, Filter *f )); - -/* - * id2children.c - */ - -int bdb2i_has_children LDAP_P(( BackendDB *be, Entry *p )); - -/* - * id2entry.c - */ - -int bdb2i_id2entry_add LDAP_P(( BackendDB *be, Entry *e )); -int bdb2i_id2entry_delete LDAP_P(( BackendDB *be, Entry *e )); - -Entry * bdb2i_id2entry_rw LDAP_P(( BackendDB *be, ID id, int rw )); -#define bdb2i_id2entry_r(be, id) bdb2i_id2entry_rw((be), (id), 0) -#define bdb2i_id2entry_w(be, id) bdb2i_id2entry_rw((be), (id), 1) - -/* - * idl.c - */ - -ID_BLOCK * bdb2i_idl_alloc LDAP_P(( unsigned int nids )); -ID_BLOCK * bdb2i_idl_allids LDAP_P(( BackendDB *be )); -void bdb2i_idl_free LDAP_P(( ID_BLOCK *idl )); -ID_BLOCK * bdb2i_idl_fetch LDAP_P(( BackendDB *be, struct dbcache *db, Datum key )); -int bdb2i_idl_insert_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id )); -int bdb2i_idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids )); -int bdb2i_idl_delete_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id )); -ID_BLOCK * bdb2i_idl_intersection LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b )); -ID_BLOCK * bdb2i_idl_union LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b )); -ID_BLOCK * bdb2i_idl_notin LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b )); -ID bdb2i_idl_firstid LDAP_P(( ID_BLOCK *idl, ID *cursor )); -ID bdb2i_idl_nextid LDAP_P(( ID_BLOCK *idl, ID *cursor )); - -/* - * index.c - */ - -int bdb2i_index_add_entry LDAP_P(( BackendDB *be, Entry *e )); -int bdb2i_index_add_mods LDAP_P(( BackendDB *be, LDAPModList *ml, ID id )); -ID_BLOCK * bdb2i_index_read LDAP_P(( BackendDB *be, char *type, int indextype, char *val )); -int bdb2i_index_add_values LDAP_P(( BackendDB *be, char *type, struct berval **vals, ID id )); - -/* - * kerberos.c - */ - -#ifdef HAVE_KERBEROS -/* bdb2i_krbv4_ldap_auth LDAP_P(( BackendDB *be, struct berval *cred, AUTH_DAT *ad )); */ -#endif - -/* - * modify.c - * These prototypes are placed here because they are used by modify and - * modify rdn which are implemented in different files. - * - * We need bdb2i_back_modify_internal here because of LDAP modrdn & modify use - * it. If we do not add this, there would be a bunch of code replication - * here and there and of course the likelihood of bugs increases. - * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99 - * - */ - -int bdb2i_add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); -int bdb2i_delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); -int bdb2i_replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); -int bdb2i_back_modify_internal LDAP_P((Backend *be, Connection *conn, Operation *op, - char *dn, LDAPModList *mods, Entry *e)); -/* - * nextid.c - */ - -ID bdb2i_next_id LDAP_P(( BackendDB *be )); -void bdb2i_next_id_return LDAP_P(( BackendDB *be, ID id )); -ID bdb2i_next_id_get LDAP_P(( BackendDB *be )); -int bdb2i_next_id_save LDAP_P(( BackendDB *be )); - -/* - * startup.c - */ - -int bdb2i_back_startup LDAP_P(( BackendInfo *bi )); -int bdb2i_back_shutdown LDAP_P(( BackendInfo *bi )); -int bdb2i_back_db_startup LDAP_P(( BackendDB *be )); -int bdb2i_back_db_shutdown LDAP_P(( BackendDB *be )); - -/* - * timing.c - */ - -void bdb2i_uncond_start_timing LDAP_P(( struct timeval *time1 )); -#define bdb2i_start_timing(bi,time1) if ( with_timing( bi )) bdb2i_uncond_start_timing( (time1) ) -void bdb2i_uncond_stop_timing LDAP_P(( struct timeval time1, - char *func, Connection *conn, Operation *op, int level )); -#define bdb2i_stop_timing(bi,time1,func,conn,op) if ( with_timing( bi )) bdb2i_uncond_stop_timing( (time1), (func), (conn), (op), LDAP_DEBUG_ANY ) - -/* - * porter.c - */ - -int bdb2i_enter_backend_rw LDAP_P(( DB_LOCK *lock, int writer )); -#define bdb2i_enter_backend_r(lock) bdb2i_enter_backend_rw((lock), 0 ) -#define bdb2i_enter_backend_w(lock) bdb2i_enter_backend_rw((lock), 1 ) -int bdb2i_leave_backend_rw LDAP_P(( DB_LOCK lock, int writer )); -#define bdb2i_leave_backend_r(lock) bdb2i_leave_backend_rw((lock), 0 ) -#define bdb2i_leave_backend_w(lock) bdb2i_leave_backend_rw((lock), 1 ) - -/* - * txn.c - */ - -int bdb2i_txn_head_init LDAP_P(( BDB2_TXN_HEAD *head )); -void bdb2i_txn_attr_config LDAP_P(( - struct ldbminfo *li, - char *attr, - int open )); -int bdb2i_txn_open_files LDAP_P(( BackendDB *be )); -void bdb2i_txn_close_files LDAP_P(( BackendDB *be )); -BDB2_TXN_FILES *bdb2i_get_db_file_cache LDAP_P(( - struct ldbminfo *li, - char *name )); -int bdb2i_check_additional_attr_index LDAP_P(( struct ldbminfo *li )); -void bdb2i_check_default_attr_index_add LDAP_P(( - struct ldbminfo *li, - Entry *e )); -void bdb2i_check_default_attr_index_mod LDAP_P(( - struct ldbminfo *li, - LDAPModList *modlist )); -ID bdb2i_get_nextid LDAP_P(( BackendDB *be )); -int bdb2i_put_nextid LDAP_P(( BackendDB *be, ID id )); -LDBM bdb2i_db_open LDAP_P(( char *name, int type, int rw, int mode, - int dbcachesize )); -int bdb2i_db_store LDAP_P(( LDBM ldbm, Datum key, Datum data, int flags )); -int bdb2i_db_delete LDAP_P(( LDBM ldbm, Datum key )); -Datum bdb2i_db_fetch LDAP_P(( LDBM ldbm, Datum key )); -Datum bdb2i_db_firstkey LDAP_P(( LDBM ldbm, DBC **dbch )); -Datum bdb2i_db_nextkey LDAP_P(( LDBM ldbm, Datum key, DBC *dbcp )); -int bdb2i_start_transction LDAP_P(( DB_TXNMGR *txmgr )); -int bdb2i_finish_transaction LDAP_P(( )); -int bdb2i_set_txn_checkpoint LDAP_P(( DB_TXNMGR *txmgr, int forced )); - - -LDAP_END_DECL -#endif diff --git a/servers/slapd/back-bdb2/search.c b/servers/slapd/back-bdb2/search.c deleted file mode 100644 index 4bec697151..0000000000 --- a/servers/slapd/back-bdb2/search.c +++ /dev/null @@ -1,482 +0,0 @@ -/* search.c - bdb2 backend search function */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" -#include "proto-back-bdb2.h" - -static ID_BLOCK *base_candidate( - Backend *be, Entry *e ); - -static ID_BLOCK *search_candidates( - Backend *be, Entry *e, Filter *filter, - int scope, int deref, int manageDSAit ); - -static int -bdb2i_back_search_internal( - BackendDB *be, - Connection *conn, - Operation *op, - char *base, - int scope, - int deref, - int slimit, - int tlimit, - Filter *filter, - char *filterstr, - char **attrs, - int attrsonly -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - int rc, err; - char *text; - time_t stoptime; - ID_BLOCK *candidates; - ID id, cursor; - Entry *e; - struct berval **v2refs = NULL; - Entry *matched = NULL; - char *realbase = NULL; - int nentries = 0; - int manageDSAit = get_manageDSAit( op ); - - Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0); - - /* get entry with reader lock */ - if ( deref & LDAP_DEREF_FINDING ) { - e = deref_dn_r( be, base, &err, &matched, &text ); - - } else { - e = bdb2i_dn2entry_r( be, base, &matched ); - err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL; - text = NULL; - } - - if ( e == NULL ) { - char *matched_dn = NULL; - struct berval **refs = NULL; - - if ( matched != NULL ) { - matched_dn = ch_strdup( matched->e_dn ); - - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched ) - : NULL; - - bdb2i_cache_return_entry_r( &li->li_cache, matched ); - } else { - refs = default_referral; - } - - send_ldap_result( conn, op, err, - matched_dn, text, refs, NULL ); - - if( matched != NULL ) { - ber_bvecfree( refs ); - free( matched_dn ); - } - - return 1; - } - - if (!manageDSAit && is_entry_referral( e ) ) { - /* entry is a referral, don't allow add */ - char *matched_dn = ch_strdup( e->e_dn ); - struct berval **refs = get_entry_referrals( be, - conn, op, e ); - - bdb2i_cache_return_entry_r( &li->li_cache, e ); - - Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, - 0, 0 ); - - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); - - ber_bvecfree( refs ); - free( matched_dn ); - - return 1; - } - - if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) { - tlimit = -1; /* allow root to set no limit */ - } else { - tlimit = (tlimit > be->be_timelimit || tlimit < 1) ? - be->be_timelimit : tlimit; - stoptime = op->o_time + tlimit; - } - - if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) { - slimit = -1; /* allow root to set no limit */ - } else { - slimit = (slimit > be->be_sizelimit || slimit < 1) ? - be->be_sizelimit : slimit; - } - - if ( scope == LDAP_SCOPE_BASE) { - candidates = base_candidate( be, e ); - - } else { - candidates = search_candidates( be, e, filter, - scope, deref, manageDSAit ); - } - - /* need normalized dn below */ - realbase = ch_strdup( e->e_ndn ); - bdb2i_cache_return_entry_r( &li->li_cache, e ); - - if ( candidates == NULL ) { - /* no candidates */ - Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0, - 0, 0 ); - - send_search_result( conn, op, - LDAP_SUCCESS, - NULL, NULL, NULL, NULL, 0 ); - - rc = 1; - goto done; - } - - for ( id = bdb2i_idl_firstid( candidates, &cursor ); id != NOID; - id = bdb2i_idl_nextid( candidates, &cursor ) ) - { - int scopeok = 0; - - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - rc = 0; - goto done; - } - - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - - /* check time limit */ - if ( tlimit != -1 && slap_get_time() > stoptime ) { - send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED, - NULL, NULL, v2refs, NULL, nentries ); - rc = 0; - goto done; - } - - /* get the entry with reader lock */ - e = bdb2i_id2entry_r( be, id ); - - if ( e == NULL ) { - Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n", - id, 0, 0 ); - - goto loop_continue; - } - - if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) { - Entry *matched; - int err; - char *text; - - e = deref_entry_r( be, e, &err, &matched, &text ); - - if( e == NULL ) { - e = matched; - goto loop_continue; - } - - if( e->e_id == id ) { - /* circular loop */ - goto loop_continue; - } - - /* need to skip alias which deref into scope */ - if( scope & LDAP_SCOPE_ONELEVEL ) { - char *pdn = dn_parent( NULL, e->e_ndn ); - if ( pdn != NULL ) { - if( strcmp( pdn, realbase ) ) { - free( pdn ); - goto loop_continue; - } - free(pdn); - } - - } else if ( dn_issuffix( e->e_ndn, realbase ) ) { - /* alias is within scope */ - Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n", - e->e_dn, 0, 0 ); - goto loop_continue; - } - - scopeok = 1; - } - - /* - * if it's a referral, add it to the list of referrals. only do - * this for non-base searches, and don't check the filter - * explicitly here since it's only a candidate anyway. - */ - if ( !manageDSAit && scope != LDAP_SCOPE_BASE && - is_entry_referral( e ) ) - { - struct berval **refs = get_entry_referrals( - be, conn, op, e ); - - send_search_reference( be, conn, op, - e, refs, scope, NULL, &v2refs ); - - ber_bvecfree( refs ); - - goto loop_continue; - } - - /* if it matches the filter and scope, send it */ - if ( test_filter( be, conn, op, e, filter ) == 0 ) { - char *dn; - - /* check scope */ - if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) { - if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) { - (void) dn_normalize_case( dn ); - scopeok = (dn == realbase) - ? 1 - : (strcmp( dn, realbase ) ? 0 : 1 ); - free( dn ); - - } else { - scopeok = (realbase == NULL || *realbase == '\0'); - } - - } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) { - dn = ch_strdup( e->e_ndn ); - scopeok = dn_issuffix( dn, realbase ); - free( dn ); - - } else { - scopeok = 1; - } - - if ( scopeok ) { - /* check size limit */ - if ( --slimit == -1 ) { - bdb2i_cache_return_entry_r( &li->li_cache, e ); - send_search_result( conn, op, - LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, - v2refs, NULL, nentries ); - rc = 0; - goto done; - } - - if (e) { - switch ( send_search_entry( be, conn, op, e, - attrs, attrsonly, NULL ) ) { - case 0: /* entry sent ok */ - nentries++; - break; - case 1: /* entry not sent */ - break; - case -1: /* connection closed */ - bdb2i_cache_return_entry_r( &li->li_cache, e ); - rc = 0; - goto done; - } - } - } else { - Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n", - id, 0, 0 ); - } - } else { - Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n", - id, 0, 0 ); - } - -loop_continue: - if( e != NULL ) { - /* free reader lock */ - bdb2i_cache_return_entry_r( &li->li_cache, e ); - } - - ldap_pvt_thread_yield(); - } - send_search_result( conn, op, - v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL, - NULL, NULL, v2refs, NULL, nentries ); - - rc = 0; - -done: - bdb2i_idl_free( candidates ); - - ber_bvecfree( v2refs ); - if( realbase ) free( realbase ); - - return rc; -} - - -int -bdb2_back_search( - BackendDB *be, - Connection *conn, - Operation *op, - char *base, - int scope, - int deref, - int slimit, - int tlimit, - Filter *filter, - char *filterstr, - char **attrs, - int attrsonly -) -{ - DB_LOCK lock; - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - if ( bdb2i_enter_backend_r( &lock ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return( -1 ); - - } - - ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref, - slimit, tlimit, filter, filterstr, attrs, attrsonly ); - - (void) bdb2i_leave_backend_r( lock ); - bdb2i_stop_timing( be->bd_info, time1, "SRCH", conn, op ); - - return( ret ); -} - - -static ID_BLOCK * -base_candidate( - Backend *be, - Entry *e -) -{ - ID_BLOCK *idl; - - Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", - e->e_dn, 0, 0); - - idl = bdb2i_idl_alloc( 1 ); - bdb2i_idl_insert( &idl, e->e_id, 1 ); - - return( idl ); -} - -static ID_BLOCK * -search_candidates( - Backend *be, - Entry *e, - Filter *filter, - int scope, - int deref, - int manageDSAit -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID_BLOCK *candidates; - Filter *f, *rf, *af, *lf; - - Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n", - e->e_ndn, scope, deref ); - - f = NULL; - - if( !manageDSAit ) { - /* match referrals */ - rf = (Filter *) ch_malloc( sizeof(Filter) ); - rf->f_next = NULL; - rf->f_choice = LDAP_FILTER_OR; - rf->f_or = (Filter *) ch_malloc( sizeof(Filter) ); - rf->f_or->f_choice = LDAP_FILTER_EQUALITY; - rf->f_or->f_avtype = ch_strdup( "objectclass" ); - rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" ); - rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1; - rf->f_or->f_next = filter; - f = rf; - } else { - rf = NULL; - f = filter; - } - - if( deref & LDAP_DEREF_SEARCHING ) { - /* match aliases */ - af = (Filter *) ch_malloc( sizeof(Filter) ); - af->f_next = NULL; - af->f_choice = LDAP_FILTER_OR; - af->f_or = (Filter *) ch_malloc( sizeof(Filter) ); - af->f_or->f_choice = LDAP_FILTER_EQUALITY; - af->f_or->f_avtype = ch_strdup( "objectclass" ); - af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" ); - af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1; - af->f_or->f_next = f; - f = af; - } else { - af = NULL; - } - - if ( scope == LDAP_SCOPE_SUBTREE ) { - lf = (Filter *) ch_malloc( sizeof(Filter) ); - lf->f_next = NULL; - lf->f_choice = LDAP_FILTER_AND; - lf->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - - lf->f_and->f_choice = SLAPD_FILTER_DN_SUBTREE; - lf->f_and->f_dn = e->e_ndn; - - lf->f_and->f_next = f; - f = lf; - - } else if ( scope == LDAP_SCOPE_ONELEVEL ) { - lf = (Filter *) ch_malloc( sizeof(Filter) ); - lf->f_next = NULL; - lf->f_choice = LDAP_FILTER_AND; - lf->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - - lf->f_and->f_choice = SLAPD_FILTER_DN_ONE; - lf->f_and->f_dn = e->e_ndn; - - lf->f_and->f_next = f; - f = lf; - - } else { - lf = NULL; - } - - candidates = bdb2i_filter_candidates( be, f ); - - /* free up filter additions we allocated above */ - if( lf != NULL ) { - free( lf->f_and ); - free( lf ); - } - - if( af != NULL ) { - af->f_or->f_next = NULL; - filter_free( af ); - } - - if( rf != NULL ) { - rf->f_or->f_next = NULL; - filter_free( rf ); - } - - return( candidates ); -} diff --git a/servers/slapd/back-bdb2/startup.c b/servers/slapd/back-bdb2/startup.c deleted file mode 100644 index 3bf3b09d97..0000000000 --- a/servers/slapd/back-bdb2/startup.c +++ /dev/null @@ -1,260 +0,0 @@ -/* startup.c - startup/shutdown bdb2 backend */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_DIRECT_H -#include -#endif - -#include "slap.h" -#include "back-bdb2.h" - -#include "db.h" - -static void remove_old_locks( char *home ); - - -static void -bdb2i_db_errcall( const char *prefix, char *message ) -{ - Debug( LDAP_DEBUG_ANY, "bdb2_db_errcall(): %s %s", prefix, message, 0 ); -} - - -/* startup/shutdown per backend type */ - -static int -bdb2i_back_startup_internal( - BackendInfo *bi -) -{ - struct ldbtype *lty = (struct ldbtype *) bi->bi_private; - u_int32_t envFlags; - int err = 0; - char *home; - - /* set the flags for a full-feldged transaction schema */ - envFlags = ( DB_CREATE | DB_THREAD | DB_INIT_TXN | DB_INIT_LOG | - DB_INIT_LOCK | DB_INIT_MPOOL ); - - /* make sure, dbhome is an absolute path */ - if ( *lty->lty_dbhome != *LDAP_DIRSEP ) { - char cwd[MAXPATHLEN]; - - (void) getcwd( cwd, MAXPATHLEN ); - sprintf( cwd, "%s" LDAP_DIRSEP "%s", - cwd, lty->lty_dbhome ); - free( lty->lty_dbhome ); - lty->lty_dbhome = ch_strdup( cwd ); - - } - home = lty->lty_dbhome; - - /* general initialization of the environment */ - memset( &bdb2i_dbEnv, 0, sizeof( DB_ENV )); - bdb2i_dbEnv.db_errcall = bdb2i_db_errcall; - bdb2i_dbEnv.db_errpfx = "==>"; - - /* initialize the lock subsystem */ - bdb2i_dbEnv.lk_max = 0; - - /* remove old locking tables */ - remove_old_locks( home ); - - /* initialize the mpool subsystem */ - bdb2i_dbEnv.mp_size = lty->lty_mpsize; - - /* now do the db_appinit */ - if ( ( err = db_appinit( home, NULL, &bdb2i_dbEnv, envFlags )) ) { - char error[BUFSIZ]; - - if ( err < 0 ) sprintf( error, "%ld\n", (long) err ); - else sprintf( error, "%s\n", strerror( err )); - - Debug( LDAP_DEBUG_ANY, - "bdb2i_back_startup(): FATAL error in db_appinit() : %s\n", - error, 0, 0 ); - return( 1 ); - - } - - return 0; -} - - -static int -bdb2i_back_shutdown_internal( - BackendInfo *bi -) -{ - struct ldbtype *lty = (struct ldbtype *) bi->bi_private; - int err; - - /* remove old locking tables */ - bdb2i_dbEnv.db_errpfx = "bdb2i_back_shutdown(): lock_unlink:"; - if ( ( err = lock_unlink( NULL, 1, &bdb2i_dbEnv )) != 0 ) - Debug( LDAP_DEBUG_ANY, "bdb2i_back_shutdown(): lock_unlink: %s\n", - strerror( err ), 0, 0); - - /* remove old memory pool */ - bdb2i_dbEnv.db_errpfx = "bdb2i_back_shutdown(): memp_unlink:"; - if ( ( err = memp_unlink( NULL, 1, &bdb2i_dbEnv )) != 0 ) - Debug( LDAP_DEBUG_ANY, "bdb2i_back_shutdown(): memp_unlink: %s\n", - strerror( err ), 0, 0); - - (void) db_appexit( &bdb2i_dbEnv ); - - return( 0 ); -} - - -int -bdb2i_back_startup( - BackendInfo *bi -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( bi, &time1 ); - - ret = bdb2i_back_startup_internal( bi ); - bdb2i_stop_timing( bi, time1, "BE-START", NULL, NULL ); - - return( ret ); -} - - -int -bdb2i_back_shutdown( - BackendInfo *bi -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( bi, &time1 ); - - ret = bdb2i_back_shutdown_internal( bi ); - bdb2i_stop_timing( bi, time1, "BE-SHUTDOWN", NULL, NULL ); - - return( ret ); -} - - -/* startup/shutdown per backend database */ - -static int -bdb2i_back_db_startup_internal( - BackendDB *be -) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - /* if the data directory is not an absolute path, have it relative - to the current working directory (which should not be configured !) */ - if ( *li->li_directory != *LDAP_DIRSEP ) { - char cwd[MAXPATHLEN]; - - (void) getcwd( cwd, MAXPATHLEN ); - sprintf( cwd, "%s" LDAP_DIRSEP "%s", - cwd, li->li_directory ); - - free( li->li_directory ); - li->li_directory = ch_strdup( cwd ); - - } - - /* if there are more index files, add them to the DB file list */ - if ( bdb2i_check_additional_attr_index( li ) != 0 ) - return 1; - - /* now open all DB files */ - if ( bdb2i_txn_open_files( be ) != 0 ) - return 1; - - return 0; -} - - -static int -bdb2i_back_db_shutdown_internal( - BackendDB *be -) -{ - return 0; -} - - -int -bdb2_back_db_startup( - BackendDB *be -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_db_startup_internal( be ); - bdb2i_stop_timing( be->bd_info, time1, "DB-START", NULL, NULL ); - - return( ret ); -} - - -int -bdb2_back_db_shutdown( - BackendDB *be -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_db_shutdown_internal( be ); - bdb2i_stop_timing( be->bd_info, time1, "DB-SHUTDOWN", NULL, NULL ); - - return( ret ); -} - - -static void -remove_old_locks( char *home ) -{ - DB_ENV dbEnv; - int err; - - memset( &dbEnv, 0, sizeof( DB_ENV )); - dbEnv.db_errcall = bdb2i_db_errcall; - dbEnv.db_errpfx = "remove_old_locks(): db_appinit:"; - dbEnv.lk_max = 0; - - if ( ( err = db_appinit( home, NULL, &dbEnv, 0 )) != 0 ) - Debug( LDAP_DEBUG_ANY, "remove_old_locks(): db_appinit: %s\n", - strerror( err ), 0, 0); - - dbEnv.db_errpfx = "remove_old_locks(): lock_unlink:"; - if ( ( err = lock_unlink( NULL, 1, &dbEnv )) != 0 ) - Debug( LDAP_DEBUG_ANY, "remove_old_locks(): lock_unlink: %s\n", - strerror( err ), 0, 0); - - dbEnv.db_errpfx = "remove_old_locks(): db_appexit:"; - if ( ( err = db_appexit( &dbEnv )) != 0 ) - Debug( LDAP_DEBUG_ANY, "remove_old_locks(): db_appexit: %s\n", - strerror( err ), 0, 0); - -} - - diff --git a/servers/slapd/back-bdb2/timing.c b/servers/slapd/back-bdb2/timing.c deleted file mode 100644 index c1d6605674..0000000000 --- a/servers/slapd/back-bdb2/timing.c +++ /dev/null @@ -1,70 +0,0 @@ -/* timing.c - timing bdb2 backend */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include - -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - - -static char * -bdb2i_elapsed( struct timeval firsttime, struct timeval secondtime ) -{ - long int elapsedmicrosec, elapsedsec; - char elapsed_string[BUFSIZ]; - - elapsedsec = secondtime.tv_sec - firsttime.tv_sec; - elapsedmicrosec = secondtime.tv_usec - firsttime.tv_usec; - if(elapsedmicrosec < 0) { - elapsedmicrosec += 1000000; - elapsedsec -= 1; - } - - sprintf( elapsed_string, "%ld.%.6ld", elapsedsec, elapsedmicrosec ); - return( ch_strdup( elapsed_string )); -} - - -void -bdb2i_uncond_start_timing( - struct timeval *time1 -) -{ - gettimeofday( time1, NULL ); -} - - -void -bdb2i_uncond_stop_timing( - struct timeval time1, - char *func, - Connection *conn, - Operation *op, - int level -) -{ - struct timeval time2; - char *elapsed_time; - char buf[BUFSIZ]; - - *buf = '\0'; - - gettimeofday( &time2, NULL); - elapsed_time = bdb2i_elapsed( time1, time2 ); - - if ( conn != NULL ) sprintf( buf, "conn=%d ", conn->c_connid ); - if ( op != NULL ) sprintf( buf, "%sop=%d ", buf, op->o_opid ); - - Debug( level, "%s%s elapsed=%s\n", buf, func, elapsed_time ); - - free( elapsed_time ); - -} - - diff --git a/servers/slapd/back-bdb2/tools.c b/servers/slapd/back-bdb2/tools.c deleted file mode 100644 index 662381dfb0..0000000000 --- a/servers/slapd/back-bdb2/tools.c +++ /dev/null @@ -1,249 +0,0 @@ -/* tools.c - tools for slap tools */ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ - -#include "portable.h" - -#include - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static LDBMCursor *cursorp = NULL; -static DBCache *id2entry = NULL; - -int bdb2_tool_entry_open( - BackendDB *be, int mode ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - int flags; - - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry == NULL ); - - switch( mode ) { - case 1: - flags = LDBM_WRCREAT; - break; - case 2: -#ifdef TRUNCATE_MODE - flags = LDBM_NEWDB; -#else - flags = LDBM_WRCREAT; -#endif - break; - default: - flags = LDBM_READER; - } - - li->li_dbcachewsync = 0; - - if ( (id2entry = bdb2i_cache_open( be, "id2entry", BDB2_SUFFIX, flags )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" BDB2_SUFFIX "\n", - 0, 0, 0 ); - return( -1 ); - } - - return 0; -} - -int bdb2_tool_entry_close( - BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry != NULL ); - - bdb2i_cache_close( be, id2entry ); - li->li_dbcachewsync = 1; - id2entry = NULL; - - return 0; -} - -ID bdb2_tool_entry_first( - BackendDB *be ) -{ - Datum key; - ID id; - - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry != NULL ); - - key = ldbm_firstkey( id2entry->dbc_db, &cursorp ); - - if( key.dptr == NULL ) { - return NOID; - } - - memcpy( &id, key.dptr, key.dsize ); - - ldbm_datum_free( id2entry->dbc_db, key ); - - return id; -} - -ID bdb2_tool_entry_next( - BackendDB *be ) -{ - Datum key; - ID id; - - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry != NULL ); - - /* allow for NEXTID */ - ldbm_datum_init( key ); - - key = ldbm_nextkey( id2entry->dbc_db, key, cursorp ); - - if( key.dptr == NULL ) { - return NOID; - } - - memcpy( &id, key.dptr, key.dsize ); - - ldbm_datum_free( id2entry->dbc_db, key ); - - return id; -} - -Entry* bdb2_tool_entry_get( BackendDB *be, ID id ) -{ - Entry *e; - Datum key, data; - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry != NULL ); - - ldbm_datum_init( key ); - - key.dptr = (char *) &id; - key.dsize = sizeof(ID); - - data = bdb2i_cache_fetch( id2entry, key ); - - if ( data.dptr == NULL ) { - return NULL; - } - - e = str2entry( data.dptr ); - ldbm_datum_free( id2entry->dbc_db, data ); - - return e; -} - -ID bdb2_tool_entry_put( - BackendDB *be, - Entry *e ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - Datum key, data; - int rc, len; - - assert( slapMode & SLAP_TOOL_MODE ); - assert( id2entry != NULL ); - - if( bdb2i_next_id_get( be ) == NOID ) { - return NOID; - } - - e->e_id = li->li_nextid++; - - Debug( LDAP_DEBUG_TRACE, "=> bdb2_tool_entry_put( %ld, \"%s\" )\n", - e->e_id, e->e_dn, 0 ); - - rc = bdb2i_index_add_entry( be, e ); - - if( rc != 0 ) { - return NOID; - } - - rc = bdb2i_dn2id_add( be, e->e_ndn, e->e_id ); - - if( rc != 0 ) { - return NOID; - } - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - key.dptr = (char *) &e->e_id; - key.dsize = sizeof(ID); - - data.dptr = entry2str( e, &len ); - data.dsize = len + 1; - - /* store it */ - rc = bdb2i_cache_store( id2entry, key, data, LDBM_REPLACE ); - - if( rc != 0 ) { - (void) bdb2i_dn2id_delete( be, e->e_ndn, e->e_id ); - return NOID; - } - - return e->e_id; -} - -int bdb2_tool_index_attr( - BackendDB *be, - char* type ) -{ - static DBCache *db = NULL; - int indexmask, syntaxmask; - char * at_cn; - - assert( slapMode & SLAP_TOOL_MODE ); - - bdb2i_attr_masks( be->be_private, type, &indexmask, &syntaxmask ); - - attr_normalize( type ); - at_cn = at_canonical_name( type ); - - if ( (db = bdb2i_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_NEWDB )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= index_read NULL (could not open %s%s)\n", at_cn, - BDB2_SUFFIX, 0 ); - return 0; - } - - bdb2i_cache_close( be, db ); - - return indexmask != 0; -} - -int bdb2_tool_index_change( - BackendDB *be, - char* type, - struct berval **bv, - ID id, - int op ) -{ - assert( slapMode & SLAP_TOOL_MODE ); - - bdb2i_index_add_values( be, - type, bv, id ); - - return 0; -} - -int bdb2_tool_sync( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - assert( slapMode & SLAP_TOOL_MODE ); - - if ( li->li_nextid != NOID ) { - bdb2i_next_id_save( be ); - } - - return 0; -} diff --git a/servers/slapd/back-bdb2/txn.c b/servers/slapd/back-bdb2/txn.c deleted file mode 100644 index 2a711385d1..0000000000 --- a/servers/slapd/back-bdb2/txn.c +++ /dev/null @@ -1,825 +0,0 @@ -/* txn.c - TP support functions of the bdb2 backend */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#include "txn.h" - -/* default DB files */ -char *bdb2i_fixed_filenames[] = { - "id2entry", - "dn2id", - "objectclass", - NULL -}; - - -int -bdb2i_txn_head_init( BDB2_TXN_HEAD *head ) -{ - int dbFile; - BDB2_TXN_FILES **fileNodeH; - - /* for each fixed DB file allocate a file descriptor node and - initialize the file's name */ - fileNodeH = &head->dbFiles; - - for ( dbFile = 0; bdb2i_fixed_filenames[dbFile] != NULL; dbFile++ ) { - char fileName[MAXPATHLEN]; - - *fileNodeH = (BDB2_TXN_FILES *) ch_calloc( 1, sizeof( BDB2_TXN_FILES )); - - if ( *fileNodeH == NULL ) { - Debug( LDAP_DEBUG_ANY, "bdb2i_txn_head_init(): out of memory!\n", - 0, 0, 0 ); - return( 1 ); - } - - sprintf( fileName, "%s" BDB2_SUFFIX, bdb2i_fixed_filenames[dbFile] ); - (*fileNodeH)->dbc_name = ch_strdup( fileName ); - - fileNodeH = &(*fileNodeH)->next; - - } - - /* set defaults for checkpointing */ - head->txn_log = BDB2_TXN_CHKP_MAX_LOG; - head->txn_time = BDB2_TXN_CHKP_MAX_TIME; - - /* initialize the txn_dirty_mutex */ - ldap_pvt_thread_mutex_init( &txn_dirty_mutex ); - - return 0; -} - - -static void -bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo ) -{ - struct stat st; - char buf[MAXPATHLEN]; - - fileinfo->dbc_refcnt = 1; - - sprintf( buf, "%s" LDAP_DIRSEP "%s", - li->li_directory, fileinfo->dbc_name ); - - if ( stat( buf, &st ) == 0 ) { - fileinfo->dbc_blksize = st.st_blksize; - } else { - fileinfo->dbc_blksize = DEFAULT_BLOCKSIZE; - } - - fileinfo->dbc_maxids = ( fileinfo->dbc_blksize / sizeof( ID )) - - ID_BLOCK_IDS_OFFSET; - fileinfo->dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS / - fileinfo->dbc_maxids ) + 1; - -} - - -/* create a DB file cache entry for a specified index attribute - (if not already done); the function is called during config - file read for all index'ed attributes; if "default" index with - a non-none selection is given, this is remembered for run-time - extension of the list of index files; the function is also - called before add or modify operations to check for putative - new "default" index files; at that time, files are also opened -*/ -void -bdb2i_txn_attr_config( - struct ldbminfo *li, - char *attr, - int open ) -{ - BDB2_TXN_HEAD *head = &li->li_txn_head; - - /* the "attribute" 'default' is special */ - if ( strcasecmp( attr, "default" )) { - - /* create a new index file node, if the index is not known already */ - BDB2_TXN_FILES **fileNodeH; - char fileName[MAXPATHLEN]; - - sprintf( fileName, "%s%s", attr, BDB2_SUFFIX ); - - /* search for the end of the list or a node describing - the current attribute */ - for ( fileNodeH = &head->dbFiles; - ( *fileNodeH && strcasecmp( (*fileNodeH)->dbc_name, fileName )); - fileNodeH = &(*fileNodeH)->next ) { - - } - - /* unless we have that attribute already... */ - if ( *fileNodeH == NULL ) { - BDB2_TXN_FILES *p; - - Debug( LDAP_DEBUG_TRACE, - "bdb2i_txn_attr_config(): adding node for \"%s\"\n", - fileName, 0, 0 ); - - /* if we're out of memory, we have to see, how to exit... */ - if ( ( *fileNodeH = p = (BDB2_TXN_FILES *) - ch_calloc( 1, sizeof( BDB2_TXN_FILES )) ) == NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_txn_attr_config(): out of memory -- FATAL.\n", - 0, 0, 0 ); - - /* during configuration (no files are opened) - we can just exit, otherwise we kill ourself and - hope to shutdown cleanly... */ - if ( open ) { - pthread_kill( pthread_self(), LDAP_SIGUSR1 ); - } else { - exit( EXIT_FAILURE ); - } - } - - p->dbc_name = ch_strdup( fileName ); - - /* if requested for, we have to open the DB file */ - /* BUT NOT "objectclass", 'cause that's a default index ! */ - if ( open && strcasecmp( fileName, "objectclass" )) { - - /* re-use filename to get the complete path */ - sprintf( fileName, "%s" LDAP_DIRSEP "%s", - li->li_directory, p->dbc_name ); - - /* since we have an mpool, we should not define a cache size */ - p->dbc_db = bdb2i_db_open( fileName, DB_TYPE, - LDBM_WRCREAT, li->li_mode, 0 ); - - /* if the files could not be opened, something is wrong; - complain */ - if ( p->dbc_db == NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n", - p->dbc_name, 0, 0 ); - pthread_kill( pthread_self(), LDAP_SIGUSR1 ); - - } - - bdb2i_init_db_file_cache( li, p ); - - Debug( LDAP_DEBUG_TRACE, - "bdb2i_txn_attr_config(): NEW INDEX FILE \"%s\"\n", - p->dbc_name, 0, 0 ); - - } - } - - } else { /* it is "attribute" 'default' */ - - head->withDefIDX = BDB2_WITH_DEF_IDX; - - } -} - - -/* open the NEXTID file for read/write; if it does not exist, - create it (access to the file must be preceeded by a rewind) -*/ -static int -bdb2i_open_nextid( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - BDB2_TXN_HEAD *head = &li->li_txn_head; - LDBM db = NULL; - DB_INFO dbinfo; - char fileName[MAXPATHLEN]; - - sprintf( fileName, "%s" LDAP_DIRSEP "%s", - li->li_directory, NEXTID_NAME ); - - /* try to open the file for read and write */ - memset( &dbinfo, 0, sizeof( dbinfo )); - dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE; - dbinfo.db_malloc = ldbm_malloc; - - (void) db_open( fileName, DB_RECNO, DB_CREATE | DB_THREAD, - li->li_mode, &bdb2i_dbEnv, &dbinfo, &db ); - - if ( db == NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_open_nextid: could not open \"%s\"\n", - NEXTID_NAME, 0, 0 ); - return( -1 ); - - } - - /* the file is open for read/write */ - head->nextidFile = db; - - return( 0 ); -} - - -/* open all DB during startup of the backend (necessary due to TP) - additional files may be opened during slapd life-time due to - default indexes (must be configured in slapd.conf; - see bdb2i_txn_attr_config) - also, set the counter and timer for TP checkpointing -*/ -int -bdb2i_txn_open_files( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - BDB2_TXN_HEAD *head = &li->li_txn_head; - BDB2_TXN_FILES *dbFile; - int rc; - - for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) { - char fileName[MAXPATHLEN]; - - sprintf( fileName, "%s" LDAP_DIRSEP "%s", - li->li_directory, dbFile->dbc_name ); - - /* since we have an mpool, we should not define a cache size */ - dbFile->dbc_db = bdb2i_db_open( fileName, DB_TYPE, - LDBM_WRCREAT, li->li_mode, 0 ); - - /* if the files could not be opened, something is wrong; complain */ - if ( dbFile->dbc_db == NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n", - dbFile->dbc_name, 0, 0 ); - return( -1 ); - - } - - /* initialize the file info */ - bdb2i_init_db_file_cache( li, dbFile ); - - Debug( LDAP_DEBUG_TRACE, "bdb2i_txn_open_files(): OPEN INDEX \"%s\"\n", - dbFile->dbc_name, 0, 0 ); - - } - - rc = bdb2i_open_nextid( be ); - - txn_max_pending_log = head->txn_log; - txn_max_pending_time = head->txn_time; - - return rc; -} - - -/* close all DB files during shutdown of the backend */ -void -bdb2i_txn_close_files( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - BDB2_TXN_HEAD *head = &li->li_txn_head; - BDB2_TXN_FILES *dbFile; - - for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) { - - ldbm_close( dbFile->dbc_db ); - - } - - if ( head->nextidFile ) - ldbm_close( head->nextidFile ); - -} - - -/* get the db_cache structure associated with a specified - DB file (replaces the on-the-fly opening of files in cache_open() -*/ -BDB2_TXN_FILES * -bdb2i_get_db_file_cache( struct ldbminfo *li, char *name ) -{ - BDB2_TXN_HEAD *head = &li->li_txn_head; - BDB2_TXN_FILES *dbFile; - int dbFileNum; - - Debug( LDAP_DEBUG_TRACE, "bdb2i_get_db_file_cache(): looking for file %s\n", - name, 0, 0 ); - - for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) { - - /* we've got it */ - if ( !strcasecmp( dbFile->dbc_name, name )) return( dbFile ); - - } - - Debug( LDAP_DEBUG_ANY, - "bdb2i_get_db_file_cache(): UPS, could't find \"%s\" \n", name, 0, 0 ); - - /* ups, we couldn't find the file */ - return( NULL ); - -} - - -/* check for new attribute indexes, that might have been created - during former runs of slapd */ -/* this is called during startup of the slapd server */ -int -bdb2i_check_additional_attr_index( struct ldbminfo *li ) -{ - DIR *datadir; - struct dirent *file; - - if ( ( datadir = opendir( li->li_directory ) ) == NULL ) { - int err = errno; - - Debug( LDAP_DEBUG_ANY, - "bdb2i_check_additional_attr_index(): ERROR while opening datadir: %s\n", - strerror( err ), 0, 0 ); - return( 1 ); - - } - - for ( file = readdir( datadir ); file; file = readdir( datadir )) { - char filename[MAXPATHLEN]; - int namelen; - - strcpy( filename, file->d_name ); - namelen = strlen( filename ); - - if ( namelen > strlen( BDB2_SUFFIX )) { - - if ( !strcasecmp( filename + namelen - strlen( BDB2_SUFFIX ), - BDB2_SUFFIX )) { - - *(filename + namelen - strlen( BDB2_SUFFIX )) = '\0'; - bdb2i_txn_attr_config( li, filename, 0 ); - - Debug( LDAP_DEBUG_TRACE, "INDEX FILE: %s\n", filename, 0, 0 ); - - } - - } - - } - - closedir( datadir ); - - return 0; -} - - -/* check for the addition of new attribute indexes during add */ -/* this is called after startup of the slapd server */ -/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US - FROM ADDING ATTRIBUTES LATER ON */ -void -bdb2i_check_default_attr_index_add( struct ldbminfo *li, Entry *e ) -{ - BDB2_TXN_HEAD *head = &li->li_txn_head; - - if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) { - Attribute *ap; - - for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) { - if ( strcasecmp( ap->a_type, "objectclass" )) - bdb2i_txn_attr_config( li, ap->a_type, 1 ); - } - } -} - - -/* check for the addition of new attribute indexes during modify */ -/* this is called after startup of the slapd server */ -/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US - FROM ADDING ATTRIBUTES LATER ON */ -void -bdb2i_check_default_attr_index_mod( struct ldbminfo *li, LDAPModList *modlist ) -{ - BDB2_TXN_HEAD *head = &li->li_txn_head; - - if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) { - LDAPModList *ml; - char *default_attrs[] = { "modifytimestamp", "modifiersname", NULL }; - int attr; - - for ( ml = modlist; ml != NULL; ml = ml->ml_next ) { - LDAPMod *mod = &ml->ml_mod; - - if (( mod->mod_op & ~LDAP_MOD_BVALUES ) == LDAP_MOD_ADD ) - if ( strcasecmp( mod->mod_type, "objectclass" )) - bdb2i_txn_attr_config( li, mod->mod_type, 1 ); - } - - /* these attributes are default when modifying */ - for ( attr = 0; default_attrs[attr]; attr++ ) { - bdb2i_txn_attr_config( li, default_attrs[attr], 1 ); - } - } -} - - -/* get the next ID from the NEXTID file */ -ID -bdb2i_get_nextid( BackendDB *be ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - BDB2_TXN_HEAD *head = &li->li_txn_head; - ID id; - Datum key; - Datum data; - db_recno_t rec = NEXTID_RECNO; - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - key.data = &rec; - key.size = sizeof( rec ); - - data = bdb2i_db_fetch( head->nextidFile, key ); - if ( data.data == NULL ) { - Debug( LDAP_DEBUG_ANY, - "next_id_read: could not get nextid from \"%s\"\n", - NEXTID_NAME, 0, 0 ); - return NOID; - } - - id = atol( data.data ); - ldbm_datum_free( head->nextidFile, data ); - - if ( id < 1 ) { - Debug( LDAP_DEBUG_ANY, - "next_id_read %ld: return non-positive integer\n", - id, 0, 0 ); - return NOID; - } - - return( id ); -} - - -int -bdb2i_put_nextid( BackendDB *be, ID id ) -{ - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - BDB2_TXN_HEAD *head = &li->li_txn_head; - int rc, flags; - Datum key; - Datum data; - db_recno_t rec = NEXTID_RECNO; - char buf[20]; - - sprintf( buf, "%ld\n", id ); - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - key.data = &rec; - key.size = sizeof( rec ); - - data.data = &buf; - data.size = sizeof( buf ); - - flags = LDBM_REPLACE; - if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; - - if (( rc = bdb2i_db_store( head->nextidFile, key, data, flags )) != 0 ) { - Debug( LDAP_DEBUG_ANY, "next_id_write(%ld): store failed (%d)\n", - id, rc, 0 ); - return( -1 ); - } - - return( rc ); -} - - -/* BDB2 backend-private functions of libldbm */ -LDBM -bdb2i_db_open( - char *name, - int type, - int rw, - int mode, - int dbcachesize ) -{ - LDBM ret = NULL; - DB_INFO dbinfo; - - memset( &dbinfo, 0, sizeof( dbinfo )); - if ( bdb2i_dbEnv.mp_info == NULL ) - dbinfo.db_cachesize = dbcachesize; - dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE; - dbinfo.db_malloc = ldbm_malloc; - - (void) db_open( name, type, rw, mode, &bdb2i_dbEnv, &dbinfo, &ret ); - - return( ret ); -} - - -int -bdb2i_db_store( LDBM ldbm, Datum key, Datum data, int flags ) -{ - int rc; - - rc = (*ldbm->put)( ldbm, txnid, &key, &data, flags & ~LDBM_SYNC ); - rc = (-1 ) * rc; - - if ( txnid != NULL ) { - - /* if the store was OK, set the dirty flag, - otherwise set the abort flag */ - if ( rc == 0 ) { - - txn_dirty = 1; - - } else { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_store: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - } - - return( rc ); -} - - -int -bdb2i_db_delete( LDBM ldbm, Datum key ) -{ - int rc; - - rc = (*ldbm->del)( ldbm, txnid, &key, 0 ); - rc = (-1 ) * rc; - - if ( txnid != NULL ) { - - /* if the delete was OK, set the dirty flag, - otherwise set the abort flag */ - if ( rc == 0 ) { - - txn_dirty = 1; - - } else { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_delete: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - } - - return( rc ); -} - - -Datum -bdb2i_db_fetch( LDBM ldbm, Datum key ) -{ - Datum data; - int rc; - - ldbm_datum_init( data ); - data.flags = DB_DBT_MALLOC; - - if ( (rc = (*ldbm->get)( ldbm, txnid, &key, &data, 0 )) != 0 ) { - if (( txnid != NULL ) && ( rc != DB_NOTFOUND )) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_fetch: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - if ( data.dptr ) free( data.dptr ); - data.dptr = NULL; - data.dsize = 0; - } - - return( data ); -} - - -Datum -bdb2i_db_firstkey( LDBM ldbm, DBC **dbch ) -{ - Datum key, data; - int rc; - DBC *dbci; - - ldbm_datum_init( key ); - ldbm_datum_init( data ); - - key.flags = data.flags = DB_DBT_MALLOC; - -#if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \ - DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 - - if ( (*ldbm->cursor)( ldbm, txnid, &dbci )) - -#else - - if ( (*ldbm->cursor)( ldbm, txnid, &dbci, 0 )) - -#endif - { - if ( txnid != NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_firstkey: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - key.flags = 0; - return( key ); - } else { - *dbch = dbci; - if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) { - ldbm_datum_free( ldbm, data ); - } else { - if ( txnid != NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_firstkey: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - ldbm_datum_free( ldbm, key ); - key.flags = 0; - key.dptr = NULL; - key.dsize = 0; - } - } - - return( key ); -} - - -Datum -bdb2i_db_nextkey( LDBM ldbm, Datum key, DBC *dbcp ) -{ - Datum data; - int rc; - - ldbm_datum_init( data ); - ldbm_datum_free( ldbm, key ); - key.flags = data.flags = DB_DBT_MALLOC; - - if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) { - ldbm_datum_free( ldbm, data ); - } else { - if ( txnid != NULL ) { - - Debug( LDAP_DEBUG_ANY, - "bdb2i_db_nextkey: transaction failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - - } - key.flags = 0; - key.dptr = NULL; - key.dsize = 0; - } - - return( key ); -} - - -/* Transaction control of write access */ -/* Since these functions are only used by one writer at a time, - we do not have any concurrency (locking) problem */ - -/* initialize a new transaction */ -int -bdb2i_start_transction( DB_TXNMGR *txmgr ) -{ - int rc; - - txnid = NULL; - txn_do_abort = 0; - - if (( rc = txn_begin( txmgr, NULL, &txnid )) != 0 ) { - int err = errno; - Debug( LDAP_DEBUG_ANY, "bdb2i_start_transction failed: %d: errno=%s\n", - rc, strerror( err ), 0 ); - - if ( txnid != NULL ) - (void) txn_abort( txnid ); - return( -1 ); - } - - Debug( LDAP_DEBUG_TRACE, - "bdb2i_start_transaction: transaction started.\n", - 0, 0, 0 ); - - return( 0 ); -} - - -/* finish the transaction */ -int -bdb2i_finish_transaction() -{ - int rc = 0; - - /* if transaction was NOT selected, just return */ - if ( txnid == NULL ) return( 0 ); - - /* if nothing was wrong so far, we can try to commit the transaction */ - /* complain, if the commit fails */ - if (( txn_do_abort == 0 ) && ( txn_commit( txnid )) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "bdb2i_finish_transaction: transaction commit failed: aborted.\n", - 0, 0, 0 ); - txn_do_abort = 1; - } - - /* if anything went wrong, we have to abort the transaction */ - if ( txn_do_abort ) { - Debug( LDAP_DEBUG_ANY, - "bdb2i_finish_transaction: transaction aborted.\n", - 0, 0, 0 ); - (void) txn_abort( txnid ); - rc = -1; - } else { - Debug( LDAP_DEBUG_TRACE, - "bdb2i_finish_transaction: transaction commited.\n", - 0, 0, 0 ); - } - - /* XXX do NOT free the txnid memory !!! */ - txnid = NULL; - txn_do_abort = 0; - - return( rc ); -} - - -/* set a checkpoint - either forced (during shutdown) or when logsize or time are exceeded - (is called by reader and writer, so protect txn_dirty) -*/ -int -bdb2i_set_txn_checkpoint( DB_TXNMGR *txmgr, int forced ) -{ - int rc = 0; - - /* set dirty mutex */ - ldap_pvt_thread_mutex_lock( &txn_dirty_mutex ); - - if ( txn_dirty ) { - int rc; - u_int32_t logsize; - u_int32_t mins; - time_t now; - - logsize = forced ? (u_int32_t) 0 : txn_max_pending_log; - mins = forced ? (u_int32_t) 0 : txn_max_pending_time; - - now = slap_get_time(); - - rc = txn_checkpoint( txmgr, logsize, mins ); - - /* if checkpointing was successful, reset txn_dirty */ - if ( rc == 0 ) { - DB_TXN_STAT *statp = NULL; - - /* check whether the checkpoint was actually written; - if so, unset the txn_dirty flag */ - if (( rc = txn_stat( txmgr, &statp, ldbm_malloc )) == 0 ) { - - if ( statp && ( statp->st_time_ckp >= now )) { - - Debug( LDAP_DEBUG_TRACE, - "bdb2i_set_txn_checkpoint succeded.\n", - 0, 0, 0 ); - txn_dirty = 0; - - } - - if ( statp ) free( statp ); - - } else { - Debug( LDAP_DEBUG_ANY, - "bdb2i_set_txn_checkpoint: txn_stat failed: %d\n", - rc, 0, 0 ); - } - } else { - Debug( LDAP_DEBUG_ANY, "bdb2i_set_txn_checkpoint failed: %d\n", - rc, 0, 0 ); - } - } - - /* release dirty mutex */ - ldap_pvt_thread_mutex_unlock( &txn_dirty_mutex ); - - return( rc ); -} - - diff --git a/servers/slapd/back-bdb2/txn.h b/servers/slapd/back-bdb2/txn.h deleted file mode 100644 index 9093127ae2..0000000000 --- a/servers/slapd/back-bdb2/txn.h +++ /dev/null @@ -1,51 +0,0 @@ -/* txn.h - Header for TP support functions of the bdb2 backend */ -/* $OpenLDAP$ */ - -#ifndef _BDB2_TXN_H_ -#define _BDB2_TXN_H_ - -#include "portable.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - - - -/* the DB environment for the backend */ -DB_ENV bdb2i_dbEnv; - - -/* variables for transaction support */ -DB_TXN *txnid = NULL; -int txn_do_abort = 0; - -u_int32_t txn_max_pending_log; -u_int32_t txn_max_pending_time; -int txn_dirty = 0; -ldap_pvt_thread_mutex_t txn_dirty_mutex; - -/* defaults for checkpointing */ -#define BDB2_TXN_CHKP_MAX_LOG 2000 /* checkpoint every 2MB lock file - (approx. 20 ADD TXNs) */ -#define BDB2_TXN_CHKP_MAX_TIME 5 /* checkpoint after 5 minutes */ - - -/* the name of the file and the record number of the NEXTID datum */ -#define NEXTID_NAME "NEXTID" -#define NEXTID_RECNO (db_recno_t) 1 - - - -#endif /* _BDB2_TXN_H_ */ - diff --git a/servers/slapd/back-bdb2/unbind.c b/servers/slapd/back-bdb2/unbind.c deleted file mode 100644 index b2c179dee9..0000000000 --- a/servers/slapd/back-bdb2/unbind.c +++ /dev/null @@ -1,39 +0,0 @@ -/* unbind.c - handle an ldap unbind operation */ -/* $OpenLDAP$ */ - -#include "portable.h" - -#include -#include - -#include "slap.h" -#include "back-bdb2.h" - -static int -bdb2i_back_unbind_internal( - BackendDB *be, - Connection *conn, - Operation *op -) -{ - return( 0 ); -} - - -int -bdb2_back_unbind( - BackendDB *be, - Connection *conn, - Operation *op -) -{ - struct timeval time1; - int ret; - - bdb2i_start_timing( be->bd_info, &time1 ); - - ret = bdb2i_back_unbind_internal( be, conn, op ); - bdb2i_stop_timing( be->bd_info, time1, "UNBIND", conn, op ); - - return( ret ); -} diff --git a/servers/slapd/back-dnssrv/Makefile.in b/servers/slapd/back-dnssrv/Makefile.in new file mode 100644 index 0000000000..8849ce38a0 --- /dev/null +++ b/servers/slapd/back-dnssrv/Makefile.in @@ -0,0 +1,34 @@ +# $OpenLDAP$ +########################################################################### +# Copyright 2000, OpenLDAP Foundation, All rights reserved. +# +# Redistribution and use in source and binary forms are permitted only +# as authorized by the OpenLDAP Public License. A copy of this +# license is available at http://www.OpenLDAP.org/license.html or +# in file LICENSE in the top-level directory of the distribution. +########################################################################### +# DNSSRV backend written by Kurt Zeilenga +########################################################################## + +SRCS = init.c bind.c search.c config.c compare.c \ + modify.c add.c modrdn.c delete.c request.c +OBJS = init.lo bind.lo search.lo config.lo compare.lo \ + modify.lo add.lo modrdn.lo delete.lo request.lo + +LDAP_INCDIR= ../../../include +LDAP_LIBDIR= ../../../libraries + +BUILD_OPT = "--enable-dnssrv" +BUILD_MOD = @BUILD_DNSSRV@ +LINKAGE = @BUILD_DNSSRV_DYNAMIC@ + +LIBBASE = back_dnssrv + +XINCPATH = -I.. -I$(srcdir)/.. +XDEFS = $(MODULES_CPPFLAGS) + +all-local-lib: ../.backend + +../.backend: lib$(LIBBASE).a + @touch $@ + diff --git a/servers/slapd/back-dnssrv/add.c b/servers/slapd/back-dnssrv/add.c new file mode 100644 index 0000000000..67292e7bb7 --- /dev/null +++ b/servers/slapd/back-dnssrv/add.c @@ -0,0 +1,28 @@ +/* add.c - DNS SRV backend add function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_add( + Backend *be, + Connection *conn, + Operation *op, + Entry *e +) +{ + return dnssrv_back_request( be, conn, op, e->e_dn, e->e_ndn, + 0, NULL, NULL, 0 ); +} diff --git a/servers/slapd/back-dnssrv/back-dnssrv.h b/servers/slapd/back-dnssrv/back-dnssrv.h new file mode 100644 index 0000000000..e4a401d8c8 --- /dev/null +++ b/servers/slapd/back-dnssrv/back-dnssrv.h @@ -0,0 +1,29 @@ +/* $OpenLDAP$ */ +/* + * Copyright 2000, OpenLDAP Foundation, All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + +#ifndef DNSSRV_BACK_H +#define DNSSRV_BACK_H 1 + +#include "external.h" + +LDAP_BEGIN_DECL + +int dnssrv_result(); + +extern int dnssrv_back_request LDAP_P(( + BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn, + int scope, Filter *filter, + char **attrs, int attrsonly )); + +LDAP_END_DECL + +#endif /* DNSSRV_BACK_H */ diff --git a/servers/slapd/back-dnssrv/bind.c b/servers/slapd/back-dnssrv/bind.c new file mode 100644 index 0000000000..4739746a2e --- /dev/null +++ b/servers/slapd/back-dnssrv/bind.c @@ -0,0 +1,59 @@ +/* bind.c - DNS SRV backend bind function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_bind( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + int method, + struct berval *cred, + char **edn +) +{ + Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind %s (%d)\n", + dn == NULL ? "" : dn, + method, NULL ); + + if( method == LDAP_AUTH_SIMPLE && cred != NULL && cred->bv_len ) { + Statslog( LDAP_DEBUG_STATS, + "conn=%ld op=%d DNSSRV BIND dn=\"%s\" provided passwd\n", + op->o_connid, op->o_opid, + dn == NULL ? "" : dn , 0, 0 ); + + Debug( LDAP_DEBUG_TRACE, + "DNSSRV: BIND dn=\"%s\" provided cleartext password\n", + dn == NULL ? "" : dn, 0, 0 ); + + send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, + NULL, "you shouldn\'t send strangers your password", + NULL, NULL ); + + } else { + Debug( LDAP_DEBUG_TRACE, "DNSSRV: BIND dn=\"%s\"\n", + dn == NULL ? "" : dn, 0, 0 ); + + send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, + NULL, "anonymous bind expected", + NULL, NULL ); + } + + return 1; +} diff --git a/servers/slapd/back-dnssrv/compare.c b/servers/slapd/back-dnssrv/compare.c new file mode 100644 index 0000000000..0d1beaa936 --- /dev/null +++ b/servers/slapd/back-dnssrv/compare.c @@ -0,0 +1,30 @@ +/* compare.c - DNS SRV backend compare function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_compare( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + AttributeAssertion *ava +) +{ + return dnssrv_back_request( be, conn, op, dn, ndn, + 0, NULL, NULL, 0 ); +} diff --git a/servers/slapd/back-dnssrv/config.c b/servers/slapd/back-dnssrv/config.c new file mode 100644 index 0000000000..5aaa66f558 --- /dev/null +++ b/servers/slapd/back-dnssrv/config.c @@ -0,0 +1,43 @@ +/* config.c - DNS SRV backend configuration file routine */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_db_config( + BackendDB *be, + const char *fname, + int lineno, + int argc, + char **argv +) +{ + struct ldapinfo *li = (struct ldapinfo *) be->be_private; + char *port; + + if ( li == NULL ) { + fprintf( stderr, "%s: line %d: DNSSRV backend info is null!\n", + fname, lineno ); + return( 1 ); + } + + /* no configuration options (yet) */ + { + fprintf( stderr, +"%s: line %d: unknown directive \"%s\" in DNSSRV database definition (ignored)\n", + fname, lineno, argv[0] ); + } + return 0; +} diff --git a/servers/slapd/back-dnssrv/delete.c b/servers/slapd/back-dnssrv/delete.c new file mode 100644 index 0000000000..abcbf3fe67 --- /dev/null +++ b/servers/slapd/back-dnssrv/delete.c @@ -0,0 +1,30 @@ +/* delete.c - DNS SRV backend delete function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_delete( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn +) +{ + return dnssrv_back_request( be, conn, op, dn, ndn, + 0, NULL, NULL, 0 ); +} diff --git a/servers/slapd/back-dnssrv/external.h b/servers/slapd/back-dnssrv/external.h new file mode 100644 index 0000000000..3358a30827 --- /dev/null +++ b/servers/slapd/back-dnssrv/external.h @@ -0,0 +1,63 @@ +/* $OpenLDAP$ */ +/* + * Copyright 2000, OpenLDAP Foundation, All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ +#ifndef _DNSSRV_EXTERNAL_H +#define _DNSSRV_EXTERNAL_H + +LDAP_BEGIN_DECL + +extern int dnssrv_back_initialize LDAP_P(( BackendInfo *bi )); +extern int dnssrv_back_open LDAP_P(( BackendInfo *bi )); +extern int dnssrv_back_close LDAP_P(( BackendInfo *bi )); +extern int dnssrv_back_destroy LDAP_P(( BackendInfo *bi )); + +extern int dnssrv_back_db_init LDAP_P(( BackendDB *bd )); +extern int dnssrv_back_db_destroy LDAP_P(( BackendDB *bd )); + +extern int dnssrv_back_db_config LDAP_P(( BackendDB *bd, + const char *fname, int lineno, int argc, char **argv )); + +extern int dnssrv_back_bind LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn, int method, + struct berval *cred, char** edn )); + +extern int dnssrv_back_search LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *base, const char *nbase, + int scope, int deref, int sizelimit, int timelimit, + Filter *filter, const char *filterstr, + char **attrs, int attrsonly )); + +extern int dnssrv_back_compare LDAP_P((BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn, AttributeAssertion *ava )); + +extern int dnssrv_back_modify LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn, + Modifications *ml )); + +extern int dnssrv_back_modrdn LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn, + const char *newrdn, int deleteoldrdn, + const char *newSuperior )); + +extern int dnssrv_back_add LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, Entry *e )); + +extern int dnssrv_back_delete LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *dn, const char *ndn )); + +LDAP_END_DECL + +#endif /* _DNSSRV_EXTERNAL_H */ + diff --git a/servers/slapd/back-dnssrv/init.c b/servers/slapd/back-dnssrv/init.c new file mode 100644 index 0000000000..9a77eff1dd --- /dev/null +++ b/servers/slapd/back-dnssrv/init.c @@ -0,0 +1,122 @@ +/* init.c - initialize ldap backend */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include + +#include "slap.h" +#include "back-dnssrv.h" + +#ifdef SLAPD_DNSSRV_DYNAMIC + +int back_dnssrv_LTX_init_module(int argc, char *argv[]) { + BackendInfo bi; + + memset( &bi, '\0', sizeof(bi) ); + bi.bi_type = "dnssrv"; + bi.bi_init = dnssrv_back_initialize; + + backend_add(&bi); + return 0; +} + +#endif /* SLAPD_DNSSRV_DYNAMIC */ + +int +dnssrv_back_initialize( + BackendInfo *bi +) +{ + static char *controls[] = { + LDAP_CONTROL_MANAGEDSAIT, + NULL + }; + + bi->bi_controls = controls; + + bi->bi_open = 0; + bi->bi_config = 0; + bi->bi_close = 0; + bi->bi_destroy = 0; + + bi->bi_db_init = dnssrv_back_db_init; + bi->bi_db_config = dnssrv_back_db_config; + bi->bi_db_open = 0; + bi->bi_db_close = 0; + bi->bi_db_destroy = dnssrv_back_db_destroy; + + bi->bi_op_bind = dnssrv_back_bind; + bi->bi_op_unbind = 0; + bi->bi_op_search = dnssrv_back_search; + bi->bi_op_compare = dnssrv_back_compare; + bi->bi_op_modify = dnssrv_back_modify; + bi->bi_op_modrdn = dnssrv_back_modrdn; + bi->bi_op_add = dnssrv_back_add; + bi->bi_op_delete = dnssrv_back_delete; + bi->bi_op_abandon = 0; + + bi->bi_extended = 0; + + bi->bi_acl_group = 0; + +#ifdef HAVE_CYRUS_SASL + bi->bi_sasl_authorize = 0; + bi->bi_sasl_getsecret = 0; + bi->bi_sasl_putsecret = 0; +#endif /* HAVE_CYRUS_SASL */ + + bi->bi_connection_init = 0; + bi->bi_connection_destroy = 0; + + return 0; +} + +int +dnssrv_back_db_init( + Backend *be +) +{ +#if 0 + struct ldapinfo *li; + + li = (struct ldapinfo *) ch_calloc( 1, sizeof(struct ldapinfo) ); + ldap_pvt_thread_mutex_init( &li->conn_mutex ); + + be->be_private = li; + + return li == NULL; +#else + return 0; +#endif +} + +int +dnssrv_back_db_destroy( + Backend *be +) +{ +#if 0 + struct ldapinfo *li; + + if (be->be_private) { + li = (struct ldapinfo *)be->be_private; + if (li->host) { + free(li->host); + li->host = NULL; + } + ldap_pvt_thread_mutex_destroy( &li->conn_mutex ); + } + + free( be->be_private ); + return 0; +#else + return 0; +#endif +} diff --git a/servers/slapd/back-dnssrv/modify.c b/servers/slapd/back-dnssrv/modify.c new file mode 100644 index 0000000000..53d7c23a52 --- /dev/null +++ b/servers/slapd/back-dnssrv/modify.c @@ -0,0 +1,31 @@ +/* modify.c - DNS SRV backend modify function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_modify( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + Modifications *ml +) +{ + return dnssrv_back_request( be, conn, op, dn, ndn, + 0, NULL, NULL, 0 ); +} diff --git a/servers/slapd/back-dnssrv/modrdn.c b/servers/slapd/back-dnssrv/modrdn.c new file mode 100644 index 0000000000..c595dcbc4f --- /dev/null +++ b/servers/slapd/back-dnssrv/modrdn.c @@ -0,0 +1,32 @@ +/* modrdn.c - DNS SRV backend modrdn function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_modrdn( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + const char *newrdn, + int deleteoldrdn, + const char *newSuperior +) +{ + return dnssrv_back_request( be, conn, op, dn, ndn, + 0, NULL, NULL, 0 ); +} diff --git a/servers/slapd/back-dnssrv/request.c b/servers/slapd/back-dnssrv/request.c new file mode 100644 index 0000000000..a79f632ba5 --- /dev/null +++ b/servers/slapd/back-dnssrv/request.c @@ -0,0 +1,231 @@ +/* add.c - DNS SRV backend request handler */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_request( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + int scope, Filter *filter, + char **attrs, int attrsonly ) +{ + int i; + int rc; + char *domain = NULL; + char *hostlist = NULL; + char **hosts = NULL; + struct berval **urls = NULL; + int manageDSAit = get_manageDSAit( op ); + + if( ndn == NULL || *ndn == '\0' ) { + send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, + NULL, "operation upon null (empty) DN disallowed", + NULL, NULL ); + goto done; + } + + if( ldap_dn2domain( dn, &domain ) ) { + send_ldap_result( conn, op, LDAP_REFERRAL, + NULL, NULL, default_referral, NULL ); + goto done; + } + + Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", + dn == NULL ? "" : dn, + domain == NULL ? "" : domain, + 0 ); + + if( rc = ldap_domain2hostlist( domain, &hostlist ) ) { + Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n", + rc, 0, 0 ); + send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, + NULL, "no DNS SRV RR available for DN", NULL, NULL ); + goto done; + } + + hosts = str2charray( hostlist, " " ); + + if( hosts == NULL ) { + Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "problem processing DNS SRV records for DN", NULL, NULL ); + goto done; + } + + for( i=0; hosts[i] != NULL; i++) { + struct berval *url = ch_malloc( sizeof( struct berval ) ); + + url->bv_len = sizeof("ldap://")-1 + strlen(hosts[i]); + url->bv_val = ch_malloc( url->bv_len + 1 ); + + strcpy( url->bv_val, "ldap://" ); + strcpy( &url->bv_val[sizeof("ldap://")-1], hosts[i] ); + + if( ber_bvecadd( &urls, url ) < 0 ) { + ber_bvfree( url ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "problem processing DNS SRV records for DN", + NULL, NULL ); + goto done; + } + } + + Statslog( LDAP_DEBUG_STATS, + "conn=%ld op=%d DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", + op->o_connid, op->o_opid, op->o_protocol, dn, urls[0]->bv_val ); + + Debug( LDAP_DEBUG_TRACE, "DNSSRV: %sdn=\"%s\" -> url=\"%s\"\n", + manageDSAit ? "ManageDSAit " : "", + dn == NULL ? "" : dn, + urls[0]->bv_val ); + + if( manageDSAit ) { + char *refdn, *nrefdn; + rc = ldap_domain2dn(domain, &refdn); + + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "DNS SRV problem processing manageDSAit control", + NULL, NULL ); + goto done; + } + + nrefdn = ch_strdup( refdn ); + dn_normalize(nrefdn); + + if( strcmp( nrefdn, ndn ) != 0 ) { + /* requested dn is subordinate */ + + Debug( LDAP_DEBUG_TRACE, + "DNSSRV: dn=\"%s\" subordindate to refdn=\"%s\"\n", + dn == NULL ? "" : dn, + refdn == NULL ? "" : refdn, + NULL ); + + send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, + refdn, NULL, + NULL, NULL ); + + } else if( op->o_tag != LDAP_REQ_SEARCH ) { + send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, + dn, "DNS SRV ManageDSAIT control disallowed", + NULL, NULL ); + + } else if ( scope != LDAP_SCOPE_ONELEVEL ) { + struct berval val; + struct berval *vals[2]; + Entry *e = ch_calloc( 1, sizeof(Entry) ); + AttributeDescription *ad_objectClass + = slap_schema.si_ad_objectClass; + AttributeDescription *ad_ref = slap_schema.si_ad_ref; + e->e_dn = strdup( dn ); + e->e_ndn = strdup( ndn ); + + e->e_attrs = NULL; + e->e_private = NULL; + + vals[0] = &val; + vals[1] = NULL; + + val.bv_val = "top"; + val.bv_len = sizeof("top")-1; + attr_merge( e, ad_objectClass, vals ); + + val.bv_val = "referral"; + val.bv_len = sizeof("referral")-1; + attr_merge( e, ad_objectClass, vals ); + + val.bv_val = "extensibleObject"; + val.bv_len = sizeof("extensibleObject")-1; + attr_merge( e, ad_objectClass, vals ); + + { + AttributeDescription *ad = NULL; + const char *text; + + rc = slap_str2ad( "dc", &ad, &text ); + + if( rc == LDAP_SUCCESS ) { + char *p; + val.bv_val = ch_strdup( domain ); + + p = strchr( val.bv_val, '.' ); + + if( p == val.bv_val ) { + val.bv_val[1] = '\0'; + } else if ( p != NULL ) { + *p = '\0'; + } + + val.bv_len = strlen(val.bv_val); + attr_merge( e, ad, vals ); + + ad_free( ad, 1 ); + } + } + + { + AttributeDescription *ad = NULL; + const char *text; + + rc = slap_str2ad( "associatedDomain", &ad, &text ); + + if( rc == LDAP_SUCCESS ) { + val.bv_val = domain; + val.bv_len = strlen(domain); + attr_merge( e, ad, vals ); + + ad_free( ad, 1 ); + } + } + + attr_merge( e, ad_ref, urls ); + + rc = test_filter( be, conn, op, e, filter ); + + if( rc == LDAP_COMPARE_TRUE ) { + send_search_entry( be, conn, op, + e, attrs, attrsonly, NULL ); + } + + entry_free( e ); + + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); + + } else { + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); + } + + free( refdn ); + free( nrefdn ); + + } else { + send_ldap_result( conn, op, LDAP_REFERRAL, + NULL, "DNS SRV generated referrals", urls, NULL ); + } + +done: + if( domain != NULL ) ch_free( domain ); + if( hostlist != NULL ) ch_free( hostlist ); + if( hosts != NULL ) charray_free( hosts ); + if( urls != NULL ) ber_bvecfree( urls ); + return 0; +} diff --git a/servers/slapd/back-dnssrv/search.c b/servers/slapd/back-dnssrv/search.c new file mode 100644 index 0000000000..d9dea2e3ed --- /dev/null +++ b/servers/slapd/back-dnssrv/search.c @@ -0,0 +1,39 @@ +/* search.c - DNS SRV backend search function */ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + + +#include "portable.h" + +#include + +#include +#include +#include + +#include "slap.h" +#include "back-dnssrv.h" + +int +dnssrv_back_search( + Backend *be, + Connection *conn, + Operation *op, + const char *dn, + const char *ndn, + int scope, + int deref, + int size, + int time, + Filter *filter, + const char *filterstr, + char **attrs, + int attrsonly +) +{ + return dnssrv_back_request( be, conn, op, dn, ndn, + scope, filter, attrs, attrsonly ); +} diff --git a/servers/slapd/back-ldap/Makefile.in b/servers/slapd/back-ldap/Makefile.in index fe015081fc..99808c446e 100644 --- a/servers/slapd/back-ldap/Makefile.in +++ b/servers/slapd/back-ldap/Makefile.in @@ -1,9 +1,9 @@ # $OpenLDAP$ SRCS = init.c config.c search.c bind.c unbind.c add.c compare.c \ - delete.c modify.c modrdn.c + delete.c modify.c modrdn.c group.c OBJS = init.lo config.lo search.lo bind.lo unbind.lo add.lo compare.lo \ - delete.lo modify.lo modrdn.lo + delete.lo modify.lo modrdn.lo group.lo LDAP_INCDIR= ../../../include LDAP_LIBDIR= ../../../libraries @@ -16,7 +16,6 @@ LIBBASE = back_ldap XINCPATH = -I.. -I$(srcdir)/.. XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) all-local-lib: ../.backend diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index 2ff2b7568c..13064fd27f 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -67,7 +67,7 @@ ldap_back_add( for (i=0, a=e->e_attrs; a; i++, a=a->a_next) { attrs[i] = (LDAPMod *)ch_malloc(sizeof(LDAPMod)); attrs[i]->mod_op = LDAP_MOD_BVALUES; - attrs[i]->mod_type = a->a_type; + attrs[i]->mod_type = a->a_desc->ad_cname->bv_val; attrs[i]->mod_vals.modv_bvals = a->a_vals; } diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index f3063a8c0c..1906933ab7 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -40,9 +40,10 @@ struct ldapconn { }; struct ldapinfo { - char *host; - int port; + char *url; char *suffix; + char *binddn; + char *bindpw; ldap_pvt_thread_mutex_t conn_mutex; struct ldapconn *lcs; }; diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 45f9df5c1e..705203d275 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -37,9 +37,9 @@ ldap_back_bind( Backend *be, Connection *conn, Operation *op, - char *dn, + const char *dn, + const char *ndn, int method, - char *mech, struct berval *cred, char **edn ) @@ -74,9 +74,8 @@ ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op) /* Looks like we didn't get a bind. Open a new session... */ if (!lc) { - ld = ldap_init(li->host, li->port); - if (!ld) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + if (ldap_initialize(&ld, li->url) != LDAP_SUCCESS) { + send_ldap_result( conn, op, LDAP_OTHER, NULL, "ldap_init failed", NULL, NULL ); return( NULL ); } diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index 206437d432..3cade31ce9 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -37,8 +37,9 @@ ldap_back_compare( Backend *be, Connection *conn, Operation *op, - char *dn, - Ava *ava + const char *dn, + const char *ndn, + AttributeAssertion *ava ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; @@ -54,6 +55,6 @@ ldap_back_compare( return( -1 ); } - ldap_compare_s( lc->ld, dn, ava->ava_type, ava->ava_value.bv_val ); + ldap_compare_s( lc->ld, dn, ava->aa_desc->ad_cname->bv_val, ava->aa_value->bv_val ); return( ldap_back_op_result( lc, op ) ); } diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 6326116f73..8321980c58 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -42,7 +42,6 @@ ldap_back_db_config( ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; - char *port; if ( li == NULL ) { fprintf( stderr, "%s: line %d: ldap backend info is null!\n", @@ -50,7 +49,7 @@ ldap_back_db_config( return( 1 ); } - /* server address to query */ + /* server address to query (depricated, use "uri" directive) */ if ( strcasecmp( argv[0], "server" ) == 0 ) { if (argc != 2) { fprintf( stderr, @@ -58,12 +57,47 @@ ldap_back_db_config( fname, lineno ); return( 1 ); } - port=strchr(argv[1],':'); - if (port) { - *port++ = '\0'; - li->port = atoi(port); + if (li->url != NULL) + ch_free(li->url); + li->url = ch_calloc(strlen(argv[1]) + 9, sizeof(char)); + if (li->url != NULL) { + strcpy(li->url, "ldap://"); + strcat(li->url, argv[1]); + strcat(li->url, "/"); } - li->host = ch_strdup(argv[1]); + + /* URI of server to query (preferred over "server" directive) */ + } else if ( strcasecmp( argv[0], "uri" ) == 0 ) { + if (argc != 2) { + fprintf( stderr, + "%s: line %d: missing address in \"uri
\" line\n", + fname, lineno ); + return( 1 ); + } + if (li->url != NULL) + ch_free(li->url); + li->url = ch_strdup(argv[1]); + + /* name to use for ldap_back_group */ + } else if ( strcasecmp( argv[0], "binddn" ) == 0 ) { + if (argc != 2) { + fprintf( stderr, + "%s: line %d: missing name in \"binddn \" line\n", + fname, lineno ); + return( 1 ); + } + li->binddn = ch_strdup(argv[1]); + + /* password to use for ldap_back_group */ + } else if ( strcasecmp( argv[0], "bindpw" ) == 0 ) { + if (argc != 2) { + fprintf( stderr, + "%s: line %d: missing password in \"bindpw \" line\n", + fname, lineno ); + return( 1 ); + } + li->bindpw = ch_strdup(argv[1]); + /* anything else */ } else { fprintf( stderr, diff --git a/servers/slapd/back-ldap/delete.c b/servers/slapd/back-ldap/delete.c index b5e00cc2bb..f2554ba30e 100644 --- a/servers/slapd/back-ldap/delete.c +++ b/servers/slapd/back-ldap/delete.c @@ -37,7 +37,8 @@ ldap_back_delete( Backend *be, Connection *conn, Operation *op, - char *dn + const char *dn, + const char *ndn ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; diff --git a/servers/slapd/back-ldap/external.h b/servers/slapd/back-ldap/external.h index 58b5e77a07..46c39edcac 100644 --- a/servers/slapd/back-ldap/external.h +++ b/servers/slapd/back-ldap/external.h @@ -17,7 +17,7 @@ extern int ldap_back_db_config LDAP_P(( BackendDB *bd, extern int ldap_back_bind LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, int method, char* mech, + const char *dn, const char *ndn, int method, struct berval *cred, char** edn )); extern int ldap_back_conn_destroy LDAP_P(( BackendDB *bd, @@ -25,31 +25,43 @@ extern int ldap_back_conn_destroy LDAP_P(( BackendDB *bd, extern int ldap_back_search LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter *filter, char *filterstr, char **attrs, int attrsonly )); + const char *base, const char *nbase, + int scope, int deref, int sizelimit, int timelimit, + Filter *filter, const char *filterstr, + char **attrs, int attrsonly )); -extern int ldap_back_compare LDAP_P((BackendDB *bd, +extern int ldap_back_compare LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, Ava *ava )); + const char *dn, const char *ndn, + AttributeAssertion *ava )); extern int ldap_back_modify LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, LDAPModList *ml )); + const char *dn, const char *ndn, Modifications *ml )); extern int ldap_back_modrdn LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, char*newrdn, int deleteoldrdn, - char *newSuperior )); + const char *dn, const char *ndn, + const char *newrdn, int deleteoldrdn, + const char *newSuperior )); extern int ldap_back_add LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, Entry *e )); extern int ldap_back_delete LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, char *dn )); + Connection *conn, Operation *op, + const char *dn, const char *ndn )); extern int ldap_back_abandon LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, int msgid )); +extern int ldap_back_group LDAP_P(( BackendDB *bd, + Entry *target, + const char* gr_ndn, + const char* op_ndn, + ObjectClass* group_oc, + AttributeDescription* group_at)); + LDAP_END_DECL #endif /* _LDAP_EXTERNAL_H */ diff --git a/servers/slapd/back-ldap/group.c b/servers/slapd/back-ldap/group.c new file mode 100644 index 0000000000..0864ad4d67 --- /dev/null +++ b/servers/slapd/back-ldap/group.c @@ -0,0 +1,109 @@ +/* group.c - ldap backend acl group routine */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-ldap.h" + + +/* return 0 IFF op_dn is a value in member attribute + * of entry with gr_dn AND that entry has an objectClass + * value of groupOfNames + */ +int +ldap_back_group( + Backend *be, + Entry *target, + const char *gr_ndn, + const char *op_ndn, + ObjectClass* group_oc, + AttributeDescription* group_at +) +{ + struct ldapinfo *li = (struct ldapinfo *) be->be_private; + int rc = 1; + Attribute *attr; + Entry *e; + struct berval bv; + LDAPMessage *result; + char *gattr[2]; + char *filter; + LDAP *ld; + + AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; + const char *group_oc_name = NULL; + const char *group_at_name = group_at->ad_cname->bv_val; + + if( group_oc->soc_names && group_oc->soc_names[0] ) { + group_oc_name = group_oc->soc_names[0]; + } else { + group_oc_name = group_oc->soc_oid; + } + + if (target != NULL && strcmp(target->e_ndn, gr_ndn) == 0) { + /* we already have a copy of the entry */ + e = target; + + if( is_entry_objectclass( e, group_oc ) ) { + return(1); + } + + if ((attr = attr_find(e->e_attrs, group_at)) == NULL) + return(1); + + bv.bv_val = (char *) op_ndn; + bv.bv_len = strlen( op_ndn ); + if( value_find( group_at, attr->a_vals, &bv ) == 0 ) + return(1); + + } else { + filter = ch_malloc(sizeof("(&(objectclass=)(=))") + + strlen(group_oc_name) + + strlen(group_at_name) + + strlen(op_ndn) + 1); + if (filter == NULL) + return(1); + + if (ldap_initialize(&ld, li->url) != LDAP_SUCCESS) { + ch_free(filter); + return(1); + } + + if (ldap_bind_s(ld, li->binddn, li->bindpw, LDAP_AUTH_SIMPLE) == LDAP_SUCCESS) { + strcpy(filter, "(&(objectclass="); + strcat(filter, group_oc_name); + strcat(filter, ")("); + strcat(filter, group_at_name); + strcat(filter, "="); + strcat(filter, op_ndn); + strcat(filter, "))"); + + gattr[0] = "objectclass"; + gattr[1] = NULL; + if (ldap_search_ext_s(ld, gr_ndn, LDAP_SCOPE_BASE, filter, + gattr, 0, NULL, NULL, LDAP_NO_LIMIT, + LDAP_NO_LIMIT, &result) == LDAP_SUCCESS) + { + if (ldap_first_entry(ld, result) != NULL) + rc = 0; + ldap_msgfree(result); + } + } + ldap_unbind(ld); + ch_free(filter); + return(rc); + } + + return(0); +} + diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index e1d80f76e6..98d9191ec3 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -36,7 +36,7 @@ int back_ldap_LTX_init_module(int argc, char *argv[]) { BackendInfo bi; - memset( &bi, 0, sizeof(bi) ); + memset( &bi, '\0', sizeof(bi) ); bi.bi_type = "ldap"; bi.bi_init = ldap_back_initialize; @@ -72,7 +72,15 @@ ldap_back_initialize( bi->bi_op_delete = ldap_back_delete; bi->bi_op_abandon = 0; - bi->bi_acl_group = 0; + bi->bi_extended = 0; + + bi->bi_acl_group = ldap_back_group; + +#ifdef HAVE_CYRUS_SASL + bi->bi_sasl_authorize = 0; + bi->bi_sasl_getsecret = 0; + bi->bi_sasl_putsecret = 0; +#endif /* HAVE_CYRUS_SASL */ bi->bi_connection_init = 0; bi->bi_connection_destroy = ldap_back_conn_destroy; @@ -104,9 +112,17 @@ ldap_back_db_destroy( if (be->be_private) { li = (struct ldapinfo *)be->be_private; - if (li->host) { - free(li->host); - li->host = NULL; + if (li->url) { + free(li->url); + li->url = NULL; + } + if (li->binddn) { + free(li->binddn); + li->binddn = NULL; + } + if (li->bindpw) { + free(li->bindpw); + li->bindpw = NULL; } ldap_pvt_thread_mutex_destroy( &li->conn_mutex ); } diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index c1b7df0337..f76e75f7a6 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -37,14 +37,16 @@ ldap_back_modify( Backend *be, Connection *conn, Operation *op, - char *dn, - LDAPModList *ml + const char *dn, + const char *ndn, + Modifications *modlist ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; struct ldapconn *lc; - LDAPMod **mods; - LDAPModList *m; + LDAPMod **modv; + LDAPMod *mods; + Modifications *ml; int i; lc = ldap_back_getconn(li, conn, op); @@ -57,15 +59,29 @@ ldap_back_modify( return( -1 ); } - for (i=1, m=ml->ml_next; m; i++,m=m->ml_next) + for (i=0, ml=modlist; ml; i++,ml=ml->sml_next) ; - mods = (LDAPMod **)ch_malloc((i+1)*sizeof(LDAPMod *)); - mods[i] = 0; - for (i=0, m=ml; m; i++, m=m->ml_next) - mods[i] = &m->ml_mod; + mods = (LDAPMod *)ch_malloc(i*sizeof(LDAPMod)); + if (mods == NULL) + return( -1 ); + modv = (LDAPMod **)ch_malloc((i+1)*sizeof(LDAPMod *)); + if (modv == NULL) { + free(mods); + return( -1 ); + } + + modv[i] = 0; + + for (i=0, ml=modlist; ml; i++, ml=ml->sml_next) { + modv[i] = &mods[i]; + mods[i].mod_op = ml->sml_op; + mods[i].mod_type = ml->sml_desc->ad_cname->bv_val; + mods[i].mod_bvalues = ml->sml_bvalues; + } - ldap_modify_s( lc->ld, dn, mods ); + ldap_modify_s( lc->ld, dn, modv ); free(mods); + free(modv); return( ldap_back_op_result( lc, op )); } diff --git a/servers/slapd/back-ldap/modrdn.c b/servers/slapd/back-ldap/modrdn.c index b2c4cecd3b..167c22cb75 100644 --- a/servers/slapd/back-ldap/modrdn.c +++ b/servers/slapd/back-ldap/modrdn.c @@ -37,10 +37,11 @@ ldap_back_modrdn( Backend *be, Connection *conn, Operation *op, - char *dn, - char *newrdn, + const char *dn, + const char *ndn, + const char *newrdn, int deleteoldrdn, - char *newSuperior + const char *newSuperior ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; @@ -61,6 +62,6 @@ ldap_back_modrdn( return( -1 ); } - ldap_rename2_s( lc->ld, dn, newrdn, deleteoldrdn, newSuperior ); + ldap_rename2_s( lc->ld, dn, newrdn, newSuperior, deleteoldrdn ); return( ldap_back_op_result( lc, op ) ); } diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 8eb4a31f0b..5f0c5803f4 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -41,13 +41,14 @@ ldap_back_search( Backend *be, Connection *conn, Operation *op, - char *base, + const char *base, + const char *nbase, int scope, int deref, int size, int time, Filter *filter, - char *filterstr, + const char *filterstr, char **attrs, int attrsonly ) @@ -144,21 +145,25 @@ ldap_send_entry( BerElement *ber = NULL; Attribute *attr, **attrp; struct berval *dummy = NULL; + const char *text; ent.e_dn = ldap_get_dn(lc->ld, e); ent.e_ndn = ch_strdup( ent.e_dn); - (void) dn_normalize_case( ent.e_ndn ); + (void) dn_normalize( ent.e_ndn ); ent.e_id = 0; ent.e_attrs = 0; ent.e_private = 0; attrp = &ent.e_attrs; - for (a = ldap_first_attribute(lc->ld, e, &ber); a; - a = ldap_next_attribute(lc->ld, e, ber)) { + for ( a = ldap_first_attribute(lc->ld, e, &ber); + a != NULL; + a = ldap_next_attribute(lc->ld, e, ber)) + { attr = (Attribute *)ch_malloc( sizeof(Attribute) ); + if (attr == NULL) + continue; attr->a_next = 0; - attr->a_type = ch_strdup(a); - attr->a_syntax = attr_syntax(a); + slap_str2ad(a, &attr->a_desc, &text); attr->a_vals = ldap_get_values_len(lc->ld, e, a); if (!attr->a_vals) attr->a_vals = &dummy; @@ -169,7 +174,7 @@ ldap_send_entry( for (;ent.e_attrs;) { attr=ent.e_attrs; ent.e_attrs = attr->a_next; - free(attr->a_type); + ad_free(attr->a_desc, 1); if (attr->a_vals != &dummy) ber_bvecfree(attr->a_vals); free(attr); diff --git a/servers/slapd/back-ldap/unbind.c b/servers/slapd/back-ldap/unbind.c index ac1adcb740..63519bbc98 100644 --- a/servers/slapd/back-ldap/unbind.c +++ b/servers/slapd/back-ldap/unbind.c @@ -51,8 +51,7 @@ ldap_back_conn_destroy( ldap_pvt_thread_mutex_unlock( &li->conn_mutex ); if (lc) { - if (lc->bound) - ldap_unbind(lc->ld); + ldap_unbind(lc->ld); free(lc); } diff --git a/servers/slapd/back-ldbm/Makefile.in b/servers/slapd/back-ldbm/Makefile.in index d6ce016904..8acb89f9e7 100644 --- a/servers/slapd/back-ldbm/Makefile.in +++ b/servers/slapd/back-ldbm/Makefile.in @@ -3,11 +3,13 @@ SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c id2entry.c \ index.c id2children.c nextid.c abandon.c compare.c group.c \ modify.c modrdn.c delete.c init.c config.c bind.c attr.c \ - filterindex.c unbind.c kerberos.c close.c alias.c tools.c + filterindex.c unbind.c close.c alias.c tools.c key.c \ + extended.c passwd.c sasl.c OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \ index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \ modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \ - filterindex.lo unbind.lo kerberos.lo close.lo alias.lo tools.lo + filterindex.lo unbind.lo close.lo alias.lo tools.lo key.lo \ + extended.lo passwd.lo sasl.lo LDAP_INCDIR= ../../../include LDAP_LIBDIR= ../../../libraries @@ -16,11 +18,21 @@ BUILD_OPT = "--enable-ldbm" BUILD_MOD = @BUILD_LDBM@ LINKAGE = @BUILD_LDBM_DYNAMIC@ +DYN_DEFS = -DLIBLBER_DECL=dllimport -DLIBLDAP_DECL=dllimport + +# TODO +#NT_mod_DYN_MODDEFS = +#NT_mod_STAT_MODDEFS = + +NT_yes_DYN_MODDEFS = $(DYN_DEFS) +NT_yes_STAT_MODDEFS = + +MODDEFS = $(@PLAT@_@BUILD_LDBM@_@LIB_LINKAGE@_MODDEFS) + LIBBASE = back_ldbm XINCPATH = -I.. -I$(srcdir)/.. XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) all-local-lib: ../.backend diff --git a/servers/slapd/back-ldbm/abandon.c b/servers/slapd/back-ldbm/abandon.c index 27ace1a927..a89dea223a 100644 --- a/servers/slapd/back-ldbm/abandon.c +++ b/servers/slapd/back-ldbm/abandon.c @@ -1,7 +1,7 @@ /* abandon.c - ldbm backend abandon routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index edeaf57a10..1577c74bed 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -1,7 +1,7 @@ /* add.c - ldap ldbm back-end add routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -29,6 +29,9 @@ ldbm_back_add( Entry *p = NULL; int rootlock = 0; int rc; + const char *text = NULL; + AttributeDescription *children = slap_schema.si_ad_children; + Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0); @@ -37,21 +40,21 @@ ldbm_back_add( if ( ( dn2id( be, e->e_ndn ) ) != NOID ) { ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - entry_free( e ); send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL, NULL ); return( -1 ); } - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + rc = entry_schema_check( e, NULL, &text ); + + if ( rc != LDAP_SUCCESS ) { ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", - 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "entry failed schema check: %s\n", + text, 0, 0 ); - entry_free( e ); - send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); return( -1 ); } @@ -98,7 +101,6 @@ ldbm_back_add( free( matched_dn ); } - entry_free( e ); free( pdn ); return -1; } @@ -109,18 +111,17 @@ ldbm_back_add( free(pdn); if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) + children, NULL, ACL_WRITE ) ) { /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); - Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, + Debug( LDAP_DEBUG_TRACE, "no write access to parent\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); + NULL, "no write access to parent", NULL, NULL ); - entry_free( e ); return -1; } @@ -134,9 +135,8 @@ ldbm_back_add( 0, 0 ); send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, - NULL, NULL, NULL, NULL ); + NULL, "parent is an alias", NULL, NULL ); - entry_free( e ); return -1; } @@ -157,7 +157,6 @@ ldbm_back_add( ber_bvecfree( refs ); free( matched_dn ); - entry_free( e ); return -1; } @@ -178,7 +177,6 @@ ldbm_back_add( send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); - entry_free( e ); return -1; } @@ -212,29 +210,21 @@ ldbm_back_add( Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, 0 ); - /* free the entry */ - entry_free( e ); - send_ldap_result( conn, op, - rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER, + NULL, rc > 0 ? NULL : "cache add failed", NULL, NULL ); return( -1 ); } rc = -1; - /* - * Add the entry to the attribute indexes, then add it to - * the id2children index, dn2id index, and the id2entry index. - */ - /* attribute indexes */ - if ( index_add_entry( be, e ) != 0 ) { - Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0, + if ( index_entry_add( be, e, e->e_attrs ) != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "index generation failed", NULL, NULL ); goto return_results; } @@ -243,8 +233,8 @@ ldbm_back_add( if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "DN index generation failed", NULL, NULL ); goto return_results; } @@ -254,8 +244,8 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0, 0, 0 ); (void) dn2id_delete( be, e->e_ndn, e->e_id ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "entry store failed", NULL, NULL ); goto return_results; } diff --git a/servers/slapd/back-ldbm/alias.c b/servers/slapd/back-ldbm/alias.c index ccc68804e3..fb7256c5ef 100644 --- a/servers/slapd/back-ldbm/alias.c +++ b/servers/slapd/back-ldbm/alias.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -17,25 +17,26 @@ static char* get_alias_dn( Entry *e, int *err, - char **errmsg ); + const char **errmsg ); static char* new_superior( - char *dn, - char *oldSup, - char *newSup ); + const char *dn, + const char *oldSup, + const char *newSup ); static int dnlist_subordinate( char** dnlist, - char *dn ); + const char *dn ); Entry *deref_internal_r( Backend* be, Entry* alias, - char* dn, + const char* dn_in, int* err, Entry** matched, - char** text ) + const char** text ) { + char *dn; struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *entry; Entry *sup; @@ -49,7 +50,7 @@ Entry *deref_internal_r( *text = NULL; if( alias == NULL ) { - dn = ch_strdup( dn ); + dn = ch_strdup( dn_in ); entry = dn2entry_r( be, dn, &sup ); } else { @@ -205,6 +206,7 @@ Entry *deref_internal_r( } free( dn ); + charray_free( dnlist ); return entry; } @@ -212,9 +214,12 @@ Entry *deref_internal_r( static char* get_alias_dn( Entry *e, int *err, - char **errmsg ) + const char **errmsg ) { - Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" ); + Attribute *a; + AttributeDescription *aliasedObjectName = slap_schema.si_ad_aliasedObjectName; + + a = attr_find( e->e_attrs, aliasedObjectName ); if( a == NULL ) { /* @@ -247,9 +252,9 @@ static char* get_alias_dn( } char* new_superior( - char *dn, - char *oldSup, - char *newSup ) + const char *dn, + const char *oldSup, + const char *newSup ) { char *newDN; size_t dnlen, olen, nlen; @@ -270,7 +275,7 @@ char* new_superior( static int dnlist_subordinate( char** dnlist, - char *dn ) + const char *dn ) { int i; assert( dnlist ); diff --git a/servers/slapd/back-ldbm/attr.c b/servers/slapd/back-ldbm/attr.c index 37a5cf94b3..9eb492000d 100644 --- a/servers/slapd/back-ldbm/attr.c +++ b/servers/slapd/back-ldbm/attr.c @@ -1,7 +1,7 @@ /* attr.c - backend routines for dealing with attributes */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -15,13 +15,32 @@ #include "slap.h" #include "back-ldbm.h" + +/* for the cache of attribute information (which are indexed, etc.) */ +typedef struct ldbm_attrinfo { +#ifdef SLAPD_USE_AD + AttributeDescription *ai_desc; /* attribute description cn;lang-en */ +#else + char *ai_desc; +#endif + slap_index ai_indexmask; /* how the attr is indexed */ +} AttrInfo; + static int ainfo_type_cmp( - char *type, +#ifdef SLAPD_USE_AD + AttributeDescription *desc, +#else + char *desc, +#endif AttrInfo *a ) { - return( strcasecmp( type, a->ai_type ) ); +#ifdef SLAPD_USE_AD + return ad_cmp( desc, a->ai_desc ); +#else + return( strcasecmp( desc, a->ai_desc ) ); +#endif } static int @@ -30,146 +49,186 @@ ainfo_cmp( AttrInfo *b ) { - return( strcasecmp( a->ai_type, b->ai_type ) ); -} - -/* - * Called when a duplicate "index" line is encountered. - * - * returns 1 => original from init code, indexmask updated - * 2 => original not from init code, warn the user - */ - -static int -ainfo_dup( - AttrInfo *a, - AttrInfo *b -) -{ - /* - * if the duplicate definition is because we initialized the attr, - * just add what came from the config file. otherwise, complain. - */ - if ( a->ai_indexmask & INDEX_FROMINIT ) { - a->ai_indexmask |= b->ai_indexmask; - - return( 1 ); - } - - return( 2 ); +#ifdef SLAPD_USE_AD + return ad_cmp( a->ai_desc, b->ai_desc ); +#else + return( strcasecmp( a->ai_desc, b->ai_desc ) ); +#endif } void -attr_masks( +attr_mask( struct ldbminfo *li, - char *type, - int *indexmask, - int *syntaxmask -) +#ifdef SLAPD_USE_AD + AttributeDescription *desc, +#else + const char *desc, +#endif + slap_index *indexmask ) { AttrInfo *a; - *indexmask = 0; - *syntaxmask = 0; - if ( (a = (AttrInfo *) avl_find( li->li_attrs, type, - (AVL_CMP) ainfo_type_cmp )) == NULL ) { - if ( (a = (AttrInfo *) avl_find( li->li_attrs, "default", - (AVL_CMP) ainfo_type_cmp )) == NULL ) { - return; - } - } - *indexmask = a->ai_indexmask; - if ( strcasecmp( a->ai_type, "default" ) == 0 ) { - *syntaxmask = attr_syntax( type ); - } else { - *syntaxmask = a->ai_syntaxmask; - } + a = (AttrInfo *) avl_find( li->li_attrs, desc, + (AVL_CMP) ainfo_type_cmp ); + + *indexmask = a != NULL ? a->ai_indexmask : 0; } -void +int attr_index_config( struct ldbminfo *li, const char *fname, int lineno, int argc, - char **argv, - int init -) + char **argv ) { - int i, j; - char **attrs, **indexes; - AttrInfo *a; + int rc; + int i; + slap_index mask; + char **attrs; + char **indexes = NULL; attrs = str2charray( argv[0], "," ); + + if( attrs == NULL ) { + fprintf( stderr, "%s: line %d: " + "no attributes specified: %s\n", + fname, lineno, argv[0] ); + return LDAP_PARAM_ERROR; + } + if ( argc > 1 ) { indexes = str2charray( argv[1], "," ); + + if( indexes == NULL ) { + fprintf( stderr, "%s: line %d: " + "no indexes specified: %s\n", + fname, lineno, argv[1] ); + return LDAP_PARAM_ERROR; + } } + + if( indexes == NULL ) { + mask = li->li_defaultmask; + + } else { + mask = 0; + + for ( i = 0; indexes[i] != NULL; i++ ) { + slap_index index; + rc = slap_str2index( indexes[i], &index ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: line %d: " + "index type \"%s\" undefined\n", + fname, lineno, indexes[i] ); + return LDAP_PARAM_ERROR; + } + + mask |= index; + } + } + + if( !mask ) { + fprintf( stderr, "%s: line %d: " + "no indexes selected\n", + fname, lineno ); + return LDAP_PARAM_ERROR; + } + for ( i = 0; attrs[i] != NULL; i++ ) { + AttrInfo *a; + AttributeDescription *ad; + const char *text; + + if( strcasecmp( attrs[i], "default" ) == 0 ) { + li->li_defaultmask = mask; + continue; + } + a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) ); - a->ai_type = ch_strdup( attrs[i] ); - a->ai_syntaxmask = attr_syntax( a->ai_type ); - if ( argc == 1 ) { - a->ai_indexmask = (INDEX_PRESENCE | INDEX_EQUALITY | - INDEX_APPROX | INDEX_SUB); - } else { - a->ai_indexmask = 0; - for ( j = 0; indexes[j] != NULL; j++ ) { - if ( strncasecmp( indexes[j], "pres", 4 ) - == 0 ) { - a->ai_indexmask |= INDEX_PRESENCE; - } else if ( strncasecmp( indexes[j], "eq", 2 ) - == 0 ) { - a->ai_indexmask |= INDEX_EQUALITY; - } else if ( strncasecmp( indexes[j], "approx", - 6 ) == 0 ) { - a->ai_indexmask |= INDEX_APPROX; - } else if ( strncasecmp( indexes[j], "sub", 3 ) - == 0 ) { - a->ai_indexmask |= INDEX_SUB; - } else if ( strncasecmp( indexes[j], "none", 4 ) - == 0 ) { - if ( a->ai_indexmask != 0 ) { - fprintf( stderr, -"%s: line %d: index type \"none\" cannot be combined with other types\n", - fname, lineno ); - } - a->ai_indexmask = 0; - } else { - fprintf( stderr, - "%s: line %d: unknown index type \"%s\" (ignored)\n", - fname, lineno, indexes[j] ); - fprintf( stderr, - "valid index types are \"pres\", \"eq\", \"approx\", or \"sub\"\n" ); - } - } + + ad = NULL; + rc = slap_str2ad( attrs[i], &ad, &text ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: line %d: " + "index attribute \"%s\" undefined\n", + fname, lineno, attrs[i] ); + return rc; + } + + if( slap_ad_is_binary( ad ) ) { + fprintf( stderr, "%s: line %d: " + "index of attribute \"%s\" disallowed\n", + fname, lineno, attrs[i] ); + return LDAP_UNWILLING_TO_PERFORM; + } + + if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !( + ( ad->ad_type->sat_approx + && ad->ad_type->sat_approx->smr_indexer + && ad->ad_type->sat_approx->smr_filter ) + && ( ad->ad_type->sat_equality + && ad->ad_type->sat_equality->smr_indexer + && ad->ad_type->sat_equality->smr_filter ) ) ) + { + fprintf( stderr, "%s: line %d: " + "approx index of attribute \"%s\" disallowed\n", + fname, lineno, attrs[i] ); + return LDAP_INAPPROPRIATE_MATCHING; } - if ( init ) { - a->ai_indexmask |= INDEX_FROMINIT; + + if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !( + ad->ad_type->sat_equality + && ad->ad_type->sat_equality->smr_indexer + && ad->ad_type->sat_equality->smr_filter ) ) + { + fprintf( stderr, "%s: line %d: " + "equality index of attribute \"%s\" disallowed\n", + fname, lineno, attrs[i] ); + return LDAP_INAPPROPRIATE_MATCHING; } - switch (avl_insert( &li->li_attrs, (caddr_t) a, - (AVL_CMP) ainfo_cmp, (AVL_DUP) ainfo_dup )) + if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !( + ad->ad_type->sat_substr + && ad->ad_type->sat_substr->smr_indexer + && ad->ad_type->sat_substr->smr_filter ) ) { - case 1: /* duplicate - updating init version */ - free( a->ai_type ); - free( (char *) a ); - break; - - case 2: /* user duplicate - ignore and warn */ - fprintf( stderr, - "%s: line %d: duplicate index definition for attr \"%s\" (ignored)\n", - fname, lineno, a->ai_type ); - free( a->ai_type ); - free( (char *) a ); - break; - - default:; /* inserted ok */ - /* FALL */ + fprintf( stderr, "%s: line %d: " + "substr index of attribute \"%s\" disallowed\n", + fname, lineno, attrs[i] ); + return LDAP_INAPPROPRIATE_MATCHING; + } + + Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04x\n", + ad->ad_cname->bv_val, mask, 0 ); + +#ifdef SLAPD_USE_AD + a->ai_desc = ad; +#else + a->ai_desc = ch_strdup( ad->ad_cname->bv_val ); + ad_free( ad, 1 ); +#endif + + a->ai_indexmask = mask; + + rc = avl_insert( &li->li_attrs, (caddr_t) a, + (AVL_CMP) ainfo_cmp, (AVL_DUP) avl_dup_error ); + + if( rc ) { + fprintf( stderr, "%s: line %d: duplicate index definition " + "for attr \"%s\" (ignored)\n", + fname, lineno, attrs[i] ); + + return LDAP_PARAM_ERROR; } } + charray_free( attrs ); - if ( argc > 1 ) - charray_free( indexes ); + if ( indexes != NULL ) charray_free( indexes ); + + return LDAP_SUCCESS; } @@ -177,7 +236,11 @@ static void ainfo_free( void *attr ) { AttrInfo *ai = attr; - free( ai->ai_type ); +#ifdef SLAPD_USE_AD + ad_free( ai->ai_desc, 1 ); +#else + free( ai->ai_desc ); +#endif free( ai ); } diff --git a/servers/slapd/back-ldbm/back-ldbm.h b/servers/slapd/back-ldbm/back-ldbm.h index cf381da96f..6ea8e8c3a1 100644 --- a/servers/slapd/back-ldbm/back-ldbm.h +++ b/servers/slapd/back-ldbm/back-ldbm.h @@ -1,7 +1,7 @@ /* back-ldbm.h - ldap ldbm back-end header file */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -14,37 +14,26 @@ LDAP_BEGIN_DECL #define DEFAULT_CACHE_SIZE 1000 -#ifdef HAVE_BERKELEY_DB2 +#if defined(HAVE_BERKELEY_DB) && DB_VERSION_MAJOR >= 2 # define DEFAULT_DBCACHE_SIZE (100 * DEFAULT_DB_PAGE_SIZE) #else # define DEFAULT_DBCACHE_SIZE 100000 #endif -#define DEFAULT_DB_DIRECTORY "/usr/tmp" +#define DEFAULT_DB_DIRECTORY LDAP_RUNDIR LDAP_DIRSEP "openldap-ldbm" #define DEFAULT_MODE 0600 -#define SUBLEN 3 - -#define DN_BASE_PREFIX '=' -#define DN_ONE_PREFIX '@' -#define DN_SUBTREE_PREFIX '?' - -#define SLAPD_FILTER_DN_ONE ((ber_tag_t) -2) -#define SLAPD_FILTER_DN_SUBTREE ((ber_tag_t) -3) +#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX +#define DN_ONE_PREFIX '%' +#define DN_SUBTREE_PREFIX '@' /* * there is a single index for each attribute. these prefixes ensure * that there is no collision among keys. */ -#define EQ_PREFIX '=' /* prefix for equality keys */ -#define APPROX_PREFIX '~' /* prefix for approx keys */ -#define SUB_PREFIX '*' /* prefix for substring keys */ -#define CONT_PREFIX '\\' /* prefix for continuation keys */ -/* allow 3 characters per byte + PREFIX + EOS */ -#define CONT_SIZE ( sizeof(long)*3 + 1 + 1 ) - -#define UNKNOWN_PREFIX '?' /* prefix for unknown keys */ +/* allow PREFIX + byte for continuate number */ +#define SLAP_INDEX_CONT_SIZE ( sizeof(SLAP_INDEX_CONT_PREFIX) + sizeof(unsigned char) ) #define DEFAULT_BLOCKSIZE 8192 @@ -102,32 +91,14 @@ typedef struct ldbm_dbcache { int dbc_refcnt; int dbc_maxids; int dbc_maxindirect; + int dbc_dirty; time_t dbc_lastref; long dbc_blksize; char *dbc_name; LDBM dbc_db; } DBCache; -/* for the cache of attribute information (which are indexed, etc.) */ -typedef struct ldbm_attrinfo { - char *ai_type; /* type name (cn, sn, ...) */ - int ai_indexmask; /* how the attr is indexed */ -#define INDEX_PRESENCE 0x0001 -#define INDEX_EQUALITY 0x0002 -#define INDEX_APPROX 0x0004 -#define INDEX_SUB 0x0008 -#define INDEX_UNKNOWN 0x0010 -#define INDEX_FROMINIT 0x1000 - int ai_syntaxmask; /* what kind of syntax */ -/* ...from slap.h... -#define SYNTAX_CIS 0x01 -#define SYNTAX_CES 0x02 -#define SYNTAX_BIN 0x04 - ... etc. ... -*/ -} AttrInfo; - -#define MAXDBCACHE 16 +#define MAXDBCACHE 128 struct ldbminfo { ID li_nextid; @@ -135,17 +106,16 @@ struct ldbminfo { ldap_pvt_thread_mutex_t li_root_mutex; ldap_pvt_thread_mutex_t li_add_mutex; int li_mode; + slap_index li_defaultmask; char *li_directory; Cache li_cache; Avlnode *li_attrs; + int li_dblocking; /* lock databases */ + int li_dbwritesync; /* write sync */ int li_dbcachesize; - int li_dbcachewsync; DBCache li_dbcache[MAXDBCACHE]; ldap_pvt_thread_mutex_t li_dbcache_mutex; ldap_pvt_thread_cond_t li_dbcache_cv; -#ifdef HAVE_BERKELEY_DB2 - DB_ENV li_db_env; -#endif }; LDAP_END_DECL diff --git a/servers/slapd/back-ldbm/backldbm.dsp b/servers/slapd/back-ldbm/backldbm.dsp index 377cc8ad3c..5aeb74523d 100644 --- a/servers/slapd/back-ldbm/backldbm.dsp +++ b/servers/slapd/back-ldbm/backldbm.dsp @@ -39,9 +39,10 @@ CPP=cl.exe # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\Release" -# PROP Intermediate_Dir "..\Release\backldbm" +# PROP Output_Dir "..\..\..\Release" +# PROP Intermediate_Dir "..\..\..\Release\backldbm" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -60,9 +61,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\Debug" -# PROP Intermediate_Dir "..\Debug\backldbm" +# PROP Output_Dir "..\..\..\Debug" +# PROP Intermediate_Dir "..\..\..\Debug\backldbm" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -81,9 +83,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\SDebug" -# PROP Intermediate_Dir "..\SDebug\backldbm" +# PROP Output_Dir "..\..\..\SDebug" +# PROP Intermediate_Dir "..\..\..\SDebug\backldbm" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c # ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\\" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c BSC32=bscmake.exe @@ -102,9 +105,10 @@ LIB32=link.exe -lib # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\SRelease" -# PROP Intermediate_Dir "..\SRelease\backldbm" +# PROP Output_Dir "..\..\..\SRelease" +# PROP Intermediate_Dir "..\..\..\SRelease\backldbm" # PROP Target_Dir "" +RSC=rc.exe # ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /I "..\\" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c BSC32=bscmake.exe @@ -180,6 +184,10 @@ SOURCE=.\entry.c # End Source File # Begin Source File +SOURCE=.\extended.c +# End Source File +# Begin Source File + SOURCE=.\external.h # End Source File # Begin Source File @@ -212,7 +220,7 @@ SOURCE=.\init.c # End Source File # Begin Source File -SOURCE=.\kerberos.c +SOURCE=.\key.c # End Source File # Begin Source File @@ -228,15 +236,15 @@ SOURCE=.\nextid.c # End Source File # Begin Source File -SOURCE=".\proto-back-ldbm.h" +SOURCE=.\passwd.c # End Source File # Begin Source File -SOURCE=.\search.c +SOURCE=".\proto-back-ldbm.h" # End Source File # Begin Source File -SOURCE=.\startup.c +SOURCE=.\search.c # End Source File # Begin Source File diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index 1880a8a8cc..1c72e0eda1 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -1,7 +1,7 @@ /* bind.c - ldbm backend bind and unbind routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -18,59 +18,14 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" -#include - -#ifdef HAVE_KERBEROS -extern int krbv4_ldap_auth(); -#endif - -static int -crypted_value_find( - struct berval **vals, - struct berval *v, - int syntax, - int normalize, - struct berval *cred -) -{ - int i; - for ( i = 0; vals[i] != NULL; i++ ) { - if ( syntax != SYNTAX_BIN ) { - int result; - -#ifdef SLAPD_CRYPT - ldap_pvt_thread_mutex_lock( &crypt_mutex ); -#endif - - result = lutil_passwd( - (char*) cred->bv_val, - (char*) vals[i]->bv_val, - NULL ); - -#ifdef SLAPD_CRYPT - ldap_pvt_thread_mutex_unlock( &crypt_mutex ); -#endif - - return result; - - } else { - if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) { - return( 0 ); - } - } - } - - return( 1 ); -} - int ldbm_back_bind( Backend *be, Connection *conn, Operation *op, - char *dn, + const char *dn, + const char *ndn, int method, - char *mech, struct berval *cred, char** edn ) @@ -80,14 +35,18 @@ ldbm_back_bind( Attribute *a; int rc; Entry *matched; -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char krbname[MAX_K_NAME_SZ + 1]; AUTH_DAT ad; #endif + AttributeDescription *password = slap_schema.si_ad_userPassword; + AttributeDescription *entry = slap_schema.si_ad_entry; + Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn, 0, 0); *edn = NULL; + dn = ndn; /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { @@ -109,34 +68,26 @@ ldbm_back_bind( /* allow noauth binds */ rc = 1; if ( method == LDAP_AUTH_SIMPLE ) { - if( cred->bv_len == 0 ) { - /* SUCCESS */ - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - - } else if ( be_isroot_pw( be, dn, cred ) ) { + if ( be_isroot_pw( be, dn, cred ) ) { *edn = ch_strdup( be_root_dn( be ) ); rc = 0; /* front end will send result */ - } else { + } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); - } - } else if ( method == LDAP_AUTH_SASL ) { - if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) { - /* insert DIGEST calls here */ - send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, NULL, NULL, NULL ); - } else { - send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED, + send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } - } else { + } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); + + } else { + send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, + NULL, NULL, NULL, NULL ); } if ( matched != NULL ) { @@ -151,7 +102,7 @@ ldbm_back_bind( /* check for deleted */ if ( ! access_allowed( be, conn, op, e, - "entry", NULL, ACL_AUTH ) ) + entry, NULL, ACL_AUTH ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); @@ -165,7 +116,7 @@ ldbm_back_bind( 0, 0 ); send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, - NULL, NULL, NULL, NULL ); + NULL, "entry is alias", NULL, NULL ); rc = 1; goto return_results; @@ -179,8 +130,14 @@ ldbm_back_bind( Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); + if( refs != NULL ) { + send_ldap_result( conn, op, LDAP_REFERRAL, + e->e_dn, NULL, refs, NULL ); + + } else { + send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, + NULL, NULL, NULL, NULL ); + } ber_bvecfree( refs ); @@ -190,15 +147,6 @@ ldbm_back_bind( switch ( method ) { case LDAP_AUTH_SIMPLE: - if ( cred->bv_len == 0 ) { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - - /* stop front end from sending result */ - rc = 1; - goto return_results; - } - /* check for root dn/passwd */ if ( be_isroot_pw( be, dn, cred ) ) { /* front end will send result */ @@ -209,7 +157,7 @@ ldbm_back_bind( } if ( ! access_allowed( be, conn, op, e, - "userpassword", NULL, ACL_AUTH ) ) + password, NULL, ACL_AUTH ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); @@ -217,7 +165,7 @@ ldbm_back_bind( goto return_results; } - if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) { + if ( (a = attr_find( e->e_attrs, password )) == NULL ) { send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL ); @@ -226,8 +174,7 @@ ldbm_back_bind( goto return_results; } - if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 ) - { + if ( slap_passwd_check( a, cred ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); /* stop front end from sending result */ @@ -238,17 +185,8 @@ ldbm_back_bind( rc = 0; break; -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND case LDAP_AUTH_KRBV41: - if ( ! access_allowed( be, conn, op, e, - "krbname", NULL, ACL_AUTH ) ) - { - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); - rc = 1; - goto return_results; - } - if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); @@ -268,10 +206,9 @@ ldbm_back_bind( sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "." : "", ad.pinst, ad.prealm ); - if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) { /* - * no krbName values present: check against DN + * no krbname values present: check against DN */ if ( strcasecmp( dn, krbname ) == 0 ) { rc = 0; @@ -282,7 +219,7 @@ ldbm_back_bind( rc = 1; goto return_results; - } else { /* look for krbName match */ + } else { /* look for krbname match */ struct berval krbval; krbval.bv_val = krbname; @@ -307,12 +244,9 @@ ldbm_back_bind( goto return_results; #endif - case LDAP_AUTH_SASL: - /* insert SASL code here */ - default: send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED, - NULL, "auth method not supported", NULL, NULL ); + NULL, "authentication method not supported", NULL, NULL ); rc = 1; goto return_results; } diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c index 0ef36d7d34..c1ad171020 100644 --- a/servers/slapd/back-ldbm/cache.c +++ b/servers/slapd/back-ldbm/cache.c @@ -1,7 +1,7 @@ /* cache.c - routines to maintain an in-core cache of entries */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -36,6 +36,7 @@ typedef struct ldbm_entry_info { Entry *lei_lrunext; /* for cache lru list */ Entry *lei_lruprev; } EntryInfo; +#undef LEI #define LEI(e) ((EntryInfo *) ((e)->e_private)) static int cache_delete_entry_internal(Cache *cache, Entry *e); @@ -445,7 +446,7 @@ cache_find_entry_dn2id( e.e_dn = (char *) dn; e.e_ndn = ch_strdup( dn ); - (void) dn_normalize_case( e.e_ndn ); + (void) dn_normalize( e.e_ndn ); try_again: /* set cache mutex */ @@ -685,7 +686,9 @@ cache_release_all( Cache *cache ) Debug( LDAP_DEBUG_TRACE, "====> cache_release_all\n", 0, 0, 0 ); while ( (e = cache->c_lrutail) != NULL && LEI(e)->lei_refcnt == 0 ) { +#ifdef LDAP_RDWR_DEBUG assert(!ldap_pvt_thread_rdwr_active(&LEI(e)->lei_rdwr)); +#endif /* delete from cache and lru q */ /* XXX do we need rc ? */ diff --git a/servers/slapd/back-ldbm/close.c b/servers/slapd/back-ldbm/close.c index 9aa2ca4169..5ba0c64503 100644 --- a/servers/slapd/back-ldbm/close.c +++ b/servers/slapd/back-ldbm/close.c @@ -1,7 +1,7 @@ /* close.c - close ldbm backend */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/back-ldbm/compare.c b/servers/slapd/back-ldbm/compare.c index 96932cecfc..d17c1f4cbb 100644 --- a/servers/slapd/back-ldbm/compare.c +++ b/servers/slapd/back-ldbm/compare.c @@ -1,7 +1,7 @@ /* compare.c - ldbm backend compare routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -21,8 +21,9 @@ ldbm_back_compare( Backend *be, Connection *conn, Operation *op, - char *dn, - Ava *ava + const char *dn, + const char *ndn, + AttributeAssertion *ava ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; @@ -33,7 +34,7 @@ ldbm_back_compare( int manageDSAit = get_manageDSAit( op ); /* get entry with reader lock */ - if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { + if ( (e = dn2entry_r( be, ndn, &matched )) == NULL ) { char *matched_dn = NULL; struct berval **refs = NULL; @@ -76,7 +77,7 @@ ldbm_back_compare( } if ( ! access_allowed( be, conn, op, e, - ava->ava_type, &ava->ava_value, ACL_COMPARE ) ) + ava->aa_desc, ava->aa_value, ACL_COMPARE ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); @@ -84,21 +85,29 @@ ldbm_back_compare( goto return_results; } - if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) { - send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, - NULL, NULL, NULL, NULL ); - rc = 1; - goto return_results; + rc = LDAP_NO_SUCH_ATTRIBUTE; + + for(a = attrs_find( e->e_attrs, ava->aa_desc ); + a != NULL; + a = attrs_find( a->a_next, ava->aa_desc )) + { + rc = LDAP_COMPARE_FALSE; + + if ( value_find( ava->aa_desc, a->a_vals, ava->aa_value ) == 0 ) + { + rc = LDAP_COMPARE_TRUE; + break; + } + } - if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) - send_ldap_result( conn, op, LDAP_COMPARE_TRUE, - NULL, NULL, NULL, NULL ); - else - send_ldap_result( conn, op, LDAP_COMPARE_FALSE, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, rc, + NULL, NULL, NULL, NULL ); + + if( rc != LDAP_NO_SUCH_ATTRIBUTE ) { + rc = 0; + } - rc = 0; return_results:; cache_return_entry_r( &li->li_cache, e ); diff --git a/servers/slapd/back-ldbm/config.c b/servers/slapd/back-ldbm/config.c index ef06a4fcc7..a6c3e15a5b 100644 --- a/servers/slapd/back-ldbm/config.c +++ b/servers/slapd/back-ldbm/config.c @@ -1,7 +1,7 @@ /* config.c - ldbm backend configuration file routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -25,6 +25,7 @@ ldbm_back_db_config( char **argv ) { + int rc; struct ldbminfo *li = (struct ldbminfo *) be->be_private; if ( li == NULL ) { @@ -67,7 +68,9 @@ ldbm_back_db_config( "%s: line %d: extra junk after \"index [pres,eq,approx,sub]\" line (ignored)\n", fname, lineno ); } - attr_index_config( li, fname, lineno, argc - 1, &argv[1], 0 ); + rc = attr_index_config( li, fname, lineno, argc - 1, &argv[1] ); + + if( rc != LDAP_SUCCESS ) return 1; /* size of the cache in entries */ } else if ( strcasecmp( argv[0], "cachesize" ) == 0 ) { @@ -89,9 +92,15 @@ ldbm_back_db_config( } li->li_dbcachesize = atoi( argv[1] ); - /* no write sync */ - } else if ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) { - li->li_dbcachewsync = 0; + /* no locking (not safe) */ + } else if ( strcasecmp( argv[0], "dbnolocking" ) == 0 ) { + li->li_dblocking = 0; + + /* no write sync (not safe) */ + } else if ( ( strcasecmp( argv[0], "dbnosync" ) == 0 ) + || ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) ) + { + li->li_dbwritesync = 0; /* anything else */ } else { diff --git a/servers/slapd/back-ldbm/dbcache.c b/servers/slapd/back-ldbm/dbcache.c index eecf2c954b..ad65ddc73e 100644 --- a/servers/slapd/back-ldbm/dbcache.c +++ b/servers/slapd/back-ldbm/dbcache.c @@ -1,7 +1,7 @@ /* ldbmcache.c - maintain a cache of open ldbm files */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -13,21 +13,16 @@ #include #include #include - #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - #include "slap.h" #include "back-ldbm.h" DBCache * ldbm_cache_open( Backend *be, - char *name, - char *suffix, + const char *name, + const char *suffix, int flags ) { @@ -42,6 +37,18 @@ ldbm_cache_open( sprintf( buf, "%s" LDAP_DIRSEP "%s%s", li->li_directory, name, suffix ); + if( li->li_dblocking ) { + flags |= LDBM_LOCKING; + } else { + flags |= LDBM_NOLOCKING; + } + + if( li->li_dbwritesync ) { + flags |= LDBM_SYNC; + } else { + flags |= LDBM_NOSYNC; + } + Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf, flags, li->li_mode ); @@ -108,6 +115,7 @@ ldbm_cache_open( li->li_dbcache[i].dbc_name = ch_strdup( buf ); li->li_dbcache[i].dbc_refcnt = 1; li->li_dbcache[i].dbc_lastref = curtime; + li->li_dbcache[i].dbc_dirty = 0; #ifdef HAVE_ST_BLKSIZE if ( stat( buf, &st ) == 0 ) { li->li_dbcache[i].dbc_blksize = st.st_blksize; @@ -118,8 +126,10 @@ ldbm_cache_open( } li->li_dbcache[i].dbc_maxids = (li->li_dbcache[i].dbc_blksize / sizeof(ID)) - ID_BLOCK_IDS_OFFSET; - li->li_dbcache[i].dbc_maxindirect = (SLAPD_LDBM_MIN_MAXIDS / - li->li_dbcache[i].dbc_maxids) + 1; + li->li_dbcache[i].dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS / + li->li_dbcache[i].dbc_maxids ) + 1; + + assert( li->li_dbcache[i].dbc_maxindirect < 256 ); Debug( LDAP_DEBUG_ARGS, "ldbm_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n", @@ -135,6 +145,11 @@ ldbm_cache_close( Backend *be, DBCache *db ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; + if( li->li_dbwritesync && db->dbc_dirty ) { + ldbm_sync( db->dbc_db ); + db->dbc_dirty = 0; + } + ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex ); if ( --db->dbc_refcnt == 0 ) { ldap_pvt_thread_cond_signal( &li->li_dbcache_cv ); @@ -169,6 +184,7 @@ ldbm_cache_flush_all( Backend *be ) Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n", li->li_dbcache[i].dbc_name, 0, 0 ); ldbm_sync( li->li_dbcache[i].dbc_db ); + li->li_dbcache[i].dbc_dirty = 0; if ( li->li_dbcache[i].dbc_refcnt != 0 ) { Debug( LDAP_DEBUG_TRACE, "refcnt = %d, couldn't close db (%s)\n", @@ -229,6 +245,7 @@ ldbm_cache_store( flags, 0, 0, 0, 0 ); #endif /* LDBM_DEBUG */ + db->dbc_dirty = 1; rc = ldbm_store( db->dbc_db, key, data, flags ); return( rc ); @@ -242,6 +259,7 @@ ldbm_cache_delete( { int rc; + db->dbc_dirty = 1; rc = ldbm_delete( db->dbc_db, key ); return( rc ); diff --git a/servers/slapd/back-ldbm/delete.c b/servers/slapd/back-ldbm/delete.c index eb3ed850e2..c216f6b901 100644 --- a/servers/slapd/back-ldbm/delete.c +++ b/servers/slapd/back-ldbm/delete.c @@ -1,7 +1,7 @@ /* delete.c - ldbm backend delete routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -21,7 +21,8 @@ ldbm_back_delete( Backend *be, Connection *conn, Operation *op, - char *dn + const char *dn, + const char *ndn ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; @@ -31,11 +32,12 @@ ldbm_back_delete( int rootlock = 0; int rc = -1; int manageDSAit = get_manageDSAit( op ); + AttributeDescription *children = slap_schema.si_ad_children; Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0); /* get entry with writer lock */ - if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { + if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char *matched_dn = NULL; struct berval **refs = NULL; @@ -99,7 +101,7 @@ ldbm_back_delete( Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n", dn, 0, 0); send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, - NULL, NULL, NULL, NULL ); + NULL, "subtree delete not supported", NULL, NULL ); goto return_results; } @@ -109,14 +111,14 @@ ldbm_back_delete( Debug( LDAP_DEBUG_TRACE, "<=- ldbm_back_delete: parent does not exist\n", 0, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "could not locate parent of entry", NULL, NULL ); goto return_results; } /* check parent for "children" acl */ if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) + children, NULL, ACL_WRITE ) ) { Debug( LDAP_DEBUG_TRACE, "<=- ldbm_back_delete: no access to parent\n", 0, @@ -146,8 +148,8 @@ ldbm_back_delete( Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: operations error %s\n", dn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "DN index delete failed", NULL, NULL ); goto return_results; } @@ -156,8 +158,8 @@ ldbm_back_delete( Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: operations error %s\n", dn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "entry delete failed", NULL, NULL ); goto return_results; } diff --git a/servers/slapd/back-ldbm/dn2id.c b/servers/slapd/back-ldbm/dn2id.c index afa1c27de6..ca614d978a 100644 --- a/servers/slapd/back-ldbm/dn2id.c +++ b/servers/slapd/back-ldbm/dn2id.c @@ -1,7 +1,7 @@ /* dn2id.c - routines to deal with the dn2id index */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -48,8 +48,6 @@ dn2id_add( data.dsize = sizeof(ID); flags = LDBM_INSERT; - if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; - rc = ldbm_cache_store( db, key, data, flags ); free( key.dptr ); diff --git a/servers/slapd/back-ldbm/entry.c b/servers/slapd/back-ldbm/entry.c index 7ff873b855..9f644faeef 100644 --- a/servers/slapd/back-ldbm/entry.c +++ b/servers/slapd/back-ldbm/entry.c @@ -1,7 +1,7 @@ /* entry.c - ldbm backend entry_release routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/back-ldbm/extended.c b/servers/slapd/back-ldbm/extended.c new file mode 100644 index 0000000000..5e4762e49d --- /dev/null +++ b/servers/slapd/back-ldbm/extended.c @@ -0,0 +1,56 @@ +/* extended.c - ldbm backend extended routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-ldbm.h" +#include "proto-back-ldbm.h" + +struct exop { + char *oid; + SLAP_EXTENDED_FN extended; +} exop_table[] = { + { LDAP_EXOP_X_MODIFY_PASSWD, ldbm_back_exop_passwd }, + { NULL, NULL } +}; + +int +ldbm_back_extended( + Backend *be, + Connection *conn, + Operation *op, + const char *reqoid, + struct berval *reqdata, + char **rspoid, + struct berval **rspdata, + LDAPControl *** rspctrls, + const char** text, + struct berval *** refs +) +{ + int i; + + for( i=0; exop_table[i].oid != NULL; i++ ) { + if( strcmp( exop_table[i].oid, reqoid ) == 0 ) { + return (exop_table[i].extended)( + be, conn, op, + reqoid, reqdata, + rspoid, rspdata, rspctrls, + text, refs ); + } + } + + *text = ch_strdup("not supported within naming context"); + return LDAP_OPERATIONS_ERROR; +} + diff --git a/servers/slapd/back-ldbm/external.h b/servers/slapd/back-ldbm/external.h index e1b8696db6..5ba17a182e 100644 --- a/servers/slapd/back-ldbm/external.h +++ b/servers/slapd/back-ldbm/external.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -20,11 +20,22 @@ extern int ldbm_back_db_close LDAP_P(( BackendDB *bd )); extern int ldbm_back_db_destroy LDAP_P(( BackendDB *bd )); extern int ldbm_back_db_config LDAP_P(( BackendDB *bd, - const char *fname, int lineno, int argc, char **argv )); + const char *fname, int lineno, + int argc, char **argv )); + +extern int ldbm_back_extended LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *reqoid, + struct berval *reqdata, + char **rspoid, + struct berval **rspdata, + LDAPControl *** rspctrls, + const char **text, + struct berval *** refs )); extern int ldbm_back_bind LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, int method, char* mech, + const char *dn, const char *ndn, int method, struct berval *cred, char** edn )); extern int ldbm_back_unbind LDAP_P(( BackendDB *bd, @@ -32,34 +43,42 @@ extern int ldbm_back_unbind LDAP_P(( BackendDB *bd, extern int ldbm_back_search LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter *filter, char *filterstr, char **attrs, int attrsonly )); + const char *base, const char *nbase, + int scope, int deref, int sizelimit, int timelimit, + Filter *filter, const char *filterstr, + char **attrs, int attrsonly )); -extern int ldbm_back_compare LDAP_P((BackendDB *bd, +extern int ldbm_back_compare LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, Ava *ava )); + const char *dn, const char *ndn, + AttributeAssertion *ava )); extern int ldbm_back_modify LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, LDAPModList *ml )); + const char *dn, const char *ndn, Modifications *ml )); extern int ldbm_back_modrdn LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, char* newrdn, int deleteoldrdn, - char *newSuperior )); + const char *dn, const char *ndn, + const char* newrdn, int deleteoldrdn, + const char *newSuperior )); extern int ldbm_back_add LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, Entry *e )); extern int ldbm_back_delete LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, char *dn )); + Connection *conn, Operation *op, + const char *dn, const char *ndn )); extern int ldbm_back_abandon LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, ber_int_t msgid )); extern int ldbm_back_group LDAP_P(( BackendDB *bd, - Entry *target, const char* gr_ndn, const char* op_ndn, - const char* objectclassValue, const char* groupattrName)); + Entry *target, + const char* gr_ndn, + const char* op_ndn, + ObjectClass* group_oc, + AttributeDescription* group_at)); /* hooks for slap tools */ @@ -69,8 +88,11 @@ extern ID ldbm_tool_entry_first LDAP_P(( BackendDB *be )); extern ID ldbm_tool_entry_next LDAP_P(( BackendDB *be )); extern Entry* ldbm_tool_entry_get LDAP_P(( BackendDB *be, ID id )); extern ID ldbm_tool_entry_put LDAP_P(( BackendDB *be, Entry *e )); -extern int ldbm_tool_index_attr LDAP_P(( BackendDB *be, char* type )); -extern int ldbm_tool_index_change LDAP_P(( BackendDB *be, char* type, + +extern int ldbm_tool_index_attr LDAP_P(( BackendDB *be, + AttributeDescription* desc )); +extern int ldbm_tool_index_change LDAP_P(( BackendDB *be, + AttributeDescription* desc, struct berval **bv, ID id, int op )); extern int ldbm_tool_sync LDAP_P(( BackendDB *be )); diff --git a/servers/slapd/back-ldbm/filterindex.c b/servers/slapd/back-ldbm/filterindex.c index 81deb55a60..59acdb94a1 100644 --- a/servers/slapd/back-ldbm/filterindex.c +++ b/servers/slapd/back-ldbm/filterindex.c @@ -1,7 +1,7 @@ /* filterindex.c - generate the list of candidate entries from a filter */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -15,19 +15,20 @@ #include "slap.h" #include "back-ldbm.h" -static ID_BLOCK *ava_candidates( Backend *be, Ava *ava, int type ); -static ID_BLOCK *presence_candidates( Backend *be, char *type ); -static ID_BLOCK *approx_candidates( Backend *be, Ava *ava ); -static ID_BLOCK *list_candidates( Backend *be, Filter *flist, int ftype ); -static ID_BLOCK *substring_candidates( Backend *be, Filter *f ); -static ID_BLOCK *substring_comp_candidates( Backend *be, char *type, char *val, int prepost ); - -/* - * test_filter - test a filter against a single entry. - * returns 0 filter matched - * -1 filter did not match - * >0 an ldap error code - */ +static ID_BLOCK *presence_candidates( + Backend *be, + AttributeDescription *desc ); +static ID_BLOCK *equality_candidates( + Backend *be, AttributeAssertion *ava ); +static ID_BLOCK *approx_candidates( + Backend *be, AttributeAssertion *ava ); +static ID_BLOCK *substring_candidates( + Backend *be, + Filter *f ); +static ID_BLOCK *list_candidates( + Backend *be, + Filter *flist, + int ftype ); ID_BLOCK * filter_candidates( @@ -51,9 +52,19 @@ filter_candidates( result = dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX ); break; + case LDAP_FILTER_PRESENT: + Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 ); + result = presence_candidates( be, f->f_desc ); + break; + case LDAP_FILTER_EQUALITY: Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_EQUALITY ); + result = equality_candidates( be, f->f_ava ); + break; + + case LDAP_FILTER_APPROX: + Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 ); + result = approx_candidates( be, f->f_ava ); break; case LDAP_FILTER_SUBSTRINGS: @@ -63,22 +74,12 @@ filter_candidates( case LDAP_FILTER_GE: Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_GE ); + result = idl_allids( be ); break; case LDAP_FILTER_LE: Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 ); - result = ava_candidates( be, &f->f_ava, LDAP_FILTER_LE ); - break; - - case LDAP_FILTER_PRESENT: - Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 ); - result = presence_candidates( be, f->f_type ); - break; - - case LDAP_FILTER_APPROX: - Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 ); - result = approx_candidates( be, &f->f_ava ); + result = idl_allids( be ); break; case LDAP_FILTER_AND: @@ -107,49 +108,165 @@ filter_candidates( } static ID_BLOCK * -ava_candidates( +presence_candidates( Backend *be, - Ava *ava, - int type + AttributeDescription *desc ) { ID_BLOCK *idl; + DBCache *db; + int rc; + char *dbname; + slap_index mask; + struct berval *prefix; - Debug( LDAP_DEBUG_TRACE, "=> ava_candidates 0x%x\n", type, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 ); - switch ( type ) { - case LDAP_FILTER_EQUALITY: - idl = index_read( be, ava->ava_type, INDEX_EQUALITY, - ava->ava_value.bv_val ); - break; + idl = idl_allids( be ); - case LDAP_FILTER_GE: - idl = idl_allids( be ); - break; + rc = index_param( be, desc, LDAP_FILTER_PRESENT, + &dbname, &mask, &prefix ); - case LDAP_FILTER_LE: - idl = idl_allids( be ); - break; + if( rc != LDAP_SUCCESS ) { + return idl; + } + + if( dbname == NULL ) { + /* not indexed */ + return idl; + } + + db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_READER ); + + if ( db == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= presense_candidates db open failed (%s%s)\n", + dbname, LDBM_SUFFIX, 0 ); + return idl; + } + + if( prefix != NULL ) { + idl_free( idl ); + idl = NULL; + + rc = key_read( be, db, prefix, &idl ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "<= presense_candidates key read failed (%d)\n", + rc, 0, 0 ); + + } else if( idl == NULL ) { + Debug( LDAP_DEBUG_TRACE, "<= presense_candidates NULL\n", + 0, 0, 0 ); + } } - Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %ld\n", + ldbm_cache_close( be, db ); + + + Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n", idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); return( idl ); } static ID_BLOCK * -presence_candidates( +equality_candidates( Backend *be, - char *type + AttributeAssertion *ava ) { ID_BLOCK *idl; + DBCache *db; + int i; + int rc; + char *dbname; + slap_index mask; + struct berval *prefix; + struct berval **keys = NULL; + MatchingRule *mr; - Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "=> equality_candidates\n", 0, 0, 0 ); - idl = index_read( be, type, 0, "*" ); + idl = idl_allids( be ); - Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n", + rc = index_param( be, ava->aa_desc, LDAP_FILTER_EQUALITY, + &dbname, &mask, &prefix ); + + if( rc != LDAP_SUCCESS ) { + return idl; + } + + if( dbname == NULL ) { + /* not indexed */ + return idl; + } + + mr = ava->aa_desc->ad_type->sat_equality; + if( !mr ) { + /* return LDAP_INAPPROPRIATE_MATCHING; */ + return idl; + } + + if( !mr->smr_filter ) { + return idl; + } + + rc = (mr->smr_filter)( + LDAP_FILTER_EQUALITY, + ava->aa_desc->ad_type->sat_syntax, + mr, + prefix, + ava->aa_value, + &keys ); + + if( rc != LDAP_SUCCESS ) { + return idl; + } + + db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_READER ); + + if ( db == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= equality_candidates db open failed (%s%s)\n", + dbname, LDBM_SUFFIX, 0 ); + return idl; + } + + for ( i= 0; keys[i] != NULL; i++ ) { + ID_BLOCK *save; + ID_BLOCK *tmp; + + rc = key_read( be, db, keys[i], &tmp ); + + if( rc != LDAP_SUCCESS ) { + idl_free( idl ); + idl = NULL; + Debug( LDAP_DEBUG_TRACE, "<= equality_candidates key read failed (%d)\n", + rc, 0, 0 ); + break; + } + + if( tmp == NULL ) { + idl_free( idl ); + idl = NULL; + Debug( LDAP_DEBUG_TRACE, "<= equality_candidates NULL\n", + 0, 0, 0 ); + break; + } + + save = idl; + idl = idl_intersection( be, idl, tmp ); + idl_free( save ); + + if( idl == NULL ) break; + } + + ber_bvecfree( keys ); + + ldbm_cache_close( be, db ); + + + Debug( LDAP_DEBUG_TRACE, "<= equality_candidates %ld\n", idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); return( idl ); } @@ -157,35 +274,104 @@ presence_candidates( static ID_BLOCK * approx_candidates( Backend *be, - Ava *ava + AttributeAssertion *ava ) { - char *w, *c; - ID_BLOCK *idl, *tmp; + ID_BLOCK *idl; + DBCache *db; + int i; + int rc; + char *dbname; + slap_index mask; + struct berval *prefix; + struct berval **keys = NULL; + MatchingRule *mr; Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 ); - idl = NULL; - for ( w = first_word( ava->ava_value.bv_val ); w != NULL; - w = next_word( w ) ) { - c = phonetic( w ); - if ( (tmp = index_read( be, ava->ava_type, INDEX_APPROX, c )) - == NULL ) { - free( c ); + idl = idl_allids( be ); + + rc = index_param( be, ava->aa_desc, LDAP_FILTER_EQUALITY, + &dbname, &mask, &prefix ); + + if( rc != LDAP_SUCCESS ) { + return idl; + } + + if( dbname == NULL ) { + /* not indexed */ + return idl; + } + + mr = ava->aa_desc->ad_type->sat_approx; + if( mr == NULL ) { + /* no approx matching rule, try equality matching rule */ + mr = ava->aa_desc->ad_type->sat_equality; + } + + if( !mr ) { + /* return LDAP_INAPPROPRIATE_MATCHING; */ + return idl; + } + + if( !mr->smr_filter ) { + return idl; + } + + rc = (mr->smr_filter)( + LDAP_FILTER_EQUALITY, + ava->aa_desc->ad_type->sat_syntax, + mr, + prefix, + ava->aa_value, + &keys ); + + if( rc != LDAP_SUCCESS ) { + return idl; + } + + db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_READER ); + + if ( db == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= approx_candidates db open failed (%s%s)\n", + dbname, LDBM_SUFFIX, 0 ); + return idl; + } + + for ( i= 0; keys[i] != NULL; i++ ) { + ID_BLOCK *save; + ID_BLOCK *tmp; + + rc = key_read( be, db, keys[i], &tmp ); + + if( rc != LDAP_SUCCESS ) { + idl_free( idl ); + idl = NULL; + Debug( LDAP_DEBUG_TRACE, "<= approx_candidates key read failed (%d)\n", + rc, 0, 0 ); + break; + } + + if( tmp == NULL ) { idl_free( idl ); + idl = NULL; Debug( LDAP_DEBUG_TRACE, "<= approx_candidates NULL\n", 0, 0, 0 ); - return( NULL ); + break; } - free( c ); - if ( idl == NULL ) { - idl = tmp; - } else { - idl = idl_intersection( be, idl, tmp ); - } + save = idl; + idl = idl_intersection( be, idl, tmp ); + idl_free( save ); + + if( idl == NULL ) break; } + ber_bvecfree( keys ); + + ldbm_cache_close( be, db ); + Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %ld\n", idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); return( idl ); @@ -238,136 +424,13 @@ substring_candidates( Filter *f ) { - int i; - ID_BLOCK *idl, *tmp, *tmp2; + ID_BLOCK *idl; Debug( LDAP_DEBUG_TRACE, "=> substring_candidates\n", 0, 0, 0 ); - idl = NULL; - - /* initial */ - if ( f->f_sub_initial != NULL ) { - if ( (int) strlen( f->f_sub_initial ) < SUBLEN - 1 ) { - idl = idl_allids( be ); - } else if ( (idl = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_initial, '^' )) == NULL ) { - return( NULL ); - } - } - - /* final */ - if ( f->f_sub_final != NULL ) { - if ( (int) strlen( f->f_sub_final ) < SUBLEN - 1 ) { - tmp = idl_allids( be ); - } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_final, '$' )) == NULL ) { - idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = idl_intersection( be, idl, tmp ); - idl_free( tmp ); - idl_free( tmp2 ); - } - } - - for ( i = 0; f->f_sub_any != NULL && f->f_sub_any[i] != NULL; i++ ) { - if ( (int) strlen( f->f_sub_any[i] ) < SUBLEN ) { - tmp = idl_allids( be ); - } else if ( (tmp = substring_comp_candidates( be, f->f_sub_type, - f->f_sub_any[i], 0 )) == NULL ) { - idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = idl_intersection( be, idl, tmp ); - idl_free( tmp ); - idl_free( tmp2 ); - } - } - + idl = idl_allids( be ); Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %ld\n", idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); return( idl ); } -static ID_BLOCK * -substring_comp_candidates( - Backend *be, - char *type, - char *val, - int prepost -) -{ - int i, len; - ID_BLOCK *idl, *tmp, *tmp2; - char *p; - char buf[SUBLEN + 1]; - - Debug( LDAP_DEBUG_TRACE, "=> substring_comp_candidates\n", 0, 0, 0 ); - - len = strlen( val ); - idl = NULL; - - /* prepend ^ for initial substring */ - if ( prepost == '^' ) { - buf[0] = '^'; - for ( i = 0; i < SUBLEN - 1; i++ ) { - buf[i + 1] = val[i]; - } - buf[SUBLEN] = '\0'; - - if ( (idl = index_read( be, type, INDEX_SUB, buf )) == NULL ) { - return( NULL ); - } - } else if ( prepost == '$' ) { - p = val + len - SUBLEN + 1; - for ( i = 0; i < SUBLEN - 1; i++ ) { - buf[i] = p[i]; - } - buf[SUBLEN - 1] = '$'; - buf[SUBLEN] = '\0'; - - if ( (idl = index_read( be, type, INDEX_SUB, buf )) == NULL ) { - return( NULL ); - } - } - - for ( p = val; p < (val + len - SUBLEN + 1); p++ ) { - for ( i = 0; i < SUBLEN; i++ ) { - buf[i] = p[i]; - } - buf[SUBLEN] = '\0'; - - if ( (tmp = index_read( be, type, INDEX_SUB, buf )) == NULL ) { - idl_free( idl ); - return( NULL ); - } - - if ( idl == NULL ) { - idl = tmp; - } else { - tmp2 = idl; - idl = idl_intersection( be, idl, tmp ); - idl_free( tmp ); - idl_free( tmp2 ); - } - - /* break if no candidates */ - if( idl == NULL ) { - break; - } - } - - Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %ld\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); -} diff --git a/servers/slapd/back-ldbm/group.c b/servers/slapd/back-ldbm/group.c index 8dbe75922a..d5b8aad439 100644 --- a/servers/slapd/back-ldbm/group.c +++ b/servers/slapd/back-ldbm/group.c @@ -1,7 +1,7 @@ /* group.c - ldbm backend acl group routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -27,17 +27,26 @@ ldbm_back_group( Entry *target, const char *gr_ndn, const char *op_ndn, - const char *objectclassValue, - const char *groupattrName + ObjectClass *group_oc, + AttributeDescription *group_at ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *e; int rc = 1; - Attribute *attr; struct berval bv; + AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; + const char *group_oc_name = NULL; + const char *group_at_name = group_at->ad_cname->bv_val; + + if( group_oc->soc_names && group_oc->soc_names[0] ) { + group_oc_name = group_oc->soc_names[0]; + } else { + group_oc_name = group_oc->soc_oid; + } + Debug( LDAP_DEBUG_ARGS, "=> ldbm_back_group: gr dn: \"%s\"\n", gr_ndn, 0, 0 ); @@ -45,8 +54,8 @@ ldbm_back_group( "=> ldbm_back_group: op dn: \"%s\"\n", op_ndn, 0, 0 ); Debug( LDAP_DEBUG_ARGS, - "=> ldbm_back_group: objectClass: \"%s\" attrName: \"%s\"\n", - objectclassValue, groupattrName, 0 ); + "=> ldbm_back_group: oc: \"%s\" at: \"%s\"\n", + group_oc_name, group_at_name, 0 ); Debug( LDAP_DEBUG_ARGS, "=> ldbm_back_group: tr dn: \"%s\"\n", @@ -80,66 +89,52 @@ ldbm_back_group( rc = 1; - if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) { - Debug( LDAP_DEBUG_ACL, - "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 ); - goto return_results; - } - bv.bv_val = "ALIAS"; - bv.bv_len = sizeof("ALIAS")-1; - - if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) { + if( is_entry_alias( e ) ) { Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: group is an alias\n", 0, 0, 0 ); goto return_results; } - bv.bv_val = "REFERRAL"; - bv.bv_len = sizeof("REFERRAL")-1; - - if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) { + if( is_entry_referral( e ) ) { Debug( LDAP_DEBUG_ACL, - "<= ldbm_back_group: group is a referral\n", - 0, 0, 0 ); + "<= ldbm_back_group: group is an referral\n", 0, 0, 0 ); goto return_results; } - bv.bv_val = (char *) objectclassValue; - bv.bv_len = strlen( bv.bv_val ); - - if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { + if( is_entry_objectclass( e, group_oc ) ) { Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: failed to find %s in objectClass\n", - objectclassValue, 0, 0 ); + group_oc_name, 0, 0 ); goto return_results; } - if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) { + if ((attr = attr_find(e->e_attrs, group_at)) == NULL) { Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: failed to find %s\n", - groupattrName, 0, 0 ); + group_at_name, 0, 0 ); goto return_results; } Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: found objectClass %s and %s\n", - objectclassValue, groupattrName, 0 ); + group_oc_name, group_at_name, 0 ); bv.bv_val = (char *) op_ndn; bv.bv_len = strlen( op_ndn ); - if( value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) - { + if( value_find( group_at, attr->a_vals, &bv ) == 0 ) { Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n", - op_ndn, gr_ndn, groupattrName ); + op_ndn, gr_ndn, group_at_name ); goto return_results; } + + Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n", - op_ndn, gr_ndn, groupattrName ); + op_ndn, gr_ndn, group_at_name ); rc = 0; diff --git a/servers/slapd/back-ldbm/id2children.c b/servers/slapd/back-ldbm/id2children.c index acbab8fd77..983f4e05cb 100644 --- a/servers/slapd/back-ldbm/id2children.c +++ b/servers/slapd/back-ldbm/id2children.c @@ -1,7 +1,7 @@ /* id2children.c - routines to deal with the id2children index */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/back-ldbm/id2entry.c b/servers/slapd/back-ldbm/id2entry.c index 53f52d85a5..f38802126d 100644 --- a/servers/slapd/back-ldbm/id2entry.c +++ b/servers/slapd/back-ldbm/id2entry.c @@ -1,7 +1,7 @@ /* id2entry.c - routines to deal with the id2entry index */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -49,7 +49,6 @@ id2entry_add( Backend *be, Entry *e ) /* store it */ flags = LDBM_REPLACE; - if ( li->li_dbcachewsync ) flags |= LDBM_SYNC; rc = ldbm_cache_store( db, key, data, flags ); ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); @@ -73,7 +72,7 @@ id2entry_delete( Backend *be, Entry *e ) e->e_dn, 0 ); #ifdef notdef -#ifdef LDAP_DEBUG +#ifdef LDAP_RDWR_DEBUG /* check for writer lock */ assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1); #endif diff --git a/servers/slapd/back-ldbm/idl.c b/servers/slapd/back-ldbm/idl.c index f528fa8665..7d18956361 100644 --- a/servers/slapd/back-ldbm/idl.c +++ b/servers/slapd/back-ldbm/idl.c @@ -1,7 +1,7 @@ /* idl.c - ldap id list handling routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -17,6 +17,32 @@ static ID_BLOCK* idl_dup( ID_BLOCK *idl ); +static void cont_alloc( Datum cont, Datum key ) +{ + ldbm_datum_init( cont ); + cont.dsize = 1 + sizeof(ID) + key.dsize; + cont.dptr = ch_malloc( cont.dsize ); + + memcpy( &((unsigned char *)cont.dptr)[1 + sizeof(ID)], + key.dptr, key.dsize ); +} + +static void cont_id( Datum cont, ID id ) +{ + int i; + + for( i=1; i <= sizeof(id); i++) { + ((unsigned char *)cont.dptr)[i] = (unsigned char)(id & 0xFF); + id >>= 8; + } + +} + +static void cont_free( Datum cont ) +{ + ch_free( cont.dptr ); +} + /* Allocate an ID_BLOCK with room for nids ids */ ID_BLOCK * idl_alloc( unsigned int nids ) @@ -106,7 +132,6 @@ idl_fetch( Datum data; ID_BLOCK *idl; ID_BLOCK **tmp; - char *kstr; int i, nids; idl = idl_fetch_one( be, db, key ); @@ -141,27 +166,21 @@ idl_fetch( tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) ); /* read in all the blocks */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); + cont_alloc( data, key ); nids = 0; for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) { - ldbm_datum_init( data ); - - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i), key.dptr ); - - data.dptr = kstr; - data.dsize = strlen( kstr ) + 1; + cont_id( data, ID_BLOCK_ID(idl, i) ); if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) { Debug( LDAP_DEBUG_ANY, - "idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 ); + "idl_fetch: one returned NULL\n", 0, 0, 0 ); continue; } nids += ID_BLOCK_NIDS(tmp[i]); } tmp[i] = NULL; - free( kstr ); + cont_free( data ); idl_free( idl ); /* allocate space for the big block */ @@ -217,7 +236,6 @@ idl_store( #endif flags = LDBM_REPLACE; - if( li->li_dbcachewsync ) flags |= LDBM_SYNC; rc = ldbm_cache_store( db, key, data, flags ); /* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */ @@ -295,19 +313,17 @@ idl_change_first( /* delete old key block */ if ( (rc = ldbm_cache_delete( db, bkey )) != 0 ) { Debug( LDAP_DEBUG_ANY, - "ldbm_delete of (%s) returns %d\n", bkey.dptr, rc, - 0 ); + "idl_change_first: ldbm_cache_delete returned %d\n", + rc, 0, 0 ); return( rc ); } /* write block with new key */ - sprintf( bkey.dptr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(b, 0), hkey.dptr ); + cont_id( bkey, ID_BLOCK_ID(b, 0) ); - bkey.dsize = strlen( bkey.dptr ) + 1; if ( (rc = idl_store( be, db, bkey, b )) != 0 ) { Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", bkey.dptr, rc, 0 ); + "idl_change_first: idl_store returned %d\n", rc, 0, 0 ); return( rc ); } @@ -315,7 +331,7 @@ idl_change_first( ID_BLOCK_ID(h, pos) = ID_BLOCK_ID(b, 0); if ( (rc = idl_store( be, db, hkey, h )) != 0 ) { Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", hkey.dptr, rc, 0 ); + "idl_change_first: idl_store returned %d\n", rc, 0, 0 ); return( rc ); } @@ -333,17 +349,9 @@ idl_insert_key( { int i, j, first, rc; ID_BLOCK *idl, *tmp, *tmp2, *tmp3; - char *kstr; Datum k2; - ldbm_datum_init( k2 ); - if ( (idl = idl_fetch_one( be, db, key )) == NULL ) { -#ifdef LDBM_DEBUG - Statslog( LDAP_DEBUG_STATS, "=> idl_insert_key(): no key yet\n", - 0, 0, 0, 0, 0 ); -#endif - idl = idl_alloc( 1 ); ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)++) = id; rc = idl_store( be, db, key, idl ); @@ -393,23 +401,16 @@ idl_insert_key( /* store it */ rc = idl_store( be, db, key, idl ); - /* store the first id block */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp, 0), key.dptr ); + cont_alloc( k2, key ); + cont_id( k2, ID_BLOCK_ID(tmp, 0) ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; rc = idl_store( be, db, k2, tmp ); - /* store the second id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp2, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_id( k2, ID_BLOCK_ID(tmp2, 0) ); rc = idl_store( be, db, k2, tmp2 ); - free( kstr ); + cont_free( k2 ); + idl_free( tmp ); idl_free( tmp2 ); break; @@ -430,6 +431,7 @@ idl_insert_key( /* select the block to try inserting into *//* XXX linear search XXX */ for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ ) ; /* NULL */ + if ( i != 0 ) { i--; first = 0; @@ -438,15 +440,13 @@ idl_insert_key( } /* get the block */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_alloc( k2, key ); + cont_id( k2, ID_BLOCK_ID(idl, i) ); + if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) { - Debug( LDAP_DEBUG_ANY, "nonexistent continuation block (%s)\n", - k2.dptr, 0, 0 ); - free( kstr ); + Debug( LDAP_DEBUG_ANY, "idl_insert_key: nonexistent continuation block\n", + 0, 0, 0 ); + cont_free( k2 ); idl_free( idl ); return( -1 ); } @@ -456,7 +456,7 @@ idl_insert_key( case 0: /* id inserted ok */ if ( (rc = idl_store( be, db, k2, tmp )) != 0 ) { Debug( LDAP_DEBUG_ANY, - "idl_store of (%s) returns %d\n", k2.dptr, rc, 0 ); + "idl_insert_key: idl_store returned %d\n", rc, 0, 0 ); } break; @@ -485,18 +485,51 @@ idl_insert_key( /* is there a next block? */ if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) { /* read it in */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, i + 1), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_alloc( k2, key ); + cont_id( k2, ID_BLOCK_ID(idl, i) ); if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) { Debug( LDAP_DEBUG_ANY, - "idl_fetch_one (%s) returns NULL\n", - k2.dptr, 0, 0 ); + "idl_insert_key: idl_fetch_one returned NULL\n", + 0, 0, 0 ); /* split the original block */ + cont_free( k2 ); goto split; } + /* If the new id is less than the last id in the + * current block, it must not be put into the next + * block. Push the last id of the current block + * into the next block instead. + */ + if (id < ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1)) { + ID id2 = ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1); + Datum k3; + + ldbm_datum_init( k3 ); + + --ID_BLOCK_NIDS(tmp); + /* This must succeed since we just popped one + * ID off the end of it. + */ + rc = idl_insert( &tmp, id, db->dbc_maxids ); + + k3.dptr = ch_malloc(k2.dsize); + k3.dsize = k2.dsize; + memcpy(k3.dptr, k2.dptr, k3.dsize); + if ( (rc = idl_store( be, db, k3, tmp )) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "idl_insert_key: idl_store returned %d\n", rc, 0, 0 ); + } + + free( k3.dptr ); + + id = id2; + /* This new id will necessarily be inserted + * as the first id of the next block by the + * following switch() statement. + */ + } + switch ( (rc = idl_insert( &tmp2, id, db->dbc_maxids )) ) { case 1: /* id inserted first in block */ @@ -505,13 +538,18 @@ idl_insert_key( /* FALL */ case 2: /* id already there - how? */ - case 0: /* id inserted */ + case 0: /* id inserted: this can never be + * the result of idl_insert, because + * we guaranteed that idl_change_first + * will always be called. + */ if ( rc == 2 ) { Debug( LDAP_DEBUG_ANY, - "id %ld already in next block\n", + "idl_insert_key: id %ld already in next block\n", id, 0, 0 ); } - free( kstr ); + + assert( 0 ); /* not yet implemented */ idl_free( tmp ); idl_free( tmp2 ); idl_free( idl ); @@ -549,10 +587,7 @@ split: /* delete all indirect blocks */ for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) { - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, j), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_id( k2, ID_BLOCK_ID(idl, j) ); rc = ldbm_cache_delete( db, k2 ); } @@ -562,7 +597,7 @@ split: idl = idl_allids( be ); rc = idl_store( be, db, key, idl ); - free( kstr ); + cont_free( k2 ); idl_free( idl ); idl_free( tmp ); return( rc ); @@ -592,17 +627,11 @@ split: rc = idl_store( be, db, key, tmp ); /* store the first id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp2, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_id( k2, ID_BLOCK_ID(tmp2, 0) ); rc = idl_store( be, db, k2, tmp2 ); /* store the second id block */ - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(tmp3, 0), key.dptr ); - k2.dptr = kstr; - k2.dsize = strlen( kstr ) + 1; + cont_id( k2, ID_BLOCK_ID(tmp3, 0) ); rc = idl_store( be, db, k2, tmp3 ); idl_free( tmp2 ); @@ -610,7 +639,7 @@ split: break; } - free( kstr ); + cont_free( k2 ); idl_free( tmp ); idl_free( idl ); return( rc ); @@ -685,7 +714,6 @@ idl_delete_key ( ID_BLOCK *idl; unsigned i; int j, nids; - char *kstr; if ( (idl = idl_fetch_one( be, db, key ) ) == NULL ) { @@ -729,20 +757,17 @@ idl_delete_key ( */ for ( nids = 0; !ID_BLOCK_NOID(idl, nids); nids++ ) ; /* NULL */ - kstr = (char *) ch_malloc( key.dsize + CONT_SIZE ); + + cont_alloc( data, key ); for ( j = 0; !ID_BLOCK_NOID(idl, j); j++ ) { ID_BLOCK *tmp; - ldbm_datum_init( data ); - sprintf( kstr, "%c%ld%s", CONT_PREFIX, - ID_BLOCK_ID(idl, j), key.dptr ); - data.dptr = kstr; - data.dsize = strlen( kstr ) + 1; + cont_id( data, ID_BLOCK_ID(idl, j) ); if ( (tmp = idl_fetch_one( be, db, data )) == NULL ) { Debug( LDAP_DEBUG_ANY, - "idl_fetch of (%s) returns NULL\n", data.dptr, 0, 0 ); + "idl_delete_key: idl_fetch of returned NULL\n", 0, 0, 0 ); continue; } /* @@ -776,14 +801,15 @@ idl_delete_key ( idl_store( be, db, key, idl ); } idl_free( tmp ); - free( kstr ); + cont_free( data ); idl_free( idl ); return 0; } } idl_free( tmp ); } - free( kstr ); + + cont_free( data ); idl_free( idl ); return -1; } diff --git a/servers/slapd/back-ldbm/index.c b/servers/slapd/back-ldbm/index.c index 12db542582..0d93e525ea 100644 --- a/servers/slapd/back-ldbm/index.c +++ b/servers/slapd/back-ldbm/index.c @@ -1,7 +1,7 @@ /* index.c - routines for dealing with attribute indexes */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -15,446 +15,318 @@ #include "slap.h" #include "back-ldbm.h" -static int change_value(Backend *be, - DBCache *db, - char *type, - int indextype, - char *val, - ID id, - int - (*idl_func)(Backend *, DBCache *, Datum, ID)); -static int index2prefix(int indextype); - -int -index_add_entry( - Backend *be, - Entry *e -) +static index_mask( + Backend *be, + AttributeDescription *desc, + char **dbname, + char **atname ) { - Attribute *ap; - struct berval bv; - struct berval *bvals[2]; - - Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id, - e->e_dn, 0 ); - - /* - * dn index entry - make it look like an attribute so it works - * with index_change_values() call - */ - - bv.bv_val = ch_strdup( e->e_ndn ); - bv.bv_len = strlen( bv.bv_val ); - bvals[0] = &bv; - bvals[1] = NULL; - - /* add the dn to the indexes */ - { - char *dn = ch_strdup("dn"); - index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP ); - free( dn ); - } + AttributeType *at; + slap_index mask = 0; - free( bv.bv_val ); + /* we do support indexing of binary attributes */ + if( slap_ad_is_binary( desc ) ) return 0; - /* add each attribute to the indexes */ - for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) { - index_change_values( be, ap->a_type, ap->a_vals, e->e_id, - SLAP_INDEX_ADD_OP ); + attr_mask( be->be_private, desc->ad_cname->bv_val, &mask ); + + if( mask ) { + *atname = desc->ad_cname->bv_val; + *dbname = desc->ad_cname->bv_val; + return mask; } - Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id, - e->e_ndn, 0 ); - return( 0 ); -} + if( slap_ad_is_lang( desc ) ) { + /* has language tag */ + attr_mask( be->be_private, desc->ad_type->sat_cname, &mask ); -int -index_add_mods( - Backend *be, - LDAPModList *ml, - ID id -) -{ - int rc; - - for ( ; ml != NULL; ml = ml->ml_next ) { - LDAPMod *mod = &ml->ml_mod; - - switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) { - case LDAP_MOD_REPLACE: - /* XXX: Delete old index data==>problem when this - * gets called we lost values already! - */ - case LDAP_MOD_ADD: - rc = index_change_values( be, - mod->mod_type, - mod->mod_bvalues, - id, - SLAP_INDEX_ADD_OP ); - break; - case LDAP_MOD_DELETE: - rc = index_change_values( be, - mod->mod_type, - mod->mod_bvalues, - id, - SLAP_INDEX_DELETE_OP ); - break; - case LDAP_MOD_SOFTADD: /* SOFTADD means index was there */ - rc = 0; - break; + if( mask & SLAP_INDEX_AUTO_LANG ) { + *atname = desc->ad_cname->bv_val; + *dbname = desc->ad_type->sat_cname; + return mask; + } + if( mask & SLAP_INDEX_LANG ) { + *atname = desc->ad_type->sat_cname; + *dbname = desc->ad_type->sat_cname; + return mask; } + } - if ( rc != 0 ) { - return( rc ); + /* see if supertype defined mask for its subtypes */ + for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) { + attr_mask( be->be_private, at->sat_cname, &mask ); + + if( mask & SLAP_INDEX_AUTO_SUBTYPES ) { + *atname = desc->ad_type->sat_cname; + *dbname = at->sat_cname; + return mask; + } + if( mask & SLAP_INDEX_SUBTYPES ) { + *atname = at->sat_cname; + *dbname = at->sat_cname; + return mask; } + + if( mask ) break; } - return( 0 ); + return 0; } -ID_BLOCK * -index_read( - Backend *be, - char *type, - int indextype, - char *val -) +int index_param( + Backend *be, + AttributeDescription *desc, + int ftype, + char **dbnamep, + slap_index *maskp, + struct berval **prefixp ) { - DBCache *db; - Datum key; - ID_BLOCK *idl; - int indexmask, syntax; - char prefix; - char *realval, *tmpval; - char buf[BUFSIZ]; - - char *at_cn; - - ldbm_datum_init( key ); - - prefix = index2prefix( indextype ); - Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n", - prefix, type, val ); - - attr_masks( be->be_private, type, &indexmask, &syntax ); - if ( ! (indextype & indexmask) ) { - idl = idl_allids( be ); - Debug( LDAP_DEBUG_TRACE, - "<= index_read %ld candidates (allids - not indexed)\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); - } + slap_index mask; + char *dbname; + char *atname; - attr_normalize( type ); - at_cn = at_canonical_name( type ); + mask = index_mask( be, desc, &dbname, &atname ); - if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= index_read NULL (could not open %s%s)\n", at_cn, - LDBM_SUFFIX, 0 ); - return( NULL ); + if( mask == 0 ) { + return LDAP_INAPPROPRIATE_MATCHING; } - realval = val; - tmpval = NULL; - if ( prefix != UNKNOWN_PREFIX ) { - unsigned int len = strlen( val ); - - if ( (len + 2) < sizeof(buf) ) { - realval = buf; - } else { - /* value + prefix + null */ - tmpval = (char *) ch_malloc( len + 2 ); - realval = tmpval; + switch(ftype) { + case LDAP_FILTER_PRESENT: + if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { + goto done; + } + break; + + case LDAP_FILTER_APPROX: + if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { + goto done; } + /* fall thru */ - realval[0] = prefix; - strcpy( &realval[1], val ); - } + case LDAP_FILTER_EQUALITY: + if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { + goto done; + } + break; - key.dptr = realval; - key.dsize = strlen( realval ) + 1; + case LDAP_FILTER_SUBSTRINGS: + if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { + goto done; + } + break; - idl = idl_fetch( be, db, key ); - if ( tmpval != NULL ) { - free( tmpval ); + default: + return LDAP_OTHER; } - ldbm_cache_close( be, db ); + return LDAP_INAPPROPRIATE_MATCHING; - Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n", - idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); - return( idl ); +done: + *dbnamep = dbname; + *prefixp = ber_bvstrdup( atname ); + *maskp = mask; + return LDAP_SUCCESS; } -/* Add or remove stuff from index files */ - -static int -change_value( - Backend *be, - DBCache *db, - char *type, - int indextype, - char *val, - ID id, - int (*idl_func)(Backend *, DBCache *, Datum, ID) -) +static int indexer( + Backend *be, + char *dbname, + char *atname, + struct berval **vals, + ID id, + int op, + slap_index mask ) { - int rc; - Datum key; - char *tmpval = NULL; - char *realval = val; - char buf[BUFSIZ]; - - char prefix = index2prefix( indextype ); - - ldbm_datum_init( key ); - - Debug( LDAP_DEBUG_TRACE, - "=> change_value( \"%c%s\", op=%s )\n", - prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") ); - - if ( prefix != UNKNOWN_PREFIX ) { - unsigned int len = strlen( val ); - - if ( (len + 2) < sizeof(buf) ) { - realval = buf; - } else { - /* value + prefix + null */ - tmpval = (char *) ch_malloc( len + 2 ); - realval = tmpval; - } - realval[0] = prefix; - strcpy( &realval[1], val ); - } + int rc, i; + const char *text; + DBCache *db; + AttributeDescription *ad = NULL; + struct berval **keys; + struct berval prefix; - key.dptr = realval; - key.dsize = strlen( realval ) + 1; + assert( mask ); - rc = idl_func( be, db, key, id ); + rc = slap_str2ad( atname, &ad, &text ); - if ( tmpval != NULL ) { - free( tmpval ); - } - - ldap_pvt_thread_yield(); - - Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 ); - - return( rc ); - -}/* static int change_value() */ - - -int -index_change_values( - Backend *be, - char *type, - struct berval **vals, - ID id, - unsigned int op -) -{ - char *val, *p, *code, *w; - unsigned i, j, len; - int indexmask, syntax; - char buf[SUBLEN + 1]; - char vbuf[BUFSIZ]; - char *bigbuf; - DBCache *db; - - int (*idl_funct)(Backend *, - DBCache *, - Datum, ID); - char *at_cn; /* Attribute canonical name */ - int mode; - - if( vals == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "=> index_change_values( %s, NULL, %ld, op=%s )\n", - type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) ); - return 0; - } + if( rc != LDAP_SUCCESS ) return rc; - Debug( LDAP_DEBUG_TRACE, - "=> index_change_values( \"%s\", %ld, op=%s )\n", - type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) ); + prefix.bv_val = atname; + prefix.bv_len = strlen( atname ); + db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT ); - if (op == SLAP_INDEX_ADD_OP) { + if ( db == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= index_read NULL (could not open %s%s)\n", + dbname, LDBM_SUFFIX, 0 ); + ad_free( ad, 1 ); + return LDAP_OTHER; + } - /* Add values */ + if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { + key_change( be, db, &prefix, id, op ); + } - idl_funct = idl_insert_key; - mode = LDBM_WRCREAT; + if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { + rc = ad->ad_type->sat_equality->smr_indexer( + mask, + ad->ad_type->sat_syntax, + ad->ad_type->sat_equality, + &prefix, vals, &keys ); + + if( rc == LDAP_SUCCESS ) { + for( i= 0; keys[i] != NULL; i++ ) { + key_change( be, db, keys[i], id, op ); + } + } + } - } else { + if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { + rc = ad->ad_type->sat_approx->smr_indexer( + mask, + ad->ad_type->sat_syntax, + ad->ad_type->sat_approx, + &prefix, vals, &keys ); + + if( rc == LDAP_SUCCESS ) { + for( i= 0; keys[i] != NULL; i++ ) { + key_change( be, db, keys[i], id, op ); + } + } + } - /* Delete values */ + if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { + rc = ad->ad_type->sat_substr->smr_indexer( + mask, + ad->ad_type->sat_syntax, + ad->ad_type->sat_substr, + &prefix, vals, &keys ); + + if( rc == LDAP_SUCCESS ) { + for( i= 0; keys[i] != NULL; i++ ) { + key_change( be, db, keys[i], id, op ); + } + } + } - idl_funct = idl_delete_key; - mode = LDBM_WRITER; + ldbm_cache_close( be, db ); + ad_free( ad, 1 ); + return LDAP_SUCCESS; +} +static int index_at_values( + Backend *be, + AttributeType *type, + const char *lang, + struct berval **vals, + ID id, + int op, + char ** dbnamep, + slap_index *maskp ) +{ + slap_index mask; + slap_index tmpmask = 0; + int lindex = 0; + + if( type->sat_sup ) { + /* recurse */ + (void) index_at_values( be, + type->sat_sup, lang, + vals, id, op, + dbnamep, &tmpmask ); } - attr_normalize(type); - attr_masks( be->be_private, type, &indexmask, &syntax ); + attr_mask( be->be_private, type->sat_cname, &mask ); - if ( indexmask == 0 ) { - return( 0 ); + if( mask ) { + *dbnamep = type->sat_cname; + } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) { + mask = tmpmask; } - at_cn = at_canonical_name( type ); - - if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode )) - == NULL ) { - Debug( LDAP_DEBUG_ANY, - "<= index_change_values (couldn't open(%s%s),md=%s)\n", - at_cn, - LDBM_SUFFIX, - ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") ); - return( -1 ); + if( mask ) { + indexer( be, *dbnamep, + type->sat_cname, + vals, id, op, + mask ); } + if( lang ) { + char *dbname = NULL; + size_t tlen = strlen( type->sat_cname ); + size_t llen = strlen( lang ); + char *lname = ch_malloc( tlen + llen + sizeof(";") ); - for ( i = 0; vals[i] != NULL; i++ ) { - /* - * presence index entry - */ - if ( indexmask & INDEX_PRESENCE ) { + sprintf( lname, "%s;%s", type->sat_cname, lang ); - change_value( be, db, at_cn, INDEX_PRESENCE, - "*", id, idl_funct ); + attr_mask( be->be_private, lname, &tmpmask ); + if( tmpmask ) { + dbname = lname; + } else if ( mask & SLAP_INDEX_AUTO_LANG ) { + dbname = *dbnamep; + tmpmask = mask; } - Debug( LDAP_DEBUG_TRACE, - "index_change_values syntax 0x%x syntax bin 0x%x\n", - syntax, SYNTAX_BIN, 0 ); - - if ( syntax & SYNTAX_BIN ) { + if( dbname != NULL ) { + indexer( be, dbname, lname, + vals, id, op, + tmpmask ); + } - ldbm_cache_close( be, db ); - return( 0 ); + ch_free( lname ); + } - } + return LDAP_SUCCESS; +} - bigbuf = NULL; - len = vals[i]->bv_len; +int index_values( + Backend *be, + AttributeDescription *desc, + struct berval **vals, + ID id, + int op ) +{ + char *dbname = NULL; + slap_index mask; - /* value + null */ - if ( len + 2 > sizeof(vbuf) ) { - bigbuf = (char *) ch_malloc( len + 1 ); - val = bigbuf; - } else { - val = vbuf; - } - (void) memcpy( val, vals[i]->bv_val, len ); - val[len] = '\0'; + if( slap_ad_is_binary( desc ) ) { + /* binary attributes have no index capabilities */ + return LDAP_SUCCESS; + } - value_normalize( val, syntax ); + (void) index_at_values( be, + desc->ad_type, desc->ad_lang, + vals, id, op, + &dbname, &mask ); - /* value_normalize could change the length of val */ - len = strlen( val ); + return LDAP_SUCCESS; +} - /* - * equality index entry - */ - if ( indexmask & INDEX_EQUALITY ) { - - change_value( be, db, at_cn, INDEX_EQUALITY, - val, id, idl_funct); - } +int +index_entry( + Backend *be, + int op, + Entry *e, + Attribute *ap +) +{ - /* - * approximate index entry - */ - if ( indexmask & INDEX_APPROX ) { - for ( w = first_word( val ); w != NULL; - w = next_word( w ) ) { - if ( (code = phonetic( w )) != NULL ) { - change_value( be, - db, - at_cn, - INDEX_APPROX, - code, - id, - idl_funct ); - free( code ); - } - } - } + Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n", + op == SLAP_INDEX_ADD_OP ? "add" : "del", + e->e_id, e->e_dn ); - /* - * substrings index entry - */ - if ( indexmask & INDEX_SUB ) { - /* leading and trailing */ - if ( len > SUBLEN - 2 ) { - buf[0] = '^'; - for ( j = 0; j < SUBLEN - 1; j++ ) { - buf[j + 1] = val[j]; - } - buf[SUBLEN] = '\0'; - - change_value( be, db, at_cn, INDEX_SUB, - buf, id, idl_funct ); - - p = val + len - SUBLEN + 1; - for ( j = 0; j < SUBLEN - 1; j++ ) { - buf[j] = p[j]; - } - buf[SUBLEN - 1] = '$'; - buf[SUBLEN] = '\0'; - - change_value( be, db, at_cn, INDEX_SUB, - buf, id, idl_funct ); - } - - /* any */ - for ( p = val; p < (val + len - SUBLEN + 1); p++ ) { - for ( j = 0; j < SUBLEN; j++ ) { - buf[j] = p[j]; - } - buf[SUBLEN] = '\0'; - - change_value( be, db, at_cn, INDEX_SUB, - buf, id, idl_funct ); - } - } - if ( bigbuf != NULL ) { - free( bigbuf ); - } + /* add each attribute to the indexes */ + for ( ap; ap != NULL; ap = ap->a_next ) { + index_values( be, ap->a_desc, ap->a_vals, e->e_id, op ); } - ldbm_cache_close( be, db ); - - return( 0 ); + Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n", + op == SLAP_INDEX_ADD_OP ? "add" : "del", + e->e_id, e->e_dn ); + return LDAP_SUCCESS; } -static int -index2prefix( int indextype ) -{ - int prefix; - - switch ( indextype ) { - case INDEX_EQUALITY: - prefix = EQ_PREFIX; - break; - case INDEX_APPROX: - prefix = APPROX_PREFIX; - break; - case INDEX_SUB: - prefix = SUB_PREFIX; - break; - default: - prefix = UNKNOWN_PREFIX; - break; - } - - return( prefix ); -} diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index d7b6345e9f..5dcd6507b9 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -1,7 +1,7 @@ /* init.c - initialize ldbm backend */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -20,7 +20,7 @@ int back_ldbm_LTX_init_module(int argc, char *argv[]) { BackendInfo bi; - memset( &bi, 0, sizeof(bi) ); + memset( &bi, '\0', sizeof(bi) ); bi.bi_type = "ldbm"; bi.bi_init = ldbm_back_initialize; @@ -35,6 +35,13 @@ ldbm_back_initialize( BackendInfo *bi ) { + static char *controls[] = { + LDAP_CONTROL_MANAGEDSAIT, + NULL + }; + + bi->bi_controls = controls; + bi->bi_open = ldbm_back_open; bi->bi_config = 0; bi->bi_close = ldbm_back_close; @@ -56,6 +63,8 @@ ldbm_back_initialize( bi->bi_op_delete = ldbm_back_delete; bi->bi_op_abandon = ldbm_back_abandon; + bi->bi_extended = ldbm_back_extended; + bi->bi_entry_release_rw = ldbm_back_entry_release_rw; bi->bi_acl_group = ldbm_back_group; @@ -69,9 +78,14 @@ ldbm_back_initialize( bi->bi_tool_entry_get = ldbm_tool_entry_get; bi->bi_tool_entry_put = ldbm_tool_entry_put; bi->bi_tool_index_attr = ldbm_tool_index_attr; - bi->bi_tool_index_change = ldbm_tool_index_change; bi->bi_tool_sync = ldbm_tool_sync; +#ifdef HAVE_CYRUS_SASL + bi->bi_sasl_authorize = 0; + bi->bi_sasl_getsecret = 0; + bi->bi_sasl_putsecret = 0; +#endif /* HAVE_CYRUS_SASL */ + bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; @@ -116,7 +130,6 @@ ldbm_back_db_init( ) { struct ldbminfo *li; - char *argv[ 4 ]; /* allocate backend-database-specific stuff */ li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) ); @@ -130,8 +143,11 @@ ldbm_back_db_init( /* default database cache size */ li->li_dbcachesize = DEFAULT_DBCACHE_SIZE; - /* default cache mode is sync on write */ - li->li_dbcachewsync = 1; + /* default db mode is with locking */ + li->li_dblocking = 1; + + /* default db mode is with write synchronization */ + li->li_dbwritesync = 1; /* default file creation mode */ li->li_mode = DEFAULT_MODE; @@ -139,12 +155,6 @@ ldbm_back_db_init( /* default database directory */ li->li_directory = ch_strdup( DEFAULT_DB_DIRECTORY ); - argv[ 0 ] = "objectclass"; - argv[ 1 ] = "pres,eq"; - argv[ 2 ] = NULL; - attr_index_config( li, "ldbm objectclass initialization", - 0, 2, argv, 1 ); - /* initialize various mutex locks & condition variables */ ldap_pvt_thread_mutex_init( &li->li_root_mutex ); ldap_pvt_thread_mutex_init( &li->li_add_mutex ); diff --git a/servers/slapd/back-ldbm/key.c b/servers/slapd/back-ldbm/key.c new file mode 100644 index 0000000000..c8dc26e690 --- /dev/null +++ b/servers/slapd/back-ldbm/key.c @@ -0,0 +1,80 @@ +/* index.c - routines for dealing with attribute indexes */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-ldbm.h" + +/* read a key */ +int +key_read( + Backend *be, + DBCache *db, + struct berval *k, + ID_BLOCK **idout +) +{ + Datum key; + ID_BLOCK *idl; + + Debug( LDAP_DEBUG_TRACE, "=> key_read\n", 0, 0, 0 ); + + ldbm_datum_init( key ); + key.dptr = k->bv_val; + key.dsize = k->bv_len; + + idl = idl_fetch( be, db, key ); + + Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n", + idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 ); + + *idout = idl; + return LDAP_SUCCESS; +} + +/* Add or remove stuff from index files */ +int +key_change( + Backend *be, + DBCache *db, + struct berval *k, + ID id, + int op +) +{ + int rc; + Datum key; + + Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n", + op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id, 0 ); + + ldbm_datum_init( key ); + key.dptr = k->bv_val; + key.dsize = k->bv_len; + + if (op == SLAP_INDEX_ADD_OP) { + /* Add values */ + rc = idl_insert_key( be, db, key, id ); + + } else { + /* Delete values */ + rc = idl_delete_key( be, db, key, id ); + } + + + Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc, 0, 0 ); + + ldap_pvt_thread_yield(); + + return rc; +} diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index 770be8dbc2..7791816a6d 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -1,7 +1,7 @@ /* modify.c - ldbm backend modify routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -17,6 +17,10 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" +static int add_values LDAP_P(( Entry *e, Modification *mod, char *dn )); +static int delete_values LDAP_P(( Entry *e, Modification *mod, char *dn )); +static int replace_values LDAP_P(( Entry *e, Modification *mod, char *dn )); + /* We need this function because of LDAP modrdn. If we do not * add this there would be a bunch of code replication here * and there and of course the likelihood of bugs increases. @@ -27,66 +31,96 @@ int ldbm_modify_internal( Backend *be, Connection *conn, Operation *op, - char *dn, - LDAPModList *modlist, - Entry *e + const char *dn, + Modifications *modlist, + Entry *e, + const char **text ) { - int err; - LDAPMod *mod; - LDAPModList *ml; - Attribute *a; + int rc, err; + Modification *mod; + Modifications *ml; Attribute *save_attrs; - if ( (err = acl_check_modlist( be, conn, op, e, modlist )) - != LDAP_SUCCESS ) - { - send_ldap_result( conn, op, err, - NULL, NULL, NULL, NULL ); - return -1; + Debug(LDAP_DEBUG_TRACE, "ldbm_modify_internal:\n", 0, 0, 0); + + if ( !acl_check_modlist( be, conn, op, e, modlist )) { + return LDAP_INSUFFICIENT_ACCESS; } save_attrs = e->e_attrs; e->e_attrs = attrs_dup( e->e_attrs ); - for ( ml = modlist; ml != NULL; ml = ml->ml_next ) { - mod = &ml->ml_mod; + for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { + mod = &ml->sml_mod; - switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) { + switch ( mod->sm_op ) { case LDAP_MOD_ADD: + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: add\n", 0, 0, 0); err = add_values( e, mod, op->o_ndn ); + + if( err != LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", + err, text, 0); + *text = "modify: add values failed"; + } break; case LDAP_MOD_DELETE: + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: delete\n", 0, 0, 0); err = delete_values( e, mod, op->o_ndn ); + assert( err != LDAP_TYPE_OR_VALUE_EXISTS ); + if( err != LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", + err, text, 0); + *text = "modify: delete values failed"; + } break; case LDAP_MOD_REPLACE: + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: replace\n", 0, 0, 0); err = replace_values( e, mod, op->o_ndn ); + assert( err != LDAP_TYPE_OR_VALUE_EXISTS ); + if( err != LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", + err, text, 0); + *text = "modify: replace values failed"; + } break; - case LDAP_MOD_SOFTADD: + case SLAP_MOD_SOFTADD: + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: softadd\n", 0, 0, 0); /* Avoid problems in index_add_mods() * We need to add index if necessary. */ - mod->mod_op = LDAP_MOD_ADD; - if ( (err = add_values( e, mod, op->o_ndn )) - == LDAP_TYPE_OR_VALUE_EXISTS ) { - + mod->sm_op = LDAP_MOD_ADD; + err = add_values( e, mod, op->o_ndn ); + + if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; - mod->mod_op = LDAP_MOD_SOFTADD; - } + + if( err != LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", + err, text, 0); + *text = "modify: (soft)add values failed"; + } break; + + default: + Debug(LDAP_DEBUG_ANY, "ldbm_modify_internal: invalid op %d\n", + mod->sm_op, 0, 0); + *text = "Invalid modify operation"; + err = LDAP_OTHER; + Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", + err, text, 0); } if ( err != LDAP_SUCCESS ) { attrs_free( e->e_attrs ); e->e_attrs = save_attrs; /* unlock entry, delete from cache */ - send_ldap_result( conn, op, err, - NULL, NULL, NULL, NULL ); - return -1; + return err; } } @@ -96,18 +130,18 @@ int ldbm_modify_internal( attrs_free( e->e_attrs ); e->e_attrs = save_attrs; ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - return -1; + return SLAPD_ABANDON; } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); /* check that the entry still obeys the schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + rc = entry_schema_check( e, save_attrs, text ); + if ( rc != LDAP_SUCCESS ) { attrs_free( e->e_attrs ); e->e_attrs = save_attrs; - Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, NULL, NULL ); - return -1; + Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n", + *text, 0, 0 ); + return rc; } /* check for abandon */ @@ -116,49 +150,19 @@ int ldbm_modify_internal( attrs_free( e->e_attrs ); e->e_attrs = save_attrs; ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - return -1; + return SLAPD_ABANDON; } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - /* remove old indices */ - if( save_attrs != NULL ) { - for ( ml = modlist; ml != NULL; ml = ml->ml_next ) { - mod = &ml->ml_mod; - if( ( mod->mod_op & ~LDAP_MOD_BVALUES ) - == LDAP_MOD_REPLACE ) - { - /* Need to remove all values from indexes */ - a = attr_find( save_attrs, mod->mod_type ); - - if( a != NULL ) { - (void) index_change_values( be, - mod->mod_type, - a->a_vals, - e->e_id, - SLAP_INDEX_DELETE_OP); - } - } - } - attrs_free( save_attrs ); - } + /* delete indices for old attributes */ + index_entry_del( be, e, save_attrs); - /* modify indexes */ - if ( index_add_mods( be, modlist, e->e_id ) != 0 ) { - /* our indices are likely hosed */ - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return -1; - } + /* add indices for new attributes */ + index_entry_add( be, e, e->e_attrs); - /* check for abandon */ - ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); - if ( op->o_abandon ) { - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - return -1; - } - ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); + attrs_free( save_attrs ); - return 0; + return LDAP_SUCCESS; } @@ -167,19 +171,22 @@ ldbm_back_modify( Backend *be, Connection *conn, Operation *op, - char *dn, - LDAPModList *modlist + const char *dn, + const char *ndn, + Modifications *modlist ) { + int rc; struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *matched; Entry *e; int manageDSAit = get_manageDSAit( op ); + const char *text = NULL; Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0); /* acquire and lock entry */ - if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { + if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char* matched_dn = NULL; struct berval **refs = NULL; @@ -222,19 +229,27 @@ ldbm_back_modify( } /* Modify the entry */ - if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) { + rc = ldbm_modify_internal( be, conn, op, ndn, modlist, e, &text ); + + if( rc != LDAP_SUCCESS ) { + if( rc != SLAPD_ABANDON ) { + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + } + goto error_return; } /* change the entry itself */ if ( id2entry_add( be, e ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "id2entry failure", NULL, NULL ); goto error_return; } send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL ); + cache_return_entry_w( &li->li_cache, e ); return( 0 ); @@ -243,65 +258,121 @@ error_return:; return( -1 ); } -int +static int add_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { int i; Attribute *a; + /* char *desc = mod->sm_desc->ad_cname->bv_val; */ + MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; + + if( mr == NULL ) { + return LDAP_INAPPROPRIATE_MATCHING; + } + + + a = attr_find( e->e_attrs, mod->sm_desc ); + /* check if the values we're adding already exist */ - if ( (a = attr_find( e->e_attrs, mod->mod_type )) != NULL ) { - for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) { - if ( value_find( a->a_vals, mod->mod_bvalues[i], - a->a_syntax, 3 ) == 0 ) { - return( LDAP_TYPE_OR_VALUE_EXISTS ); + if ( a != NULL ) { + for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) { + int rc; + int j; + const char *text = NULL; + struct berval *asserted; + + rc = value_normalize( mod->sm_desc, + SLAP_MR_EQUALITY, + mod->sm_bvalues[i], + &asserted, + &text ); + + if( rc != LDAP_SUCCESS ) return rc; + + for ( j = 0; a->a_vals[j] != NULL; j++ ) { + int match; + int rc = value_match( &match, mod->sm_desc, mr, + a->a_vals[j], asserted, &text ); + + if( rc == LDAP_SUCCESS && match == 0 ) { + ber_bvfree( asserted ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } } + + ber_bvfree( asserted ); } } /* no - add them */ - if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) { - return( LDAP_CONSTRAINT_VIOLATION ); + if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) { + /* this should return result return of attr_merge */ + return LDAP_OTHER; } - return( LDAP_SUCCESS ); + return LDAP_SUCCESS; } -int +static int delete_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { int i, j, k, found; Attribute *a; + char *desc = mod->sm_desc->ad_cname->bv_val; + MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; + + if( mr == NULL || !mr->smr_match ) { + return LDAP_INAPPROPRIATE_MATCHING; + } /* delete the entire attribute */ - if ( mod->mod_bvalues == NULL ) { + if ( mod->sm_bvalues == NULL ) { Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", - mod->mod_type, 0, 0 ); - return( attr_delete( &e->e_attrs, mod->mod_type ) ? + desc, 0, 0 ); + return( attr_delete( &e->e_attrs, mod->sm_desc ) ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS ); } /* delete specific values - find the attribute first */ - if ( (a = attr_find( e->e_attrs, mod->mod_type )) == NULL ) { - Debug( LDAP_DEBUG_ARGS, "could not find attribute %s\n", - mod->mod_type, 0, 0 ); + if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) { + Debug( LDAP_DEBUG_ARGS, "ldap_modify_delete: " + "could not find attribute %s\n", + desc, 0, 0 ); return( LDAP_NO_SUCH_ATTRIBUTE ); } /* find each value to delete */ - for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) { + for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) { + int rc; + const char *text = NULL; + + struct berval *asserted; + + rc = value_normalize( mod->sm_desc, + SLAP_MR_EQUALITY, + mod->sm_bvalues[i], + &asserted, + &text ); + + if( rc != LDAP_SUCCESS ) return rc; + found = 0; for ( j = 0; a->a_vals[j] != NULL; j++ ) { - if ( value_cmp( mod->mod_bvalues[i], a->a_vals[j], - a->a_syntax, 3 ) != 0 ) { + int match; + int rc = value_match( &match, mod->sm_desc, mr, + a->a_vals[j], asserted, &text ); + + if( rc == LDAP_SUCCESS && match != 0 ) + { continue; } found = 1; @@ -317,8 +388,9 @@ delete_values( if ( a->a_vals[0] == NULL) { Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", - mod->mod_type, 0, 0 ); - if ( attr_delete( &e->e_attrs, mod->mod_type ) ) { + desc, 0, 0 ); + if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) { + ber_bvfree( asserted ); return LDAP_NO_SUCH_ATTRIBUTE; } } @@ -326,32 +398,38 @@ delete_values( break; } + ber_bvfree( asserted ); + /* looked through them all w/o finding it */ if ( ! found ) { Debug( LDAP_DEBUG_ARGS, - "could not find value for attr %s\n", - mod->mod_type, 0, 0 ); - return( LDAP_NO_SUCH_ATTRIBUTE ); + "ldbm_modify_delete: could not find value for attr %s\n", + desc, 0, 0 ); + return LDAP_NO_SUCH_ATTRIBUTE; } } - return( LDAP_SUCCESS ); + return LDAP_SUCCESS; } -int +static int replace_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { - (void) attr_delete( &e->e_attrs, mod->mod_type ); + int rc = attr_delete( &e->e_attrs, mod->sm_desc ); + + if( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) { + return rc; + } - if ( mod->mod_bvalues != NULL && - attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) + if ( mod->sm_bvalues != NULL && + attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) { - return( LDAP_CONSTRAINT_VIOLATION ); + return LDAP_OTHER; } - return( LDAP_SUCCESS ); + return LDAP_SUCCESS; } diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index 08300fbf68..3f1438fbf9 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -1,7 +1,7 @@ /* modrdn.c - ldbm backend modrdn routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -37,12 +37,14 @@ ldbm_back_modrdn( Backend *be, Connection *conn, Operation *op, - char *dn, - char *newrdn, + const char *dn, + const char *ndn, + const char *newrdn, int deleteoldrdn, - char *newSuperior + const char *newSuperior ) { + AttributeDescription *children = slap_schema.si_ad_children; struct ldbminfo *li = (struct ldbminfo *) be->be_private; char *p_dn = NULL, *p_ndn = NULL; char *new_dn = NULL, *new_ndn = NULL; @@ -50,6 +52,7 @@ ldbm_back_modrdn( Entry *matched; int rootlock = 0; int rc = -1; + const char *text = NULL; /* Added to support LDAP v2 correctly (deleteoldrdn thing) */ char *new_rdn_val = NULL; /* Val of new rdn */ char *new_rdn_type = NULL; /* Type of new rdn */ @@ -66,7 +69,7 @@ ldbm_back_modrdn( struct berval *add_bvals[2]; /* Stores new rdn att */ struct berval del_bv; /* Stores old rdn att */ struct berval *del_bvals[2]; /* Stores old rdn att */ - LDAPModList mod[2]; /* Used to delete old rdn */ + Modifications mod[2]; /* Used to delete old rdn */ int manageDSAit = get_manageDSAit( op ); Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n", @@ -74,7 +77,7 @@ ldbm_back_modrdn( 0, 0 ); /* get entry with writer lock */ - if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { + if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char* matched_dn = NULL; struct berval** refs = NULL; @@ -137,14 +140,14 @@ ldbm_back_modrdn( if( (p = dn2entry_w( be, p_ndn, NULL )) == NULL) { Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + send_ldap_result( conn, op, LDAP_OTHER, NULL, NULL, NULL, NULL ); goto return_results; } /* check parent for "children" acl */ if ( ! access_allowed( be, conn, op, p, - "children", NULL, ACL_WRITE ) ) + children, NULL, ACL_WRITE ) ) { Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); @@ -184,13 +187,14 @@ ldbm_back_modrdn( new_parent_dn = p_dn; /* New Parent unless newSuperior given */ - if ( (np_dn = newSuperior) != NULL) { + if ( newSuperior != NULL ) { Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: new parent requested...\n", - 0, 0, 0 ); + "ldbm_back_modrdn: new parent \"%s\" requested...\n", + newSuperior, 0, 0 ); + np_dn = ch_strdup( newSuperior ); np_ndn = ch_strdup( np_dn ); - (void) dn_normalize_case( np_ndn ); + (void) dn_normalize( np_ndn ); /* newSuperior == oldParent?, if so ==> ERROR */ /* newSuperior == entry being moved?, if so ==> ERROR */ @@ -200,7 +204,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: newSup(ndn=%s) not here!\n", np_ndn, 0, 0); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + send_ldap_result( conn, op, LDAP_OTHER, NULL, NULL, NULL, NULL ); goto return_results; } @@ -210,7 +214,7 @@ ldbm_back_modrdn( np, np->e_id, 0 ); /* check newSuperior for "children" acl */ - if ( !access_allowed( be, conn, op, np, "children", NULL, + if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) { Debug( LDAP_DEBUG_TRACE, @@ -257,7 +261,7 @@ ldbm_back_modrdn( new_ndn = ch_strdup(new_dn); - (void) dn_normalize_case( new_ndn ); + (void) dn_normalize( new_ndn ); Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n", new_ndn, 0, 0 ); @@ -290,7 +294,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out type of newrdn\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + NULL, "unknown type used in RDN", NULL, NULL ); goto return_results; } @@ -301,7 +305,7 @@ ldbm_back_modrdn( "ldbm_back_modrdn: can't figure out val of newrdn\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + NULL, "could not parse RDN value", NULL, NULL ); goto return_results; } @@ -313,40 +317,30 @@ ldbm_back_modrdn( /* Retrieve the old rdn from the entry's dn */ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) { - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: can't figure out old_rdn from dn\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "could not parse old DN", NULL, NULL ); goto return_results; - } if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) { - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: can't figure out the old_rdn type\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "count parse RDN from old DN", NULL, NULL ); goto return_results; - } if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) { - /* Not a big deal but we may say something */ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n", old_rdn_type, new_rdn_type, 0 ); - } -#ifdef DNS_DN - if ( dn_type( old_rdn ) == DN_X500 ) { -#endif - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n", 0, 0, 0 ); @@ -359,10 +353,24 @@ ldbm_back_modrdn( add_bv.bv_val = new_rdn_val; add_bv.bv_len = strlen(new_rdn_val); - mod[0].ml_type = new_rdn_type; - mod[0].ml_bvalues = add_bvals; - mod[0].ml_op = LDAP_MOD_SOFTADD; - mod[0].ml_next = NULL; + { + int rc; + + mod[0].sml_desc = NULL; + rc = slap_str2ad( new_rdn_type, &mod[0].sml_desc, &text ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "ldbm_back_modrdn: %s: %s (new)\n", + text, new_rdn_type, 0 ); + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + goto return_results; + } + } + mod[0].sml_bvalues = add_bvals; + mod[0].sml_op = SLAP_MOD_SOFTADD; + mod[0].sml_next = NULL; /* Remove old rdn value if required */ @@ -375,8 +383,8 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "could not parse value from old RDN", NULL, NULL ); goto return_results; } @@ -388,36 +396,31 @@ ldbm_back_modrdn( del_bv.bv_val = old_rdn_val; del_bv.bv_len = strlen(old_rdn_val); - /* No need to normalize old_rdn_type, delete_values() - * does that for us - */ - mod[0].ml_next = &mod[1]; - mod[1].ml_type = old_rdn_type; - mod[1].ml_bvalues = del_bvals; - mod[1].ml_op = LDAP_MOD_DELETE; - mod[1].ml_next = NULL; + { + int rc; + + mod[1].sml_desc = NULL; + rc = slap_str2ad( old_rdn_type, &mod[1].sml_desc, &text ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "ldbm_back_modrdn: %s: %s (old)\n", + text, old_rdn_type, 0 ); + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + goto return_results; + } + } + mod[0].sml_next = &mod[1]; + mod[1].sml_bvalues = del_bvals; + mod[1].sml_op = LDAP_MOD_DELETE; + mod[1].sml_next = NULL; Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: removing old_rdn_val=%s\n", old_rdn_val, 0, 0 ); } -#ifdef DNS_DN - } else { - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n", - 0, 0, 0 ); - /* XXXV3: not sure of what to do here */ - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: not fully implemented...\n", - 0, 0, 0 ); - - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - goto return_results; - - } -#endif - /* check for abandon */ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); if ( op->o_abandon ) { @@ -428,8 +431,8 @@ ldbm_back_modrdn( /* delete old one */ if ( dn2id_delete( be, e->e_ndn, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "DN index delete fail", NULL, NULL ); goto return_results; } @@ -446,14 +449,19 @@ ldbm_back_modrdn( /* add new one */ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "DN index add failed", NULL, NULL ); goto return_results; } /* modify memory copy of entry */ - if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e ) - != 0 ) { + rc = ldbm_modify_internal( be, conn, op, dn, &mod[0], e, &text ); + + if( rc != LDAP_SUCCESS ) { + if( rc != SLAPD_ABANDON ) { + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + } goto return_results; } @@ -467,8 +475,8 @@ ldbm_back_modrdn( /* id2entry index */ if ( id2entry_add( be, e ) != 0 ) { entry_free( e ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "entry update failed", NULL, NULL ); goto return_results; } diff --git a/servers/slapd/back-ldbm/nextid.c b/servers/slapd/back-ldbm/nextid.c index ebe6f38971..37cbfc5f05 100644 --- a/servers/slapd/back-ldbm/nextid.c +++ b/servers/slapd/back-ldbm/nextid.c @@ -1,7 +1,7 @@ /* nextid.c - keep track of the next id to be given out */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -77,8 +77,6 @@ next_id_write( Backend *be, ID id ) data.dsize = sizeof(ID); flags = LDBM_REPLACE; - if( li->li_dbcachewsync ) flags |= LDBM_SYNC; - if ( ldbm_cache_store( db, key, data, flags ) != 0 ) { id = NOID; } diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c new file mode 100644 index 0000000000..8f2c968db9 --- /dev/null +++ b/servers/slapd/back-ldbm/passwd.c @@ -0,0 +1,161 @@ +/* extended.c - ldbm backend extended routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-ldbm.h" +#include "proto-back-ldbm.h" + +int +ldbm_back_exop_passwd( + Backend *be, + Connection *conn, + Operation *op, + const char *reqoid, + struct berval *reqdata, + char **rspoid, + struct berval **rspdata, + LDAPControl *** rspctrls, + const char **text, + struct berval *** refs +) +{ + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + int rc; + Entry *e = NULL; + struct berval *hash = NULL; + + struct berval *id = NULL; + struct berval *new = NULL; + + char *dn; + + AttributeDescription *entry = slap_schema.si_ad_entry; + + assert( reqoid != NULL ); + assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, reqoid ) == 0 ); + + rc = slap_passwd_parse( reqdata, + &id, NULL, &new, text ); + + Debug( LDAP_DEBUG_ARGS, "==> ldbm_back_exop_passwd: \"%s\"\n", + id ? id->bv_val : "", 0, 0 ); + + if( rc != LDAP_SUCCESS ) { + goto done; + } + + if( new == NULL || new->bv_len == 0 ) { + new = slap_passwd_generate(); + + if( new == NULL || new->bv_len == 0 ) { + *text = "password generation failed."; + rc = LDAP_OTHER; + goto done; + } + + *rspdata = slap_passwd_return( new ); + } + + hash = slap_passwd_hash( new ); + + if( hash == NULL || hash->bv_len == 0 ) { + *text = "password hash failed"; + rc = LDAP_OTHER; + goto done; + } + + dn = id ? id->bv_val : op->o_dn; + + Debug( LDAP_DEBUG_TRACE, "passwd: \"%s\"%s\n", + dn, id ? " (proxy)" : "", 0 ); + + if( dn == NULL || dn[0] == '\0' ) { + *text = "No password is associated with the Root DSE"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + e = dn2entry_w( be, dn, NULL ); + + if( e == NULL ) { + *text = "could not locate authorization entry"; + rc = LDAP_OPERATIONS_ERROR; + goto done; + } + + if( ! access_allowed( be, conn, op, e, entry, NULL, ACL_WRITE ) ) { + *text = "access to authorization entry denied"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto done; + } + + if( is_entry_alias( e ) ) { + /* entry is an alias, don't allow operation */ + *text = "authorization entry is alias"; + rc = LDAP_ALIAS_PROBLEM; + goto done; + } + + rc = LDAP_OPERATIONS_ERROR; + + if( is_entry_referral( e ) ) { + /* entry is an referral, don't allow operation */ + *text = "authorization entry is referral"; + goto done; + } + + { + Modifications ml; + struct berval *vals[2]; + + vals[0] = hash; + vals[1] = NULL; + + ml.sml_desc = slap_schema.si_ad_userPassword; + ml.sml_bvalues = vals; + ml.sml_op = LDAP_MOD_REPLACE; + ml.sml_next = NULL; + + rc = ldbm_modify_internal( be, + conn, op, op->o_ndn, &ml, e, text ); + + } + + if( rc == LDAP_SUCCESS ) { + /* change the entry itself */ + if( id2entry_add( be, e ) != 0 ) { + *text = "entry update failed"; + rc = LDAP_OTHER; + } + } + +done: + if( e != NULL ) { + cache_return_entry_w( &li->li_cache, e ); + } + + if( id != NULL ) { + ber_bvfree( id ); + } + + if( new != NULL ) { + ber_bvfree( new ); + } + + if( hash != NULL ) { + ber_bvfree( hash ); + } + + return rc; +} diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index 1b466f4eb6..a50cc73196 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -19,10 +19,10 @@ LDAP_BEGIN_DECL Entry *deref_internal_r LDAP_P(( Backend *be, Entry *e, - char *dn, + const char *dn, int *err, Entry **matched, - char **text )); + const char **text )); #define deref_entry_r( be, e, err, matched, text ) \ deref_internal_r( be, e, NULL, err, matched, text ) @@ -33,11 +33,13 @@ Entry *deref_internal_r LDAP_P(( * attr.c */ -void attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask, - int *syntaxmask )); -void attr_index_config LDAP_P(( struct ldbminfo *li, +void attr_mask LDAP_P(( struct ldbminfo *li, + const char *desc, + slap_index *indexmask )); + +int attr_index_config LDAP_P(( struct ldbminfo *li, const char *fname, int lineno, - int argc, char **argv, int init )); + int argc, char **argv )); void attr_index_destroy LDAP_P(( Avlnode *tree )); /* @@ -60,7 +62,7 @@ void cache_release_all LDAP_P(( Cache *cache )); */ DBCache * ldbm_cache_open LDAP_P(( Backend *be, - char *name, char *suffix, int flags )); + const char *name, const char *suffix, int flags )); void ldbm_cache_close LDAP_P(( Backend *be, DBCache *db )); void ldbm_cache_really_close LDAP_P(( Backend *be, DBCache *db )); void ldbm_cache_flush_all LDAP_P(( Backend *be )); @@ -131,26 +133,59 @@ ID idl_nextid LDAP_P(( ID_BLOCK *idl, ID *cursor )); /* * index.c */ +extern int +index_param LDAP_P(( + Backend *be, + AttributeDescription *desc, + int ftype, + char **dbname, + slap_index *mask, + struct berval **prefix )); + +extern int +index_values LDAP_P(( + Backend *be, + AttributeDescription *desc, + struct berval **vals, + ID id, + int op )); + +int index_entry LDAP_P(( Backend *be, int r, Entry *e, Attribute *ap )); +#define index_entry_add(be,e,ap) index_entry((be),SLAP_INDEX_ADD_OP,(e),(ap)) +#define index_entry_del(be,e,ap) index_entry((be),SLAP_INDEX_DELETE_OP,(e),(ap)) -int index_add_entry LDAP_P(( Backend *be, Entry *e )); -int index_add_mods LDAP_P(( Backend *be, LDAPModList *ml, ID id )); -ID_BLOCK * index_read LDAP_P(( Backend *be, - char *type, int indextype, char *val )); -/* Possible operations supported (op) by index_change_values() */ -int index_change_values LDAP_P(( Backend *be, - char *type, - struct berval **vals, - ID id, - unsigned int op )); /* - * kerberos.c + * key.c */ +extern int +key_change LDAP_P(( + Backend *be, + DBCache *db, + struct berval *k, + ID id, + int op )); +extern int +key_read LDAP_P(( + Backend *be, + DBCache *db, + struct berval *k, + ID_BLOCK **idout )); -#ifdef HAVE_KERBEROS -/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */ -#endif +/* + * passwd.c + */ +extern int ldbm_back_exop_passwd LDAP_P(( BackendDB *bd, + Connection *conn, Operation *op, + const char *reqoid, + struct berval *reqdata, + char **rspoid, + struct berval **rspdata, + LDAPControl ***rspctrls, + const char **text, + struct berval *** refs )); + /* * modify.c * These prototypes are placed here because they are used by modify and @@ -163,12 +198,35 @@ int index_change_values LDAP_P(( Backend *be, * */ -int add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); -int delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); -int replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn )); +/* returns LDAP error code indicating error OR SLAPD_ABANDON */ int ldbm_modify_internal LDAP_P((Backend *be, Connection *conn, Operation *op, - char *dn, LDAPModList *mods, Entry *e)); + const char *dn, Modifications *mods, Entry *e, + const char ** )); + +#ifdef HAVE_CYRUS_SASL +/* + * sasl.c + */ +int ldbm_sasl_authorize LDAP_P(( + BackendDB *be, + const char *auth_identity, + const char *requested_user, + const char **user, + const char **errstring )); +int ldbm_sasl_getsecret LDAP_P(( + Backend *be, + const char *mechanism, + const char *auth_identity, + const char *realm, + sasl_secret_t **secret )); +int ldbm_sasl_putsecret LDAP_P(( + Backend *be, + const char *mechanism, + const char *auth_identity, + const char *realm, + const sasl_secret_t *secret )); +#endif /* HAVE_CYRUS_SASL */ /* * nextid.c diff --git a/servers/slapd/back-ldbm/sasl.c b/servers/slapd/back-ldbm/sasl.c new file mode 100644 index 0000000000..37e6c7afef --- /dev/null +++ b/servers/slapd/back-ldbm/sasl.c @@ -0,0 +1,59 @@ +/* bind.c - ldbm backend bind and unbind routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#ifdef HAVE_CYRUS_SASL + +#include "portable.h" + +#include + +#include +#include +#include +#include + +#include "slap.h" +#include "back-ldbm.h" +#include "proto-back-ldbm.h" + +int +back_ldbm_sasl_authorize( + BackendDB *be, + const char *auth_identity, + const char *requested_user, + const char **user, + const char **errstring) +{ + return SASL_FAIL; +} + +int +back_ldbm_sasl_getsecret( + Backend *be, + const char *mechanism, + const char *auth_identity, + const char *realm, + sasl_secret_t **secret) +{ + return SASL_FAIL; +} + +int +back_ldbm_sasl_putsecret( + Backend *be, + const char *mechanism, + const char *auth_identity, + const char *realm, + const sasl_secret_t *secret) +{ + return SASL_FAIL; +} + +#else +static int dummy = 1; +#endif + diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 2858e24961..36bbc008fa 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -1,7 +1,7 @@ /* search.c - ldbm backend search function */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -29,20 +29,21 @@ ldbm_back_search( Backend *be, Connection *conn, Operation *op, - char *base, + const char *base, + const char *nbase, int scope, int deref, int slimit, int tlimit, Filter *filter, - char *filterstr, + const char *filterstr, char **attrs, int attrsonly ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; int rc, err; - char *text; + const char *text = NULL; time_t stoptime; ID_BLOCK *candidates; ID id, cursor; @@ -57,10 +58,10 @@ ldbm_back_search( /* get entry with reader lock */ if ( deref & LDAP_DEREF_FINDING ) { - e = deref_dn_r( be, base, &err, &matched, &text ); + e = deref_dn_r( be, nbase, &err, &matched, &text ); } else { - e = dn2entry_r( be, base, &matched ); + e = dn2entry_r( be, nbase, &matched ); err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL; text = NULL; } @@ -127,7 +128,7 @@ ldbm_back_search( be->be_sizelimit : slimit; } - if ( scope == LDAP_SCOPE_BASE) { + if ( scope == LDAP_SCOPE_BASE ) { candidates = base_candidate( be, e ); } else { @@ -137,6 +138,7 @@ ldbm_back_search( /* need normalized dn below */ realbase = ch_strdup( e->e_ndn ); + cache_return_entry_r( &li->li_cache, e ); if ( candidates == NULL ) { @@ -189,7 +191,7 @@ ldbm_back_search( if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) { Entry *matched; int err; - char *text; + const char *text; e = deref_entry_r( be, e, &err, &matched, &text ); @@ -244,13 +246,13 @@ ldbm_back_search( } /* if it matches the filter and scope, send it */ - if ( test_filter( be, conn, op, e, filter ) == 0 ) { + if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) { char *dn; /* check scope */ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) { if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) { - (void) dn_normalize_case( dn ); + (void) dn_normalize( dn ); scopeok = (dn == realbase) ? 1 : (strcmp( dn, realbase ) ? 0 : 1 ); @@ -281,8 +283,52 @@ ldbm_back_search( } if (e) { - switch ( send_search_entry( be, conn, op, e, - attrs, attrsonly, NULL ) ) { + int result; +#ifdef BROKEN_NUM_SUBORDINATES + /* Tack on subordinates attr */ + ID_BLOCK *idl = NULL; + char CATTR_SUBS[] = "numsubordinates"; + + if (attrs && + charray_inlist(attrs, + CATTR_SUBS)) + { + idl = dn2idl(be, e->e_ndn, + DN_ONE_PREFIX); + if (idl) + { + char buf[30]; + struct berval val, *vals[2]; + + vals[0] = &val; + vals[1] = NULL; + + sprintf(buf, "%lu", + ID_BLOCK_NIDS(idl)); + + val.bv_val = buf; + val.bv_len = strlen(buf); + + attr_merge(e, CATTR_SUBS, + vals); + } + } +#endif + + result = send_search_entry(be, conn, op, + e, attrs, attrsonly, NULL); + +#ifdef BROKEN_NUM_SUBORDINATES + if (idl) + { + idl_free(idl); + attr_delete(&e->e_attrs, + CATTR_SUBS); + } +#endif + + switch (result) + { case 0: /* entry sent ok */ nentries++; break; @@ -355,91 +401,7 @@ search_candidates( ) { ID_BLOCK *candidates; - Filter *f, *rf, *af, *lf; - - Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n", - e->e_ndn, scope, deref ); - - f = NULL; - - if( !manageDSAit ) { - /* match referrals */ - rf = (Filter *) ch_malloc( sizeof(Filter) ); - rf->f_next = NULL; - rf->f_choice = LDAP_FILTER_OR; - rf->f_or = (Filter *) ch_malloc( sizeof(Filter) ); - rf->f_or->f_choice = LDAP_FILTER_EQUALITY; - rf->f_or->f_avtype = ch_strdup( "objectclass" ); - rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" ); - rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1; - rf->f_or->f_next = filter; - f = rf; - } else { - rf = NULL; - f = filter; - } - - if( deref & LDAP_DEREF_SEARCHING ) { - /* match aliases */ - af = (Filter *) ch_malloc( sizeof(Filter) ); - af->f_next = NULL; - af->f_choice = LDAP_FILTER_OR; - af->f_or = (Filter *) ch_malloc( sizeof(Filter) ); - af->f_or->f_choice = LDAP_FILTER_EQUALITY; - af->f_or->f_avtype = ch_strdup( "objectclass" ); - af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" ); - af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1; - af->f_or->f_next = f; - f = af; - } else { - af = NULL; - } - - if ( scope == LDAP_SCOPE_SUBTREE ) { - lf = (Filter *) ch_malloc( sizeof(Filter) ); - lf->f_next = NULL; - lf->f_choice = LDAP_FILTER_AND; - lf->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - - lf->f_and->f_choice = SLAPD_FILTER_DN_SUBTREE; - lf->f_and->f_dn = e->e_ndn; - - lf->f_and->f_next = f; - f = lf; - - } else if ( scope == LDAP_SCOPE_ONELEVEL ) { - lf = (Filter *) ch_malloc( sizeof(Filter) ); - lf->f_next = NULL; - lf->f_choice = LDAP_FILTER_AND; - lf->f_and = (Filter *) ch_malloc( sizeof(Filter) ); - - lf->f_and->f_choice = SLAPD_FILTER_DN_ONE; - lf->f_and->f_dn = e->e_ndn; - - lf->f_and->f_next = f; - f = lf; - - } else { - lf = NULL; - } - - candidates = filter_candidates( be, f ); - - /* free up filter additions we allocated above */ - if( lf != NULL ) { - free( lf->f_and ); - free( lf ); - } - - if( af != NULL ) { - af->f_or->f_next = NULL; - filter_free( af ); - } - - if( rf != NULL ) { - rf->f_or->f_next = NULL; - filter_free( rf ); - } + candidates = filter_candidates( be, filter ); return( candidates ); } diff --git a/servers/slapd/back-ldbm/startup.c b/servers/slapd/back-ldbm/startup.c deleted file mode 100644 index 8137e0bd1b..0000000000 --- a/servers/slapd/back-ldbm/startup.c +++ /dev/null @@ -1,103 +0,0 @@ -/* startup.c - startup ldbm backend */ -/* $OpenLDAP$ */ -/* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ - -#include "portable.h" - -#include -#include - -#include -#include - -#include "slap.h" -#include "back-ldbm.h" - -#ifdef HAVE_DB1_DB_H -# include -#else -# include -#endif - -#ifdef HAVE_BERKELEY_DB2 - -void -ldbm_db_errcall( const char *prefix, const char *message ) -{ - Debug( LDAP_DEBUG_ANY, "ldbm_db_errcall(): %s %s", prefix, message, 0 ); -} - -#endif /* HAVE_BERKELEY_DB2 */ - - -void -ldbm_back_startup( - Backend *be -) -{ -#ifndef HAVE_BERKELEY_DB2 - /* make sure we have one and only one big mutex */ - static int protect = 0; - - if(!protect++) { - ldap_pvt_thread_mutex_init( &ldbm_big_mutex ); - } - -#else - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - DB_ENV *dbEnv = &li->li_db_env; - u_int32_t envFlags = DB_CREATE | DB_THREAD; - int err = 0; - char *home; - - /* if the data directory is not an absolute path, have it relative - to the current working directory (which should not be configured !) */ - if ( *li->li_directory != *LDAP_DIRSEP ) { - char cwd[MAXPATHLEN]; - - (void) getcwd( cwd, MAXPATHLEN ); - sprintf( cwd, "%s" LDAP_DIRSEP "%s", cwd, li->li_directory ); - free( li->li_directory ); - li->li_directory = strdup( cwd ); - - } - - /* set the DB home directory to the data dir */ - home = li->li_directory; - - /* general initialization of the environment */ - memset( dbEnv, 0, sizeof( DB_ENV )); - dbEnv->db_errcall = ldbm_db_errcall; - dbEnv->db_errpfx = "==>"; - - /* now do the db_appinit */ - if ( ( err = db_appinit( home, NULL, dbEnv, envFlags )) ) { - char error[BUFSIZ]; - - if ( err < 0 ) sprintf( error, "%ld\n", (long) err ); - else sprintf( error, "%s\n", strerror( err )); - - fprintf( stderr, - "ldbm_back_startup(): FATAL error in db_appinit() : %s\n", - error ); - exit( EXIT_FAILURE ); - - } -#endif -} - - -void -ldbm_back_shutdown( - Backend *be -) -{ -#ifdef HAVE_BERKELEY_DB2 - struct ldbminfo *li = (struct ldbminfo *) be->be_private; - - (void) db_appexit( &li->li_db_env ); -#endif -} diff --git a/servers/slapd/back-ldbm/tools.c b/servers/slapd/back-ldbm/tools.c index 840449e473..1715465e69 100644 --- a/servers/slapd/back-ldbm/tools.c +++ b/servers/slapd/back-ldbm/tools.c @@ -1,7 +1,7 @@ /* tools.c - tools for slap tools */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -42,7 +42,7 @@ int ldbm_tool_entry_open( flags = LDBM_READER; } - li->li_dbcachewsync = 0; + li->li_dbwritesync = 0; if ( (id2entry = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, flags )) == NULL ) { @@ -63,7 +63,7 @@ int ldbm_tool_entry_close( assert( id2entry != NULL ); ldbm_cache_close( be, id2entry ); - li->li_dbcachewsync = 1; + li->li_dbwritesync = 1; id2entry = NULL; return 0; @@ -160,7 +160,7 @@ ID ldbm_tool_entry_put( Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n", e->e_id, e->e_dn, 0 ); - rc = index_add_entry( be, e ); + rc = index_entry_add( be, e, e->e_attrs ); if( rc != 0 ) { return NOID; @@ -194,23 +194,25 @@ ID ldbm_tool_entry_put( int ldbm_tool_index_attr( BackendDB *be, - char* type ) + AttributeDescription *desc +) { static DBCache *db = NULL; - int indexmask, syntaxmask; - char * at_cn; + slap_index indexmask; + char *at_cname; assert( slapMode & SLAP_TOOL_MODE ); - attr_masks( be->be_private, type, &indexmask, &syntaxmask ); + at_cname = desc->ad_cname->bv_val; - attr_normalize( type ); - at_cn = at_canonical_name( type ); + assert( desc != NULL ); + attr_mask( be->be_private, at_cname, &indexmask ); - if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_NEWDB )) - == NULL ) { + if ( (db = ldbm_cache_open( be, at_cname, LDBM_SUFFIX, LDBM_NEWDB )) + == NULL ) + { Debug( LDAP_DEBUG_ANY, - "<= index_read NULL (could not open %s%s)\n", at_cn, + "<= index_attr NULL (could not open %s%s)\n", at_cname, LDBM_SUFFIX, 0 ); return 0; } @@ -222,15 +224,14 @@ int ldbm_tool_index_attr( int ldbm_tool_index_change( BackendDB *be, - char* type, + AttributeDescription *desc, struct berval **bv, ID id, int op ) { assert( slapMode & SLAP_TOOL_MODE ); - index_change_values( be, - type, bv, id, op ); + index_values( be, desc, bv, id, op ); return 0; } diff --git a/servers/slapd/back-ldbm/unbind.c b/servers/slapd/back-ldbm/unbind.c index 69538da67b..d859d7a884 100644 --- a/servers/slapd/back-ldbm/unbind.c +++ b/servers/slapd/back-ldbm/unbind.c @@ -1,7 +1,7 @@ /* unbind.c - handle an ldap unbind operation */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ diff --git a/servers/slapd/back-passwd/Makefile.in b/servers/slapd/back-passwd/Makefile.in index 090ff008a0..a3a7aa5d05 100644 --- a/servers/slapd/back-passwd/Makefile.in +++ b/servers/slapd/back-passwd/Makefile.in @@ -14,7 +14,6 @@ LIBBASE = back_passwd XINCPATH = -I.. -I$(srcdir)/.. XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) all-local-lib: ../.backend diff --git a/servers/slapd/back-passwd/external.h b/servers/slapd/back-passwd/external.h index 92dd26e95d..1561c8d4a6 100644 --- a/servers/slapd/back-passwd/external.h +++ b/servers/slapd/back-passwd/external.h @@ -8,8 +8,10 @@ extern int passwd_back_initialize LDAP_P(( BackendInfo *bi )); extern int passwd_back_search LDAP_P(( BackendDB *be, Connection *c, Operation *o, - char *base, int scope, int deref, int slimit, int tlimit, - Filter *f, char *filterstr, char **attrs, int attrsonly)); + const char *base, const char *nbase, + int scope, int deref, int slimit, int tlimit, + Filter *f, const char *filterstr, + char **attrs, int attrsonly)); extern int passwd_back_db_config LDAP_P((BackendDB *bd, const char *fname, int lineno, int argc, char **argv )); diff --git a/servers/slapd/back-passwd/init.c b/servers/slapd/back-passwd/init.c index 609231dba4..3e310d49e4 100644 --- a/servers/slapd/back-passwd/init.c +++ b/servers/slapd/back-passwd/init.c @@ -15,7 +15,7 @@ int back_passwd_LTX_init_module(int argc, char *argv[]) { BackendInfo bi; - memset( &bi, 0, sizeof(bi) ); + memset( &bi, '\0', sizeof(bi) ); bi.bi_type = "passwd"; bi.bi_init = passwd_back_initialize; @@ -51,8 +51,16 @@ passwd_back_initialize( bi->bi_op_delete = 0; bi->bi_op_abandon = 0; + bi->bi_extended = 0; + bi->bi_acl_group = 0; +#ifdef HAVE_CYRUS_SASL + bi->bi_sasl_authorize = 0; + bi->bi_sasl_getsecret = 0; + bi->bi_sasl_putsecret = 0; +#endif /* HAVE_CYRUS_SASL */ + bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c index 68af4b3fa4..fbd84fd209 100644 --- a/servers/slapd/back-passwd/search.c +++ b/servers/slapd/back-passwd/search.c @@ -26,13 +26,14 @@ passwd_back_search( Backend *be, Connection *conn, Operation *op, - char *base, + const char *base, + const char *nbase, int scope, int deref, int slimit, int tlimit, Filter *filter, - char *filterstr, + const char *filterstr, char **attrs, int attrsonly ) @@ -50,6 +51,8 @@ passwd_back_search( char *matched = NULL; char *user = NULL; + AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; + tlimit = (tlimit > be->be_timelimit || tlimit < 1) ? be->be_timelimit : tlimit; stoptime = op->o_time + tlimit; @@ -65,7 +68,7 @@ passwd_back_search( #endif /* HAVE_SETPWFILE */ /* Handle a query for the base of this backend */ - if ( be_issuffix( be, base ) ) { + if ( be_issuffix( be, nbase ) ) { struct berval val, *vals[2]; vals[0] = &val; @@ -74,6 +77,9 @@ passwd_back_search( matched = ch_strdup( base ); if( scope != LDAP_SCOPE_ONELEVEL ) { + char *type; + AttributeDescription *desc = NULL; + /* Create an entry corresponding to the base DN */ e = (Entry *) ch_calloc(1, sizeof(Entry)); e->e_attrs = NULL; @@ -86,12 +92,30 @@ passwd_back_search( if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) { err = LDAP_INVALID_DN_SYNTAX; + free(rdn); goto done; } val.bv_val = rdn_attr_value(rdn); val.bv_len = strlen( val.bv_val ); - attr_merge( e, rdn_attr_type(rdn), vals ); + + type = rdn_attr_type(rdn); + + { + int rc; + const char *text; + rc = slap_str2ad( type, &desc, &text ); + + if( rc != LDAP_SUCCESS ) { + err = LDAP_NO_SUCH_OBJECT; + free(rdn); + goto done; + } + } + + attr_merge( e, desc, vals ); + + ad_free( desc, 1 ); free(rdn); rdn = NULL; @@ -104,10 +128,10 @@ passwd_back_search( * should be a configuratable item */ val.bv_val = "organizationalUnit"; - val.bv_len = strlen( val.bv_val ); - attr_merge( e, "objectClass", vals ); + val.bv_len = sizeof("organizationalUnit")-1; + attr_merge( e, ad_objectClass, vals ); - if ( test_filter( be, conn, op, e, filter ) == 0 ) { + if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) { send_search_entry( be, conn, op, e, attrs, attrsonly, NULL ); sent++; @@ -137,7 +161,7 @@ passwd_back_search( e = pw2entry( be, pw, NULL ); - if ( test_filter( be, conn, op, e, filter ) == 0 ) { + if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) { /* check size limit */ if ( --slimit == -1 ) { send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED, @@ -164,8 +188,8 @@ passwd_back_search( */ if( !be_issuffix( be, parent ) ) { int i; - for( i=0; be->be_suffix[i] != NULL; i++ ) { - if( dn_issuffix( base, be->be_suffix[i] ) ) { + for( i=0; be->be_nsuffix[i] != NULL; i++ ) { + if( dn_issuffix( nbase, be->be_nsuffix[i] ) ) { matched = ch_strdup( be->be_suffix[i] ); break; } @@ -185,8 +209,6 @@ passwd_back_search( goto done; } - user = ldap_pvt_str2lower( user ); - if ( (pw = getpwnam( user )) == NULL ) { matched = parent; parent = NULL; @@ -196,7 +218,7 @@ passwd_back_search( e = pw2entry( be, pw, rdn ); - if ( test_filter( be, conn, op, e, filter ) == 0 ) { + if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) { send_search_entry( be, conn, op, e, attrs, attrsonly, NULL ); sent++; @@ -226,6 +248,28 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn ) struct berval val; struct berval *vals[2]; + int rc; + const char *text; + + AttributeDescription *ad_objectClass = NULL; + AttributeDescription *ad_cn = NULL; + AttributeDescription *ad_sn = NULL; + AttributeDescription *ad_uid = NULL; + AttributeDescription *ad_description = NULL; + + rc = slap_str2ad( "objectClass", &ad_objectClass, &text ); + + if(rc != LDAP_SUCCESS) return NULL; + rc = slap_str2ad( "cn", &ad_cn, &text ); + if(rc != LDAP_SUCCESS) return NULL; + rc = slap_str2ad( "sn", &ad_sn, &text ); + if(rc != LDAP_SUCCESS) return NULL; + rc = slap_str2ad( "uid", &ad_uid, &text ); + if(rc != LDAP_SUCCESS) return NULL; + rc = slap_str2ad( "description", &ad_description, &text ); + if(rc != LDAP_SUCCESS) return NULL; + + vals[0] = &val; vals[1] = NULL; @@ -237,17 +281,30 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn ) e = (Entry *) ch_calloc( 1, sizeof(Entry) ); e->e_attrs = NULL; + /* objectclasses should be configuratable items */ + val.bv_val = "top"; + val.bv_len = sizeof("top")-1; + attr_merge( e, ad_objectClass, vals ); + + val.bv_val = "person"; + val.bv_len = sizeof("person")-1; + attr_merge( e, ad_objectClass, vals ); + + val.bv_val = "uidObject"; + val.bv_len = sizeof("uidObject")-1; + attr_merge( e, ad_objectClass, vals ); + /* rdn attribute type should be a configuratable item */ sprintf( buf, "uid=%s,%s", pw->pw_name, be->be_suffix[0] ); e->e_dn = ch_strdup( buf ); e->e_ndn = ch_strdup( buf ); - (void) dn_normalize_case( e->e_ndn ); + (void) dn_normalize( e->e_ndn ); val.bv_val = pw->pw_name; val.bv_len = strlen( pw->pw_name ); - attr_merge( e, "uid", vals ); /* required by uidObject */ - attr_merge( e, "cn", vals ); /* required by person */ - attr_merge( e, "sn", vals ); /* required by person */ + attr_merge( e, ad_uid, vals ); /* required by uidObject */ + attr_merge( e, ad_cn, vals ); /* required by person */ + attr_merge( e, ad_sn, vals ); /* required by person */ #ifdef HAVE_PW_GECOS /* @@ -260,7 +317,7 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn ) val.bv_val = pw->pw_gecos; val.bv_len = strlen(val.bv_val); - attr_merge(e, "description", vals); + attr_merge(e, ad_description, vals); s = strchr(val.bv_val, ','); if (s) @@ -277,22 +334,14 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn ) } val.bv_len = strlen(val.bv_val); if ( strcmp( val.bv_val, pw->pw_name )) - attr_merge( e, "cn", vals ); + attr_merge( e, ad_cn, vals ); if ( (s=strrchr(val.bv_val, ' '))) { val.bv_val = s + 1; val.bv_len = strlen(val.bv_val); - attr_merge(e, "sn", vals); + attr_merge(e, ad_sn, vals); } } #endif - /* objectclasses should be configuratable items */ - val.bv_val = "person"; - val.bv_len = strlen( val.bv_val ); - attr_merge( e, "objectclass", vals ); - - val.bv_val = "uidObject"; - val.bv_len = strlen( val.bv_val ); - attr_merge( e, "objectclass", vals ); return( e ); } diff --git a/servers/slapd/back-perl/Makefile.in b/servers/slapd/back-perl/Makefile.in deleted file mode 100644 index aaaf32df41..0000000000 --- a/servers/slapd/back-perl/Makefile.in +++ /dev/null @@ -1,35 +0,0 @@ -# $OpenLDAP$ -########################################################################### -# -# Copyright 1999, John C. Quillan, All rights reserved. -# -# Redistribution and use in source and binary forms are permitted only -# as authorized by the OpenLDAP Public License. A copy of this -# license is available at http://www.OpenLDAP.org/license.html or -# in file LICENSE in the top-level directory of the distribution. -# -########################################################################## - -SRCS = init.c search.c close.c config.c bind.c unbind.c compare.c \ - modify.c add.c modrdn.c delete.c -OBJS = init.lo search.lo close.lo config.lo bind.lo unbind.lo compare.lo \ - modify.lo add.lo modrdn.lo delete.lo - -LDAP_INCDIR= ../../../include -LDAP_LIBDIR= ../../../libraries - -BUILD_OPT = "--enable-perl" -BUILD_MOD = @BUILD_PERL@ -LINKAGE = @BUILD_PERL_DYNAMIC@ - -LIBBASE = back_perl - -XINCPATH = -I.. -I$(srcdir)/.. -XDEFS = $(PERL_CPPFLAGS) $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) - -all-local-lib: ../.backend - -../.backend: lib$(LIBBASE).a - @touch $@ - diff --git a/servers/slapd/back-perl/add.c b/servers/slapd/back-perl/add.c deleted file mode 100644 index 707b140f94..0000000000 --- a/servers/slapd/back-perl/add.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -int -perl_back_add( - Backend *be, - Connection *conn, - Operation *op, - Entry *e -) -{ - int len; - int count; - int return_code; - - PerlBackend *perl_back = (PerlBackend *) be->be_private; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - ldap_pvt_thread_mutex_lock( &entry2str_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp); - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( entry2str( e, &len ), 0 ))); - - PUTBACK; - - count = perl_call_method("add", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in back_search\n"); - } - - return_code = POPi; - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - } - - Debug( LDAP_DEBUG_ANY, "Here ADD\n", 0, 0, 0 ); - return( 0 ); -} diff --git a/servers/slapd/back-perl/bind.c b/servers/slapd/back-perl/bind.c deleted file mode 100644 index 9d20afd783..0000000000 --- a/servers/slapd/back-perl/bind.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" -/* init.c - initialize shell backend */ - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - - -/********************************************************** - * - * Bind - * - **********************************************************/ -int -perl_back_bind( - Backend *be, - Connection *conn, - Operation *op, - char *dn, - int method, - char *mech, - struct berval *cred, - char** edn -) -{ - int return_code; - int count; - - PerlBackend *perl_back = (PerlBackend *) be->be_private; - - *edn = NULL; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp); - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( dn , 0))); - XPUSHs(sv_2mortal(newSVpv( cred->bv_val , cred->bv_len))); - PUTBACK; - - count = perl_call_method("bind", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in back_search\n"); - } - - return_code = POPi; - - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - Debug( LDAP_DEBUG_ANY, "Perl BIND\n", 0, 0, 0 ); - - return ( return_code ); -} - - diff --git a/servers/slapd/back-perl/close.c b/servers/slapd/back-perl/close.c deleted file mode 100644 index 79b62afe2c..0000000000 --- a/servers/slapd/back-perl/close.c +++ /dev/null @@ -1,65 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" -/* init.c - initialize shell backend */ - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -/********************************************************** - * - * Close - * - **********************************************************/ - -int -perl_back_close( - BackendInfo *bd -) -{ - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - perl_destruct(perl_interpreter); - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - return 0; -} - -int -perl_back_destroy( - BackendInfo *bd -) -{ - perl_free(perl_interpreter); - perl_interpreter = NULL; - - ldap_pvt_thread_mutex_destroy( &perl_interpreter_mutex ); - - return 0; -} - -int -perl_back_db_destroy( - BackendDB *be -) -{ - free( be->be_private ); - be->be_private = NULL; -} diff --git a/servers/slapd/back-perl/compare.c b/servers/slapd/back-perl/compare.c deleted file mode 100644 index 4c9f3904ef..0000000000 --- a/servers/slapd/back-perl/compare.c +++ /dev/null @@ -1,85 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -/********************************************************** - * - * Compare - * - **********************************************************/ - -perl_back_compare( - Backend *be, - Connection *conn, - Operation *op, - char *dn, - Ava *ava -) -{ - int return_code; - int count; - - PerlBackend *perl_back = (PerlBackend *)be->be_private; - - send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, - NULL, "not yet implemented", NULL, NULL ); - -#ifdef notdef - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp); - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( dn , 0))); - /* XPUSHs(sv_2mortal(newSVpv( cred->bv_val , cred->bv_len))); */ - PUTBACK; - - count = perl_call_method("bind", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in back_search\n"); - } - - return_code = POPi; - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_COMPARE_TRUE, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_COMPARE_FALSE, NULL, NULL ); - } -#endif - - Debug( LDAP_DEBUG_ANY, "Here BIND\n", 0, 0, 0 ); - - return (0); -} - diff --git a/servers/slapd/back-perl/config.c b/servers/slapd/back-perl/config.c deleted file mode 100644 index f68a0a1282..0000000000 --- a/servers/slapd/back-perl/config.c +++ /dev/null @@ -1,134 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" -/* init.c - initialize shell backend */ - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - - -/********************************************************** - * - * Config - * - **********************************************************/ -int -perl_back_db_config( - BackendDB *be, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - SV* loc_sv; - PerlBackend *perl_back = (PerlBackend *) be->be_private; - char eval_str[EVAL_BUF_SIZE]; - int count ; - int args; - int return_code; - - - if ( strcasecmp( argv[0], "perlModule" ) == 0 ) { - if ( argc < 2 ) { - Debug( LDAP_DEBUG_ANY, - "%s.pm: line %d: missing module in \"perlModule \" line\n", - fname, lineno, 0 ); - return( 1 ); - } - - strncpy(eval_str, argv[1], EVAL_BUF_SIZE ); - - perl_require_pv( strcat( eval_str, ".pm" )); - - if (SvTRUE(GvSV(errgv))) { - fprintf(stderr , "Error %s\n", SvPV(GvSV(errgv), na)) ; - - } else { - dSP; ENTER; SAVETMPS; - PUSHMARK(sp); - XPUSHs(sv_2mortal(newSVpv(argv[1], 0))); - PUTBACK; - - count = perl_call_method("new", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in config\n") ; - } - - perl_back->pb_obj_ref = newSVsv(POPs); - - PUTBACK; FREETMPS; LEAVE ; - } - - } else if ( strcasecmp( argv[0], "perlModulePath" ) == 0 ) { - if ( argc < 2 ) { - fprintf( stderr, - "%s: line %d: missing module in \"PerlModulePath \" line\n", - fname, lineno ); - return( 1 ); - } - - sprintf( eval_str, "push @INC, '%s';", argv[1] ); - loc_sv = perl_eval_pv( eval_str, 0 ); - - } else { - /* - * Pass it to Perl module if defined - */ - - { - dSP ; ENTER ; SAVETMPS; - - PUSHMARK(sp) ; - XPUSHs( perl_back->pb_obj_ref ); - - /* Put all arguments on the perl stack */ - for( args = 0; args < argc; args++ ) { - XPUSHs(sv_2mortal(newSVpv(argv[args], 0))); - } - - PUTBACK ; - - count = perl_call_method("config", G_SCALAR); - - SPAGAIN ; - - if (count != 1) { - croak("Big trouble in config\n") ; - } - - return_code = POPi; - - PUTBACK ; FREETMPS ; LEAVE ; - - } - - /* if the module rejected it then we should reject it */ - if ( return_code != 0 ) { - fprintf( stderr, - "Unknown perl backeng config: %s\n", argv[0]); - exit( EXIT_FAILURE ); - } - } - - return 0; -} diff --git a/servers/slapd/back-perl/delete.c b/servers/slapd/back-perl/delete.c deleted file mode 100644 index 19d2346f9a..0000000000 --- a/servers/slapd/back-perl/delete.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include -/* #include -#include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -perl_back_delete( - Backend *be, - Connection *conn, - Operation *op, - char *dn -) -{ - int len; - int count; - int return_code; - - PerlBackend *perl_back = (PerlBackend *) be->be_private; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp); - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( dn , 0 ))); - - PUTBACK; - - count = perl_call_method("delete", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in perl-back_delete\n"); - } - - return_code = POPi; - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - } - - Debug( LDAP_DEBUG_ANY, "Here DELETE\n", 0, 0, 0 ); - return( 0 ); -} diff --git a/servers/slapd/back-perl/external.h b/servers/slapd/back-perl/external.h deleted file mode 100644 index d41fb13ea5..0000000000 --- a/servers/slapd/back-perl/external.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $OpenLDAP$ */ -#ifndef _PERL_EXTERNAL_H -#define _PERL_EXTERNAL_H - -LDAP_BEGIN_DECL - -extern int perl_back_initialize LDAP_P(( BackendInfo *bi )); -extern int perl_back_open LDAP_P(( BackendInfo *bi )); -extern int perl_back_close LDAP_P(( BackendInfo *bi )); -extern int perl_back_destroy LDAP_P(( BackendInfo *bi )); - -extern int perl_back_db_init LDAP_P(( BackendDB *bd )); -extern int perl_back_db_destroy LDAP_P(( BackendDB *bd )); - -extern int perl_back_db_config LDAP_P(( BackendDB *bd, - const char *fname, int lineno, int argc, char **argv )); - -extern int perl_back_bind LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, int method, char* mech, - struct berval *cred, char** edn )); - -extern int perl_back_unbind LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op )); - -extern int perl_back_search LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter *filter, char *filterstr, char **attrs, int attrsonly )); - -extern int perl_back_compare LDAP_P((BackendDB *bd, - Connection *conn, Operation *op, - char *dn, Ava *ava )); - -extern int perl_back_modify LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, LDAPModList *ml )); - -extern int perl_back_modrdn LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, - char *dn, char*newrdn, int deleteoldrdn, - char *newSuperior )); - -extern int perl_back_add LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, Entry *e )); - -extern int perl_back_delete LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, char *dn )); - -LDAP_END_DECL - -#endif /* _PERL_EXTERNAL_H */ - diff --git a/servers/slapd/back-perl/init.c b/servers/slapd/back-perl/init.c deleted file mode 100644 index e215acd2e6..0000000000 --- a/servers/slapd/back-perl/init.c +++ /dev/null @@ -1,124 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - /* init.c - initialize shell backend */ - -#include -/* #include - #include -*/ - - - -#include -#include - -#include "slap.h" -#include "perl_back.h" - - - -PerlInterpreter *perl_interpreter = NULL; -ldap_pvt_thread_mutex_t perl_interpreter_mutex; - -#ifdef SLAPD_PERL_DYNAMIC - -int back_perl_LTX_init_module(int argc, char *argv[]) { - BackendInfo bi; - - memset( &bi, 0, sizeof(bi) ); - bi.bi_type = "perl"; - bi.bi_init = perl_back_initialize; - - backend_add(&bi); - return 0; -} - -#endif /* SLAPD_PERL_DYNAMIC */ - - -/********************************************************** - * - * Init - * - **********************************************************/ - -int -perl_back_initialize( - BackendInfo *bi -) -{ - char *embedding[] = { "", "-e", "0" }; - - Debug( LDAP_DEBUG_TRACE, "perl backend open\n", 0, 0, 0 ); - - if( perl_interpreter != NULL ) { - Debug( LDAP_DEBUG_ANY, "perl backend open: already opened\n", - 0, 0, 0 ); - return 1; - } - - perl_interpreter = perl_alloc(); - perl_construct(perl_interpreter); - perl_parse(perl_interpreter, NULL, 3, embedding, (char **)NULL); - perl_run(perl_interpreter); - - bi->bi_open = perl_back_open; - bi->bi_config = 0; - bi->bi_close = perl_back_close; - bi->bi_destroy = perl_back_destroy; - - bi->bi_db_init = perl_back_db_init; - bi->bi_db_config = perl_back_db_config; - bi->bi_db_open = 0; - bi->bi_db_close = 0; - bi->bi_db_destroy = perl_back_db_destroy; - - bi->bi_op_bind = perl_back_bind; - bi->bi_op_unbind = perl_back_unbind; - bi->bi_op_search = perl_back_search; - bi->bi_op_compare = perl_back_compare; - bi->bi_op_modify = perl_back_modify; - bi->bi_op_modrdn = perl_back_modrdn; - bi->bi_op_add = perl_back_add; - bi->bi_op_delete = perl_back_delete; - bi->bi_op_abandon = 0; - - bi->bi_acl_group = 0; - - bi->bi_connection_init = 0; - bi->bi_connection_destroy = 0; - - return 0; -} - -int -perl_back_open( - BackendInfo *bi -) -{ - ldap_pvt_thread_mutex_init( &perl_interpreter_mutex ); - return 0; -} - -int -perl_back_db_init( - Backend *be -) -{ - be->be_private = (PerlBackend *) ch_malloc( sizeof(PerlBackend) ); - memset( be->be_private, 0, sizeof(PerlBackend)); - - Debug( LDAP_DEBUG_TRACE, "perl backend db init\n", 0, 0, 0 ); - - return 0; -} - diff --git a/servers/slapd/back-perl/modify.c b/servers/slapd/back-perl/modify.c deleted file mode 100644 index 028b42e136..0000000000 --- a/servers/slapd/back-perl/modify.c +++ /dev/null @@ -1,108 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -int -perl_back_modify( - Backend *be, - Connection *conn, - Operation *op, - char *dn, - LDAPModList *modlist -) -{ - char test[500]; - int return_code; - int count; - int i; - int err = 0; - char *matched = NULL, *info = NULL; - - PerlBackend *perl_back = (PerlBackend *)be->be_private; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp); - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( dn , 0))); - - for (; modlist != NULL; modlist = modlist->ml_next ) { - LDAPMod *mods = &modlist->ml_mod; - - switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) { - case LDAP_MOD_ADD: - XPUSHs(sv_2mortal(newSVpv("ADD", 0 ))); - break; - - case LDAP_MOD_DELETE: - XPUSHs(sv_2mortal(newSVpv("DELETE", 0 ))); - break; - - case LDAP_MOD_REPLACE: - XPUSHs(sv_2mortal(newSVpv("REPLACE", 0 ))); - break; - } - - - XPUSHs(sv_2mortal(newSVpv( mods->mod_type, 0 ))); - - for ( i = 0; - mods->mod_bvalues != NULL && mods->mod_bvalues[i] != NULL; - i++ ) - { - XPUSHs(sv_2mortal(newSVpv( mods->mod_bvalues[i]->bv_val, 0 ))); - } - } - - PUTBACK; - - count = perl_call_method("modify", G_SCALAR); - - SPAGAIN; - - if (count != 1) { - croak("Big trouble in back_search\n"); - } - - return_code = POPi; - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - } - - Debug( LDAP_DEBUG_ANY, "Perl MODIFY\n", 0, 0, 0 ); - return( 0 ); -} - diff --git a/servers/slapd/back-perl/modrdn.c b/servers/slapd/back-perl/modrdn.c deleted file mode 100644 index d74701418f..0000000000 --- a/servers/slapd/back-perl/modrdn.c +++ /dev/null @@ -1,97 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -/* - * LDAP v3 newSuperior support. - * - * Copyright 1999, Juan C. Gomez, All rights reserved. - * This software is not subject to any license of Silicon Graphics - * Inc. or Purdue University. - * - * Redistribution and use in source and binary forms are permitted - * without restriction or fee of any kind as long as this notice - * is preserved. - * - */ - -#include "portable.h" - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -int -perl_back_modrdn( - Backend *be, - Connection *conn, - Operation *op, - char *dn, - char *newrdn, - int deleteoldrdn, - char *newSuperior -) -{ - int len; - int count; - int return_code; - - PerlBackend *perl_back = (PerlBackend *) be->be_private; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp) ; - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( dn , 0 ))); - XPUSHs(sv_2mortal(newSVpv( newrdn , 0 ))); - XPUSHs(sv_2mortal(newSViv( deleteoldrdn ))); - if ( newSuperior != NULL ) { - XPUSHs(sv_2mortal(newSVpv( newSuperior , 0 ))); - } - PUTBACK ; - - count = perl_call_method("modrdn", G_SCALAR); - - SPAGAIN ; - - if (count != 1) { - croak("Big trouble in back_search\n") ; - } - - return_code = POPi; - - PUTBACK; FREETMPS; LEAVE ; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - } - - Debug( LDAP_DEBUG_ANY, "Perl MODRDN\n", 0, 0, 0 ); - return( 0 ); -} - - diff --git a/servers/slapd/back-perl/perl_back.h b/servers/slapd/back-perl/perl_back.h deleted file mode 100644 index 6e53a7f25f..0000000000 --- a/servers/slapd/back-perl/perl_back.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $OpenLDAP$ */ -#ifndef PERL_BACK_H -#define PERL_BACK_H 1 - -LDAP_BEGIN_DECL - -/* - */ -#define EVAL_BUF_SIZE 500 - -extern PerlInterpreter *perl_interpreter; -extern ldap_pvt_thread_mutex_t perl_interpreter_mutex; - -typedef struct perl_backend_instance { - char *pb_module_name; - SV *pb_obj_ref; -} PerlBackend; - -LDAP_END_DECL - -#include "external.h" - -#endif diff --git a/servers/slapd/back-perl/search.c b/servers/slapd/back-perl/search.c deleted file mode 100644 index 0feb28852d..0000000000 --- a/servers/slapd/back-perl/search.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - -/********************************************************** - * - * Search - * - **********************************************************/ -int -perl_back_search( - Backend *be, - Connection *conn, - Operation *op, - char *base, - int scope, - int deref, - int sizelimit, - int timelimit, - Filter *filter, - char *filterstr, - char **attrs, - int attrsonly - ) -{ - char test[500]; - int count ; - int err = 0; - char *matched = NULL, *info = NULL; - PerlBackend *perl_back = (PerlBackend *)be->be_private; - Entry *e; - char *buf; - int i; - int return_code; - - ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex ); - - { - dSP; ENTER; SAVETMPS; - - PUSHMARK(sp) ; - XPUSHs( perl_back->pb_obj_ref ); - XPUSHs(sv_2mortal(newSVpv( filterstr , 0))); - XPUSHs(sv_2mortal(newSViv( sizelimit ))); - XPUSHs(sv_2mortal(newSViv( timelimit ))); - XPUSHs(sv_2mortal(newSViv( attrsonly ))); - - for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) { - XPUSHs(sv_2mortal(newSVpv( attrs[i] , 0))); - } - PUTBACK; - - count = perl_call_method("search", G_ARRAY ); - - SPAGAIN; - - if (count < 1) { - croak("Big trouble in back_search\n") ; - } - - if ( count > 1 ) { - - for ( i = 1; i < count; i++ ) { - - buf = POPp; - - if ( (e = str2entry( buf )) == NULL ) { - Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", buf, 0, 0 ); - - } else { - send_search_entry( be, conn, op, - e, attrs, attrsonly, NULL ); - - entry_free( e ); - } - } - } - - /* - * We grab the return code last because the stack comes - * from perl in reverse order. - * - * ex perl: return ( 0, $res_1, $res_2 ); - * - * ex stack: <$res_2> <$res_1> <0> - */ - - return_code = POPi; - - - - PUTBACK; FREETMPS; LEAVE; - } - - ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex ); - - if( return_code != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - - } else { - send_ldap_result( conn, op, LDAP_SUCCESS, - NULL, NULL, NULL, NULL ); - } -} - diff --git a/servers/slapd/back-perl/unbind.c b/servers/slapd/back-perl/unbind.c deleted file mode 100644 index a79f9062f8..0000000000 --- a/servers/slapd/back-perl/unbind.c +++ /dev/null @@ -1,41 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1999, John C. Quillan, All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - /* init.c - initialize shell backend */ - -#include -/* #include - #include -*/ - -#include -#include - -#include "slap.h" -#include "perl_back.h" - - -/********************************************************** - * - * UnBind - * - **********************************************************/ -int -perl_back_unbind( - Backend *be, - Connection *conn, - Operation *op -) -{ - Debug( LDAP_DEBUG_TRACE, "Perl UNBIND\n", 0, 0, 0 ); - return 0; -} - diff --git a/servers/slapd/back-shell/Makefile.in b/servers/slapd/back-shell/Makefile.in index e0c052cc3d..d7f85df220 100644 --- a/servers/slapd/back-shell/Makefile.in +++ b/servers/slapd/back-shell/Makefile.in @@ -1,4 +1,6 @@ # $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file SRCS = init.c config.c fork.c search.c bind.c unbind.c add.c delete.c \ modify.c modrdn.c compare.c abandon.c result.c @@ -16,7 +18,6 @@ LIBBASE = back_shell XINCPATH = -I.. -I$(srcdir)/.. XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) all-local-lib: ../.backend diff --git a/servers/slapd/back-shell/abandon.c b/servers/slapd/back-shell/abandon.c index 4f2932793e..620b2939d4 100644 --- a/servers/slapd/back-shell/abandon.c +++ b/servers/slapd/back-shell/abandon.c @@ -1,5 +1,9 @@ /* abandon.c - shell backend abandon function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/servers/slapd/back-shell/add.c b/servers/slapd/back-shell/add.c index 293f3a8709..b2c7b80b95 100644 --- a/servers/slapd/back-shell/add.c +++ b/servers/slapd/back-shell/add.c @@ -1,5 +1,9 @@ /* add.c - shell backend add function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/servers/slapd/back-shell/bind.c b/servers/slapd/back-shell/bind.c index 44bd6cd5e2..aa5ef04ef9 100644 --- a/servers/slapd/back-shell/bind.c +++ b/servers/slapd/back-shell/bind.c @@ -1,5 +1,9 @@ /* bind.c - shell backend bind function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -16,9 +20,9 @@ shell_back_bind( Backend *be, Connection *conn, Operation *op, - char *dn, + const char *dn, + const char *ndn, int method, - char *mech, struct berval *cred, char **edn ) diff --git a/servers/slapd/back-shell/compare.c b/servers/slapd/back-shell/compare.c index 940f213fc5..c7c85f8d68 100644 --- a/servers/slapd/back-shell/compare.c +++ b/servers/slapd/back-shell/compare.c @@ -1,5 +1,9 @@ /* compare.c - shell backend compare function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -16,8 +20,9 @@ shell_back_compare( Backend *be, Connection *conn, Operation *op, - char *dn, - Ava *ava + const char *dn, + const char *ndn, + AttributeAssertion *ava ) { struct shellinfo *si = (struct shellinfo *) be->be_private; @@ -36,12 +41,19 @@ shell_back_compare( return( -1 ); } + /* + * FIX ME: This should use LDIF routines so that binary + * values are properly dealt with + */ + /* write out the request to the compare process */ fprintf( wfp, "COMPARE\n" ); fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid ); print_suffixes( wfp, be ); fprintf( wfp, "dn: %s\n", dn ); - fprintf( wfp, "%s: %s\n", ava->ava_type, ava->ava_value.bv_val ); + fprintf( wfp, "%s: %s\n", + ava->aa_desc->ad_cname->bv_val, + ava->aa_value->bv_val /* could be binary! */ ); fclose( wfp ); /* read in the result and send it along */ diff --git a/servers/slapd/back-shell/config.c b/servers/slapd/back-shell/config.c index 03c7b7da76..5fa4876a35 100644 --- a/servers/slapd/back-shell/config.c +++ b/servers/slapd/back-shell/config.c @@ -1,5 +1,9 @@ /* config.c - shell backend configuration file routine */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/servers/slapd/back-shell/delete.c b/servers/slapd/back-shell/delete.c index 27f67a2c63..feb737fe35 100644 --- a/servers/slapd/back-shell/delete.c +++ b/servers/slapd/back-shell/delete.c @@ -1,5 +1,9 @@ /* delete.c - shell backend delete function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -16,7 +20,8 @@ shell_back_delete( Backend *be, Connection *conn, Operation *op, - char *dn + const char *dn, + const char *ndn ) { struct shellinfo *si = (struct shellinfo *) be->be_private; diff --git a/servers/slapd/back-shell/external.h b/servers/slapd/back-shell/external.h index 64c2dce5bc..0ace4657f7 100644 --- a/servers/slapd/back-shell/external.h +++ b/servers/slapd/back-shell/external.h @@ -1,4 +1,8 @@ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #ifndef _SHELL_EXTERNAL_H #define _SHELL_EXTERNAL_H @@ -17,7 +21,7 @@ extern int shell_back_db_config LDAP_P(( BackendDB *bd, extern int shell_back_bind LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, int method, char* mech, + const char *dn, const char *ndn, int method, struct berval *cred, char** edn )); extern int shell_back_unbind LDAP_P(( BackendDB *bd, @@ -25,27 +29,33 @@ extern int shell_back_unbind LDAP_P(( BackendDB *bd, extern int shell_back_search LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter *filter, char *filterstr, char **attrs, int attrsonly )); + const char *base, const char *nbase, + int scope, int deref, int sizelimit, int timelimit, + Filter *filter, const char *filterstr, + char **attrs, int attrsonly )); extern int shell_back_compare LDAP_P((BackendDB *bd, Connection *conn, Operation *op, - char *dn, Ava *ava )); + const char *dn, const char *ndn, + AttributeAssertion *ava )); extern int shell_back_modify LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, LDAPModList *ml )); + const char *dn, const char *ndn, + Modifications *ml )); extern int shell_back_modrdn LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, - char *dn, char*newrdn, int deleteoldrdn, - char *newSuperior )); + const char *dn, const char *ndn, + const char *newrdn, int deleteoldrdn, + const char *newSuperior )); extern int shell_back_add LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, Entry *e )); extern int shell_back_delete LDAP_P(( BackendDB *bd, - Connection *conn, Operation *op, char *dn )); + Connection *conn, Operation *op, + const char *dn, const char *ndn )); extern int shell_back_abandon LDAP_P(( BackendDB *bd, Connection *conn, Operation *op, int msgid )); diff --git a/servers/slapd/back-shell/fork.c b/servers/slapd/back-shell/fork.c index 34adf8b5a3..ebe44be45c 100644 --- a/servers/slapd/back-shell/fork.c +++ b/servers/slapd/back-shell/fork.c @@ -1,5 +1,9 @@ /* fork.c - fork and exec a process, connecting stdin/out w/pipes */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/servers/slapd/back-shell/init.c b/servers/slapd/back-shell/init.c index 57c3742c4e..cb88e851f0 100644 --- a/servers/slapd/back-shell/init.c +++ b/servers/slapd/back-shell/init.c @@ -1,5 +1,9 @@ /* init.c - initialize shell backend */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -15,7 +19,7 @@ int back_shell_LTX_init_module(int argc, char *argv[]) { BackendInfo bi; - memset( &bi, 0, sizeof(bi) ); + memset( &bi, '\0', sizeof(bi) ); bi.bi_type = "shell"; bi.bi_init = shell_back_initialize; @@ -51,8 +55,16 @@ shell_back_initialize( bi->bi_op_delete = shell_back_delete; bi->bi_op_abandon = shell_back_abandon; + bi->bi_extended = 0; + bi->bi_acl_group = 0; +#ifdef HAVE_CYRUS_SASL + bi->bi_sasl_authorize = 0; + bi->bi_sasl_getsecret = 0; + bi->bi_sasl_putsecret = 0; +#endif /* HAVE_CYRUS_SASL */ + bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-shell/modify.c b/servers/slapd/back-shell/modify.c index 154bd2a6eb..4d97851eab 100644 --- a/servers/slapd/back-shell/modify.c +++ b/servers/slapd/back-shell/modify.c @@ -1,5 +1,9 @@ /* modify.c - shell backend modify function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -16,10 +20,12 @@ shell_back_modify( Backend *be, Connection *conn, Operation *op, - char *dn, - LDAPModList *ml + const char *dn, + const char *ndn, + Modifications *ml ) { + Modification *mod; struct shellinfo *si = (struct shellinfo *) be->be_private; FILE *rfp, *wfp; int i; @@ -42,25 +48,30 @@ shell_back_modify( fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid ); print_suffixes( wfp, be ); fprintf( wfp, "dn: %s\n", dn ); - for ( ; ml != NULL; ml = ml->ml_next ) { - switch ( ml->ml_op & ~LDAP_MOD_BVALUES ) { + for ( ; ml != NULL; ml = ml->sml_next ) { + mod = &ml->sml_mod; + + /* FIXME: should use LDIF routines to deal with binary data */ + + switch ( mod->sm_op ) { case LDAP_MOD_ADD: - fprintf( wfp, "add: %s\n", ml->ml_type ); + fprintf( wfp, "add: %s\n", mod->sm_desc->ad_cname->bv_val ); break; case LDAP_MOD_DELETE: - fprintf( wfp, "delete: %s\n", ml->ml_type ); + fprintf( wfp, "delete: %s\n", mod->sm_desc->ad_cname->bv_val ); break; case LDAP_MOD_REPLACE: - fprintf( wfp, "replace: %s\n", ml->ml_type ); + fprintf( wfp, "replace: %s\n", mod->sm_desc->ad_cname->bv_val ); break; } - for ( i = 0; ml->ml_bvalues != NULL && ml->ml_bvalues[i] - != NULL; i++ ) { - fprintf( wfp, "%s: %s\n", ml->ml_type, - ml->ml_bvalues[i]->bv_val ); + if( mod->sm_bvalues != NULL ) { + for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) { + fprintf( wfp, "%s: %s\n", mod->sm_desc->ad_cname->bv_val, + mod->sm_bvalues[i]->bv_val /* binary! */ ); + } } } fclose( wfp ); @@ -69,5 +80,4 @@ shell_back_modify( read_and_send_results( be, conn, op, rfp, NULL, 0 ); fclose( rfp ); return( 0 ); - } diff --git a/servers/slapd/back-shell/modrdn.c b/servers/slapd/back-shell/modrdn.c index 1df37d579c..ec831f1ce0 100644 --- a/servers/slapd/back-shell/modrdn.c +++ b/servers/slapd/back-shell/modrdn.c @@ -1,5 +1,9 @@ /* modrdn.c - shell backend modrdn function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * LDAP v3 newSuperior support. @@ -29,10 +33,11 @@ shell_back_modrdn( Backend *be, Connection *conn, Operation *op, - char *dn, - char *newrdn, + const char *dn, + const char *ndn, + const char *newrdn, int deleteoldrdn, - char *newSuperior + const char *newSuperior ) { struct shellinfo *si = (struct shellinfo *) be->be_private; diff --git a/servers/slapd/back-shell/result.c b/servers/slapd/back-shell/result.c index 4d9f39c2f5..113439b62a 100644 --- a/servers/slapd/back-shell/result.c +++ b/servers/slapd/back-shell/result.c @@ -1,5 +1,9 @@ /* result.c - shell backend result reading function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -43,8 +47,10 @@ read_and_send_results( } len = strlen( line ); while ( bp + len - buf > bsize ) { + size_t offset = bp - buf; bsize += BUFSIZ; buf = (char *) ch_realloc( buf, bsize ); + bp = &buf[offset]; } strcpy( bp, line ); bp += len; diff --git a/servers/slapd/back-shell/search.c b/servers/slapd/back-shell/search.c index b2b6587719..15560870c8 100644 --- a/servers/slapd/back-shell/search.c +++ b/servers/slapd/back-shell/search.c @@ -1,5 +1,9 @@ /* search.c - shell backend search function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -16,13 +20,14 @@ shell_back_search( Backend *be, Connection *conn, Operation *op, - char *base, + const char *base, + const char *nbase, int scope, int deref, int size, int time, Filter *filter, - char *filterstr, + const char *filterstr, char **attrs, int attrsonly ) diff --git a/servers/slapd/back-shell/searchexample.conf b/servers/slapd/back-shell/searchexample.conf index 4defa4ba65..864ab22a3a 100644 --- a/servers/slapd/back-shell/searchexample.conf +++ b/servers/slapd/back-shell/searchexample.conf @@ -1,4 +1,7 @@ -referral ldap://ldap.itd.umich.edu +# $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file + database shell -suffix "o=university of michigan, c=us" +suffix "dc=openldap,dc=org" search /usr/local/etc/searchexample.sh diff --git a/servers/slapd/back-shell/searchexample.sh b/servers/slapd/back-shell/searchexample.sh index 26b70fefbd..c0489d67d6 100644 --- a/servers/slapd/back-shell/searchexample.sh +++ b/servers/slapd/back-shell/searchexample.sh @@ -1,4 +1,7 @@ -#!/bin/sh +#! /bin/sh +# $OpenLDAP$ +## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file while [ 1 ]; do read TAG VALUE @@ -25,6 +28,8 @@ sleep 60 if [ $? = 0 ]; then echo $PWLINE | awk -F: '{ printf("dn: cn=%s,%s\n", $1, base); + printf("objectclass: top\n"); + printf("objectclass: person\n"); printf("cn: %s\n", $1); printf("cn: %s\n", $5); printf("sn: %s\n", $1); diff --git a/servers/slapd/back-shell/shell.h b/servers/slapd/back-shell/shell.h index 573f485e8d..bb72f0587f 100644 --- a/servers/slapd/back-shell/shell.h +++ b/servers/slapd/back-shell/shell.h @@ -1,5 +1,9 @@ /* shell.h - shell backend header file */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #ifndef SLAPD_SHELL_H #define SLAPD_SHELL_H diff --git a/servers/slapd/back-shell/unbind.c b/servers/slapd/back-shell/unbind.c index ca091da436..8cbd1116b9 100644 --- a/servers/slapd/back-shell/unbind.c +++ b/servers/slapd/back-shell/unbind.c @@ -1,5 +1,9 @@ /* unbind.c - shell backend unbind function */ /* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" diff --git a/servers/slapd/back-tcl/Makefile.in b/servers/slapd/back-tcl/Makefile.in deleted file mode 100644 index 6a565402e6..0000000000 --- a/servers/slapd/back-tcl/Makefile.in +++ /dev/null @@ -1,37 +0,0 @@ -# $OpenLDAP$ -########################################################################### -# -# Copyright 1999, Ben Collins , All rights reserved. -# -# Redistribution and use in source and binary forms are permitted only -# as authorized by the OpenLDAP Public License. A copy of this -# license is available at http://www.OpenLDAP.org/license.html or -# in file LICENSE in the top-level directory of the distribution. -# -########################################################################## - -SRCS = tcl_init.c tcl_search.c tcl_close.c tcl_config.c tcl_bind.c \ - tcl_unbind.c tcl_compare.c tcl_modify.c tcl_add.c tcl_modrdn.c \ - tcl_delete.c tcl_abandon.c tcl_util.c -OBJS = tcl_init.lo tcl_search.lo tcl_close.lo tcl_config.lo tcl_bind.lo \ - tcl_unbind.lo tcl_compare.lo tcl_modify.lo tcl_add.lo tcl_modrdn.lo \ - tcl_delete.lo tcl_abandon.lo tcl_util.lo - -LDAP_INCDIR= ../../../include -LDAP_LIBDIR= ../../../libraries - -BUILD_OPT = "--enable-tcl" -BUILD_MOD = @BUILD_TCL@ -LINKAGE = @BUILD_TCL_DYNAMIC@ - -LIBBASE = back_tcl - -XDEFS = $(MODULES_CPPFLAGS) -XLDFLAGS = $(MODULES_LDFLAGS) -XINCPATH = -I.. -I$(srcdir)/.. - -all-local-lib: ../.backend - -../.backend: lib$(LIBBASE).a - @touch $@ - diff --git a/servers/slapd/back-tcl/external.h b/servers/slapd/back-tcl/external.h deleted file mode 100644 index ece4c51e62..0000000000 --- a/servers/slapd/back-tcl/external.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenLDAP$ */ - -#ifndef _TCL_EXTERNAL_H -#define _TCL_EXTERNAL_H - -LDAP_BEGIN_DECL - -extern int tcl_back_initialize LDAP_P ((BackendInfo * bi)); -extern int tcl_back_open LDAP_P ((BackendInfo * bi)); -extern int tcl_back_close LDAP_P ((BackendInfo * bi)); -extern int tcl_back_destroy LDAP_P ((BackendInfo * bi)); - -extern int tcl_back_db_init LDAP_P ((BackendDB * bd)); -extern int tcl_back_db_open LDAP_P ((BackendDB * bd)); -extern int tcl_back_db_close LDAP_P ((BackendDB * bd)); -extern int tcl_back_db_destroy LDAP_P ((BackendDB * bd)); - -extern int tcl_back_db_config LDAP_P ((BackendDB * bd, - const char *fname, int lineno, int argc, char **argv)); - -extern int tcl_back_bind LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, - char *dn, int method, char *mech, - struct berval * cred, char **edn)); - -extern int tcl_back_unbind LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op)); - -extern int tcl_back_search LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, - char *base, int scope, int deref, int sizelimit, int timelimit, - Filter * filter, char *filterstr, char **attrs, int attrsonly)); - -extern int tcl_back_compare LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, - char *dn, Ava * ava)); - -extern int tcl_back_modify LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, - char *dn, LDAPModList * ml)); - -extern int tcl_back_modrdn LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, - char *dn, char *newrdn, int deleteoldrdn, - char *newSuperior)); - -extern int tcl_back_add LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, Entry * e)); - -extern int tcl_back_delete LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, char *dn)); - -extern int tcl_back_abandon LDAP_P ((BackendDB * bd, - Connection * conn, Operation * op, int msgid)); - -LDAP_END_DECL - -#endif /* _TCL_EXTERNAL_H */ diff --git a/servers/slapd/back-tcl/tcl_abandon.c b/servers/slapd/back-tcl/tcl_abandon.c deleted file mode 100644 index 5fcf8c5a28..0000000000 --- a/servers/slapd/back-tcl/tcl_abandon.c +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenLDAP$ */ -/* abandon.c - tcl abandon routine - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -int -tcl_back_abandon ( - Backend * be, - Connection * conn, - Operation * op, - int msgid -) -{ - char *suf_tcl, *results, *command; - int i, code, err = 0; - struct tclinfo *ti = (struct tclinfo *) be->be_private; - - if (ti->ti_abandon == NULL) { - return (-1); - } - - for (i = 0; be->be_suffix[i] != NULL; i++); - suf_tcl = Tcl_Merge (i, be->be_suffix); - - command = (char *) ch_malloc (strlen (ti->ti_abandon) + strlen (suf_tcl) - + 20); - sprintf (command, "%s ABANDON {%ld} {%s}", - ti->ti_abandon, op->o_msgid, suf_tcl); - Tcl_Free (suf_tcl); - - ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex); - code = Tcl_GlobalEval (ti->ti_ii->interp, command); - results = (char *) ch_strdup (ti->ti_ii->interp->result); - ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex); - free (command); - - if (code != TCL_OK) { - err = LDAP_OPERATIONS_ERROR; - Debug (LDAP_DEBUG_SHELL, "tcl_abandon_error: %s\n", results, - 0, 0); - } - - free (results); - return (err); -} diff --git a/servers/slapd/back-tcl/tcl_add.c b/servers/slapd/back-tcl/tcl_add.c deleted file mode 100644 index e2d324bba6..0000000000 --- a/servers/slapd/back-tcl/tcl_add.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $OpenLDAP$ */ -/* add.c - tcl add routine - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -int -tcl_back_add ( - Backend * be, - Connection * conn, - Operation * op, - Entry * e -) -{ - char *command, *suf_tcl, *entrystr, *results; - int i, code, err = 0; - struct tclinfo *ti = (struct tclinfo *) be->be_private; - - if (ti->ti_add == NULL) { - send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL, - "add not implemented", NULL, NULL ); - return (-1); - } - - for (i = 0; be->be_suffix[i] != NULL; i++); - suf_tcl = Tcl_Merge (i, be->be_suffix); - - entrystr = tcl_clean_entry (e); - - command = (char *) ch_malloc (strlen (ti->ti_add) + strlen - (suf_tcl) + - strlen (entrystr) + 32); - sprintf (command, "%s ADD {%ld} {%s} {%s}", - ti->ti_add, op->o_msgid, suf_tcl, entrystr); - Tcl_Free (suf_tcl); - free (entrystr); - - ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex); - code = Tcl_GlobalEval (ti->ti_ii->interp, command); - results = (char *) ch_strdup (ti->ti_ii->interp->result); - ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex); - free (command); - - if (code != TCL_OK) { - err = LDAP_OPERATIONS_ERROR; - Debug (LDAP_DEBUG_SHELL, "tcl_add_error: %s\n", results, 0, 0); - } else { - interp_send_results (be, conn, op, results, NULL, 0); - } - - if (err != LDAP_SUCCESS) - send_ldap_result (conn, op, err, NULL, - "internal backend error", NULL, NULL ); - - free (results); - return (err); -} diff --git a/servers/slapd/back-tcl/tcl_back.h b/servers/slapd/back-tcl/tcl_back.h deleted file mode 100644 index cba34eb176..0000000000 --- a/servers/slapd/back-tcl/tcl_back.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $OpenLDAP$ */ -/* tcl_back.h - tcl backend header (structs, functions) - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include - -#ifndef SLAPD_TCL_H -#define SLAPD_TCL_H - -#include -#include "external.h" - -extern ldap_pvt_thread_mutex_t tcl_interpreter_mutex; - -struct i_info { - Tcl_Interp *interp; - char *name; - struct i_info *next; - int count; -}; - -extern struct i_info *global_i; - -struct tclinfo { - char *script_path; - struct i_info *ti_ii; - char *ti_bind; - char *ti_unbind; - char *ti_search; - char *ti_compare; - char *ti_modify; - char *ti_modrdn; - char *ti_add; - char *ti_delete; - char *ti_abandon; -}; - -void readtclscript (char *script, Tcl_Interp * my_tcl); -char *tcl_clean_entry (Entry * e); - -int tcl_ldap_debug ( - ClientData clientData, - Tcl_Interp * interp, - int argc, - char *argv[] -); - -int interp_send_results ( - Backend * be, - Connection * conn, - Operation * op, - char *result, - char **attrs, - int attrsonly -); - -#endif diff --git a/servers/slapd/back-tcl/tcl_bind.c b/servers/slapd/back-tcl/tcl_bind.c deleted file mode 100644 index a26da559f9..0000000000 --- a/servers/slapd/back-tcl/tcl_bind.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $OpenLDAP$ */ -/* bind.c - tcl bind routines - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -int -tcl_back_bind ( - Backend * be, - Connection * conn, - Operation * op, - char *dn, - int method, - char *mech, - struct berval *cred, - char **edn -) -{ - char *command, *suf_tcl, *results; - int i, code, err = 0; - struct tclinfo *ti = (struct tclinfo *) be->be_private; - - *edn = NULL; - - if (ti->ti_bind == NULL) { - send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL, - "bind not implemented", NULL, NULL ); - return (-1); - } - - for (i = 0; be->be_suffix[i] != NULL; i++); - suf_tcl = Tcl_Merge (i, be->be_suffix); - - command = (char *) ch_malloc (strlen (ti->ti_bind) + strlen - (suf_tcl) + - strlen (dn) + strlen (cred->bv_val) + 64); - sprintf (command, "%s BIND {%ld} {%s} {%s} {%d} {%lu} {%s}", - ti->ti_bind, op->o_msgid, suf_tcl, dn, method, cred->bv_len, - cred->bv_val); - Tcl_Free (suf_tcl); - - ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex); - code = Tcl_GlobalEval (ti->ti_ii->interp, command); - results = (char *) ch_strdup (ti->ti_ii->interp->result); - ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex); - free (command); - - if (code != TCL_OK) { - err = LDAP_OPERATIONS_ERROR; - Debug (LDAP_DEBUG_SHELL, "tcl_bind_error: %s\n", results, 0, 0); - } else { - err = interp_send_results (be, conn, op, results, NULL, 0); - } - - if (err != LDAP_SUCCESS) - send_ldap_result (conn, op, err, NULL, - "internal backend error", NULL, NULL ); - - free (results); - return (err); -} diff --git a/servers/slapd/back-tcl/tcl_close.c b/servers/slapd/back-tcl/tcl_close.c deleted file mode 100644 index 4fb893a51e..0000000000 --- a/servers/slapd/back-tcl/tcl_close.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $OpenLDAP$ */ -/* close.c - tcl close routines - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -int -tcl_back_close ( - BackendInfo * bi -) -{ - Tcl_DeleteInterp (global_i->interp); - - return (0); -} - -int -tcl_back_destroy ( - BackendInfo * bi -) -{ - free (global_i->interp); - free (global_i); - ldap_pvt_thread_mutex_destroy (&tcl_interpreter_mutex); - - return (0); -} - -int -tcl_back_db_close ( - BackendDB * bd -) -{ - struct tclinfo *ti = (struct tclinfo *) bd->be_private; - struct i_info *ti_tmp; - - /* Disable the interp and associated struct */ - ti->ti_ii->count--; - if (!ti->ti_ii->count && strcasecmp ("default", ti->ti_ii->name)) { - /* no more db's using this and it's not the default */ - for (ti_tmp = global_i; ti_tmp->next != ti->ti_ii; ti_tmp - = ti_tmp->next); - /* This bypasses this interp struct in the global hash */ - ti_tmp->next = ti->ti_ii->next; - Tcl_DeleteInterp (ti->ti_ii->interp); - } - return (0); -} - -int -tcl_back_db_destroy ( - BackendDB * bd -) -{ - struct tclinfo *ti = (struct tclinfo *) bd->be_private; - - /* - * Now free up the allocated memory used - */ - ti->ti_ii->count--; - if (!ti->ti_ii->count && strcasecmp ("default", ti->ti_ii->name)) { - free (ti->ti_ii->interp); - free (ti->ti_ii); - free (ti); - } - free (bd->be_private); - bd->be_private = NULL; - - return (0); -} diff --git a/servers/slapd/back-tcl/tcl_compare.c b/servers/slapd/back-tcl/tcl_compare.c deleted file mode 100644 index 06d23f54de..0000000000 --- a/servers/slapd/back-tcl/tcl_compare.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $OpenLDAP$ */ -/* compare.c - tcl compare routines - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -int -tcl_back_compare ( - Backend * be, - Connection * conn, - Operation * op, - char *dn, - Ava * ava -) -{ - char *command, *suf_tcl, *results; - int i, code, err = 0; - struct tclinfo *ti = (struct tclinfo *) be->be_private; - - if (ti->ti_compare == NULL) { - send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL, - "compare not implemented", NULL, NULL ); - return (-1); - } - - for (i = 0; be->be_suffix[i] != NULL; i++); - suf_tcl = Tcl_Merge (i, be->be_suffix); - - command = (char *) ch_malloc (strlen (ti->ti_compare) + - strlen (suf_tcl) + strlen (dn) + strlen (ava->ava_type) + - strlen (ava->ava_value.bv_val) + 64); - sprintf (command, "%s COMPARE {%ld} {%s} {%s} {%s: %s}", - ti->ti_compare, op->o_msgid, suf_tcl, dn, ava->ava_type, - ava->ava_value.bv_val); - Tcl_Free (suf_tcl); - - ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex); - code = Tcl_GlobalEval (ti->ti_ii->interp, command); - results = (char *) ch_strdup (ti->ti_ii->interp->result); - ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex); - free (command); - - if (code != TCL_OK) { - err = LDAP_OPERATIONS_ERROR; - Debug (LDAP_DEBUG_SHELL, "tcl_compare_error: %s\n", results, - 0, 0); - } else { - interp_send_results (be, conn, op, results, NULL, 0); - } - - if (err != LDAP_SUCCESS) - send_ldap_result (conn, op, err, NULL, - "internal backend error", NULL, NULL ); - - free (results); - return (err); -} diff --git a/servers/slapd/back-tcl/tcl_config.c b/servers/slapd/back-tcl/tcl_config.c deleted file mode 100644 index 64174bca83..0000000000 --- a/servers/slapd/back-tcl/tcl_config.c +++ /dev/null @@ -1,182 +0,0 @@ -/* $OpenLDAP$ */ -/* config.c - tcl backend configuration file routine - * - * Copyright 1999, Ben Collins , All rights reserved. - * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. - */ - -#include "portable.h" - -#include - -#include "slap.h" -#include "tcl_back.h" - -struct i_info *global_i; - -int -tcl_back_db_config ( - BackendDB * bd, - const char *fname, - int lineno, - int argc, - char **argv -) -{ - struct tclinfo *ti = (struct tclinfo *) bd->be_private; - int script_loaded = 0; - - if (ti == NULL) { - fprintf (stderr, - "%s: line %d: tcl backend info is null!\n", fname, - lineno); - return (1); - } - if (ti->ti_ii == NULL) { - ti->ti_ii = global_i; - } - - /* Script to load */ - if (strcasecmp (argv[0], "scriptpath") == 0) { - if (argc < 2) { - Debug (LDAP_DEBUG_CONFIG, - "%s: line %d: missing script in \"scriptpath