From 9ed4414232dc652ea9419e6b673765fb45ccd564 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Sun, 3 Nov 2019 13:17:15 -0500 Subject: Issue mcp-graveyard/UXP#1258 - Part 2: Use binoc-central version of ldap --- ldap/c-sdk/common.mozbuild | 26 + ldap/c-sdk/liblber/bprint.c | 102 + ldap/c-sdk/liblber/decode.c | 833 ++++++++ ldap/c-sdk/liblber/dtest.c | 113 + ldap/c-sdk/liblber/encode.c | 699 ++++++ ldap/c-sdk/liblber/etest.c | 193 ++ ldap/c-sdk/liblber/idtest.c | 100 + ldap/c-sdk/liblber/io.c | 1757 +++++++++++++++ ldap/c-sdk/liblber/lber-int.h | 305 +++ ldap/c-sdk/liblber/moz.build | 23 + ldap/c-sdk/libldap/abandon.c | 303 +++ ldap/c-sdk/libldap/add.c | 225 ++ ldap/c-sdk/libldap/authzidctrl.c | 157 ++ ldap/c-sdk/libldap/bind.c | 170 ++ ldap/c-sdk/libldap/cache.c | 145 ++ ldap/c-sdk/libldap/charray.c | 248 +++ ldap/c-sdk/libldap/charset.c | 1845 ++++++++++++++++ ldap/c-sdk/libldap/cldap.c | 585 +++++ ldap/c-sdk/libldap/compare.c | 194 ++ ldap/c-sdk/libldap/compat.c | 108 + ldap/c-sdk/libldap/control.c | 559 +++++ ldap/c-sdk/libldap/countvalues.c | 67 + ldap/c-sdk/libldap/delete.c | 169 ++ ldap/c-sdk/libldap/disptmpl.c | 770 +++++++ ldap/c-sdk/libldap/dllmain.c | 178 ++ ldap/c-sdk/libldap/dsparse.c | 227 ++ ldap/c-sdk/libldap/error.c | 490 +++++ ldap/c-sdk/libldap/extendop.c | 275 +++ ldap/c-sdk/libldap/free.c | 156 ++ ldap/c-sdk/libldap/freevalues.c | 73 + ldap/c-sdk/libldap/friendly.c | 151 ++ ldap/c-sdk/libldap/getattr.c | 150 ++ ldap/c-sdk/libldap/getdn.c | 371 ++++ ldap/c-sdk/libldap/getdxbyname.c | 279 +++ ldap/c-sdk/libldap/geteffectiverightsctrl.c | 109 + ldap/c-sdk/libldap/getentry.c | 141 ++ ldap/c-sdk/libldap/getfilter.c | 553 +++++ ldap/c-sdk/libldap/getoption.c | 475 +++++ ldap/c-sdk/libldap/getvalues.c | 480 +++++ ldap/c-sdk/libldap/ldap-int.h | 888 ++++++++ ldap/c-sdk/libldap/libldap.def | 352 +++ ldap/c-sdk/libldap/memcache.c | 2244 ++++++++++++++++++++ ldap/c-sdk/libldap/message.c | 105 + ldap/c-sdk/libldap/modify.c | 226 ++ ldap/c-sdk/libldap/moz.build | 88 + ldap/c-sdk/libldap/mozock.c | 714 +++++++ ldap/c-sdk/libldap/nsprthreadtest.c | 621 ++++++ ldap/c-sdk/libldap/open.c | 912 ++++++++ ldap/c-sdk/libldap/os-ip.c | 1862 ++++++++++++++++ ldap/c-sdk/libldap/proxyauthctrl.c | 164 ++ ldap/c-sdk/libldap/psearch.c | 190 ++ ldap/c-sdk/libldap/pthreadtest.c | 1028 +++++++++ ldap/c-sdk/libldap/pwmodext.c | 265 +++ ldap/c-sdk/libldap/pwpctrl.c | 315 +++ ldap/c-sdk/libldap/referral.c | 177 ++ ldap/c-sdk/libldap/regex.c | 920 ++++++++ ldap/c-sdk/libldap/rename.c | 265 +++ ldap/c-sdk/libldap/request.c | 1659 +++++++++++++++ ldap/c-sdk/libldap/reslist.c | 86 + ldap/c-sdk/libldap/result.c | 1473 +++++++++++++ ldap/c-sdk/libldap/saslbind.c | 877 ++++++++ ldap/c-sdk/libldap/saslio.c | 635 ++++++ ldap/c-sdk/libldap/sbind.c | 214 ++ ldap/c-sdk/libldap/search.c | 1022 +++++++++ ldap/c-sdk/libldap/setoption.c | 411 ++++ ldap/c-sdk/libldap/sort.c | 355 ++++ ldap/c-sdk/libldap/sortctrl.c | 438 ++++ ldap/c-sdk/libldap/srchpref.c | 434 ++++ ldap/c-sdk/libldap/test.c | 1898 +++++++++++++++++ ldap/c-sdk/libldap/tmplout.c | 1144 ++++++++++ ldap/c-sdk/libldap/tmpltest.c | 319 +++ ldap/c-sdk/libldap/ufn.c | 563 +++++ ldap/c-sdk/libldap/unbind.c | 248 +++ ldap/c-sdk/libldap/unescape.c | 84 + ldap/c-sdk/libldap/url.c | 527 +++++ ldap/c-sdk/libldap/userstatusctrl.c | 228 ++ ldap/c-sdk/libldap/utf8.c | 282 +++ ldap/c-sdk/libldap/vlistctrl.c | 259 +++ ldap/c-sdk/libldap/whoami.c | 130 ++ ldap/c-sdk/libldif/libldif.def | 58 + ldap/c-sdk/libldif/line64.c | 612 ++++++ ldap/c-sdk/libldif/moz.build | 23 + ldap/c-sdk/libprldap/ldappr-dns.c | 166 ++ ldap/c-sdk/libprldap/ldappr-error.c | 335 +++ ldap/c-sdk/libprldap/ldappr-int.h | 139 ++ ldap/c-sdk/libprldap/ldappr-io.c | 744 +++++++ ldap/c-sdk/libprldap/ldappr-public.c | 454 ++++ ldap/c-sdk/libprldap/ldappr-threads.c | 643 ++++++ ldap/c-sdk/libprldap/libprldap.def | 59 + ldap/c-sdk/libprldap/moz.build | 31 + ldap/c-sdk/libraries/liblber/bprint.c | 102 - ldap/c-sdk/libraries/liblber/decode.c | 833 -------- ldap/c-sdk/libraries/liblber/dtest.c | 113 - ldap/c-sdk/libraries/liblber/encode.c | 699 ------ ldap/c-sdk/libraries/liblber/etest.c | 193 -- ldap/c-sdk/libraries/liblber/idtest.c | 100 - ldap/c-sdk/libraries/liblber/io.c | 1757 --------------- ldap/c-sdk/libraries/liblber/lber-int.h | 305 --- ldap/c-sdk/libraries/liblber/moz.build | 23 - ldap/c-sdk/libraries/libldap/abandon.c | 303 --- ldap/c-sdk/libraries/libldap/add.c | 225 -- ldap/c-sdk/libraries/libldap/authzidctrl.c | 157 -- ldap/c-sdk/libraries/libldap/bind.c | 170 -- ldap/c-sdk/libraries/libldap/cache.c | 145 -- ldap/c-sdk/libraries/libldap/charray.c | 248 --- ldap/c-sdk/libraries/libldap/charset.c | 1845 ---------------- ldap/c-sdk/libraries/libldap/cldap.c | 585 ----- ldap/c-sdk/libraries/libldap/compare.c | 194 -- ldap/c-sdk/libraries/libldap/compat.c | 108 - ldap/c-sdk/libraries/libldap/control.c | 559 ----- ldap/c-sdk/libraries/libldap/countvalues.c | 67 - ldap/c-sdk/libraries/libldap/delete.c | 169 -- ldap/c-sdk/libraries/libldap/disptmpl.c | 770 ------- ldap/c-sdk/libraries/libldap/dllmain.c | 178 -- ldap/c-sdk/libraries/libldap/dsparse.c | 227 -- ldap/c-sdk/libraries/libldap/error.c | 490 ----- ldap/c-sdk/libraries/libldap/extendop.c | 275 --- ldap/c-sdk/libraries/libldap/free.c | 156 -- ldap/c-sdk/libraries/libldap/freevalues.c | 73 - ldap/c-sdk/libraries/libldap/friendly.c | 151 -- ldap/c-sdk/libraries/libldap/getattr.c | 150 -- ldap/c-sdk/libraries/libldap/getdn.c | 371 ---- ldap/c-sdk/libraries/libldap/getdxbyname.c | 279 --- .../libraries/libldap/geteffectiverightsctrl.c | 109 - ldap/c-sdk/libraries/libldap/getentry.c | 141 -- ldap/c-sdk/libraries/libldap/getfilter.c | 553 ----- ldap/c-sdk/libraries/libldap/getoption.c | 475 ----- ldap/c-sdk/libraries/libldap/getvalues.c | 480 ----- ldap/c-sdk/libraries/libldap/ldap-int.h | 888 -------- ldap/c-sdk/libraries/libldap/libldap.def | 352 --- ldap/c-sdk/libraries/libldap/memcache.c | 2244 -------------------- ldap/c-sdk/libraries/libldap/message.c | 105 - ldap/c-sdk/libraries/libldap/modify.c | 226 -- ldap/c-sdk/libraries/libldap/moz.build | 88 - ldap/c-sdk/libraries/libldap/mozock.c | 714 ------- ldap/c-sdk/libraries/libldap/nsprthreadtest.c | 621 ------ ldap/c-sdk/libraries/libldap/open.c | 912 -------- ldap/c-sdk/libraries/libldap/os-ip.c | 1862 ---------------- ldap/c-sdk/libraries/libldap/proxyauthctrl.c | 164 -- ldap/c-sdk/libraries/libldap/psearch.c | 190 -- ldap/c-sdk/libraries/libldap/pthreadtest.c | 1028 --------- ldap/c-sdk/libraries/libldap/pwmodext.c | 265 --- ldap/c-sdk/libraries/libldap/pwpctrl.c | 315 --- ldap/c-sdk/libraries/libldap/referral.c | 177 -- ldap/c-sdk/libraries/libldap/regex.c | 920 -------- ldap/c-sdk/libraries/libldap/rename.c | 265 --- ldap/c-sdk/libraries/libldap/request.c | 1659 --------------- ldap/c-sdk/libraries/libldap/reslist.c | 86 - ldap/c-sdk/libraries/libldap/result.c | 1473 ------------- ldap/c-sdk/libraries/libldap/saslbind.c | 877 -------- ldap/c-sdk/libraries/libldap/saslio.c | 635 ------ ldap/c-sdk/libraries/libldap/sbind.c | 214 -- ldap/c-sdk/libraries/libldap/search.c | 1022 --------- ldap/c-sdk/libraries/libldap/setoption.c | 411 ---- ldap/c-sdk/libraries/libldap/sort.c | 355 ---- ldap/c-sdk/libraries/libldap/sortctrl.c | 438 ---- ldap/c-sdk/libraries/libldap/srchpref.c | 434 ---- ldap/c-sdk/libraries/libldap/test.c | 1898 ----------------- ldap/c-sdk/libraries/libldap/tmplout.c | 1144 ---------- ldap/c-sdk/libraries/libldap/tmpltest.c | 319 --- ldap/c-sdk/libraries/libldap/ufn.c | 563 ----- ldap/c-sdk/libraries/libldap/unbind.c | 248 --- ldap/c-sdk/libraries/libldap/unescape.c | 84 - ldap/c-sdk/libraries/libldap/url.c | 527 ----- ldap/c-sdk/libraries/libldap/userstatusctrl.c | 228 -- ldap/c-sdk/libraries/libldap/utf8.c | 282 --- ldap/c-sdk/libraries/libldap/vlistctrl.c | 259 --- ldap/c-sdk/libraries/libldap/whoami.c | 130 -- ldap/c-sdk/libraries/libldif/libldif.def | 58 - ldap/c-sdk/libraries/libldif/line64.c | 612 ------ ldap/c-sdk/libraries/libldif/moz.build | 23 - ldap/c-sdk/libraries/libprldap/ldappr-dns.c | 166 -- ldap/c-sdk/libraries/libprldap/ldappr-error.c | 335 --- ldap/c-sdk/libraries/libprldap/ldappr-int.h | 139 -- ldap/c-sdk/libraries/libprldap/ldappr-io.c | 744 ------- ldap/c-sdk/libraries/libprldap/ldappr-public.c | 454 ---- ldap/c-sdk/libraries/libprldap/ldappr-threads.c | 643 ------ ldap/c-sdk/libraries/libprldap/libprldap.def | 59 - ldap/c-sdk/libraries/libprldap/moz.build | 31 - ldap/c-sdk/libraries/moz.build | 11 - ldap/c-sdk/moz.build | 19 + ldap/ldap-sdk.mozbuild | 26 - ldap/moz.build | 11 +- ldap/xpcom/src/moz.build | 2 +- ldap/xpcom/src/nsLDAPURL.cpp | 25 + 185 files changed, 41737 insertions(+), 41711 deletions(-) create mode 100644 ldap/c-sdk/common.mozbuild create mode 100644 ldap/c-sdk/liblber/bprint.c create mode 100644 ldap/c-sdk/liblber/decode.c create mode 100644 ldap/c-sdk/liblber/dtest.c create mode 100644 ldap/c-sdk/liblber/encode.c create mode 100644 ldap/c-sdk/liblber/etest.c create mode 100644 ldap/c-sdk/liblber/idtest.c create mode 100644 ldap/c-sdk/liblber/io.c create mode 100644 ldap/c-sdk/liblber/lber-int.h create mode 100644 ldap/c-sdk/liblber/moz.build create mode 100644 ldap/c-sdk/libldap/abandon.c create mode 100644 ldap/c-sdk/libldap/add.c create mode 100644 ldap/c-sdk/libldap/authzidctrl.c create mode 100644 ldap/c-sdk/libldap/bind.c create mode 100644 ldap/c-sdk/libldap/cache.c create mode 100644 ldap/c-sdk/libldap/charray.c create mode 100644 ldap/c-sdk/libldap/charset.c create mode 100644 ldap/c-sdk/libldap/cldap.c create mode 100644 ldap/c-sdk/libldap/compare.c create mode 100644 ldap/c-sdk/libldap/compat.c create mode 100644 ldap/c-sdk/libldap/control.c create mode 100644 ldap/c-sdk/libldap/countvalues.c create mode 100644 ldap/c-sdk/libldap/delete.c create mode 100644 ldap/c-sdk/libldap/disptmpl.c create mode 100644 ldap/c-sdk/libldap/dllmain.c create mode 100644 ldap/c-sdk/libldap/dsparse.c create mode 100644 ldap/c-sdk/libldap/error.c create mode 100644 ldap/c-sdk/libldap/extendop.c create mode 100644 ldap/c-sdk/libldap/free.c create mode 100644 ldap/c-sdk/libldap/freevalues.c create mode 100644 ldap/c-sdk/libldap/friendly.c create mode 100644 ldap/c-sdk/libldap/getattr.c create mode 100644 ldap/c-sdk/libldap/getdn.c create mode 100644 ldap/c-sdk/libldap/getdxbyname.c create mode 100644 ldap/c-sdk/libldap/geteffectiverightsctrl.c create mode 100644 ldap/c-sdk/libldap/getentry.c create mode 100644 ldap/c-sdk/libldap/getfilter.c create mode 100644 ldap/c-sdk/libldap/getoption.c create mode 100644 ldap/c-sdk/libldap/getvalues.c create mode 100644 ldap/c-sdk/libldap/ldap-int.h create mode 100644 ldap/c-sdk/libldap/libldap.def create mode 100644 ldap/c-sdk/libldap/memcache.c create mode 100644 ldap/c-sdk/libldap/message.c create mode 100644 ldap/c-sdk/libldap/modify.c create mode 100644 ldap/c-sdk/libldap/moz.build create mode 100644 ldap/c-sdk/libldap/mozock.c create mode 100644 ldap/c-sdk/libldap/nsprthreadtest.c create mode 100644 ldap/c-sdk/libldap/open.c create mode 100644 ldap/c-sdk/libldap/os-ip.c create mode 100644 ldap/c-sdk/libldap/proxyauthctrl.c create mode 100644 ldap/c-sdk/libldap/psearch.c create mode 100644 ldap/c-sdk/libldap/pthreadtest.c create mode 100644 ldap/c-sdk/libldap/pwmodext.c create mode 100644 ldap/c-sdk/libldap/pwpctrl.c create mode 100644 ldap/c-sdk/libldap/referral.c create mode 100644 ldap/c-sdk/libldap/regex.c create mode 100644 ldap/c-sdk/libldap/rename.c create mode 100644 ldap/c-sdk/libldap/request.c create mode 100644 ldap/c-sdk/libldap/reslist.c create mode 100644 ldap/c-sdk/libldap/result.c create mode 100644 ldap/c-sdk/libldap/saslbind.c create mode 100644 ldap/c-sdk/libldap/saslio.c create mode 100644 ldap/c-sdk/libldap/sbind.c create mode 100644 ldap/c-sdk/libldap/search.c create mode 100644 ldap/c-sdk/libldap/setoption.c create mode 100644 ldap/c-sdk/libldap/sort.c create mode 100644 ldap/c-sdk/libldap/sortctrl.c create mode 100644 ldap/c-sdk/libldap/srchpref.c create mode 100644 ldap/c-sdk/libldap/test.c create mode 100644 ldap/c-sdk/libldap/tmplout.c create mode 100644 ldap/c-sdk/libldap/tmpltest.c create mode 100644 ldap/c-sdk/libldap/ufn.c create mode 100644 ldap/c-sdk/libldap/unbind.c create mode 100644 ldap/c-sdk/libldap/unescape.c create mode 100644 ldap/c-sdk/libldap/url.c create mode 100644 ldap/c-sdk/libldap/userstatusctrl.c create mode 100644 ldap/c-sdk/libldap/utf8.c create mode 100644 ldap/c-sdk/libldap/vlistctrl.c create mode 100644 ldap/c-sdk/libldap/whoami.c create mode 100644 ldap/c-sdk/libldif/libldif.def create mode 100644 ldap/c-sdk/libldif/line64.c create mode 100644 ldap/c-sdk/libldif/moz.build create mode 100644 ldap/c-sdk/libprldap/ldappr-dns.c create mode 100644 ldap/c-sdk/libprldap/ldappr-error.c create mode 100644 ldap/c-sdk/libprldap/ldappr-int.h create mode 100644 ldap/c-sdk/libprldap/ldappr-io.c create mode 100644 ldap/c-sdk/libprldap/ldappr-public.c create mode 100644 ldap/c-sdk/libprldap/ldappr-threads.c create mode 100644 ldap/c-sdk/libprldap/libprldap.def create mode 100644 ldap/c-sdk/libprldap/moz.build delete mode 100644 ldap/c-sdk/libraries/liblber/bprint.c delete mode 100644 ldap/c-sdk/libraries/liblber/decode.c delete mode 100644 ldap/c-sdk/libraries/liblber/dtest.c delete mode 100644 ldap/c-sdk/libraries/liblber/encode.c delete mode 100644 ldap/c-sdk/libraries/liblber/etest.c delete mode 100644 ldap/c-sdk/libraries/liblber/idtest.c delete mode 100644 ldap/c-sdk/libraries/liblber/io.c delete mode 100644 ldap/c-sdk/libraries/liblber/lber-int.h delete mode 100644 ldap/c-sdk/libraries/liblber/moz.build delete mode 100644 ldap/c-sdk/libraries/libldap/abandon.c delete mode 100644 ldap/c-sdk/libraries/libldap/add.c delete mode 100644 ldap/c-sdk/libraries/libldap/authzidctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/bind.c delete mode 100644 ldap/c-sdk/libraries/libldap/cache.c delete mode 100644 ldap/c-sdk/libraries/libldap/charray.c delete mode 100644 ldap/c-sdk/libraries/libldap/charset.c delete mode 100644 ldap/c-sdk/libraries/libldap/cldap.c delete mode 100644 ldap/c-sdk/libraries/libldap/compare.c delete mode 100644 ldap/c-sdk/libraries/libldap/compat.c delete mode 100644 ldap/c-sdk/libraries/libldap/control.c delete mode 100644 ldap/c-sdk/libraries/libldap/countvalues.c delete mode 100644 ldap/c-sdk/libraries/libldap/delete.c delete mode 100644 ldap/c-sdk/libraries/libldap/disptmpl.c delete mode 100644 ldap/c-sdk/libraries/libldap/dllmain.c delete mode 100644 ldap/c-sdk/libraries/libldap/dsparse.c delete mode 100644 ldap/c-sdk/libraries/libldap/error.c delete mode 100644 ldap/c-sdk/libraries/libldap/extendop.c delete mode 100644 ldap/c-sdk/libraries/libldap/free.c delete mode 100644 ldap/c-sdk/libraries/libldap/freevalues.c delete mode 100644 ldap/c-sdk/libraries/libldap/friendly.c delete mode 100644 ldap/c-sdk/libraries/libldap/getattr.c delete mode 100644 ldap/c-sdk/libraries/libldap/getdn.c delete mode 100644 ldap/c-sdk/libraries/libldap/getdxbyname.c delete mode 100644 ldap/c-sdk/libraries/libldap/geteffectiverightsctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/getentry.c delete mode 100644 ldap/c-sdk/libraries/libldap/getfilter.c delete mode 100644 ldap/c-sdk/libraries/libldap/getoption.c delete mode 100644 ldap/c-sdk/libraries/libldap/getvalues.c delete mode 100644 ldap/c-sdk/libraries/libldap/ldap-int.h delete mode 100644 ldap/c-sdk/libraries/libldap/libldap.def delete mode 100644 ldap/c-sdk/libraries/libldap/memcache.c delete mode 100644 ldap/c-sdk/libraries/libldap/message.c delete mode 100644 ldap/c-sdk/libraries/libldap/modify.c delete mode 100644 ldap/c-sdk/libraries/libldap/moz.build delete mode 100644 ldap/c-sdk/libraries/libldap/mozock.c delete mode 100644 ldap/c-sdk/libraries/libldap/nsprthreadtest.c delete mode 100644 ldap/c-sdk/libraries/libldap/open.c delete mode 100644 ldap/c-sdk/libraries/libldap/os-ip.c delete mode 100644 ldap/c-sdk/libraries/libldap/proxyauthctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/psearch.c delete mode 100644 ldap/c-sdk/libraries/libldap/pthreadtest.c delete mode 100644 ldap/c-sdk/libraries/libldap/pwmodext.c delete mode 100644 ldap/c-sdk/libraries/libldap/pwpctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/referral.c delete mode 100644 ldap/c-sdk/libraries/libldap/regex.c delete mode 100644 ldap/c-sdk/libraries/libldap/rename.c delete mode 100644 ldap/c-sdk/libraries/libldap/request.c delete mode 100644 ldap/c-sdk/libraries/libldap/reslist.c delete mode 100644 ldap/c-sdk/libraries/libldap/result.c delete mode 100644 ldap/c-sdk/libraries/libldap/saslbind.c delete mode 100644 ldap/c-sdk/libraries/libldap/saslio.c delete mode 100644 ldap/c-sdk/libraries/libldap/sbind.c delete mode 100644 ldap/c-sdk/libraries/libldap/search.c delete mode 100644 ldap/c-sdk/libraries/libldap/setoption.c delete mode 100644 ldap/c-sdk/libraries/libldap/sort.c delete mode 100644 ldap/c-sdk/libraries/libldap/sortctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/srchpref.c delete mode 100644 ldap/c-sdk/libraries/libldap/test.c delete mode 100644 ldap/c-sdk/libraries/libldap/tmplout.c delete mode 100644 ldap/c-sdk/libraries/libldap/tmpltest.c delete mode 100644 ldap/c-sdk/libraries/libldap/ufn.c delete mode 100644 ldap/c-sdk/libraries/libldap/unbind.c delete mode 100644 ldap/c-sdk/libraries/libldap/unescape.c delete mode 100644 ldap/c-sdk/libraries/libldap/url.c delete mode 100644 ldap/c-sdk/libraries/libldap/userstatusctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/utf8.c delete mode 100644 ldap/c-sdk/libraries/libldap/vlistctrl.c delete mode 100644 ldap/c-sdk/libraries/libldap/whoami.c delete mode 100644 ldap/c-sdk/libraries/libldif/libldif.def delete mode 100644 ldap/c-sdk/libraries/libldif/line64.c delete mode 100644 ldap/c-sdk/libraries/libldif/moz.build delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-dns.c delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-error.c delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-int.h delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-io.c delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-public.c delete mode 100644 ldap/c-sdk/libraries/libprldap/ldappr-threads.c delete mode 100644 ldap/c-sdk/libraries/libprldap/libprldap.def delete mode 100644 ldap/c-sdk/libraries/libprldap/moz.build delete mode 100644 ldap/c-sdk/libraries/moz.build create mode 100644 ldap/c-sdk/moz.build delete mode 100644 ldap/ldap-sdk.mozbuild (limited to 'ldap') diff --git a/ldap/c-sdk/common.mozbuild b/ldap/c-sdk/common.mozbuild new file mode 100644 index 0000000000..4377982c5a --- /dev/null +++ b/ldap/c-sdk/common.mozbuild @@ -0,0 +1,26 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +NO_VISIBILITY_FLAGS = True +DISABLE_STL_WRAPPING = True +ALLOW_COMPILER_WARNINGS = True + +if CONFIG['OS_TARGET'] == 'Linux': + DEFINES['LINUX'] = 1 + DEFINES['LINUX2_0'] = True + DEFINES['linux'] = 1 +elif CONFIG['OS_TARGET'] == 'Darwin': + DEFINES["DARWIN"] = 1 +elif CONFIG['OS_TARGET'] in ('OpenBSD', 'FreeBSD', 'NetBSD'): + DEFINES[CONFIG['OS_TARGET'].upper()] = True +elif CONFIG['OS_ARCH'] == 'WINNT': + DEFINES['_WINDOWS'] = True + +DEFINES['_PR_PTHREADS'] = True +DEFINES['NET_SSL'] = True +DEFINES['NS_DOMESTIC'] = True + +if CONFIG['MOZ_DEBUG']: + DEFINES['LDAP_DEBUG'] = True diff --git a/ldap/c-sdk/liblber/bprint.c b/ldap/c-sdk/liblber/bprint.c new file mode 100644 index 0000000000..7a7ccc01f2 --- /dev/null +++ b/ldap/c-sdk/liblber/bprint.c @@ -0,0 +1,102 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* bprint.c - a printing utility for debuging output */ +#include +#include "lber-int.h" + +#ifdef LDAP_DEBUG +/* + * Print arbitrary stuff, for debugging. + */ + +#define BPLEN 48 + +void +lber_bprint( char *data, int len ) +{ + static char hexdig[] = "0123456789abcdef"; + char out[ BPLEN ]; + int i = 0; + + memset( out, 0, BPLEN ); + for ( ;; ) { + if ( len < 1 ) { + char msg[BPLEN + 80]; + sprintf( msg, "\t%s\n", ( i == 0 ) ? "(end)" : out ); + ber_err_print( msg ); + break; + } + +#ifndef HEX + if ( isgraph( (unsigned char)*data )) { + out[ i ] = ' '; + out[ i+1 ] = *data; + } else { +#endif + out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; + out[ i+1 ] = hexdig[ *data & 0x0f ]; +#ifndef HEX + } +#endif + i += 2; + len--; + data++; + + if ( i > BPLEN - 2 ) { + char msg[BPLEN + 80]; + sprintf( msg, "\t%s\n", out ); + ber_err_print( msg ); + memset( out, 0, BPLEN ); + i = 0; + continue; + } + out[ i++ ] = ' '; + } +} + +#endif + +void ber_err_print( char *data ) +{ +#ifdef USE_DEBUG_WIN + OutputDebugString( data ); +#else + fputs( data, stderr ); + fflush( stderr ); +#endif +} diff --git a/ldap/c-sdk/liblber/decode.c b/ldap/c-sdk/liblber/decode.c new file mode 100644 index 0000000000..732dd6e646 --- /dev/null +++ b/ldap/c-sdk/liblber/decode.c @@ -0,0 +1,833 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ + +/* decode.c - ber input decoding routines */ + +#include "lber-int.h" + +/* + * Note: ber_get_tag() only uses the ber_end and ber_ptr elements of ber. + * If that changes, the ber_peek_tag() and/or ber_skip_tag() implementations + * will need to be changed. + */ +/* return the tag - LBER_DEFAULT returned means trouble */ +ber_tag_t +LDAP_CALL +ber_get_tag( BerElement *ber ) +{ + unsigned char xbyte; + ber_tag_t tag; + char *tagp; + int i; + + if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) + return( LBER_DEFAULT ); + + if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) + return( (ber_uint_t) xbyte ); + + tagp = (char *) &tag; + tagp[0] = xbyte; + for ( i = 1; i < sizeof(ber_int_t); i++ ) { + if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) + return( LBER_DEFAULT ); + + tagp[i] = xbyte; + + if ( ! (xbyte & LBER_MORE_TAG_MASK) ) + break; + } + + /* tag too big! */ + if ( i == sizeof(ber_int_t) ) + return( LBER_DEFAULT ); + + /* want leading, not trailing 0's */ + return( tag >> (sizeof(ber_int_t) - i - 1) ); +} + +/* + * Note: ber_skip_tag() only uses the ber_end and ber_ptr elements of ber. + * If that changes, the implementation of ber_peek_tag() will need to + * be changed. + */ +ber_tag_t +LDAP_CALL +ber_skip_tag( BerElement *ber, ber_len_t *len ) +{ + ber_tag_t tag; + unsigned char lc; + int noctets, diff; + ber_len_t netlen; + + /* + * Any ber element looks like this: tag length contents. + * Assuming everything's ok, we return the tag byte (we + * can assume a single byte), and return the length in len. + * + * Assumptions: + * 1) definite lengths + * 2) primitive encodings used whenever possible + */ + + /* + * First, we read the tag. + */ + + if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + + /* + * Next, read the length. The first byte contains the length of + * the length. If bit 8 is set, the length is the long form, + * otherwise it's the short form. We don't allow a length that's + * greater than what we can hold in an unsigned long. + */ + + *len = netlen = 0; + if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) + return( LBER_DEFAULT ); + if ( lc & 0x80 ) { + noctets = (lc & 0x7f); + if ( noctets > sizeof(ber_uint_t) ) + return( LBER_DEFAULT ); + diff = sizeof(ber_int_t) - noctets; + if ( ber_read( ber, (char *) &netlen + diff, noctets ) + != noctets ) + return( LBER_DEFAULT ); + *len = LBER_NTOHL( netlen ); + } else { + *len = lc; + } + + return( tag ); +} + + +/* + * Note: Previously, we passed the "ber" parameter directly to ber_skip_tag(), + * saving and restoring the ber_ptr element only. We now take advantage + * of the fact that the only ber structure elements touched by ber_skip_tag() + * are ber_end and ber_ptr. If that changes, this code must change too. + */ +ber_tag_t +LDAP_CALL +ber_peek_tag( BerElement *ber, ber_len_t *len ) +{ + BerElement bercopy; + + bercopy.ber_end = ber->ber_end; + bercopy.ber_ptr = ber->ber_ptr; + return( ber_skip_tag( &bercopy, len )); +} + +static int +ber_getnint( BerElement *ber, ber_int_t *num, ber_slen_t len ) +{ + int i; + ber_int_t value; + unsigned char buffer[sizeof(ber_int_t)]; + /* + * The tag and length have already been stripped off. We should + * be sitting right before len bytes of 2's complement integer, + * ready to be read straight into an int. We may have to sign + * extend after we read it in. + */ + + if ( len > sizeof(ber_slen_t) ) + return( -1 ); + + /* read into the low-order bytes of netnum */ + if ( ber_read( ber, (char *) buffer, len ) != len ) + return( -1 ); + + /* This sets the required sign extension */ + if ( len != 0) { + value = 0x80 & buffer[0] ? (-1) : 0; + } else { + value = 0; + } + + for ( i = 0; i < len; i++ ) + value = (value << 8) | buffer[i]; + + *num = value; + + return( len ); +} + +ber_tag_t +LDAP_CALL +ber_get_int( BerElement *ber, ber_int_t *num ) +{ + ber_tag_t tag; + ber_len_t len; + + if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + + /* + * len is being demoted to a long here -- possible conversion error + */ + + if ( ber_getnint( ber, num, (int)len ) != (ber_slen_t)len ) + return( LBER_DEFAULT ); + else + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_stringb( BerElement *ber, char *buf, ber_len_t *len ) +{ + ber_len_t datalen; + ber_tag_t tag; +#ifdef STR_TRANSLATION + char *transbuf; +#endif /* STR_TRANSLATION */ + + if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + if ( datalen > (*len - 1) ) + return( LBER_DEFAULT ); + + /* + * datalen is being demoted to a long here -- possible conversion error + */ + + if ( ber_read( ber, buf, datalen ) != (ber_slen_t) datalen ) + return( LBER_DEFAULT ); + + buf[datalen] = '\0'; + +#ifdef STR_TRANSLATION + if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) + != 0 && ber->ber_decode_translate_proc != NULL ) { + transbuf = buf; + ++datalen; + if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen, + 0 ) != 0 ) { + return( LBER_DEFAULT ); + } + if ( datalen > *len ) { + NSLBERI_FREE( transbuf ); + return( LBER_DEFAULT ); + } + SAFEMEMCPY( buf, transbuf, datalen ); + NSLBERI_FREE( transbuf ); + --datalen; + } +#endif /* STR_TRANSLATION */ + + *len = datalen; + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_stringa( BerElement *ber, char **buf ) +{ + ber_len_t datalen, ndatalen; + ber_tag_t tag; + + if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + + if ( ((ndatalen = (size_t)datalen + 1) < (size_t) datalen) || + ( datalen > (ber->ber_end - ber->ber_ptr) ) || + ( (*buf = (char *)NSLBERI_MALLOC( (size_t)ndatalen )) == NULL )) + return( LBER_DEFAULT ); + + /* + * datalen is being demoted to a long here -- possible conversion error + */ + if ( ber_read( ber, *buf, datalen ) != (ber_slen_t) datalen ) { + NSLBERI_FREE( *buf ); + *buf = NULL; + return( LBER_DEFAULT ); + } + + (*buf)[datalen] = '\0'; + +#ifdef STR_TRANSLATION + if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) + != 0 && ber->ber_decode_translate_proc != NULL ) { + ++datalen; + if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 ) + != 0 ) { + NSLBERI_FREE( *buf ); + *buf = NULL; + return( LBER_DEFAULT ); + } + } +#endif /* STR_TRANSLATION */ + + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_stringal( BerElement *ber, struct berval **bv ) +{ + ber_len_t len, nlen; + ber_tag_t tag; + + if ( (*bv = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) + == NULL ) { + return( LBER_DEFAULT ); + } + + (*bv)->bv_val = NULL; + (*bv)->bv_len = 0; + + if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { + NSLBERI_FREE( *bv ); + *bv = NULL; + return( LBER_DEFAULT ); + } + + if ( ((nlen = (size_t) len + 1) < (size_t)len) || + ( len > (ber->ber_end - ber->ber_ptr) ) || + (((*bv)->bv_val = (char *)NSLBERI_MALLOC( (size_t)nlen )) + == NULL )) { + NSLBERI_FREE( *bv ); + *bv = NULL; + return( LBER_DEFAULT ); + } + + /* + * len is being demoted to a long here -- possible conversion error + */ + if ( ber_read( ber, (*bv)->bv_val, len ) != (ber_slen_t) len ) { + NSLBERI_FREE( (*bv)->bv_val ); + (*bv)->bv_val = NULL; + NSLBERI_FREE( *bv ); + *bv = NULL; + return( LBER_DEFAULT ); + } + + ((*bv)->bv_val)[len] = '\0'; + (*bv)->bv_len = len; + +#ifdef STR_TRANSLATION + if ( len > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) != 0 + && ber->ber_decode_translate_proc != NULL ) { + ++len; + if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val), + &len, 1 ) != 0 ) { + NSLBERI_FREE( (*bv)->bv_val ); + (*bv)->bv_val = NULL; + NSLBERI_FREE( *bv ); + *bv = NULL; + return( LBER_DEFAULT ); + } + (*bv)->bv_len = len - 1; + } +#endif /* STR_TRANSLATION */ + + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_bitstringa( BerElement *ber, char **buf, ber_len_t *blen ) +{ + ber_len_t datalen; + ber_tag_t tag; + unsigned char unusedbits; + + if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + --datalen; + + if ( (datalen > (ber->ber_end - ber->ber_ptr)) || + ( (*buf = (char *)NSLBERI_MALLOC((size_t)datalen )) == NULL ) ) + return( LBER_DEFAULT ); + + if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) { + NSLBERI_FREE( *buf ); + *buf = NULL; + return( LBER_DEFAULT ); + } + + /* + * datalen is being demoted to a long here -- possible conversion error + */ + if ( ber_read( ber, *buf, datalen ) != (ber_slen_t) datalen ) { + NSLBERI_FREE( *buf ); + *buf = NULL; + return( LBER_DEFAULT ); + } + + *blen = datalen * 8 - unusedbits; + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_null( BerElement *ber ) +{ + ber_len_t len; + ber_tag_t tag; + + if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) + return( LBER_DEFAULT ); + + if ( len != 0 ) + return( LBER_DEFAULT ); + + return( tag ); +} + +ber_tag_t +LDAP_CALL +ber_get_boolean( BerElement *ber, ber_int_t *boolval ) +{ + int rc; + + rc = ber_get_int( ber, boolval ); + + return( rc ); +} + +ber_tag_t +LDAP_CALL +ber_first_element( BerElement *ber, ber_len_t *len, char **last ) +{ + /* skip the sequence header, use the len to mark where to stop */ + if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { + return( LBER_ERROR ); + } + + *last = ber->ber_ptr + *len; + + if ( *last == ber->ber_ptr ) { + return( LBER_END_OF_SEQORSET ); + } + + return( ber_peek_tag( ber, len ) ); +} + +ber_tag_t +LDAP_CALL +ber_next_element( BerElement *ber, ber_len_t *len, char *last ) +{ + if ( ber->ber_ptr == last ) { + return( LBER_END_OF_SEQORSET ); + } + + return( ber_peek_tag( ber, len ) ); +} + +/* VARARGS */ +ber_tag_t +LDAP_C +ber_scanf( BerElement *ber, const char *fmt, ... ) +{ + va_list ap; + char *last, *p; + char *s, **ss, ***sss; + struct berval ***bv, **bvp, *bval; + int *i, j; + ber_int_t *l, rc, tag; + ber_tag_t *t; + ber_len_t len; + size_t array_size; + + va_start( ap, fmt ); + +#ifdef LDAP_DEBUG + if ( lber_debug & 64 ) { + char msg[80]; + sprintf( msg, "ber_scanf fmt (%s) ber:\n", fmt ); + ber_err_print( msg ); + ber_dump( ber, 1 ); + } +#endif + for ( rc = 0, p = (char *) fmt; *p && rc != LBER_DEFAULT; p++ ) { + switch ( *p ) { + case 'a': /* octet string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + rc = ber_get_stringa( ber, ss ); + break; + + case 'b': /* boolean */ + i = va_arg( ap, int * ); + rc = ber_get_boolean( ber, i ); + break; + + case 'e': /* enumerated */ + case 'i': /* int */ + l = va_arg( ap, ber_slen_t * ); + rc = ber_get_int( ber, l ); + break; + + case 'l': /* length of next item */ + l = va_arg( ap, ber_slen_t * ); + rc = ber_peek_tag( ber, (ber_len_t *)l ); + break; + + case 'n': /* null */ + rc = ber_get_null( ber ); + break; + + case 's': /* octet string - in a buffer */ + s = va_arg( ap, char * ); + l = va_arg( ap, ber_slen_t * ); + rc = ber_get_stringb( ber, s, (ber_len_t *)l ); + break; + + case 'o': /* octet string in a supplied berval */ + bval = va_arg( ap, struct berval * ); + ber_peek_tag( ber, &bval->bv_len ); + rc = ber_get_stringa( ber, &bval->bv_val ); + break; + + case 'O': /* octet string - allocate & include length */ + bvp = va_arg( ap, struct berval ** ); + rc = ber_get_stringal( ber, bvp ); + break; + + case 'B': /* bit string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + l = va_arg( ap, ber_slen_t * ); /* for length, in bits */ + rc = ber_get_bitstringa( ber, ss, (ber_len_t *)l ); + break; + + case 't': /* tag of next item */ + t = va_arg( ap, ber_tag_t * ); + *t = rc = ber_peek_tag( ber, &len ); + break; + + case 'T': /* skip tag of next item */ + t = va_arg( ap, ber_tag_t * ); + *t = rc = ber_skip_tag( ber, &len ); + break; + + case 'v': /* sequence of strings */ + sss = va_arg( ap, char *** ); + *sss = NULL; + j = 0; + array_size = 0; + for ( tag = ber_first_element( ber, &len, &last ); + tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET + && rc != LBER_DEFAULT; + tag = ber_next_element( ber, &len, last ) ) { + if ( *sss == NULL ) { + /* Make room for at least 15 strings */ + *sss = (char **)NSLBERI_MALLOC(16 * sizeof(char *) ); + if (!*sss) { + rc = LBER_DEFAULT; + break; /* out of memory - cannot continue */ + } + array_size = 16; + } else { + char **save_sss = *sss; + if ( (size_t)(j+2) > array_size) { + /* We'v overflowed our buffer */ + *sss = (char **)NSLBERI_REALLOC( *sss, (array_size * 2) * sizeof(char *) ); + array_size = array_size * 2; + } + if (!*sss) { + rc = LBER_DEFAULT; + ber_svecfree(save_sss); + break; /* out of memory - cannot continue */ + } + } + (*sss)[j] = NULL; + rc = ber_get_stringa( ber, &((*sss)[j]) ); + j++; + } + if ( rc != LBER_DEFAULT && + tag != LBER_END_OF_SEQORSET ) { + rc = LBER_DEFAULT; + } + if ( *sss && (j > 0) ) { + (*sss)[j] = NULL; + } + break; + + case 'V': /* sequence of strings + lengths */ + bv = va_arg( ap, struct berval *** ); + *bv = NULL; + j = 0; + for ( tag = ber_first_element( ber, &len, &last ); + tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET + && rc != LBER_DEFAULT; + tag = ber_next_element( ber, &len, last ) ) { + if ( *bv == NULL ) { + *bv = (struct berval **)NSLBERI_MALLOC( + 2 * sizeof(struct berval *) ); + if (!*bv) { + rc = LBER_DEFAULT; + break; /* out of memory - cannot continue */ + } + } else { + struct berval **save_bv = *bv; + *bv = (struct berval **)NSLBERI_REALLOC( + *bv, + (j + 2) * sizeof(struct berval *) ); + if (!*bv) { + rc = LBER_DEFAULT; + ber_bvecfree(save_bv); + break; /* out of memory - cannot continue */ + } + } + rc = ber_get_stringal( ber, &((*bv)[j]) ); + j++; + } + if ( rc != LBER_DEFAULT && + tag != LBER_END_OF_SEQORSET ) { + rc = LBER_DEFAULT; + } + if ( *bv && (j > 0) ) { + (*bv)[j] = NULL; + } + break; + + case 'x': /* skip the next element - whatever it is */ + if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) + break; + ber->ber_ptr += len; + break; + + case '{': /* begin sequence */ + case '[': /* begin set */ + if ( *(p + 1) != 'v' && *(p + 1) != 'V' ) + rc = ber_skip_tag( ber, &len ); + break; + + case '}': /* end sequence */ + case ']': /* end set */ + break; + + default: + { + char msg[80]; + sprintf( msg, "unknown fmt %c\n", *p ); + ber_err_print( msg ); + } + rc = LBER_DEFAULT; + break; + } + } + + va_end( ap ); + + if (rc == LBER_DEFAULT) { + va_start( ap, fmt ); + for ( p--; fmt < p && *fmt; fmt++ ) { + switch ( *fmt ) { + case 'a': /* octet string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + NSLBERI_FREE(*ss); + *ss = NULL; + break; + + case 'b': /* boolean */ + i = va_arg( ap, int * ); + break; + + case 'e': /* enumerated */ + case 'i': /* int */ + l = va_arg( ap, ber_slen_t * ); + break; + + case 'l': /* length of next item */ + l = va_arg( ap, ber_slen_t * ); + break; + + case 'n': /* null */ + break; + + case 's': /* octet string - in a buffer */ + s = va_arg( ap, char * ); + l = va_arg( ap, ber_slen_t * ); + break; + + case 'o': /* octet string in a supplied berval */ + bval = va_arg( ap, struct berval * ); + if (bval->bv_val) NSLBERI_FREE(bval->bv_val); + memset(bval, 0, sizeof(struct berval)); + break; + + case 'O': /* octet string - allocate & include length */ + bvp = va_arg( ap, struct berval ** ); + ber_bvfree(*bvp); + bvp = NULL; + break; + + case 'B': /* bit string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + l = va_arg( ap, ber_slen_t * ); /* for length, in bits */ + if (*ss) NSLBERI_FREE(*ss); + *ss = NULL; + break; + + case 't': /* tag of next item */ + t = va_arg( ap, ber_tag_t * ); + break; + + case 'T': /* skip tag of next item */ + t = va_arg( ap, ber_tag_t * ); + break; + + case 'v': /* sequence of strings */ + sss = va_arg( ap, char *** ); + ber_svecfree(*sss); + *sss = NULL; + break; + + case 'V': /* sequence of strings + lengths */ + bv = va_arg( ap, struct berval *** ); + ber_bvecfree(*bv); + *bv = NULL; + break; + + case 'x': /* skip the next element - whatever it is */ + break; + + case '{': /* begin sequence */ + case '[': /* begin set */ + break; + + case '}': /* end sequence */ + case ']': /* end set */ + break; + + default: + break; + } + } /* for */ + va_end( ap ); + } /* if */ + + return( rc ); +} + +void +LDAP_CALL +ber_bvfree( struct berval *bv ) +{ + if ( bv != NULL ) { + if ( bv->bv_val != NULL ) { + NSLBERI_FREE( bv->bv_val ); + } + NSLBERI_FREE( (char *) bv ); + } +} + +void +LDAP_CALL +ber_bvecfree( struct berval **bv ) +{ + int i; + + if ( bv != NULL ) { + for ( i = 0; bv[i] != NULL; i++ ) { + ber_bvfree( bv[i] ); + } + NSLBERI_FREE( (char *) bv ); + } +} + +struct berval * +LDAP_CALL +ber_bvdup( const struct berval *bv ) +{ + struct berval *new; + + if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) + == NULL ) { + return( NULL ); + } + if ( bv->bv_val == NULL ) { + new->bv_val = NULL; + new->bv_len = 0; + } else { + if ( (new->bv_val = (char *)NSLBERI_MALLOC( bv->bv_len + 1 )) + == NULL ) { + NSLBERI_FREE( new ); + new = NULL; + return( NULL ); + } + SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len ); + new->bv_val[bv->bv_len] = '\0'; + new->bv_len = bv->bv_len; + } + + return( new ); +} + +void +LDAP_CALL +ber_svecfree( char **vals ) +{ + int i; + + if ( vals == NULL ) + return; + for ( i = 0; vals[i] != NULL; i++ ) + NSLBERI_FREE( vals[i] ); + NSLBERI_FREE( (char *) vals ); +} + +#ifdef STR_TRANSLATION +void +LDAP_CALL +ber_set_string_translators( + BerElement *ber, + BERTranslateProc encode_proc, + BERTranslateProc decode_proc +) +{ + ber->ber_encode_translate_proc = encode_proc; + ber->ber_decode_translate_proc = decode_proc; +} +#endif /* STR_TRANSLATION */ diff --git a/ldap/c-sdk/liblber/dtest.c b/ldap/c-sdk/liblber/dtest.c new file mode 100644 index 0000000000..71f13d45a8 --- /dev/null +++ b/ldap/c-sdk/liblber/dtest.c @@ -0,0 +1,113 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ +/* dtest.c - lber decoding test program */ + +#include +#include +#ifdef MACOS +#include +#include +#else /* MACOS */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif /* _WIN32 */ +#endif /* MACOS */ +#include "lber.h" + +int +SSL_Recv( int s, char *b, unsigned l, int dummy ) +{ + return( read( s, b, l ) ); +} + +SSL_Send( int s, char *b, unsigned l, int dummy ) +{ + return( write( s, b, l ) ); +} + +static void usage( char *name ) +{ + fprintf( stderr, "usage: %s < berfile\n", name ); +} + +main( int argc, char **argv ) +{ + long i, fd; + ber_len_t len; + ber_tag_t tag; + BerElement *ber; + Sockbuf *sb; + extern int lber_debug; + + lber_debug = 255; + if ( argc > 1 ) { + usage( argv[0] ); + exit( 1 ); + } + + sb = ber_sockbuf_alloc(); + fd = 0; + ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_DESC, &fd ); + + if ( (ber = der_alloc()) == NULL ) { + perror( "ber_alloc" ); + exit( 1 ); + } + + if ( (tag = ber_get_next( sb, &len, ber )) == LBER_ERROR ) { + perror( "ber_get_next" ); + exit( 1 ); + } + printf( "message has tag 0x%x and length %ld\n", tag, len ); + + return( 0 ); +} diff --git a/ldap/c-sdk/liblber/encode.c b/ldap/c-sdk/liblber/encode.c new file mode 100644 index 0000000000..1c47b12a02 --- /dev/null +++ b/ldap/c-sdk/liblber/encode.c @@ -0,0 +1,699 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ + +/* encode.c - ber output encoding routines */ + +#include "lber-int.h" + +static int +ber_calc_taglen( ber_tag_t tag ) +{ + int i; + ber_int_t mask; + + /* find the first non-all-zero byte in the tag */ + for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { + mask = (0xff << (i * 8)); + /* not all zero */ + if ( tag & mask ) + break; + } + + return( i + 1 ); +} + +static int +ber_put_tag( BerElement *ber, ber_tag_t tag, int nosos ) +{ + int taglen; + ber_tag_t ntag; + + taglen = ber_calc_taglen( tag ); + + ntag = LBER_HTONL( tag ); + + return( ber_write( ber, ((char *) &ntag) + sizeof(ber_int_t) - taglen, + taglen, nosos ) ); +} + +static int +ber_calc_lenlen( ber_len_t len ) +{ + /* + * short len if it's less than 128 - one byte giving the len, + * with bit 8 0. + */ + + if ( len <= 0x7F ) + return( 1 ); + + /* + * long len otherwise - one byte with bit 8 set, giving the + * length of the length, followed by the length itself. + */ + + if ( len <= 0xFF ) + return( 2 ); + if ( len <= 0xFFFF ) + return( 3 ); + if ( len <= 0xFFFFFF ) + return( 4 ); + + return( 5 ); +} + +static int +ber_put_len( BerElement *ber, ber_len_t len, int nosos ) +{ + int i; + char lenlen; + ber_int_t mask; + ber_len_t netlen; + + /* + * short len if it's less than 128 - one byte giving the len, + * with bit 8 0. + */ + + if ( len <= 127 ) { + netlen = LBER_HTONL( len ); + return( ber_write( ber, (char *) &netlen + sizeof(ber_int_t) - 1, + 1, nosos ) ); + } + + /* + * long len otherwise - one byte with bit 8 set, giving the + * length of the length, followed by the length itself. + */ + + /* find the first non-all-zero byte */ + for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { + mask = (0xff << (i * 8)); + /* not all zero */ + if ( len & mask ) + break; + } + lenlen = ++i; + if ( lenlen > 4 ) + return( -1 ); + lenlen |= 0x80; + + /* write the length of the length */ + if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) + return( -1 ); + + /* write the length itself */ + netlen = LBER_HTONL( len ); + if ( ber_write( ber, (char *) &netlen + (sizeof(ber_int_t) - i), i, nosos ) + != i ) + return( -1 ); + + return( i + 1 ); +} + +static int +ber_put_int_or_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) +{ + int i, sign, taglen; + int len, lenlen; + ber_int_t netnum, mask; + + sign = (num < 0); + + /* + * high bit is set - look for first non-all-one byte + * high bit is clear - look for first non-all-zero byte + */ + for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { + mask = (0xff << (i * 8)); + + if ( sign ) { + /* not all ones */ + if ( (num & mask) != mask ) + break; + } else { + /* not all zero */ + if ( num & mask ) + break; + } + } + + /* + * we now have the "leading byte". if the high bit on this + * byte matches the sign bit, we need to "back up" a byte. + */ + mask = (num & (0x80 << (i * 8))); + if ( (mask && !sign) || (sign && !mask) ) + i++; + + len = i + 1; + + if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) + return( -1 ); + + if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) + return( -1 ); + i++; + netnum = LBER_HTONL( num ); + if ( ber_write( ber, (char *) &netnum + (sizeof(ber_int_t) - i), i, 0 ) + == i) + /* length of tag + length + contents */ + return( taglen + lenlen + i ); + + return( -1 ); +} + +int +LDAP_CALL +ber_put_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) + tag = LBER_ENUMERATED; + + return( ber_put_int_or_enum( ber, num, tag ) ); +} + +int +LDAP_CALL +ber_put_int( BerElement *ber, ber_int_t num, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) + tag = LBER_INTEGER; + + return( ber_put_int_or_enum( ber, num, tag ) ); +} + +int +LDAP_CALL +ber_put_ostring( BerElement *ber, char *str, ber_len_t len, + ber_tag_t tag ) +{ + int taglen, lenlen, rc; +#ifdef STR_TRANSLATION + int free_str; +#endif /* STR_TRANSLATION */ + + if ( tag == LBER_DEFAULT ) + tag = LBER_OCTETSTRING; + + if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) + return( -1 ); + +#ifdef STR_TRANSLATION + if ( len > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) != 0 + && ber->ber_encode_translate_proc != NULL ) { + if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 ) + != 0 ) { + return( -1 ); + } + free_str = 1; + } else { + free_str = 0; + } +#endif /* STR_TRANSLATION */ + + /* + * Note: below is a spot where we limit ber_write + * to signed long (instead of unsigned long) + */ + + if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 || + ber_write( ber, str, len, 0 ) != (ber_int_t) len ) { + rc = -1; + } else { + /* return length of tag + length + contents */ + rc = taglen + lenlen + len; + } + +#ifdef STR_TRANSLATION + if ( free_str ) { + NSLBERI_FREE( str ); + } +#endif /* STR_TRANSLATION */ + + return( rc ); +} + +int +LDAP_CALL +ber_put_string( BerElement *ber, char *str, ber_tag_t tag ) +{ + return( ber_put_ostring( ber, str, (ber_len_t) strlen( str ), tag )); +} + +int +LDAP_CALL +ber_put_bitstring( BerElement *ber, char *str, + ber_len_t blen /* in bits */, ber_tag_t tag ) +{ + int taglen, lenlen, len; + unsigned char unusedbits; + + if ( tag == LBER_DEFAULT ) + tag = LBER_BITSTRING; + + if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) + return( -1 ); + + len = ( blen + 7 ) / 8; + unusedbits = (unsigned char) (len * 8 - blen); + if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 ) + return( -1 ); + + if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 ) + return( -1 ); + + if ( ber_write( ber, str, len, 0 ) != len ) + return( -1 ); + + /* return length of tag + length + unused bit count + contents */ + return( taglen + 1 + lenlen + len ); +} + +int +LDAP_CALL +ber_put_null( BerElement *ber, ber_tag_t tag ) +{ + int taglen; + + if ( tag == LBER_DEFAULT ) + tag = LBER_NULL; + + if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) + return( -1 ); + + if ( ber_put_len( ber, 0, 0 ) != 1 ) + return( -1 ); + + return( taglen + 1 ); +} + +int +LDAP_CALL +ber_put_boolean( BerElement *ber, ber_int_t boolval, ber_tag_t tag ) +{ + int taglen; + unsigned char trueval = 0xff; + unsigned char falseval = 0x00; + + if ( tag == LBER_DEFAULT ) + tag = LBER_BOOLEAN; + + if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) + return( -1 ); + + if ( ber_put_len( ber, 1, 0 ) != 1 ) + return( -1 ); + + if ( ber_write( ber, (char *)(boolval ? &trueval : &falseval), 1, 0 ) + != 1 ) + return( -1 ); + + return( taglen + 2 ); +} + +#define FOUR_BYTE_LEN 5 + + +/* the idea here is roughly this: we maintain a stack of these Seqorset + * structures. This is pushed when we see the beginning of a new set or + * sequence. It is popped when we see the end of a set or sequence. + * Since we don't want to malloc and free these structures all the time, + * we pre-allocate a small set of them within the ber element structure. + * thus we need to spot when we've overflowed this stack and fall back to + * malloc'ing instead. + */ +static int +ber_start_seqorset( BerElement *ber, ber_tag_t tag ) +{ + Seqorset *new_sos; + + /* can we fit into the local stack ? */ + if (ber->ber_sos_stack_posn < SOS_STACK_SIZE) { + /* yes */ + new_sos = &ber->ber_sos_stack[ber->ber_sos_stack_posn]; + } else { + /* no */ + if ( (new_sos = (Seqorset *)NSLBERI_MALLOC( sizeof(Seqorset))) + == NULLSEQORSET ) { + return( -1 ); + } + } + ber->ber_sos_stack_posn++; + + if ( ber->ber_sos == NULLSEQORSET ) + new_sos->sos_first = ber->ber_ptr; + else + new_sos->sos_first = ber->ber_sos->sos_ptr; + + /* Set aside room for a 4 byte length field */ + new_sos->sos_ptr = new_sos->sos_first + ber_calc_taglen( tag ) + FOUR_BYTE_LEN; + new_sos->sos_tag = tag; + + new_sos->sos_next = ber->ber_sos; + new_sos->sos_clen = 0; + + ber->ber_sos = new_sos; + if (ber->ber_sos->sos_ptr > ber->ber_end) { + nslberi_ber_realloc(ber, ber->ber_sos->sos_ptr - ber->ber_end); + } + return( 0 ); +} + +int +LDAP_CALL +ber_start_seq( BerElement *ber, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) + tag = LBER_SEQUENCE; + + return( ber_start_seqorset( ber, tag ) ); +} + +int +LDAP_CALL +ber_start_set( BerElement *ber, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) + tag = LBER_SET; + + return( ber_start_seqorset( ber, tag ) ); +} + +static int +ber_put_seqorset( BerElement *ber ) +{ + ber_len_t len, netlen; + int taglen, lenlen; + unsigned char ltag = 0x80 + FOUR_BYTE_LEN - 1; + Seqorset *next; + Seqorset **sos = &ber->ber_sos; + + if ( *sos == NULL ) { + /* No sequence or set to put... fatal error. */ + return( -1 ); + } + + /* + * If this is the toplevel sequence or set, we need to actually + * write the stuff out. Otherwise, it's already been put in + * the appropriate buffer and will be written when the toplevel + * one is written. In this case all we need to do is update the + * length and tag. + */ + + len = (*sos)->sos_clen; + netlen = LBER_HTONL( len ); + if ( sizeof(ber_int_t) > 4 && len > 0xFFFFFFFF ) + return( -1 ); + + if ( ber->ber_options & LBER_OPT_USE_DER ) { + lenlen = ber_calc_lenlen( len ); + } else { + lenlen = FOUR_BYTE_LEN; + } + + if ( (next = (*sos)->sos_next) == NULLSEQORSET ) { + /* write the tag */ + if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 ) + return( -1 ); + + if ( ber->ber_options & LBER_OPT_USE_DER ) { + /* Write the length in the minimum # of octets */ + if ( ber_put_len( ber, len, 1 ) == -1 ) + return( -1 ); + + if (lenlen != FOUR_BYTE_LEN) { + /* + * We set aside FOUR_BYTE_LEN bytes for + * the length field. Move the data if + * we don't actually need that much + */ + SAFEMEMCPY( (*sos)->sos_first + taglen + + lenlen, (*sos)->sos_first + taglen + + FOUR_BYTE_LEN, len ); + } + } else { + /* Fill FOUR_BYTE_LEN bytes for length field */ + /* one byte of length length */ + if ( ber_write( ber, (char *)<ag, 1, 1 ) != 1 ) + return( -1 ); + + /* the length itself */ + if ( ber_write( ber, (char *) &netlen + sizeof(ber_int_t) + - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 ) + != FOUR_BYTE_LEN - 1 ) + return( -1 ); + } + /* The ber_ptr is at the set/seq start - move it to the end */ + ber->ber_ptr += len; + } else { + ber_tag_t ntag; + + /* the tag */ + taglen = ber_calc_taglen( (*sos)->sos_tag ); + ntag = LBER_HTONL( (*sos)->sos_tag ); + SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag + + sizeof(ber_int_t) - taglen, taglen ); + + if ( ber->ber_options & LBER_OPT_USE_DER ) { + ltag = (lenlen == 1) ? (unsigned char)len : + (unsigned char) (0x80 + (lenlen - 1)); + } + + /* one byte of length length */ + SAFEMEMCPY( (*sos)->sos_first + 1, <ag, 1 ); + + if ( ber->ber_options & LBER_OPT_USE_DER ) { + if (lenlen > 1) { + /* Write the length itself */ + SAFEMEMCPY( (*sos)->sos_first + 2, + (char *)&netlen + sizeof(ber_uint_t) - + (lenlen - 1), + lenlen - 1 ); + } + if (lenlen != FOUR_BYTE_LEN) { + /* + * We set aside FOUR_BYTE_LEN bytes for + * the length field. Move the data if + * we don't actually need that much + */ + SAFEMEMCPY( (*sos)->sos_first + taglen + + lenlen, (*sos)->sos_first + taglen + + FOUR_BYTE_LEN, len ); + } + } else { + /* the length itself */ + SAFEMEMCPY( (*sos)->sos_first + taglen + 1, + (char *) &netlen + sizeof(ber_int_t) - + (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 ); + } + + next->sos_clen += (taglen + lenlen + len); + next->sos_ptr += (taglen + lenlen + len); + } + + /* we're done with this seqorset, so free it up */ + /* was this one from the local stack ? */ + if (ber->ber_sos_stack_posn <= SOS_STACK_SIZE) { + /* yes */ + } else { + /* no */ + NSLBERI_FREE( (char *) (*sos) ); + } + ber->ber_sos_stack_posn--; + *sos = next; + + return( taglen + lenlen + len ); +} + +int +LDAP_CALL +ber_put_seq( BerElement *ber ) +{ + return( ber_put_seqorset( ber ) ); +} + +int +LDAP_CALL +ber_put_set( BerElement *ber ) +{ + return( ber_put_seqorset( ber ) ); +} + +/* VARARGS */ +int +LDAP_C +ber_printf( BerElement *ber, const char *fmt, ... ) +{ + va_list ap; + char *s, **ss; + struct berval *bval, **bv; + int rc, i; + ber_len_t len; + + va_start( ap, fmt ); + +#ifdef LDAP_DEBUG + if ( lber_debug & 64 ) { + char msg[80]; + sprintf( msg, "ber_printf fmt (%s)\n", fmt ); + ber_err_print( msg ); + } +#endif + + for ( rc = 0; *fmt && rc != -1; fmt++ ) { + switch ( *fmt ) { + case 'b': /* boolean */ + i = va_arg( ap, int ); + rc = ber_put_boolean( ber, i, ber->ber_tag ); + break; + + case 'i': /* int */ + i = va_arg( ap, int ); + rc = ber_put_int( ber, (ber_int_t)i, ber->ber_tag ); + break; + + case 'e': /* enumeration */ + i = va_arg( ap, int ); + rc = ber_put_enum( ber, (ber_int_t)i, ber->ber_tag ); + break; + + case 'n': /* null */ + rc = ber_put_null( ber, ber->ber_tag ); + break; + + case 'o': /* octet string (non-null terminated) */ + s = va_arg( ap, char * ); + len = va_arg( ap, int ); + rc = ber_put_ostring( ber, s, len, ber->ber_tag ); + break; + + case 'O': /* berval octet string */ + if( ( bval = va_arg( ap, struct berval * ) ) == NULL ) + break; + if( bval->bv_len == 0 ) { + rc = ber_put_ostring( ber, "", 0, ber->ber_tag ); + } else { + rc = ber_put_ostring( ber, bval->bv_val, bval->bv_len, + ber->ber_tag ); + } + break; + + case 's': /* string */ + s = va_arg( ap, char * ); + rc = ber_put_string( ber, s, ber->ber_tag ); + break; + + case 'B': /* bit string */ + s = va_arg( ap, char * ); + len = va_arg( ap, int ); /* in bits */ + rc = ber_put_bitstring( ber, s, len, ber->ber_tag ); + break; + + case 't': /* tag for the next element */ + ber->ber_tag = va_arg( ap, ber_tag_t ); + ber->ber_usertag = 1; + break; + + case 'v': /* vector of strings */ + if ( (ss = va_arg( ap, char ** )) == NULL ) + break; + for ( i = 0; ss[i] != NULL; i++ ) { + if ( (rc = ber_put_string( ber, ss[i], + ber->ber_tag )) == -1 ) + break; + } + break; + + case 'V': /* sequences of strings + lengths */ + if ( (bv = va_arg( ap, struct berval ** )) == NULL ) + break; + for ( i = 0; bv[i] != NULL; i++ ) { + if ( (rc = ber_put_ostring( ber, bv[i]->bv_val, + bv[i]->bv_len, ber->ber_tag )) == -1 ) + break; + } + break; + + case '{': /* begin sequence */ + rc = ber_start_seq( ber, ber->ber_tag ); + break; + + case '}': /* end sequence */ + rc = ber_put_seqorset( ber ); + break; + + case '[': /* begin set */ + rc = ber_start_set( ber, ber->ber_tag ); + break; + + case ']': /* end set */ + rc = ber_put_seqorset( ber ); + break; + + default: { + char msg[80]; + sprintf( msg, "unknown fmt %c\n", *fmt ); + ber_err_print( msg ); + rc = -1; + break; + } + } + + if ( ber->ber_usertag == 0 ) + ber->ber_tag = LBER_DEFAULT; + else + ber->ber_usertag = 0; + } + + va_end( ap ); + + return( rc ); +} diff --git a/ldap/c-sdk/liblber/etest.c b/ldap/c-sdk/liblber/etest.c new file mode 100644 index 0000000000..f2bab358fc --- /dev/null +++ b/ldap/c-sdk/liblber/etest.c @@ -0,0 +1,193 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ + +/* test.c - lber encoding test program */ + +#include +#include +#ifdef MACOS +#include +#include +#include +#include +#else /* MACOS */ +#include +#ifdef _WIN32 +#include +#else +#include +#endif /* _WIN32 */ +#endif /* MACOS */ +#include "lber.h" + +int +SSL_Recv( int s, char *b, unsigned l, int dummy ) +{ + return( read( s, b, l ) ); +} + +SSL_Send( int s, char *b, unsigned l, int dummy ) +{ + return( write( s, b, l ) ); +} + +int +getline( char *prompt, char c, char *buf, int bsize ) +{ + char *p; + + if ( prompt != NULL ) { + fprintf( stderr, "%s: ", prompt ); + } else { + fprintf( stderr, "enter value for '%c': ", c ); + } + if ( fgets( buf, bsize, stdin ) == NULL ) { + return( -1 ); + } + if ( (p = strchr( buf, '\n' )) != NULL ) { + *p = '\0'; + } + + return( 0 ); +} + + +static void usage( char *name ) +{ + fprintf( stderr, "usage: %s fmtstring\n", name ); +} + +main( int argc, char **argv ) +{ + int rc, fd; + char *s, *p; + void *arg1, *arg2; + Sockbuf *sb; + BerElement *ber; + char fmt[2]; + char buf[BUFSIZ]; + extern int lber_debug; + + lber_debug = 255; + if ( argc < 2 ) { + usage( argv[0] ); + exit( 1 ); + } + + sb = ber_sockbuf_alloc(); + fd = 1; + ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_DESC, &fd ); + + if ( (ber = der_alloc()) == NULL ) { + perror( "ber_alloc" ); + exit( 1 ); + } + + rc = 0; + fmt[1] = '\0'; + for ( s = argv[1]; *s; s++ ) { + switch ( *s ) { + case 'i': /* int */ + case 'b': /* boolean */ + case 'e': /* enumeration */ + getline( NULL, *s, buf, sizeof(buf) ); + arg1 = (void *) atoi( buf ); + break; + + case 'n': /* null */ + arg1 = NULL; + break; + + case 'o': /* octet string (non-null terminated) */ + getline( NULL, *s, buf, sizeof(buf) ); + arg1 = (void *) buf; + arg2 = (void *) strlen( buf ); + break; + + case 's': /* string */ + getline( NULL, *s, buf, sizeof(buf) ); + arg1 = (void *) buf; + break; + + case 'B': /* bit string */ + getline( NULL, *s, buf, sizeof(buf) ); + arg1 = (void *) buf; + arg2 = (void *) strlen( buf ); + break; + + case 't': /* tag for the next element */ + getline( NULL, *s, buf, sizeof(buf) ); + arg1 = (void *) buf; + break; + + case '{': /* begin sequence */ + case '}': /* end sequence */ + case '[': /* begin set */ + case ']': /* end set */ + break; + + default: + fprintf( stderr, "unknown fmt %c\n", *s ); + rc = -1; + break; + } + + fmt[0] = *s; + if ( ber_printf( ber, fmt, arg1, arg2 ) == -1 ) { + fprintf( stderr, "ber_printf\n" ); + exit( 1 ); + } + } + + if ( ber_flush( sb, ber, 1 ) != 0 ) { + perror( "ber_flush" ); + rc = -1; + } + + return( rc ); +} diff --git a/ldap/c-sdk/liblber/idtest.c b/ldap/c-sdk/liblber/idtest.c new file mode 100644 index 0000000000..e6f8fa4ae7 --- /dev/null +++ b/ldap/c-sdk/liblber/idtest.c @@ -0,0 +1,100 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ + +/* idtest.c - ber decoding test program using isode libraries */ + +#include +#include +#include + +static usage( char *name ) +{ + fprintf( stderr, "usage: %s\n", name ); +} + +main( int argc, char **argv ) +{ + PE pe; + PS psin, psout, pserr; + + /* read the pe from standard in */ + if ( (psin = ps_alloc( std_open )) == NULLPS ) { + perror( "ps_alloc" ); + exit( 1 ); + } + if ( std_setup( psin, stdin ) == NOTOK ) { + perror( "std_setup" ); + exit( 1 ); + } + /* write the pe to standard out */ + if ( (psout = ps_alloc( std_open )) == NULLPS ) { + perror( "ps_alloc" ); + exit( 1 ); + } + if ( std_setup( psout, stdout ) == NOTOK ) { + perror( "std_setup" ); + exit( 1 ); + } + /* pretty print it to standard error */ + if ( (pserr = ps_alloc( std_open )) == NULLPS ) { + perror( "ps_alloc" ); + exit( 1 ); + } + if ( std_setup( pserr, stderr ) == NOTOK ) { + perror( "std_setup" ); + exit( 1 ); + } + + while ( (pe = ps2pe( psin )) != NULLPE ) { + pe2pl( pserr, pe ); + pe2ps( psout, pe ); + } + + exit( 0 ); +} diff --git a/ldap/c-sdk/liblber/io.c b/ldap/c-sdk/liblber/io.c new file mode 100644 index 0000000000..fc81a9deeb --- /dev/null +++ b/ldap/c-sdk/liblber/io.c @@ -0,0 +1,1757 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ +/* io.c - ber general i/o routines */ + +#include "lber-int.h" + +#define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \ + (unsigned char)*sb->sb_ber.ber_ptr++ : \ + ber_filbuf( sb, len )) + +# ifdef macintosh +/* + * MacTCP/OpenTransport + */ +# define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL ) +# define MAX_WRITE 65535 +# define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (lsb_sd, b, l, 0 ) +# else /* _WIN32 */ +/* + * everything else (Unix/BSD 4.3 socket API) + */ +# define BerWrite( sb, b, l ) write( sb->sb_sd, b, l ) +# define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \ + (struct sockaddr *)sb->sb_fromaddr, \ + (al = sizeof(struct sockaddr), &al)) +# define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \ + (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr)) +# endif /* _WIN32 */ +# endif /* macintosh */ + +#ifndef udp_read +#define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED +#define udp_write( sb, b, l ) CLDAP NOT SUPPORTED +#endif /* udp_read */ + +#define EXBUFSIZ 1024 +size_t lber_bufsize = EXBUFSIZ; + +#ifdef LDAP_DEBUG +int lber_debug; +#endif + +/* + * function prototypes + */ +static void nslberi_install_compat_io_fns( Sockbuf *sb ); +static int nslberi_extread_compat( int s, void *buf, int len, + struct lextiof_socket_private *arg ); +static int nslberi_extwrite_compat( int s, const void *buf, int len, + struct lextiof_socket_private *arg ); +static ber_tag_t get_tag( Sockbuf *sb, BerElement *ber); +static ber_len_t get_ber_len( BerElement *ber); +static ber_len_t read_len_in_ber( Sockbuf *sb, BerElement *ber); + +/* + * internal global structure for memory allocation callback functions + */ +static struct lber_memalloc_fns nslberi_memalloc_fns; + + +/* + * buffered read from "sb". + * returns value of first character read on success and -1 on error. + */ +static int +ber_filbuf( Sockbuf *sb, ber_slen_t len ) +{ + ssize_t rc; +#ifdef CLDAP + int addrlen; +#endif /* CLDAP */ + + if ( sb->sb_ber.ber_buf == NULL ) { + if ( (sb->sb_ber.ber_buf = (char *)NSLBERI_MALLOC( + READBUFSIZ )) == NULL ) { + return( -1 ); + } + sb->sb_ber.ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; + sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf; + sb->sb_ber.ber_end = sb->sb_ber.ber_buf; + } + + if ( sb->sb_naddr > 0 ) { +#ifdef CLDAP + rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen ); +#ifdef LDAP_DEBUG + if ( lber_debug ) { + char msg[80]; + sprintf( msg, "ber_filbuf udp_read %d bytes\n", + rc ); + ber_err_print( msg ); + if ( lber_debug > 1 && rc > 0 ) + lber_bprint( sb->sb_ber.ber_buf, rc ); + } +#endif /* LDAP_DEBUG */ +#else /* CLDAP */ + rc = -1; +#endif /* CLDAP */ + } else { + if ( sb->sb_ext_io_fns.lbextiofn_read != NULL ) { + rc = sb->sb_ext_io_fns.lbextiofn_read( + sb->sb_sd, sb->sb_ber.ber_buf, + ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) + && (len < READBUFSIZ)) ? len : READBUFSIZ, + sb->sb_ext_io_fns.lbextiofn_socket_arg ); + } else { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return( -1 ); +#else + rc = read( sb->sb_sd, sb->sb_ber.ber_buf, + ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) + && (len < READBUFSIZ)) ? len : READBUFSIZ ); +#endif + } + } + + if ( rc > 0 ) { + sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1; + sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc; + return( (unsigned char)*sb->sb_ber.ber_buf ); + } + + return( -1 ); +} + + +static ber_int_t +BerRead( Sockbuf *sb, char *buf, ber_slen_t len ) +{ + int c; + ber_int_t nread = 0; + + while (len > 0) + { + ber_int_t inberbuf = sb->sb_ber.ber_end - sb->sb_ber.ber_ptr; + if (inberbuf > 0) + { + size_t tocopy = len > inberbuf ? inberbuf : len; + SAFEMEMCPY(buf, sb->sb_ber.ber_ptr, tocopy); + buf += tocopy; + sb->sb_ber.ber_ptr += tocopy; + nread += tocopy; + len -= tocopy; + } + else + { + c = ber_filbuf(sb, len); + if (c < 0) + { + if (nread > 0) + break; + else + return c; + } + *buf++ = c; + nread++; + len--; + } + } + return (nread); +} + + +/* + * Note: ber_read() only uses the ber_end and ber_ptr elements of ber. + * Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on + * that fact, so if this code is changed to use any additional elements of + * the ber structure, those functions will need to be changed as well. + */ +ber_int_t +LDAP_CALL +ber_read( BerElement *ber, char *buf, ber_len_t len ) +{ + ber_len_t actuallen; + ber_uint_t nleft; + + nleft = ber->ber_end - ber->ber_ptr; + actuallen = nleft < len ? nleft : len; + + SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen ); + + ber->ber_ptr += actuallen; + + return( (ber_int_t)actuallen ); +} + +/* + * enlarge the ber buffer. + * return 0 on success, -1 on error. + */ +int +nslberi_ber_realloc( BerElement *ber, ber_len_t len ) +{ + ber_uint_t need, have, total; + size_t have_bytes; + Seqorset *s; + ber_int_t off; + char *oldbuf; + int freeoldbuf = 0; + + ber->ber_buf_reallocs++; + + have_bytes = ber->ber_end - ber->ber_buf; + have = have_bytes / lber_bufsize; + need = (len < lber_bufsize ? 1 : (len + (lber_bufsize - 1)) / lber_bufsize); + total = have * lber_bufsize + need * lber_bufsize * ber->ber_buf_reallocs; + + oldbuf = ber->ber_buf; + + if (ber->ber_buf == NULL) { + if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( (size_t)total )) + == NULL ) { + return( -1 ); + } + ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; + } else { + if ( !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { + freeoldbuf = 1; + } + /* transition to malloc'd buffer */ + if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( + (size_t)total )) == NULL ) { + return( -1 ); + } + ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; + /* copy existing data into new malloc'd buffer */ + SAFEMEMCPY( ber->ber_buf, oldbuf, have_bytes ); + } + + ber->ber_end = ber->ber_buf + total; + + /* + * If the stinking thing was moved, we need to go through and + * reset all the sos and ber pointers. Offsets would've been + * a better idea... oh well. + */ + + if ( ber->ber_buf != oldbuf ) { + ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); + + for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) { + off = s->sos_first - oldbuf; + s->sos_first = ber->ber_buf + off; + + off = s->sos_ptr - oldbuf; + s->sos_ptr = ber->ber_buf + off; + } + + if ( freeoldbuf && oldbuf ) { + NSLBERI_FREE( oldbuf ); + } + } + + return( 0 ); +} + +/* + * returns "len" on success and -1 on failure. + */ +ber_int_t +LDAP_CALL +ber_write( BerElement *ber, char *buf, ber_len_t len, int nosos ) +{ + if ( nosos || ber->ber_sos == NULL ) { + if ( ber->ber_ptr + len > ber->ber_end ) { + if ( nslberi_ber_realloc( ber, len ) != 0 ) + return( -1 ); + } + SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len ); + ber->ber_ptr += len; + return( len ); + } else { + if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) { + if ( nslberi_ber_realloc( ber, len ) != 0 ) + return( -1 ); + } + SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len ); + ber->ber_sos->sos_ptr += len; + ber->ber_sos->sos_clen += len; + return( len ); + } +} + +void +LDAP_CALL +ber_free( BerElement *ber, int freebuf ) +{ + if ( ber != NULL ) { + if ( freebuf && + !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { + NSLBERI_FREE(ber->ber_buf); + } + NSLBERI_FREE( (char *) ber ); + } +} + +/* + * return >= 0 on success, -1 on failure. + */ +int +LDAP_CALL +ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) +{ + ssize_t nwritten = 0, towrite, rc; + int i = 0; + + if (ber->ber_rwptr == NULL) { + ber->ber_rwptr = ber->ber_buf; + } else if (ber->ber_rwptr >= ber->ber_end) { + /* we will use the ber_rwptr to continue an exited flush, + so if rwptr is not within the buffer we return an error. */ + return( -1 ); + } + + /* writev section - for iDAR only!!! */ + if (sb->sb_ext_io_fns.lbextiofn_writev != NULL) { + + /* add the sizes of the different buffers to write with writev */ + for (towrite = 0, i = 0; i < BER_ARRAY_QUANTITY; ++i) { + /* don't add lengths of null buffers - writev will ignore them */ + if (ber->ber_struct[i].ldapiov_base) { + towrite += ber->ber_struct[i].ldapiov_len; + } + } + + rc = sb->sb_ext_io_fns.lbextiofn_writev(sb->sb_sd, ber->ber_struct, BER_ARRAY_QUANTITY, + sb->sb_ext_io_fns.lbextiofn_socket_arg); + + if ( freeit ) + ber_free( ber, 1 ); + + if (rc >= 0) { + /* return the number of bytes TO BE written */ + return (towrite - rc); + } else { + /* otherwise it's an error */ + return (rc); + } + } /* end writev section */ + + towrite = ber->ber_ptr - ber->ber_rwptr; + +#ifdef LDAP_DEBUG + if ( lber_debug ) { + char msg[80]; + sprintf( msg, "ber_flush: %d bytes to sd %ld%s\n", (int)towrite, + sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" + : "" ); + ber_err_print( msg ); + if ( lber_debug > 1 ) + lber_bprint( ber->ber_rwptr, towrite ); + } +#endif +#if !defined(macintosh) && !defined(DOS) + if ( sb->sb_options & (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY) ) { + rc = write( sb->sb_copyfd, ber->ber_buf, towrite ); + if ( sb->sb_options & LBER_SOCKBUF_OPT_TO_FILE_ONLY ) { + return( (int)rc ); + } + } +#endif + + nwritten = 0; + do { + if (sb->sb_naddr > 0) { +#ifdef CLDAP + rc = udp_write( sb, ber->ber_buf + nwritten, + (size_t)towrite ); +#else /* CLDAP */ + rc = -1; +#endif /* CLDAP */ + if ( rc <= 0 ) + return( -1 ); + /* fake error if write was not atomic */ + if (rc < towrite) { +#if !defined( macintosh ) && !defined( DOS ) + errno = EMSGSIZE; /* For Win32, see portable.h */ +#endif + return( -1 ); + } + } else { + if ( sb->sb_ext_io_fns.lbextiofn_write != NULL ) { + if ( (rc = sb->sb_ext_io_fns.lbextiofn_write( + sb->sb_sd, ber->ber_rwptr, (size_t)towrite, + sb->sb_ext_io_fns.lbextiofn_socket_arg )) + <= 0 ) { + return( -1 ); + } + } else { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return( -1 ); +#else + if ( (rc = BerWrite( sb, ber->ber_rwptr, + (size_t) towrite )) <= 0 ) { + return( -1 ); + } +#endif + } + } + towrite -= rc; + nwritten += rc; + ber->ber_rwptr += rc; + } while ( towrite > 0 ); + + if ( freeit ) + ber_free( ber, 1 ); + + return( 0 ); +} + + +/* we pre-allocate a buffer to save the extra malloc later */ +BerElement * +LDAP_CALL +ber_alloc_t( int options ) +{ + BerElement *ber; + + if ( (ber = (BerElement*)NSLBERI_CALLOC( 1, + sizeof(struct berelement) + lber_bufsize )) == NULL ) { + return( NULL ); + } + + /* + * for compatibility with the C LDAP API standard, we recognize + * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. + */ + if ( options & LBER_USE_DER ) { + options &= ~LBER_USE_DER; + options |= LBER_OPT_USE_DER; + } + + ber->ber_tag = LBER_DEFAULT; + ber->ber_options = options; + ber->ber_buf = (char*)ber + sizeof(struct berelement); + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + lber_bufsize; + ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; + + return( ber ); +} + + +BerElement * +LDAP_CALL +ber_alloc() +{ + return( ber_alloc_t( 0 ) ); +} + +BerElement * +LDAP_CALL +der_alloc() +{ + return( ber_alloc_t( LBER_OPT_USE_DER ) ); +} + +BerElement * +LDAP_CALL +ber_dup( BerElement *ber ) +{ + BerElement *new; + + if ( (new = ber_alloc()) == NULL ) + return( NULL ); + + *new = *ber; + + return( new ); +} + + +void +LDAP_CALL +ber_init_w_nullchar( BerElement *ber, int options ) +{ + (void) memset( (char *)ber, '\0', sizeof(struct berelement) ); + ber->ber_tag = LBER_DEFAULT; + + /* + * For compatibility with the C LDAP API standard, we recognize + * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. + */ + if ( options & LBER_USE_DER ) { + options &= ~LBER_USE_DER; + options |= LBER_OPT_USE_DER; + } + + ber->ber_options = options; +} + +void +LDAP_CALL +ber_reset( BerElement *ber, int was_writing ) +{ + if ( was_writing ) { + ber->ber_end = ber->ber_ptr; + ber->ber_ptr = ber->ber_buf; + } else { + ber->ber_ptr = ber->ber_end; + } + + ber->ber_rwptr = NULL; + ber->ber_tag_len_read = 0; + + memset(ber->ber_struct, 0, BER_CONTENTS_STRUCT_SIZE); +} + +/* Returns the length of the ber buffer so far, + taking into account sequences/sets also. + CAUTION: Returns 0 on null buffers as well + as 0 on empty buffers! +*/ +size_t +LDAP_CALL +ber_get_buf_datalen( BerElement *ber ) +{ + size_t datalen; + + if ( ( ber == NULL) || ( ber->ber_buf == NULL) || ( ber->ber_ptr == NULL ) ) { + datalen = 0; + } else if (ber->ber_sos == NULLSEQORSET) { + /* there are no sequences or sets yet, + so just subtract ptr from the beginning of the ber buffer */ + datalen = ber->ber_ptr - ber->ber_buf; + } else { + /* sequences exist, so just take the ptr of the sequence + on top of the stack and subtract the beginning of the + buffer from it */ + datalen = ber->ber_sos->sos_ptr - ber->ber_buf; + } + + return datalen; +} + +/* + if buf is 0 then malloc a buffer of length size + returns > 0 on success, 0 otherwise +*/ +int +LDAP_CALL +ber_stack_init(BerElement *ber, int options, char * buf, + size_t size) +{ + if (NULL == ber) + return 0; + + memset(ber, 0, sizeof(*ber)); + + /* + * for compatibility with the C LDAP API standard, we recognize + * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. + */ + + if ( options & LBER_USE_DER ) { + options &= ~LBER_USE_DER; + options |= LBER_OPT_USE_DER; + } + + ber->ber_tag = LBER_DEFAULT; + ber->ber_options = options; + + if ( ber->ber_buf && !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { + NSLBERI_FREE(ber->ber_buf); + } + + if (buf) { + ber->ber_buf = ber->ber_ptr = buf; + ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; + } else { + ber->ber_buf = ber->ber_ptr = (char *) NSLBERI_MALLOC(size); + } + + ber->ber_end = ber->ber_buf + size; + + return ber->ber_buf != 0; +} + +/* + * This call allows to release only the data part of + * the target Sockbuf. + * Other info of this Sockbuf are kept unchanged. + */ +void +LDAP_CALL +ber_sockbuf_free_data(Sockbuf *p) +{ + if ( p != NULL ) { + if ( p->sb_ber.ber_buf != NULL && + !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { + NSLBERI_FREE( p->sb_ber.ber_buf ); + p->sb_ber.ber_buf = NULL; + } + } +} + +/* simply returns ber_buf in the ber ... + explicitly for DS MMR only... +*/ +char * +LDAP_CALL +ber_get_buf_databegin (BerElement * ber) +{ + if (NULL != ber) { + return ber->ber_buf; + } else { + return NULL; + } +} + +#ifdef LDAP_DEBUG + +void +ber_dump( BerElement *ber, int inout ) +{ + char msg[128]; + sprintf( msg, "ber_dump: buf 0x%p, ptr 0x%p, rwptr 0x%p, end 0x%p\n", + ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end ); + ber_err_print( msg ); + if ( inout == 1 ) { + sprintf( msg, " current len %ld, contents:\n", + (long)(ber->ber_end - ber->ber_ptr) ); + ber_err_print( msg ); + lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr ); + } else { + sprintf( msg, " current len %ld, contents:\n", + (long)(ber->ber_ptr - ber->ber_buf) ); + ber_err_print( msg ); + lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf ); + } +} + +void +ber_sos_dump( Seqorset *sos ) +{ + char msg[80]; + ber_err_print ( "*** sos dump ***\n" ); + while ( sos != NULLSEQORSET ) { + sprintf( msg, "ber_sos_dump: clen %d first 0x%p ptr 0x%p\n", + sos->sos_clen, sos->sos_first, sos->sos_ptr ); + ber_err_print( msg ); + sprintf( msg, " current len %ld contents:\n", + (long)(sos->sos_ptr - sos->sos_first) ); + ber_err_print( msg ); + lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first ); + + sos = sos->sos_next; + } + ber_err_print( "*** end dump ***\n" ); +} + +#endif + +/* return the tag - LBER_DEFAULT returned means trouble + * assumes the tag is only one byte! */ +static ber_tag_t +get_tag( Sockbuf *sb, BerElement *ber) +{ + unsigned char xbyte; + + if ( (BerRead( sb, (char *) &xbyte, 1 )) != 1 ) { + return( LBER_DEFAULT ); + } + + /* we only handle small (one byte) tags */ + if ( (xbyte & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK ) { + return( LBER_DEFAULT ); + } + + ber->ber_tag_contents[0] = xbyte; + ber->ber_struct[BER_STRUCT_TAG].ldapiov_len = 1; + return((ber_tag_t)xbyte); +} + + +/* Error checking? */ +/* Takes a ber and returns the actual length */ +static ber_len_t +get_ber_len( BerElement *ber) +{ + int noctets; + ber_len_t len = 0; + char xbyte; + + xbyte = ber->ber_len_contents[0]; + + /* long form */ + if (xbyte & 0x80) { + noctets = (int) (xbyte & 0x7f); + if (noctets >= MAX_LEN_SIZE) { + return(LBER_DEFAULT); + } + SAFEMEMCPY((char*) &len + sizeof(ber_len_t) - noctets, &ber->ber_len_contents[1], noctets); + len = LBER_NTOHL(len); + return(len); + } else { + return((ber_len_t)(xbyte)); + } +} + +/* LBER_DEFAULT means trouble + reads in the length, stores it in ber->ber_struct, and returns get_ber_len */ +static ber_len_t +read_len_in_ber( Sockbuf *sb, BerElement *ber) +{ + unsigned char xbyte; + int noctets; + int rc = 0, read_result = 0; + + /* + * Next, read the length. The first byte contains the length + * of the length. If bit 8 is set, the length is the long + * form, otherwise it's the short form. We don't allow a + * length that's greater than what we can hold in a ber_int_t + */ + if ( ber->ber_tag_len_read == 1) { + /* the length of the length hasn't been read yet */ + if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) { + return( LBER_DEFAULT ); + } + ber->ber_tag_len_read = 2; + ber->ber_len_contents[0] = xbyte; + } else { + rc = ber->ber_tag_len_read - 2; + xbyte = ber->ber_len_contents[0]; + } + + /* long form of the length value */ + if ( xbyte & 0x80 ) { + noctets = (xbyte & 0x7f); + if ( noctets >= MAX_LEN_SIZE ) + return( LBER_DEFAULT ); + while (rc < noctets) { + read_result = BerRead( sb, &(ber->ber_len_contents[1]) + rc, noctets - rc ); + if (read_result <= 0) { + ber->ber_tag_len_read = rc + 2; /* so we can continue later - include tag and lenlen */ + return( LBER_DEFAULT ); + } + rc += read_result; + } + ber->ber_tag_len_read = rc + 2; /* adds tag (1 byte) and lenlen (1 byte) */ + ber->ber_struct[BER_STRUCT_LEN].ldapiov_len = 1 + noctets; + } else { /* short form of the length value */ + ber->ber_struct[BER_STRUCT_LEN].ldapiov_len = 1; + } + return(get_ber_len(ber)); +} + + +ber_tag_t +LDAP_CALL +ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber ) +{ + ber_len_t newlen; + ber_len_t toread; + ber_int_t rc; + ber_len_t orig_taglen_read = 0; + char * orig_rwptr = ber->ber_rwptr ? ber->ber_rwptr : ber->ber_buf; + +#ifdef LDAP_DEBUG + if ( lber_debug ) + ber_err_print( "ber_get_next\n" ); +#endif + + /* + * When rwptr is NULL this signifies that the tag and length have not been + * read in their entirety yet. (if at all) + */ + if ( ber->ber_rwptr == NULL ) { + + /* first save the amount we previously read, so we know what to return in len. */ + orig_taglen_read = ber->ber_tag_len_read; + + /* read the tag - if tag_len_read is greater than 0, then it has already been read. */ + if (ber->ber_tag_len_read == 0) { + if ((ber->ber_tag = get_tag(sb, ber)) == LBER_DEFAULT ) { + *len = 0; + return( LBER_DEFAULT ); + } + + ber->ber_tag_contents[0] = (char)ber->ber_tag; /* we only handle 1 byte tags */ + ber->ber_tag_len_read = 1; + + /* check for validity */ + if((sb->sb_options & LBER_SOCKBUF_OPT_VALID_TAG) && + (ber->ber_tag != sb->sb_valid_tag)) { + *len = 1; /* we just read the tag so far */ + return( LBER_DEFAULT); + } + } + + /* read the length */ + if ((newlen = read_len_in_ber(sb, ber)) == LBER_DEFAULT ) { + *len = ber->ber_tag_len_read - orig_taglen_read; + return( LBER_DEFAULT ); + } + + /* + * Finally, malloc a buffer for the contents and read it in. + * It's this buffer that's passed to all the other ber decoding + * routines. + */ + +#if defined( DOS ) && !( defined( _WIN32 ) || defined(XP_OS2) ) + if ( newlen > 65535 ) { /* DOS can't allocate > 64K */ + return( LBER_DEFAULT ); + } +#endif /* DOS && !_WIN32 */ + + if ( ( sb->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) + && newlen > sb->sb_max_incoming ) { + return( LBER_DEFAULT ); + } + + /* check to see if we already have enough memory allocated */ + if ( ((ber_len_t) ber->ber_end - (ber_len_t) ber->ber_buf) < newlen) { + if ( ber->ber_buf && !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { + NSLBERI_FREE(ber->ber_buf); + } + if ( (ber->ber_buf = (char *)NSLBERI_CALLOC( 1,(size_t)newlen )) + == NULL ) { + return( LBER_DEFAULT ); + } + ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; + orig_rwptr = ber->ber_buf; + } + + + ber->ber_len = newlen; + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + newlen; + ber->ber_rwptr = ber->ber_buf; + ber->ber_tag_len_read = 0; /* now that rwptr is set, this doesn't matter */ + } + + /* OK, we've malloc-ed the buffer; now read the rest of the expected length */ + toread = (ber_len_t)ber->ber_end - (ber_len_t)ber->ber_rwptr; + do { + if ( (rc = BerRead( sb, ber->ber_rwptr, (ber_int_t)toread )) <= 0 ) { + *len = (ber_len_t) ber->ber_rwptr - (ber_len_t) orig_rwptr; + return( LBER_DEFAULT ); + } + + toread -= rc; + ber->ber_rwptr += rc; + } while ( toread > 0 ); + +#ifdef LDAP_DEBUG + if ( lber_debug ) { + char msg[80]; + sprintf( msg, "ber_get_next: tag 0x%x len %d contents:\n", + ber->ber_tag, ber->ber_len ); + ber_err_print( msg ); + if ( lber_debug > 1 ) + ber_dump( ber, 1 ); + } +#endif + + *len = (ber_len_t) ber->ber_rwptr - (ber_len_t) orig_rwptr; + ber->ber_rwptr = NULL; + ber->ber_struct[BER_STRUCT_VAL].ldapiov_len = ber->ber_len; + return( ber->ber_tag ); +} + +Sockbuf * +LDAP_CALL +ber_sockbuf_alloc() +{ + return( (Sockbuf *)NSLBERI_CALLOC( 1, sizeof(struct sockbuf) ) ); +} + +void +LDAP_CALL +ber_sockbuf_free(Sockbuf *p) +{ + if ( p != NULL ) { + if ( p->sb_ber.ber_buf != NULL && + !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { + NSLBERI_FREE( p->sb_ber.ber_buf ); + } + NSLBERI_FREE(p); + } +} + +/* + * return 0 on success and -1 on error + */ +int +LDAP_CALL +ber_set_option( struct berelement *ber, int option, void *value ) +{ + + /* + * memory allocation callbacks are global, so it is OK to pass + * NULL for ber. Handle this as a special case. + */ + if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { + /* struct copy */ + nslberi_memalloc_fns = *((struct lber_memalloc_fns *)value); + return( 0 ); + } + + /* + * lber_debug is global, so it is OK to pass + * NULL for ber. Handle this as a special case. + */ + if ( option == LBER_OPT_DEBUG_LEVEL ) { +#ifdef LDAP_DEBUG + lber_debug = *(int *)value; +#endif + return( 0 ); + } + + /* + * lber_bufsize is global, so it is OK to pass + * NULL for ber. Handle this as a special case. + */ + if ( option == LBER_OPT_BUFSIZE ) { + if ( *(size_t *)value > EXBUFSIZ ) { + lber_bufsize = *(size_t *)value; + } + return( 0 ); + } + + /* + * all the rest require a non-NULL ber + */ + if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { + return( -1 ); + } + + switch ( option ) { + case LBER_OPT_USE_DER: + case LBER_OPT_TRANSLATE_STRINGS: + if ( value != NULL ) { + ber->ber_options |= option; + } else { + ber->ber_options &= ~option; + } + break; + case LBER_OPT_REMAINING_BYTES: + ber->ber_end = ber->ber_ptr + *((ber_len_t *)value); + break; + case LBER_OPT_TOTAL_BYTES: + ber->ber_end = ber->ber_buf + *((ber_len_t *)value); + break; + case LBER_OPT_BYTES_TO_WRITE: + ber->ber_ptr = ber->ber_buf + *((ber_len_t *)value); + break; + default: + return( -1 ); + } + + return( 0 ); +} + +/* + * return 0 on success and -1 on error + */ +int +LDAP_CALL +ber_get_option( struct berelement *ber, int option, void *value ) +{ + /* + * memory callocation callbacks are global, so it is OK to pass + * NULL for ber. Handle this as a special case + */ + if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { + /* struct copy */ + *((struct lber_memalloc_fns *)value) = nslberi_memalloc_fns; + return( 0 ); + } + + /* + * lber_debug is global, so it is OK to pass + * NULL for ber. Handle this as a special case. + */ + if ( option == LBER_OPT_DEBUG_LEVEL ) { +#ifdef LDAP_DEBUG + *(int *)value = lber_debug; +#endif + return( 0 ); + } + + /* + * lber_bufsize is global, so it is OK to pass + * NULL for ber. Handle this as a special case. + */ + if ( option == LBER_OPT_BUFSIZE ) { + *(size_t *)value = lber_bufsize; + return( 0 ); + } + + /* + * all the rest require a non-NULL ber + */ + if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { + return( -1 ); + } + + switch ( option ) { + case LBER_OPT_USE_DER: + case LBER_OPT_TRANSLATE_STRINGS: + *((int *) value) = (ber->ber_options & option); + break; + case LBER_OPT_REMAINING_BYTES: + *((ber_len_t *) value) = ber->ber_end - ber->ber_ptr; + break; + case LBER_OPT_TOTAL_BYTES: + *((ber_len_t *) value) = ber->ber_end - ber->ber_buf; + break; + case LBER_OPT_BYTES_TO_WRITE: + *((ber_len_t *) value) = ber->ber_ptr - ber->ber_buf; + break; + default: + return( -1 ); + } + + return( 0 ); +} + +/* + * return 0 on success and -1 on error + */ +int +LDAP_CALL +ber_sockbuf_set_option( Sockbuf *sb, int option, void *value ) +{ + struct lber_x_ext_io_fns *extiofns; + + if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { + return( -1 ); + } + + /* check for a NULL value for certain options. */ + if (NULL == value) { + switch ( option ) { + case LBER_SOCKBUF_OPT_TO_FILE: + case LBER_SOCKBUF_OPT_TO_FILE_ONLY: + case LBER_SOCKBUF_OPT_NO_READ_AHEAD: + case LBER_SOCKBUF_OPT_READ_FN: + case LBER_SOCKBUF_OPT_WRITE_FN: + case LBER_SOCKBUF_OPT_EXT_IO_FNS: + case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: + /* do nothing - it's OK to have a NULL value for these options */ + break; + default: + return( -1 ); + } + } + + switch ( option ) { + case LBER_SOCKBUF_OPT_VALID_TAG: + sb->sb_valid_tag= *((ber_tag_t *) value); + /* use NULL to reset */ + if ( value != NULL ) { + sb->sb_options |= option; + } else { + sb->sb_options &= ~option; + } + break; + case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: + if ( value != NULL ) { + sb->sb_max_incoming = *((ber_len_t *) value); + sb->sb_options |= option; + } else { + /* setting the max incoming to 0 seems to be the only + way to tell the callers of ber_sockbuf_get_option + that this option isn't set. */ + sb->sb_max_incoming = 0; + sb->sb_options &= ~option; + } + break; + case LBER_SOCKBUF_OPT_TO_FILE: + case LBER_SOCKBUF_OPT_TO_FILE_ONLY: + case LBER_SOCKBUF_OPT_NO_READ_AHEAD: + if ( value != NULL ) { + sb->sb_options |= option; + } else { + sb->sb_options &= ~option; + } + break; + case LBER_SOCKBUF_OPT_DESC: + sb->sb_sd = *((LBER_SOCKET *) value); + break; + case LBER_SOCKBUF_OPT_COPYDESC: + sb->sb_copyfd = *((LBER_SOCKET *) value); + break; + case LBER_SOCKBUF_OPT_READ_FN: + sb->sb_io_fns.lbiof_read = (LDAP_IOF_READ_CALLBACK *) value; + nslberi_install_compat_io_fns( sb ); + break; + case LBER_SOCKBUF_OPT_WRITE_FN: + sb->sb_io_fns.lbiof_write = (LDAP_IOF_WRITE_CALLBACK *) value; + nslberi_install_compat_io_fns( sb ); + break; + case LBER_SOCKBUF_OPT_EXT_IO_FNS: + extiofns = (struct lber_x_ext_io_fns *) value; + if ( extiofns == NULL ) { /* remove */ + (void)memset( (char *)&sb->sb_ext_io_fns, '\0', + sizeof(sb->sb_ext_io_fns )); + } else if ( extiofns->lbextiofn_size + == LBER_X_EXTIO_FNS_SIZE ) { + /* struct copy */ + sb->sb_ext_io_fns = *extiofns; + } else if ( extiofns->lbextiofn_size + == LBER_X_EXTIO_FNS_SIZE_REV0 ) { + /* backwards compatiblity for older struct */ + sb->sb_ext_io_fns.lbextiofn_size = + LBER_X_EXTIO_FNS_SIZE; + sb->sb_ext_io_fns.lbextiofn_read = + extiofns->lbextiofn_read; + sb->sb_ext_io_fns.lbextiofn_write = + extiofns->lbextiofn_write; + sb->sb_ext_io_fns.lbextiofn_writev = NULL; + sb->sb_ext_io_fns.lbextiofn_socket_arg = + extiofns->lbextiofn_socket_arg; + } else { + return( -1 ); + } + break; + case LBER_SOCKBUF_OPT_SOCK_ARG: + sb->sb_ext_io_fns.lbextiofn_socket_arg = + (struct lextiof_socket_private *) value; + break; + default: + return( -1 ); + } + + return( 0 ); +} + +/* + * return 0 on success and -1 on error + */ +int +LDAP_CALL +ber_sockbuf_get_option( Sockbuf *sb, int option, void *value ) +{ + struct lber_x_ext_io_fns *extiofns; + + if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb ) || (NULL == value)) { + return( -1 ); + } + + switch ( option ) { + case LBER_SOCKBUF_OPT_VALID_TAG: + *((ber_tag_t *) value) = sb->sb_valid_tag; + break; + case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: + *((ber_len_t *) value) = sb->sb_max_incoming; + break; + case LBER_SOCKBUF_OPT_TO_FILE: + case LBER_SOCKBUF_OPT_TO_FILE_ONLY: + case LBER_SOCKBUF_OPT_NO_READ_AHEAD: + *((int *) value) = (sb->sb_options & option); + break; + case LBER_SOCKBUF_OPT_DESC: + *((LBER_SOCKET *) value) = sb->sb_sd; + break; + case LBER_SOCKBUF_OPT_COPYDESC: + *((LBER_SOCKET *) value) = sb->sb_copyfd; + break; + case LBER_SOCKBUF_OPT_READ_FN: + *((LDAP_IOF_READ_CALLBACK **) value) + = sb->sb_io_fns.lbiof_read; + break; + case LBER_SOCKBUF_OPT_WRITE_FN: + *((LDAP_IOF_WRITE_CALLBACK **) value) + = sb->sb_io_fns.lbiof_write; + break; + case LBER_SOCKBUF_OPT_EXT_IO_FNS: + extiofns = (struct lber_x_ext_io_fns *) value; + if ( extiofns == NULL ) { + return( -1 ); + } else if ( extiofns->lbextiofn_size + == LBER_X_EXTIO_FNS_SIZE ) { + /* struct copy */ + *extiofns = sb->sb_ext_io_fns; + } else if ( extiofns->lbextiofn_size + == LBER_X_EXTIO_FNS_SIZE_REV0 ) { + /* backwards compatiblity for older struct */ + extiofns->lbextiofn_read = sb->sb_ext_io_fns.lbextiofn_read; + extiofns->lbextiofn_write = sb->sb_ext_io_fns.lbextiofn_write; + extiofns->lbextiofn_socket_arg = sb->sb_ext_io_fns.lbextiofn_socket_arg; + } else { + return( -1 ); + } + break; + case LBER_SOCKBUF_OPT_SOCK_ARG: + *((struct lextiof_socket_private **)value) = sb->sb_ext_io_fns.lbextiofn_socket_arg; + break; + default: + return( -1 ); + } + + return( 0 ); +} + + +/* new dboreham code below: */ + +struct byte_buffer { + unsigned char *p; + int offset; + int length; +}; +typedef struct byte_buffer byte_buffer; + + +/* This call allocates us a BerElement structure plus some extra memory. + * It returns a pointer to the BerElement, plus a pointer to the extra memory. + * This routine also allocates a ber data buffer within the same block, thus + * saving a call to calloc later when we read data. + */ +void* +LDAP_CALL +ber_special_alloc(size_t size, BerElement **ppBer) +{ + char *mem = NULL; + + /* Make sure mem size requested is aligned */ + if (0 != ( size & 0x03 )) { + size += (sizeof(ber_int_t) - (size & 0x03)); + } + + mem = NSLBERI_MALLOC(sizeof(struct berelement) + lber_bufsize + size ); + if (NULL == mem) { + return NULL; + } + *ppBer = (BerElement*) (mem + size); + memset(*ppBer,0,sizeof(struct berelement)); + (*ppBer)->ber_tag = LBER_DEFAULT; + (*ppBer)->ber_buf = mem + size + sizeof(struct berelement); + (*ppBer)->ber_ptr = (*ppBer)->ber_buf; + (*ppBer)->ber_end = (*ppBer)->ber_buf + lber_bufsize; + (*ppBer)->ber_flags = LBER_FLAG_NO_FREE_BUFFER; + return (void*)mem; +} + +void +LDAP_CALL +ber_special_free(void* buf, BerElement *ber) +{ + if (!(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { + NSLBERI_FREE(ber->ber_buf); + } + NSLBERI_FREE( buf ); +} + +/* Copy up to bytes_to_read bytes from b into return_buffer. + * Returns a count of bytes copied (always >= 0). + */ +static int +read_bytes(byte_buffer *b, unsigned char *return_buffer, int bytes_to_read) +{ + /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */ + int bytes_to_copy = 0; + + if (bytes_to_read <= (b->length - b->offset) ) { + bytes_to_copy = bytes_to_read; + } else { + bytes_to_copy = (b->length - b->offset); + } + if (1 == bytes_to_copy) { + *return_buffer = *(b->p+b->offset++); + } else if (bytes_to_copy <= 0) { + bytes_to_copy = 0; /* never return a negative result */ + } else { + SAFEMEMCPY(return_buffer,b->p+b->offset,bytes_to_copy); + b->offset += bytes_to_copy; + } + return bytes_to_copy; +} + +/* return the tag - LBER_DEFAULT returned means trouble */ +static ber_tag_t +get_buffer_tag(byte_buffer *sb ) +{ + unsigned char xbyte; + ber_tag_t tag; + char *tagp; + int i; + + if ( (i = read_bytes( sb, &xbyte, 1 )) != 1 ) { + return( LBER_DEFAULT ); + } + + if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { + return( (ber_uint_t) xbyte ); + } + + tagp = (char *) &tag; + tagp[0] = xbyte; + for ( i = 1; i < sizeof(ber_int_t); i++ ) { + if ( read_bytes( sb, &xbyte, 1 ) != 1 ) + return( LBER_DEFAULT ); + + tagp[i] = xbyte; + + if ( ! (xbyte & LBER_MORE_TAG_MASK) ) + break; + } + + /* tag too big! */ + if ( i == sizeof(ber_int_t) ) + return( LBER_DEFAULT ); + + /* want leading, not trailing 0's */ + return( tag >> (sizeof(ber_int_t) - i - 1) ); +} + +/* Like ber_get_next, but from a byte buffer the caller already has. */ +/* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */ +/* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */ +/* and is here for backward compatibility. This new function allows us to pass */ +/* the Sockbuf structure along */ + +ber_uint_t +LDAP_CALL +ber_get_next_buffer( void *buffer, size_t buffer_size, ber_len_t *len, + BerElement *ber, ber_uint_t *Bytes_Scanned ) +{ + return (ber_get_next_buffer_ext( buffer, buffer_size, len, ber, + Bytes_Scanned, NULL)); +} + +/* + * Returns the tag of the message or LBER_ return code if an error occurs. + * + * If there was not enough data in the buffer to complete the message this + * is a "soft" error. In this case, *Bytes_Scanned is set to a positive + * number and return code is set to LBER_DEFAULT. + * + * On overflow condition when the length is either bigger than ber_uint_t + * type or the value preset via LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE option, + * *Bytes_Scanned is set to zero and return code is set to LBER_OVERFLOW. + * + * For backward compatibility errno is also set on these error conditions: + * + * EINVAL - LBER_SOCKBUF_OPT_VALID_TAG option set but tag doesnt match. + * EMSGSIZE - an overflow condition as described above for LBER_OVERFLOW. + */ +ber_uint_t +LDAP_CALL +ber_get_next_buffer_ext( void *buffer, size_t buffer_size, ber_len_t *len, + BerElement *ber, ber_uint_t *Bytes_Scanned, Sockbuf *sock ) +{ + ber_tag_t tag = 0; + ber_len_t netlen; + ber_len_t toread; + unsigned char lc; + ssize_t rc; + int noctets, diff; + byte_buffer sb = {0}; + + + /* + * Any ber element looks like this: tag length contents. + * Assuming everything's ok, we return the tag byte (we + * can assume a single byte), return the length in len, + * and the rest of the undecoded element in buf. + * + * Assumptions: + * 1) small tags (less than 128) + * 2) definite lengths + * 3) primitive encodings used whenever possible + */ + + /* + * first time through - malloc the buffer, set up ptrs, and + * read the tag and the length and as much of the rest as we can + */ + + sb.p = buffer; + sb.length = buffer_size; + + if ( ber->ber_rwptr == NULL ) { + + /* + * First, we read the tag. + */ + + /* if we have been called before with a fragment not + * containing a complete length, we have no rwptr but + * a tag already + */ + if ( ber->ber_tag == LBER_DEFAULT ) { + if ( (tag = get_buffer_tag( &sb )) == LBER_DEFAULT ) { + goto premature_exit; + } + ber->ber_tag = tag; + } + + if((sock->sb_options & LBER_SOCKBUF_OPT_VALID_TAG) && + (ber->ber_tag != sock->sb_valid_tag)) { +#if !defined( macintosh ) && !defined( DOS ) + errno = EINVAL; +#endif + goto error_exit; + } + + /* If we have been called before with an incomplete length, + * the fragment of the length read is in ber->ber_len_contents + * ber->ber_tag_len_read is the # of bytes of the length available + * from a previous fragment + */ + + if (ber->ber_tag_len_read) { + int nbytes; + + noctets = ((ber->ber_len_contents[0]) & 0x7f); + diff = noctets + 1 /* tag */ - ber->ber_tag_len_read; + + if ( (nbytes = read_bytes( &sb, (unsigned char *) &ber->ber_len_contents[0] + + ber->ber_tag_len_read, diff )) != diff ) { + + if (nbytes > 0) + ber->ber_tag_len_read+=nbytes; + + goto premature_exit; + } + *len = get_ber_len(ber); /* cast ber->ber_len_contents to unsigned long */ + + } else { + /* + * Next, read the length. The first byte contains the length + * of the length. If bit 8 is set, the length is the long + * form, otherwise it's the short form. We don't allow a + * length that's greater than what we can hold in an unsigned + * long. + */ + + *len = netlen = 0; + if ( read_bytes( &sb, &lc, 1 ) != 1 ) { + goto premature_exit; + } + if ( lc & 0x80 ) { + int nbytes; + + noctets = (lc & 0x7f); + if ( noctets > sizeof(ber_uint_t) ) { +#if !defined( macintosh ) && !defined( DOS ) + errno = EMSGSIZE; +#endif + *Bytes_Scanned = 0; + return(LBER_OVERFLOW); + } + diff = sizeof(ber_uint_t) - noctets; + if ( (nbytes = read_bytes( &sb, (unsigned char *)&netlen + diff, + noctets )) != noctets ) { + /* + * The length is in long form and we don't get it in one + * fragment, so stash partial length in the ber element + * for later use + */ + + ber->ber_tag_len_read = nbytes + 1; + ber->ber_len_contents[0]=lc; + memset(&(ber->ber_len_contents[1]), 0, sizeof(ber_uint_t)); + SAFEMEMCPY(&(ber->ber_len_contents[1]), (unsigned char *)&netlen + diff, nbytes); + + goto premature_exit; + } + *len = LBER_NTOHL( netlen ); + } else { + *len = lc; + } + } + + ber->ber_len = *len; + /* length fully decoded */ + ber->ber_tag_len_read=0; + /* + * Finally, malloc a buffer for the contents and read it in. + * It's this buffer that's passed to all the other ber decoding + * routines. + */ + +#if defined( DOS ) && !defined( _WIN32 ) + if ( *len > 65535 ) { /* DOS can't allocate > 64K */ + goto premature_exit; + } +#endif /* DOS && !_WIN32 */ + + if ( (sock != NULL) && + ( sock->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) + && (*len > sock->sb_max_incoming) ) { +#if !defined( macintosh ) && !defined( DOS ) + errno = EMSGSIZE; +#endif + *Bytes_Scanned = 0; + return( LBER_OVERFLOW ); + } + + if ( ber->ber_buf + *len > ber->ber_end ) { + if ( nslberi_ber_realloc( ber, *len ) != 0 ) + goto error_exit; + } + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + *len; + ber->ber_rwptr = ber->ber_buf; + } + + toread = (ber_len_t)ber->ber_end - (ber_len_t)ber->ber_rwptr; + do { + if ( (rc = read_bytes( &sb, (unsigned char *)ber->ber_rwptr, + (ber_int_t)toread )) <= 0 ) { + goto premature_exit; + } + + toread -= rc; + ber->ber_rwptr += rc; + } while ( toread > 0 ); + + *len = ber->ber_len; + *Bytes_Scanned = sb.offset; + return( ber->ber_tag ); + +premature_exit: + /* + * we're here because we hit the end of the buffer before seeing + * all of the PDU + */ + *Bytes_Scanned = sb.offset; + return(LBER_DEFAULT); + +error_exit: + *Bytes_Scanned = 0; + return(LBER_DEFAULT); +} + + +/* 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 routine returns 0 on success and -1 on error. + * The use of ber_flatten on a BerElement in which all '{' and '}' + * format modifiers have not been properly matched can result in a + * berval whose contents are not a valid BER encoding. + * Note that the ber_ptr is not modified. + */ +int +LDAP_CALL +ber_flatten( BerElement *ber, struct berval **bvPtr ) +{ + struct berval *new; + ber_len_t len; + + /* allocate a struct berval */ + if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) + == NULL ) { + return( -1 ); + } + + /* + * Copy everything from the BerElement's ber_buf to ber_ptr + * into the berval structure. + */ + if ( ber == NULL ) { + new->bv_val = NULL; + new->bv_len = 0; + } else { + len = ber->ber_ptr - ber->ber_buf; + if ( ( new->bv_val = (char *)NSLBERI_MALLOC( len + 1 )) == NULL ) { + ber_bvfree( new ); + return( -1 ); + } + SAFEMEMCPY( new->bv_val, ber->ber_buf, (size_t)len ); + new->bv_val[len] = '\0'; + new->bv_len = len; + } + + /* set bvPtr pointer to point to the returned berval */ + *bvPtr = new; + + return( 0 ); +} + + +/* + * The ber_init function constructs and returns a new BerElement + * containing a copy of the data in the bv argument. ber_init + * returns the null pointer on error. + */ +BerElement * +LDAP_CALL +ber_init( const struct berval *bv ) +{ + BerElement *ber; + + /* construct BerElement */ + if (( ber = ber_alloc_t( 0 )) != NULLBER ) { + /* copy data from the bv argument into BerElement */ + /* XXXmcs: had to cast unsigned long bv_len to long */ + if ( (ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) + != (ber_slen_t)bv->bv_len ) { + ber_free( ber, 1 ); + return( NULL ); + } + } + + /* + * reset ber_ptr back to the beginning of buffer so that this new + * and initialized ber element can be READ + */ + ber_reset( ber, 1); + + /* + * return a ptr to a new BerElement containing a copy of the data + * in the bv argument or a null pointer on error + */ + return( ber ); +} + + +/* + * memory allocation functions. + */ +void * +nslberi_malloc( size_t size ) +{ + return( nslberi_memalloc_fns.lbermem_malloc == NULL ? + malloc( size ) : + nslberi_memalloc_fns.lbermem_malloc( size )); +} + + +void * +nslberi_calloc( size_t nelem, size_t elsize ) +{ + return( nslberi_memalloc_fns.lbermem_calloc == NULL ? + calloc( nelem, elsize ) : + nslberi_memalloc_fns.lbermem_calloc( nelem, elsize )); +} + + +void * +nslberi_realloc( void *ptr, size_t size ) +{ + return( nslberi_memalloc_fns.lbermem_realloc == NULL ? + realloc( ptr, size ) : + nslberi_memalloc_fns.lbermem_realloc( ptr, size )); +} + + +void +nslberi_free( void *ptr ) +{ + if ( nslberi_memalloc_fns.lbermem_free == NULL ) { + free( ptr ); + } else { + nslberi_memalloc_fns.lbermem_free( ptr ); + } +} + + +/* + ****************************************************************************** + * functions to bridge the gap between new extended I/O functions that are + * installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS, + * ... ). + * + * the basic strategy is to use the new extended arg to hold a pointer to the + * Sockbuf itself so we can find the old functions and call them. + * note that the integer socket s passed in is not used. we use the sb_sd + * from the Sockbuf itself because it is the correct type. + */ +static int +nslberi_extread_compat( int s, void *buf, int len, + struct lextiof_socket_private *arg ) +{ + Sockbuf *sb = (Sockbuf *)arg; + + return( sb->sb_io_fns.lbiof_read( sb->sb_sd, buf, len )); +} + + +static int +nslberi_extwrite_compat( int s, const void *buf, int len, + struct lextiof_socket_private *arg ) +{ + Sockbuf *sb = (Sockbuf *)arg; + + return( sb->sb_io_fns.lbiof_write( sb->sb_sd, buf, len )); +} + + +/* + * Install I/O compatiblity functions. This can't fail. + */ +static void +nslberi_install_compat_io_fns( Sockbuf *sb ) +{ + sb->sb_ext_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + sb->sb_ext_io_fns.lbextiofn_read = nslberi_extread_compat; + sb->sb_ext_io_fns.lbextiofn_write = nslberi_extwrite_compat; + sb->sb_ext_io_fns.lbextiofn_writev = NULL; + sb->sb_ext_io_fns.lbextiofn_socket_arg = (void *)sb; +} +/* + * end of compat I/O functions + ****************************************************************************** + */ diff --git a/ldap/c-sdk/liblber/lber-int.h b/ldap/c-sdk/liblber/lber-int.h new file mode 100644 index 0000000000..24b15bdc5f --- /dev/null +++ b/ldap/c-sdk/liblber/lber-int.h @@ -0,0 +1,305 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * 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. + */ +/* lbet-int.h - internal header file for liblber */ + +#ifndef _LBERINT_H +#define _LBERINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef macintosh +# include "ldap-macos.h" +#else /* macintosh */ +#if !defined(BSDI) && !defined(DARWIN) && !defined(FREEBSD) && !defined(OPENBSD) +# include +#endif +# include +# include +#if defined(SUNOS4) || defined(SCOOS) +# include +#endif +#if defined( _WINDOWS ) +# define WIN32_LEAN_AND_MEAN +# include +# include +# define ssize_t SSIZE_T +# include +/* No stderr in a 16-bit Windows DLL */ +# if defined(_WINDLL) && !defined(_WIN32) +# define USE_DBG_WIN +# endif +# else +/* # include */ +# include +# include +#if !defined(XP_OS2) && !defined(DARWIN) +# include +#endif +# endif /* defined( _WINDOWS ) */ +#endif /* macintosh */ + +#include +#include +#include "portable.h" + +#ifdef _WINDOWS +# if defined(FD_SETSIZE) +# else +# define FD_SETSIZE 256 /* set it before winsock sets it to 64! */ +# endif +#include +#include +#endif /* _WINDOWS */ + +#ifdef XP_OS2 +#include +#endif /* XP_OS2 */ + +/* No stderr in a 16-bit Windows DLL */ +#if defined(_WINDLL) && !defined(_WIN32) +#define stderr NULL +#endif + +#include "lber.h" + +#ifdef macintosh +#define NSLDAPI_LBER_SOCKET_IS_PTR +#endif + +#define OLD_LBER_SEQUENCE 0x10 /* w/o constructed bit - broken */ +#define OLD_LBER_SET 0x11 /* w/o constructed bit - broken */ + +#ifndef _IFP +#define _IFP +typedef int (LDAP_C LDAP_CALLBACK *IFP)(); +#endif + +typedef struct seqorset { + ber_len_t sos_clen; + ber_tag_t sos_tag; + char *sos_first; + char *sos_ptr; + struct seqorset *sos_next; +} Seqorset; +#define NULLSEQORSET ((Seqorset *) 0) + +#define SOS_STACK_SIZE 8 /* depth of the pre-allocated sos structure stack */ + +#define MAX_TAG_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the tag */ +#define MAX_LEN_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the length */ +#define MAX_VALUE_PREFIX_SIZE (2 + sizeof(ber_int_t)) /* 1 byte for the tag and 1 for the len (msgid) */ +#define BER_ARRAY_QUANTITY 7 /* 0:Tag 1:Length 2:Value-prefix 3:Value 4:Value-suffix */ +#define BER_STRUCT_TAG 0 /* 5:ControlA 6:ControlB */ +#define BER_STRUCT_LEN 1 +#define BER_STRUCT_PRE 2 +#define BER_STRUCT_VAL 3 +#define BER_STRUCT_SUF 4 +#define BER_STRUCT_CO1 5 +#define BER_STRUCT_CO2 6 + +struct berelement { + ldap_x_iovec ber_struct[BER_ARRAY_QUANTITY]; /* See above */ + + char ber_tag_contents[MAX_TAG_SIZE]; + char ber_len_contents[MAX_LEN_SIZE]; + char ber_pre_contents[MAX_VALUE_PREFIX_SIZE]; + char ber_suf_contents[MAX_LEN_SIZE+1]; + + char *ber_buf; /* update the value value when writing in case realloc is called */ + char *ber_ptr; + char *ber_end; + struct seqorset *ber_sos; + ber_len_t ber_tag_len_read; + ber_tag_t ber_tag; /* Remove me someday */ + ber_len_t ber_len; /* Remove me someday */ + int ber_usertag; + char ber_options; + char *ber_rwptr; + BERTranslateProc ber_encode_translate_proc; + BERTranslateProc ber_decode_translate_proc; + int ber_flags; +#define LBER_FLAG_NO_FREE_BUFFER 1 /* don't free ber_buf */ + unsigned int ber_buf_reallocs; /* realloc counter */ + int ber_sos_stack_posn; + Seqorset ber_sos_stack[SOS_STACK_SIZE]; +}; + +#define BER_CONTENTS_STRUCT_SIZE (sizeof(ldap_x_iovec) * BER_ARRAY_QUANTITY) + +#define NULLBER ((BerElement *)NULL) + +#ifdef LDAP_DEBUG +void ber_dump( BerElement *ber, int inout ); +#endif + + + +/* + * structure for read/write I/O callback functions. + */ +struct nslberi_io_fns { + LDAP_IOF_READ_CALLBACK *lbiof_read; + LDAP_IOF_WRITE_CALLBACK *lbiof_write; +}; + + +/* + * Old structure for use with LBER_SOCKBUF_OPT_EXT_IO_FNS: + */ +struct lber_x_ext_io_fns_rev0 { + /* lbextiofn_size should always be set to LBER_X_EXTIO_FNS_SIZE */ + int lbextiofn_size; + LDAP_X_EXTIOF_READ_CALLBACK *lbextiofn_read; + LDAP_X_EXTIOF_WRITE_CALLBACK *lbextiofn_write; + struct lextiof_socket_private *lbextiofn_socket_arg; +}; +#define LBER_X_EXTIO_FNS_SIZE_REV0 sizeof(struct lber_x_ext_io_fns_rev0) + + + +struct sockbuf { + LBER_SOCKET sb_sd; + BerElement sb_ber; + int sb_naddr; /* > 0 implies using CLDAP (UDP) */ + void *sb_useaddr; /* pointer to sockaddr to use next */ + void *sb_fromaddr; /* pointer to message source sockaddr */ + void **sb_addrs; /* actually an array of pointers to + sockaddrs */ + + int sb_options; /* to support copying ber elements */ + LBER_SOCKET sb_copyfd; /* for LBER_SOCKBUF_OPT_TO_FILE* opts */ + ber_len_t sb_max_incoming; + ber_tag_t sb_valid_tag; /* valid tag to accept */ + struct nslberi_io_fns + sb_io_fns; /* classic I/O callback functions */ + + struct lber_x_ext_io_fns + sb_ext_io_fns; /* extended I/O callback functions */ +}; +#define NULLSOCKBUF ((Sockbuf *)NULL) + +/* needed by libldap, even in non-DEBUG builds */ +void ber_err_print( char *data ); + +#ifndef NSLBERI_LBER_INT_FRIEND +/* + * Everything from this point on is excluded if NSLBERI_LBER_INT_FRIEND is + * defined. The code under ../libraries/libldap defines this. + */ + +#define READBUFSIZ 8192 + +/* + * macros used to check validity of data structures and parameters + */ +#define NSLBERI_VALID_BERELEMENT_POINTER( ber ) \ + ( (ber) != NULLBER ) + +#define NSLBERI_VALID_SOCKBUF_POINTER( sb ) \ + ( (sb) != NULLSOCKBUF ) + +#define LBER_HTONL( l ) htonl( l ) +#define LBER_NTOHL( l ) ntohl( l ) + +/* function prototypes */ +#ifdef LDAP_DEBUG +void lber_bprint( char *data, int len ); +#endif +void ber_err_print( char *data ); +void *nslberi_malloc( size_t size ); +void *nslberi_calloc( size_t nelem, size_t elsize ); +void *nslberi_realloc( void *ptr, size_t size ); +void nslberi_free( void *ptr ); +int nslberi_ber_realloc( BerElement *ber, ber_len_t len ); + +/* blame: dboreham + * slapd spends much of its time doing memcpy's for the ber code. + * Most of these are single-byte, so we special-case those and speed + * things up considerably. + */ + +#ifdef sunos4 +#define THEMEMCPY( d, s, n ) bcopy( s, d, n ) +#else /* sunos4 */ +#define THEMEMCPY( d, s, n ) memmove( d, s, n ) +#endif /* sunos4 */ + +#ifdef SAFEMEMCPY +#undef SAFEMEMCPY +#define SAFEMEMCPY(d,s,n) if (1 == n) *((char*)d) = *((char*)s); else THEMEMCPY(d,s,n); +#endif + +/* + * Memory allocation done in liblber should all go through one of the + * following macros. This is so we can plug-in alternative memory + * allocators, etc. as the need arises. + */ +#define NSLBERI_MALLOC( size ) nslberi_malloc( size ) +#define NSLBERI_CALLOC( nelem, elsize ) nslberi_calloc( nelem, elsize ) +#define NSLBERI_REALLOC( ptr, size ) nslberi_realloc( ptr, size ) +#define NSLBERI_FREE( ptr ) nslberi_free( ptr ) + +/* allow the library to access the debug variable */ + +extern int lber_debug; + +#endif /* !NSLBERI_LBER_INT_FRIEND */ + + +#ifdef __cplusplus +} +#endif +#endif /* _LBERINT_H */ diff --git a/ldap/c-sdk/liblber/moz.build b/ldap/c-sdk/liblber/moz.build new file mode 100644 index 0000000000..d2adf23bf9 --- /dev/null +++ b/ldap/c-sdk/liblber/moz.build @@ -0,0 +1,23 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include('../common.mozbuild') + +Library('lber60') + +SOURCES += [ + 'bprint.c', + 'decode.c', + 'encode.c', + 'io.c', +] + +DEFINES['USE_WAITPID'] = True +DEFINES['NEEDPROTOS'] = True + +LOCAL_INCLUDES += [ + '../include' +] + diff --git a/ldap/c-sdk/libldap/abandon.c b/ldap/c-sdk/libldap/abandon.c new file mode 100644 index 0000000000..a514cfd895 --- /dev/null +++ b/ldap/c-sdk/libldap/abandon.c @@ -0,0 +1,303 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * abandon.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +static int do_abandon( LDAP *ld, int origid, int msgid, + LDAPControl **serverctrls, LDAPControl **clientctrls ); +static int nsldapi_send_abandon_message( LDAP *ld, LDAPConn *lc, + BerElement *ber, int abandon_msgid ); + +/* + * ldap_abandon - perform an ldap abandon operation. Parameters: + * + * ld LDAP descriptor + * msgid The message id of the operation to abandon + * + * ldap_abandon returns 0 if everything went ok, -1 otherwise. + * + * Example: + * ldap_abandon( ld, msgid ); + */ +int +LDAP_CALL +ldap_abandon( LDAP *ld, int msgid ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "4e65747363617065\n", msgid, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "466f726576657221\n", msgid, 0, 0 ); + + if ( ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS ) { + return( 0 ); + } + + return( -1 ); +} + + +/* + * LDAPv3 extended abandon. + * Returns an LDAP error code. + */ +int +LDAP_CALL +ldap_abandon_ext( LDAP *ld, int msgid, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + rc = do_abandon( ld, msgid, msgid, serverctrls, clientctrls ); + + /* + * XXXmcs should use cache function pointers to hook in memcache + */ + ldap_memcache_abandon( ld, msgid ); + + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + + return( rc ); +} + + +/* + * Abandon all outstanding requests for msgid (included child requests + * spawned when chasing referrals). This function calls itself recursively. + * No locking is done is this function so it must be done by the caller. + * Returns an LDAP error code and sets it in LDAP *ld as well + */ +static int +do_abandon( LDAP *ld, int origid, int msgid, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + BerElement *ber; + int i, bererr, lderr, sendabandon; + LDAPRequest *lr = NULL; + + /* + * An abandon request looks like this: + * AbandonRequest ::= MessageID + */ + LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", + origid, msgid, 0 ); + + /* optimistic */ + lderr = LDAP_SUCCESS; + + /* + * Find the request that we are abandoning. Don't send an + * abandon message unless there is something to abandon. + */ + sendabandon = 0; + for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { + if ( lr->lr_msgid == msgid ) { /* this message */ + if ( origid == msgid && lr->lr_parent != NULL ) { + /* don't let caller abandon child requests! */ + lderr = LDAP_PARAM_ERROR; + goto set_errorcode_and_return; + } + if ( lr->lr_status == LDAP_REQST_INPROGRESS ) { + /* + * We only need to send an abandon message if + * the request is in progress. + */ + sendabandon = 1; + } + break; + } + if ( lr->lr_origid == msgid ) { /* child: abandon it */ + (void)do_abandon( ld, msgid, lr->lr_msgid, + serverctrls, clientctrls ); + /* we ignore errors from child abandons... */ + } + } + + if ( ldap_msgdelete( ld, msgid ) == 0 ) { + /* we had all the results and deleted them */ + goto set_errorcode_and_return; + } + + if ( lr != NULL && sendabandon ) { + /* create a message to send */ + if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) == + LDAP_SUCCESS ) { + int abandon_msgid; + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + abandon_msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); +#ifdef CLDAP + if ( ld->ld_dbp->sb_naddr > 0 ) { + bererr = ber_printf( ber, "{isti", + abandon_msgid, ld->ld_cldapdn, + LDAP_REQ_ABANDON, msgid ); + } else { +#endif /* CLDAP */ + bererr = ber_printf( ber, "{iti", + abandon_msgid, LDAP_REQ_ABANDON, msgid ); +#ifdef CLDAP + } +#endif /* CLDAP */ + + if ( bererr == -1 || + ( lderr = nsldapi_put_controls( ld, serverctrls, + 1, ber )) != LDAP_SUCCESS ) { + lderr = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + } else { + /* try to send the message */ + lderr = nsldapi_send_abandon_message( ld, + lr->lr_conn, ber, abandon_msgid ); + } + } + } + + if ( lr != NULL ) { + /* + * Always call nsldapi_free_connection() so that the connection's + * ref count is correctly decremented. It is OK to always pass + * 1 for the "unbind" parameter because doing so will only affect + * connections that resulted from a child request (because the + * default connection's ref count never goes to zero). + */ + nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL, + 0 /* do not force */, 1 /* send unbind before closing */ ); + + /* + * Free the entire request chain if we finished abandoning everything. + */ + if ( origid == msgid ) { + nsldapi_free_request( ld, lr, 0 ); + } + } + + /* + * Record the abandoned message ID (used to discard any server responses + * that arrive later). + */ + LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); + if ( ld->ld_abandoned == NULL ) { + if ( (ld->ld_abandoned = (int *)NSLDAPI_MALLOC( 2 + * sizeof(int) )) == NULL ) { + lderr = LDAP_NO_MEMORY; + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + goto set_errorcode_and_return; + } + i = 0; + } else { + for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) + ; /* NULL */ + if ( (ld->ld_abandoned = (int *)NSLDAPI_REALLOC( (char *) + ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) { + lderr = LDAP_NO_MEMORY; + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + goto set_errorcode_and_return; + } + } + ld->ld_abandoned[i] = msgid; + ld->ld_abandoned[i + 1] = -1; + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + +set_errorcode_and_return: + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + return( lderr ); +} + +/* + * Try to send the abandon message that is encoded in ber. Returns an + * LDAP result code. + */ +static int +nsldapi_send_abandon_message( LDAP *ld, LDAPConn *lc, BerElement *ber, + int abandon_msgid ) +{ + int lderr = LDAP_SUCCESS; + int err = 0; + + err = nsldapi_send_ber_message( ld, lc->lconn_sb, + ber, 1 /* free ber */, 0 /* will not handle EPIPE */ ); + if ( err == -2 ) { + /* + * "Would block" error. Queue the abandon as + * a pending request. + */ + LDAPRequest *lr; + + lr = nsldapi_new_request( lc, ber, abandon_msgid, + 0 /* no response expected */ ); + if ( lr == NULL ) { + lderr = LDAP_NO_MEMORY; + ber_free( ber, 1 ); + } else { + lr->lr_status = LDAP_REQST_WRITING; + nsldapi_queue_request_nolock( ld, lr ); + ++lc->lconn_pending_requests; + nsldapi_iostatus_interest_write( ld, + lc->lconn_sb ); + } + } else if ( err != 0 ) { + /* + * Fatal error (not a "would block" error). + */ + lderr = LDAP_SERVER_DOWN; + ber_free( ber, 1 ); + } + + return( lderr ); +} diff --git a/ldap/c-sdk/libldap/add.c b/ldap/c-sdk/libldap/add.c new file mode 100644 index 0000000000..0cb5dbfb5f --- /dev/null +++ b/ldap/c-sdk/libldap/add.c @@ -0,0 +1,225 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * add.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_add - initiate an ldap add operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the entry to add + * mods List of attributes for the entry. This is a null- + * terminated array of pointers to LDAPMod structures. + * only the type and values in the structures need be + * filled in. + * + * Example: + * LDAPMod *attrs[] = { + * { 0, "cn", { "babs jensen", "babs", 0 } }, + * { 0, "sn", { "jensen", 0 } }, + * { 0, "objectClass", { "person", 0 } }, + * 0 + * } + * msgid = ldap_add( ld, dn, attrs ); + */ +int +LDAP_CALL +ldap_add( LDAP *ld, const char *dn, LDAPMod **attrs ) +{ + int msgid; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_add\n", 0, 0, 0 ); + + if ( ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ) + == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + + +/* + * LDAPv3 extended add. + * Returns an LDAP error code. + */ +int +LDAP_CALL +ldap_add_ext( LDAP *ld, const char *dn, LDAPMod **attrs, + LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) +{ + BerElement *ber; + int i, rc, lderr; + + /* + * An add request looks like this: + * AddRequest ::= SEQUENCE { + * entry DistinguishedName, + * attrs SEQUENCE OF SEQUENCE { + * type AttributeType, + * values SET OF AttributeValue + * } + * } + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) + { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( attrs ) + || msgidp == NULL ) { + lderr = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + return( lderr ); + } + + if ( dn == NULL ) { + dn = ""; + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* see if we should add to the cache */ + if ( ld->ld_cache_on && ld->ld_cache_add != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_add)( ld, *msgidp, LDAP_REQ_ADD, dn, + attrs )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* create a message to send */ + if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( lderr ); + } + + if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_ADD, dn ) + == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + /* for each attribute in the entry... */ + for ( i = 0; attrs[i] != NULL; i++ ) { + if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { + rc = ber_printf( ber, "{s[V]}", attrs[i]->mod_type, + attrs[i]->mod_bvalues ); + } else { + rc = ber_printf( ber, "{s[v]}", attrs[i]->mod_type, + attrs[i]->mod_values ); + } + if ( rc == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + } + + if ( ber_printf( ber, "}}" ) == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( lderr ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_ADD, + (char *) dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +int +LDAP_CALL +ldap_add_s( LDAP *ld, const char *dn, LDAPMod **attrs ) +{ + return( ldap_add_ext_s( ld, dn, attrs, NULL, NULL )); +} + +int LDAP_CALL +ldap_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs, + LDAPControl **serverctrls, LDAPControl **clientctrls ) +{ + int err, msgid; + LDAPMessage *res; + + if (( err = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, + &msgid )) != LDAP_SUCCESS ) { + return( err ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + return( ldap_result2error( ld, res, 1 ) ); +} diff --git a/ldap/c-sdk/libldap/authzidctrl.c b/ldap/c-sdk/libldap/authzidctrl.c new file mode 100644 index 0000000000..69b776cdc4 --- /dev/null +++ b/ldap/c-sdk/libldap/authzidctrl.c @@ -0,0 +1,157 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): abobrov@sun.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_create_authzid_control: + +Parameters are + +ld LDAP pointer to the desired connection + +ctl_iscritical Indicates whether the control is critical of not. + If this field is non-zero, the operation will only be + carried out if the control is recognized by the server + and/or client + +ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_authzid_control ( + LDAP *ld, + const char ctl_iscritical, + LDAPControl **ctrlp + ) +{ + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_AUTHZID_REQ, + NULL, 0, ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + +/* ldap_parse_authzid_control: + +Parameters are + +ld LDAP pointer to the desired connection + +ctrlp An array of controls obtained from calling + ldap_parse_result on the set of results + returned by the server + +authzid authorization identity, as defined in + RFC 2829, section 9. +*/ + +int +LDAP_CALL +ldap_parse_authzid_control ( + LDAP *ld, + LDAPControl **ctrlp, + char **authzid + ) +{ + int i, foundAUTHZIDControl; + char *authzidp = NULL; + LDAPControl *AUTHZIDCtrlp = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { + return( LDAP_PARAM_ERROR ); + } + + /* find the control in the list of controls if it exists */ + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + foundAUTHZIDControl = 0; + for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundAUTHZIDControl )); i++ ) { + foundAUTHZIDControl = !strcmp( ctrlp[i]->ldctl_oid, + LDAP_CONTROL_AUTHZID_RES ); + } + + /* + * The control is only included in a bind response if the resultCode + * for the bind operation is success. + */ + if ( !foundAUTHZIDControl ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } else { + /* let local var point to the control */ + AUTHZIDCtrlp = ctrlp[i-1]; + } + + /* + * If the bind request succeeded and resulted in an identity (not anonymous), + * the controlValue contains the authorization identity (authzid), as + * defined in [AUTH] section 9, granted to the requestor. If the bind + * request resulted in an anonymous association, the controlValue field + * is a string of zero length. If the bind request resulted in more + * than one authzid, the primary authzid is returned in the controlValue + * field. + */ + if ( AUTHZIDCtrlp && AUTHZIDCtrlp->ldctl_value.bv_val && + AUTHZIDCtrlp->ldctl_value.bv_len ) { + authzidp = ( (char *)NSLDAPI_MALLOC( + ( AUTHZIDCtrlp->ldctl_value.bv_len + 1 ) ) ); + if ( authzidp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + STRLCPY( authzidp, AUTHZIDCtrlp->ldctl_value.bv_val, + ( AUTHZIDCtrlp->ldctl_value.bv_len + 1 ) ); + *authzid = authzidp; + } else { + authzid = NULL; + } + + return( LDAP_SUCCESS ); +} diff --git a/ldap/c-sdk/libldap/bind.c b/ldap/c-sdk/libldap/bind.c new file mode 100644 index 0000000000..8b5504be31 --- /dev/null +++ b/ldap/c-sdk/libldap/bind.c @@ -0,0 +1,170 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * bind.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_bind - bind to the ldap server. The dn and password + * of the entry to which to bind are supplied, along with the authentication + * method to use. The msgid of the bind request is returned on success, + * -1 if there's trouble. Note, the kerberos support assumes the user already + * has a valid tgt for now. ldap_result() should be called to find out the + * outcome of the bind request. + * + * Example: + * ldap_bind( ld, "cn=manager, o=university of michigan, c=us", "secret", + * LDAP_AUTH_SIMPLE ) + */ + +int +LDAP_CALL +ldap_bind( LDAP *ld, const char *dn, const char *passwd, int authmethod ) +{ + /* + * The bind request looks like this: + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING -- passwd + * } + * } + * all wrapped up in an LDAPMessage sequence. + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); + } + + switch ( authmethod ) { + case LDAP_AUTH_SIMPLE: + return( ldap_simple_bind( ld, dn, passwd ) ); + + default: + LDAP_SET_LDERRNO( ld, LDAP_AUTH_UNKNOWN, NULL, NULL ); + return( -1 ); + } +} + +/* + * ldap_bind_s - bind to the ldap server. The dn and password + * of the entry to which to bind are supplied, along with the authentication + * method to use. This routine just calls whichever bind routine is + * appropriate and returns the result of the bind (e.g. LDAP_SUCCESS or + * some other error indication). Note, the kerberos support assumes the + * user already has a valid tgt for now. + * + * Examples: + * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", + * "secret", LDAP_AUTH_SIMPLE ) + * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", + * NULL, LDAP_AUTH_KRBV4 ) + */ +int +LDAP_CALL +ldap_bind_s( LDAP *ld, const char *dn, const char *passwd, int authmethod ) +{ + int err; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_bind_s\n", 0, 0, 0 ); + + switch ( authmethod ) { + case LDAP_AUTH_SIMPLE: + return( ldap_simple_bind_s( ld, dn, passwd ) ); + + default: + err = LDAP_AUTH_UNKNOWN; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } +} + + +void +LDAP_CALL +ldap_set_rebind_proc( LDAP *ld, LDAP_REBINDPROC_CALLBACK *rebindproc, + void *arg ) +{ + if ( ld == NULL ) { + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + ld = &nsldapi_ld_defaults; + } + + if ( NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + ld->ld_rebind_fn = rebindproc; + ld->ld_rebind_arg = arg; + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + } +} + + +/* + * return a pointer to the bind DN for the default connection (a copy is + * not made). If there is no bind DN available, NULL is returned. + */ +char * +nsldapi_get_binddn( LDAP *ld ) +{ + char *binddn; + + binddn = NULL; /* default -- assume they are not bound */ + + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + if ( NULL != ld->ld_defconn && LDAP_CONNST_CONNECTED == + ld->ld_defconn->lconn_status && ld->ld_defconn->lconn_bound ) { + if (( binddn = ld->ld_defconn->lconn_binddn ) == NULL ) { + binddn = ""; + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + + return( binddn ); +} diff --git a/ldap/c-sdk/libldap/cache.c b/ldap/c-sdk/libldap/cache.c new file mode 100644 index 0000000000..54195e5fe3 --- /dev/null +++ b/ldap/c-sdk/libldap/cache.c @@ -0,0 +1,145 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993 The Regents of the University of Michigan. + * All rights reserved. + */ +/* + * cache.c - generic caching support for LDAP + */ + +#include "ldap-int.h" + +/* + * ldap_cache_flush - flush part of the LDAP cache. returns an + * ldap error code (LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT, etc.). + */ + +int +LDAP_CALL +ldap_cache_flush( LDAP *ld, const char *dn, const char *filter ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( dn == NULL ) { + dn = ""; + } + + return( (ld->ld_cache_flush)( ld, dn, filter ) ); +} + +/* + * nsldapi_add_result_to_cache - add an ldap entry we just read off the network + * to the ldap cache. this routine parses the ber for the entry and + * constructs the appropriate add request. this routine calls the + * cache add routine to actually add the entry. + */ + +void +nsldapi_add_result_to_cache( LDAP *ld, LDAPMessage *m ) +{ + char *dn; + LDAPMod **mods; + int i, max, rc; + char *a; + BerElement *ber; + char buf[50]; + struct berval bv; + struct berval *bvp[2]; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_add_result_to_cache id %d type %d\n", + m->lm_msgid, m->lm_msgtype, 0 ); + if ( m->lm_msgtype != LDAP_RES_SEARCH_ENTRY || + ld->ld_cache_add == NULL ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_add_result_to_cache not added\n", 0, 0, 0 ); + return; + } + +#define GRABSIZE 5 + + dn = ldap_get_dn( ld, m ); + mods = (LDAPMod **)NSLDAPI_MALLOC( GRABSIZE * sizeof(LDAPMod *) ); + max = GRABSIZE; + for ( i = 0, a = ldap_first_attribute( ld, m, &ber ); a != NULL; + a = ldap_next_attribute( ld, m, ber ), i++ ) { + if ( i == (max - 1) ) { + max += GRABSIZE; + mods = (LDAPMod **)NSLDAPI_REALLOC( mods, + sizeof(LDAPMod *) * max ); + } + + mods[i] = (LDAPMod *)NSLDAPI_CALLOC( 1, sizeof(LDAPMod) ); + mods[i]->mod_op = LDAP_MOD_BVALUES; + mods[i]->mod_type = a; + mods[i]->mod_bvalues = ldap_get_values_len( ld, m, a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + if (( rc = LDAP_GET_LDERRNO( ld, NULL, NULL )) != LDAP_SUCCESS ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_add_result_to_cache error: failed to construct mod list (%s)\n", + ldap_err2string( rc ), 0, 0 ); + ldap_mods_free( mods, 1 ); + return; + } + + /* update special cachedtime attribute */ + if ( i == (max - 1) ) { + max++; + mods = (LDAPMod **)NSLDAPI_REALLOC( mods, + sizeof(LDAPMod *) * max ); + } + mods[i] = (LDAPMod *)NSLDAPI_CALLOC( 1, sizeof(LDAPMod) ); + mods[i]->mod_op = LDAP_MOD_BVALUES; + mods[i]->mod_type = "cachedtime"; + sprintf( buf, "%ld", time( NULL ) ); + bv.bv_val = buf; + bv.bv_len = strlen( buf ); + bvp[0] = &bv; + bvp[1] = NULL; + mods[i]->mod_bvalues = bvp; + mods[++i] = NULL; + + /* msgid of -1 means don't send the result */ + rc = (ld->ld_cache_add)( ld, -1, m->lm_msgtype, dn, mods ); + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_add_result_to_cache added (rc %d)\n", rc, 0, 0 ); +} diff --git a/ldap/c-sdk/libldap/charray.c b/ldap/c-sdk/libldap/charray.c new file mode 100644 index 0000000000..043f99e8aa --- /dev/null +++ b/ldap/c-sdk/libldap/charray.c @@ -0,0 +1,248 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* charray.c - routines for dealing with char * arrays */ + + +#include "ldap-int.h" + +/* + * Add s at the end of the array of strings *a. + * Return 0 for success, -1 for failure. + */ +int +LDAP_CALL +ldap_charray_add( + char ***a, + char *s +) +{ + int n; + + if ( *a == NULL ) { + *a = (char **)NSLDAPI_MALLOC( 2 * sizeof(char *) ); + if ( *a == NULL ) { + return -1; + } + n = 0; + } else { + for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { + ; /* NULL */ + } + + *a = (char **)NSLDAPI_REALLOC( (char *) *a, + (n + 2) * sizeof(char *) ); + if ( *a == NULL ) { + return -1; + } + } + + (*a)[n++] = s; + (*a)[n] = NULL; + return 0; +} + +/* + * Add array of strings s at the end of the array of strings *a. + * Return 0 for success, -1 for failure. + */ +int +LDAP_CALL +ldap_charray_merge( + char ***a, + char **s +) +{ + int i, n, nn; + + if ( (s == NULL) || (s[0] == NULL) ) + return 0; + + for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { + ; /* NULL */ + } + for ( nn = 0; s[nn] != NULL; nn++ ) { + ; /* NULL */ + } + + *a = (char **)NSLDAPI_REALLOC( (char *) *a, + (n + nn + 1) * sizeof(char *) ); + if ( *a == NULL ) { + return -1; + } + + for ( i = 0; i < nn; i++ ) { + (*a)[n + i] = s[i]; + } + (*a)[n + nn] = NULL; + return 0; +} + +void +LDAP_CALL +ldap_charray_free( char **array ) +{ + char **a; + + if ( array == NULL ) { + return; + } + + for ( a = array; *a != NULL; a++ ) { + if ( *a != NULL ) { + NSLDAPI_FREE( *a ); + } + } + NSLDAPI_FREE( (char *) array ); +} + +int +LDAP_CALL +ldap_charray_inlist( + char **a, + char *s +) +{ + int i; + + if ( a == NULL ) + return( 0 ); + + for ( i = 0; a[i] != NULL; i++ ) { + if ( strcasecmp( s, a[i] ) == 0 ) { + return( 1 ); + } + } + + return( 0 ); +} + +/* + * Duplicate the array of strings a, return NULL upon any memory failure. + */ +char ** +LDAP_CALL +ldap_charray_dup( char **a ) +{ + int i; + char **new; + + for ( i = 0; a[i] != NULL; i++ ) + ; /* NULL */ + + new = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) ); + if ( new == NULL ) { + return NULL; + } + + for ( i = 0; a[i] != NULL; i++ ) { + new[i] = nsldapi_strdup( a[i] ); + if ( new[i] == NULL ) { + int j; + + for ( j = 0; j < i; j++ ) + NSLDAPI_FREE( new[j] ); + NSLDAPI_FREE( new ); + return NULL; + } + } + new[i] = NULL; + + return( new ); +} + +/* + * Tokenize the string str, return NULL upon any memory failure. + * XXX: on many platforms this function is not thread safe because it + * uses strtok(). + */ +char ** +LDAP_CALL +ldap_str2charray( char *str, char *brkstr ) + /* This implementation fails if brkstr contains multibyte characters. + But it works OK if str is UTF-8 and brkstr is 7-bit ASCII. + */ +{ + char **res; + char *s; + int i; +#ifdef HAVE_STRTOK_R /* defined in portable.h */ + char *lasts; +#endif + + i = 1; + for ( s = str; *s; s++ ) { + if ( strchr( brkstr, *s ) != NULL ) { + i++; + } + } + + res = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) ); + if ( res == NULL ) { + return NULL; + } + i = 0; + for ( s = STRTOK( str, brkstr, &lasts ); s != NULL; s = STRTOK( NULL, + brkstr, &lasts ) ) { + res[i++] = nsldapi_strdup( s ); + if ( res[i - 1] == NULL ) { + int j; + + for ( j = 0; j < (i - 1); j++ ) + NSLDAPI_FREE( res[j] ); + NSLDAPI_FREE( res ); + return NULL; + } + } + res[i] = NULL; + + return( res ); +} + +int +LDAP_CALL +ldap_charray_position( char **a, char *s ) +{ + int i; + + for ( i = 0; a[i] != NULL; i++ ) { + if ( strcasecmp( s, a[i] ) == 0 ) { + return( i ); + } + } + + return( -1 ); +} diff --git a/ldap/c-sdk/libldap/charset.c b/ldap/c-sdk/libldap/charset.c new file mode 100644 index 0000000000..23bad239be --- /dev/null +++ b/ldap/c-sdk/libldap/charset.c @@ -0,0 +1,1845 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * charset.c + */ + +#include "ldap-int.h" + +#ifdef STR_TRANSLATION + +void +ldap_set_string_translators( LDAP *ld, BERTranslateProc encode_proc, + BERTranslateProc decode_proc ) +{ + if ( ld == NULL ) { + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + ld = &nsldapi_ld_defaults; + } + + if ( NSLDAPI_VALID_LDAP_POINTER( ld )) { + 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 ) +{ + char *optionsp; + + if ( ld == NULL ) { + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + ld = &nsldapi_ld_defaults; + } + + optionsp = ( entry == NULLMSG ) ? &ld->ld_lberoptions : + &entry->lm_ber->ber_options; + + if ( enable ) { + *optionsp |= LBER_OPT_TRANSLATE_STRINGS; + } else { + *optionsp &= ~LBER_OPT_TRANSLATE_STRINGS; + } +} + + +int +ldap_translate_from_t61( LDAP *ld, char **bufp, unsigned long *lenp, + int free_input ) +{ + if ( ld->ld_lber_decode_translate_proc == NULL ) { + return( LDAP_SUCCESS ); + } + + return( (*ld->ld_lber_decode_translate_proc)( bufp, lenp, free_input )); +} + + +int +ldap_translate_to_t61( LDAP *ld, char **bufp, unsigned long *lenp, + int free_input ) +{ + if ( ld->ld_lber_encode_translate_proc == NULL ) { + 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; + +#ifdef NEEDPROTOS +static Byte *c_to_hh( Byte *o, Byte c ); +static Byte *c_to_cc( Byte *o, Couple *cc, Byte c ); +static int hh_to_c( Byte *h ); +static Byte *cc_to_t61( Byte *o, Byte *s ); +#else /* NEEDPROTOS */ +static Byte *c_to_hh(); +static Byte *c_to_cc(); +static int hh_to_c(); +static Byte *cc_to_t61(); +#endif /* NEEDPROTOS */ + +/* + Character choosed as base in diacritics alone: NO-BREAK SPACE. + (The standard say it must be a blank space, 0x20.) +*/ +#define ALONE 0xA0 + +static 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 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 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 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 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 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 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 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 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 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, 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, unsigned long *buflenp, int free_input ) +{ + Byte *s, *oo, *o; + unsigned int n; + int c; + unsigned long len; + Couple *cc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_t61_to_8859 input length: %ld\n", + *buflenp, 0, 0 ); + + len = *buflenp; + s = (Byte *) *bufp; + + if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, len )) == NULL ) { + NSLDAPI_FREE( o ); + return( 1 ); + } + + if ( free_input ) { + NSLDAPI_FREE( *bufp ); + } + *bufp = (char *) oo; + *buflenp = len; + return( 0 ); +} + + +static int +hh_to_c( 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, 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, unsigned long *buflenp, int free_input ) +{ + Byte *s, *oo, *o, *aux; + int c; + unsigned long len; + Couple *cc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_8859_to_t61 input length: %ld\n", + *buflenp, 0, 0 ); + + len = *buflenp; + s = (Byte *) *bufp; + + if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, len )) == NULL ) { + NSLDAPI_FREE( o ); + return( 1 ); + } + + if ( free_input ) { + NSLDAPI_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( ++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 ) +Byte *s; +{ + Byte *o, *oo; + Byte n; + + if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, strlen( o ) + 1 )) == NULL ) { + NSLDAPI_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 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; + Couple *cc; + + if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, strlen( o ) + 1 )) == NULL ) { + NSLDAPI_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/ldap/c-sdk/libldap/cldap.c b/ldap/c-sdk/libldap/cldap.c new file mode 100644 index 0000000000..829d34c287 --- /dev/null +++ b/ldap/c-sdk/libldap/cldap.c @@ -0,0 +1,585 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990, 1994 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * cldap.c - synchronous, retrying interface to the cldap protocol + */ + + +#ifdef CLDAP + +XXX not MT-safe XXX + +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990, 1994 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif + +#include +#include +#include +#ifdef macintosh +#include +#include "macos.h" +#else /* macintosh */ +#ifdef DOS +#include "msdos.h" +#else /* DOS */ +#ifdef _WINDOWS +#include +#else /* _WINDOWS */ +#include +#include +#include +#include +#include +#endif /* _WINDOWS */ +#endif /* DOS */ +#endif /* macintosh */ + +#include "ldap-int.h" + +#define DEF_CLDAP_TIMEOUT 3 +#define DEF_CLDAP_TRIES 4 + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK ((unsigned long) 0x7f000001) +#endif + + +struct cldap_retinfo { + int cri_maxtries; + int cri_try; + int cri_useaddr; + long cri_timeout; +}; + +#ifdef NEEDPROTOS +static int add_addr( LDAP *ld, struct sockaddr *sap ); +static int cldap_result( LDAP *ld, int msgid, LDAPMessage **res, + struct cldap_retinfo *crip, char *base ); +static int cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber, + LDAPMessage **res, char *base ); +#else /* NEEDPROTOS */ +static int add_addr(); +static int cldap_result(); +static int cldap_parsemsg(); +#endif /* NEEDPROTOS */ + +/* + * cldap_open - initialize and connect to an ldap server. A magic cookie to + * be used for future communication is returned on success, NULL on failure. + * + * Example: + * LDAP *ld; + * ld = cldap_open( hostname, port ); + */ + +LDAP * +cldap_open( char *host, int port ) +{ + int s; + ldap_x_in_addr_t address; + struct sockaddr_in sock; + struct hostent *hp; + LDAP *ld; + char *p; + int i; + + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_open\n", 0, 0, 0 ); + + if ( port == 0 ) { + port = LDAP_PORT; + } + + if ( (s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) { + return( NULL ); + } + + sock.sin_addr.s_addr = 0; + sock.sin_family = AF_INET; + sock.sin_port = 0; + if ( bind(s, (struct sockaddr *) &sock, sizeof(sock)) < 0) { + close( s ); + return( NULL ); + } + + if (( ld = ldap_init( host, port )) == NULL ) { + close( s ); + return( NULL ); + } + if ( (ld->ld_sbp->sb_fromaddr = (void *)NSLDAPI_CALLOC( 1, + sizeof( struct sockaddr ))) == NULL ) { + NSLDAPI_FREE( ld ); + close( s ); + return( NULL ); + } + ld->ld_sbp->sb_sd = s; + ld->ld_sbp->sb_naddr = 0; + ld->ld_version = LDAP_VERSION2; + + sock.sin_family = AF_INET; + sock.sin_port = htons( port ); + + /* + * 'host' may be a space-separated list. + */ + if ( host != NULL ) { + for ( ; host != NULL; host = p ) { + if (( p = strchr( host, ' ' )) != NULL ) { + for (*p++ = '\0'; *p == ' '; p++) { + ; + } + } + + if ( (address = inet_addr( host )) == -1 ) { +/* XXXmcs: need to use DNS callbacks here XXX */ +XXX + if ( (hp = gethostbyname( host )) == NULL ) { + LDAP_SET_ERRNO( ld, EHOSTUNREACH ); + continue; + } + + for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) { + SAFEMEMCPY( (char *)&sock.sin_addr.s_addr, + (char *)hp->h_addr_list[ i ], + sizeof(sock.sin_addr.s_addr)); + if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { + close( s ); + NSLDAPI_FREE( ld ); + return( NULL ); + } + } + + } else { + sock.sin_addr.s_addr = address; + if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { + close( s ); + NSLDAPI_FREE( ld ); + return( NULL ); + } + } + + if ( ld->ld_host == NULL ) { + ld->ld_host = nsldapi_strdup( host ); + } + } + + } else { + address = INADDR_LOOPBACK; + sock.sin_addr.s_addr = htonl( address ); + if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { + close( s ); + NSLDAPI_FREE( ld ); + return( NULL ); + } + } + + if ( ld->ld_sbp->sb_addrs == NULL + || ( ld->ld_defconn = nsldapi_new_connection( ld, NULL, 1,0,0 )) == NULL ) { + NSLDAPI_FREE( ld ); + return( NULL ); + } + + ld->ld_sbp->sb_useaddr = ld->ld_sbp->sb_addrs[ 0 ]; + cldap_setretryinfo( ld, 0, 0 ); + +#ifdef LDAP_DEBUG + putchar( '\n' ); + for ( i = 0; i < ld->ld_sbp->sb_naddr; ++i ) { + LDAPDebug( LDAP_DEBUG_TRACE, "end of cldap_open address %d is %s\n", + i, inet_ntoa( ((struct sockaddr_in *) + ld->ld_sbp->sb_addrs[ i ])->sin_addr ), 0 ); + } +#endif + + return( ld ); +} + + + +void +cldap_close( LDAP *ld ) +{ + ldap_ld_free( ld, NULL, NULL, 0 ); +} + + +void +cldap_setretryinfo( LDAP *ld, int tries, int timeout ) +{ + ld->ld_cldaptries = ( tries <= 0 ) ? DEF_CLDAP_TRIES : tries; + ld->ld_cldaptimeout = ( timeout <= 0 ) ? DEF_CLDAP_TIMEOUT : timeout; +} + + +int +cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs, + int attrsonly, LDAPMessage **res, char *logdn ) +{ + int ret, msgid; + struct cldap_retinfo cri; + + *res = NULLMSG; + + (void) memset( &cri, 0, sizeof( cri )); + + if ( logdn != NULL ) { + ld->ld_cldapdn = logdn; + } else if ( ld->ld_cldapdn == NULL ) { + ld->ld_cldapdn = ""; + } + + do { + if ( cri.cri_try != 0 ) { + --ld->ld_msgid; /* use same id as before */ + } + ld->ld_sbp->sb_useaddr = ld->ld_sbp->sb_addrs[ cri.cri_useaddr ]; + + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n", + cri.cri_try, inet_ntoa( ((struct sockaddr_in *) + ld->ld_sbp->sb_useaddr)->sin_addr ), 0 ); + + if ( (msgid = ldap_search( ld, base, scope, filter, attrs, + attrsonly )) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } +#ifndef NO_CACHE + if ( ld->ld_cache != NULL && ld->ld_responses != NULL ) { + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_search_s res from cache\n", + 0, 0, 0 ); + *res = ld->ld_responses; + ld->ld_responses = ld->ld_responses->lm_next; + return( ldap_result2error( ld, *res, 0 )); + } +#endif /* NO_CACHE */ + ret = cldap_result( ld, msgid, res, &cri, base ); + } while (ret == -1); + + return( ret ); +} + + +static int +add_addr( LDAP *ld, struct sockaddr *sap ) +{ + struct sockaddr *newsap, **addrs; + + if (( newsap = (struct sockaddr *)NSLDAPI_MALLOC( + sizeof( struct sockaddr ))) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + + if ( ld->ld_sbp->sb_naddr == 0 ) { + addrs = (struct sockaddr **)NSLDAPI_MALLOC( sizeof(struct sockaddr *)); + } else { + addrs = (struct sockaddr **)NSLDAPI_REALLOC( ld->ld_sbp->sb_addrs, + ( ld->ld_sbp->sb_naddr + 1 ) * sizeof(struct sockaddr *)); + } + + if ( addrs == NULL ) { + NSLDAPI_FREE( newsap ); + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + + SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr )); + addrs[ ld->ld_sbp->sb_naddr++ ] = newsap; + ld->ld_sbp->sb_addrs = (void **)addrs; + return( 0 ); +} + + +static int +cldap_result( LDAP *ld, int msgid, LDAPMessage **res, + struct cldap_retinfo *crip, char *base ) +{ + Sockbuf *sb = ld->ld_sbp; + BerElement ber; + char *logdn; + int ret, fromaddr, i; + ber_int_t id; + struct timeval tv; + + fromaddr = -1; + + if ( crip->cri_try == 0 ) { + crip->cri_maxtries = ld->ld_cldaptries * sb->sb_naddr; + crip->cri_timeout = ld->ld_cldaptimeout; + crip->cri_useaddr = 0; + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_result tries %d timeout %d\n", + ld->ld_cldaptries, ld->ld_cldaptimeout, 0 ); + } + + if ((tv.tv_sec = crip->cri_timeout / sb->sb_naddr) < 1 ) { + tv.tv_sec = 1; + } + tv.tv_usec = 0; + + LDAPDebug( LDAP_DEBUG_TRACE, + "cldap_result waiting up to %d seconds for a response\n", + tv.tv_sec, 0, 0 ); + ber_init_w_nullchar( &ber, 0 ); + nsldapi_set_ber_options( ld, &ber ); + + if ( cldap_getmsg( ld, &tv, &ber ) == -1 ) { + ret = LDAP_GET_LDERRNO( ld, NULL, NULL ); + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_getmsg returned -1 (%d)\n", + ret, 0, 0 ); + } else if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "cldap_result timed out\n", 0, 0, 0 ); + /* + * It timed out; is it time to give up? + */ + if ( ++crip->cri_try >= crip->cri_maxtries ) { + ret = LDAP_TIMEOUT; + --crip->cri_try; + } else { + if ( ++crip->cri_useaddr >= sb->sb_naddr ) { + /* + * new round: reset address to first one and + * double the timeout + */ + crip->cri_useaddr = 0; + crip->cri_timeout <<= 1; + } + ret = -1; + } + + } else { + /* + * Got a response. It should look like: + * { msgid, logdn, { searchresponse...}} + */ + logdn = NULL; + + if ( ber_scanf( &ber, "ia", &id, &logdn ) == LBER_ERROR ) { + NSLDAPI_FREE( ber.ber_buf ); /* gack! */ + ret = LDAP_DECODING_ERROR; + LDAPDebug( LDAP_DEBUG_TRACE, + "cldap_result: ber_scanf returned LBER_ERROR (%d)\n", + ret, 0, 0 ); + } else if ( id != msgid ) { + NSLDAPI_FREE( ber.ber_buf ); /* gack! */ + LDAPDebug( LDAP_DEBUG_TRACE, + "cldap_result: looking for msgid %d; got %ld\n", + msgid, id, 0 ); + ret = -1; /* ignore and keep looking */ + } else { + /* + * got a result: determine which server it came from + * decode into ldap message chain + */ + for ( fromaddr = 0; fromaddr < sb->sb_naddr; ++fromaddr ) { + if ( memcmp( &((struct sockaddr_in *) + sb->sb_addrs[ fromaddr ])->sin_addr, + &((struct sockaddr_in *)sb->sb_fromaddr)->sin_addr, + sizeof( struct in_addr )) == 0 ) { + break; + } + } + ret = cldap_parsemsg( ld, msgid, &ber, res, base ); + NSLDAPI_FREE( ber.ber_buf ); /* gack! */ + LDAPDebug( LDAP_DEBUG_TRACE, + "cldap_result got result (%d)\n", ret, 0, 0 ); + } + + if ( logdn != NULL ) { + NSLDAPI_FREE( logdn ); + } + } + + + /* + * If we are giving up (successfully or otherwise) then + * abandon any outstanding requests. + */ + if ( ret != -1 ) { + i = crip->cri_try; + if ( i >= sb->sb_naddr ) { + i = sb->sb_naddr - 1; + } + + for ( ; i >= 0; --i ) { + if ( i == fromaddr ) { + continue; + } + sb->sb_useaddr = sb->sb_addrs[ i ]; + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n", + msgid, inet_ntoa( ((struct sockaddr_in *) + sb->sb_useaddr)->sin_addr ), 0 ); + (void) ldap_abandon( ld, msgid ); + } + } + + LDAP_SET_LDERRNO( ld, ret, NULL, NULL ); + return( ret ); +} + + +static int +cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber, + LDAPMessage **res, char *base ) +{ + ber_tag_t tag; + ber_len_t len; + int baselen, slen, rc; + char *dn, *p, *cookie; + LDAPMessage *chain, *prev, *ldm; + struct berval *bv; + + rc = LDAP_DECODING_ERROR; /* pessimistic */ + ldm = chain = prev = NULLMSG; + baselen = ( base == NULL ) ? 0 : strlen( base ); + bv = NULL; + + for ( tag = ber_first_element( ber, &len, &cookie ); + tag != LBER_ERROR && tag != LBER_END_OF_SEQOFSET + && rc != LDAP_SUCCESS; + tag = ber_next_element( ber, &len, cookie )) { + if (( ldm = (LDAPMessage *)NSLDAPI_CALLOC( 1, sizeof(LDAPMessage))) + == NULL ) { + rc = LDAP_NO_MEMORY; + break; /* return with error */ + } else if (( rc = nsldapi_alloc_ber_with_options( ld, &ldm->lm_ber )) + != LDAP_SUCCESS ) { + break; /* return with error*/ + } + ldm->lm_msgid = msgid; + ldm->lm_msgtype = tag; + + if ( tag == LDAP_RES_SEARCH_RESULT ) { + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg got search result\n", + 0, 0, 0 ); + + if ( ber_get_stringal( ber, &bv ) == LBER_DEFAULT ) { + break; /* return w/error */ + } + + if ( ber_printf( ldm->lm_ber, "to", tag, bv->bv_val, + bv->bv_len ) == -1 ) { + break; /* return w/error */ + } + ber_bvfree( bv ); + bv = NULL; + rc = LDAP_SUCCESS; + + } else if ( tag == LDAP_RES_SEARCH_ENTRY ) { + if ( ber_scanf( ber, "{aO", &dn, &bv ) == LBER_ERROR ) { + break; /* return w/error */ + } + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg entry %s\n", dn, 0, 0 ); + if ( dn != NULL && *(dn + ( slen = strlen(dn)) - 1) == '*' && + baselen > 0 ) { + /* + * substitute original searchbase for trailing '*' + */ + if (( p = (char *)NSLDAPI_MALLOC( slen + baselen )) == NULL ) { + rc = LDAP_NO_MEMORY; + NSLDAPI_FREE( dn ); + break; /* return w/error */ + } + strcpy( p, dn ); + strcpy( p + slen - 1, base ); + NSLDAPI_FREE( dn ); + dn = p; + } + + if ( ber_printf( ldm->lm_ber, "t{so}", tag, dn, bv->bv_val, + bv->bv_len ) == -1 ) { + break; /* return w/error */ + } + NSLDAPI_FREE( dn ); + ber_bvfree( bv ); + bv = NULL; + + } else { + LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg got unknown tag %d\n", + tag, 0, 0 ); + rc = LDAP_PROTOCOL_ERROR; + break; /* return w/error */ + } + + /* Reset message ber so we can read from it later. Gack! */ + ldm->lm_ber->ber_end = ldm->lm_ber->ber_ptr; + ldm->lm_ber->ber_ptr = ldm->lm_ber->ber_buf; + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { + char msg[80]; + sprintf( msg, "cldap_parsemsg add message id %d type %d:\n", + ldm->lm_msgid, ldm->lm_msgtype ); + ber_err_print( msg ); + ber_dump( ldm->lm_ber, 1 ); + } +#endif /* LDAP_DEBUG */ + +#ifndef NO_CACHE + if ( ld->ld_cache != NULL ) { + nsldapi_add_result_to_cache( ld, ldm ); + } +#endif /* NO_CACHE */ + + if ( chain == NULL ) { + chain = ldm; + } else { + prev->lm_chain = ldm; + } + prev = ldm; + ldm = NULL; + } + + /* dispose of any leftovers */ + if ( ldm != NULL ) { + if ( ldm->lm_ber != NULLBER ) { + ber_free( ldm->lm_ber, 1 ); + } + NSLDAPI_FREE( ldm ); + } + if ( bv != NULL ) { + ber_bvfree( bv ); + } + + /* return chain, calling result2error if we got anything at all */ + *res = chain; + return(( *res == NULLMSG ) ? rc : ldap_result2error( ld, *res, 0 )); +} +#endif /* CLDAP */ diff --git a/ldap/c-sdk/libldap/compare.c b/ldap/c-sdk/libldap/compare.c new file mode 100644 index 0000000000..6ccd0e8aa5 --- /dev/null +++ b/ldap/c-sdk/libldap/compare.c @@ -0,0 +1,194 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * compare.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_compare - perform an ldap compare operation. The dn + * of the entry to compare to and the attribute and value to compare (in + * attr and value) are supplied. The msgid of the response is returned. + * + * Example: + * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) + */ +int +LDAP_CALL +ldap_compare( LDAP *ld, const char *dn, const char *attr, const char *value ) +{ + int msgid; + struct berval bv; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 ); + + bv.bv_val = (char *)value; + bv.bv_len = ( value == NULL ) ? 0 : strlen( value ); + + if ( ldap_compare_ext( ld, dn, attr, &bv, NULL, NULL, &msgid ) + == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + +int +LDAP_CALL +ldap_compare_ext( LDAP *ld, const char *dn, const char *attr, + const struct berval *bvalue, LDAPControl **serverctrls, + LDAPControl **clientctrls, int *msgidp ) +{ + BerElement *ber; + int rc, lderr; + + /* The compare request looks like this: + * CompareRequest ::= SEQUENCE { + * entry DistinguishedName, + * ava SEQUENCE { + * type AttributeType, + * value AttributeValue + * } + * } + * and must be wrapped in an LDAPMessage. + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare_ext\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + if ( attr == NULL || bvalue == NULL || bvalue->bv_len == 0 + || msgidp == NULL ) { + lderr = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + return( lderr ); + } + + if ( dn == NULL ) { + dn = ""; + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* check the cache */ + if ( ld->ld_cache_on && ld->ld_cache_compare != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_compare)( ld, *msgidp, + LDAP_REQ_COMPARE, dn, attr, bvalue )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* create a message to send */ + if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( lderr ); + } + + if ( ber_printf( ber, "{it{s{so}}", *msgidp, LDAP_REQ_COMPARE, dn, + attr, bvalue->bv_val, bvalue->bv_len ) + == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( lderr ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_COMPARE, + (char *)dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +int +LDAP_CALL +ldap_compare_s( LDAP *ld, const char *dn, const char *attr, + const char *value ) +{ + struct berval bv; + + bv.bv_val = (char *)value; + bv.bv_len = ( value == NULL ) ? 0 : strlen( value ); + + return( ldap_compare_ext_s( ld, dn, attr, &bv, NULL, NULL )); +} + +int +LDAP_CALL +ldap_compare_ext_s( LDAP *ld, const char *dn, const char *attr, + const struct berval *bvalue, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + int err, msgid; + LDAPMessage *res; + + if (( err = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, + clientctrls, &msgid )) != LDAP_SUCCESS ) { + return( err ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) + == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + return( ldap_result2error( ld, res, 1 ) ); +} diff --git a/ldap/c-sdk/libldap/compat.c b/ldap/c-sdk/libldap/compat.c new file mode 100644 index 0000000000..94e58ca7a3 --- /dev/null +++ b/ldap/c-sdk/libldap/compat.c @@ -0,0 +1,108 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1994 The Regents of the University of Michigan. + * All rights reserved. + */ +/* + * compat.c - compatibility routines. + * + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +#if defined( HPUX10 ) && defined( _REENTRANT ) && !defined(HPUX11) +extern int h_errno; + +struct hostent * +nsldapi_compat_gethostbyname_r( const char *name, struct hostent *result, + char *buffer, int buflen, int *h_errnop ) +{ + struct hostent_data *hep; + + if ( buflen < sizeof(struct hostent_data)) { /* sanity check */ + *h_errnop = NO_RECOVERY; /* XXX best error code to use? */ + return( NULL ); + } + + hep = (struct hostent_data *)buffer; + hep->current = NULL; + + if ( gethostbyname_r( name, result, hep ) == -1) { + *h_errnop = h_errno; /* XXX don't see anywhere else to get this */ + return NULL; + } + return result; +} + +char * +nsldapi_compat_ctime_r( const time_t *clock, char *buf, int buflen ) +{ + NSLDAPI_CTIME1( clock, buf, buflen ); + return buf; +} +#endif /* HPUX10 && _REENTRANT && !HPUX11 */ + +#if defined(LINUX) || defined(AIX) || defined(HPUX) || defined(_WINDOWS) +/* + * Copies src to the dstsize buffer at dst. The copy will never + * overflow the destination buffer and the buffer will always be null + * terminated. + */ +size_t nsldapi_compat_strlcpy(char *dst, const char *src, size_t len) +{ + size_t slen = strlen(src); + size_t copied; + + if (len == 0) + return (slen); + + if (slen >= len) + copied = len - 1; + else + copied = slen; + SAFEMEMCPY(dst, src, copied); + dst[copied] = '\0'; + return (slen); +} +#endif diff --git a/ldap/c-sdk/libldap/control.c b/ldap/c-sdk/libldap/control.c new file mode 100644 index 0000000000..5f2eb73758 --- /dev/null +++ b/ldap/c-sdk/libldap/control.c @@ -0,0 +1,559 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* control.c - routines to handle ldapv3 controls */ + +#include "ldap-int.h" + +static LDAPControl *ldap_control_dup( LDAPControl *ctrl ); +static int ldap_control_copy_contents( LDAPControl *ctrl_dst, + LDAPControl *ctrl_src ); + +/* + * Append a list of LDAPv3 controls to ber. If ctrls is NULL, use default + * set of controls from ld. + * Return an LDAP error code (LDAP_SUCCESS if all goes well). + * If closeseq is non-zero, we do an extra ber_put_seq() as well. + */ +int +nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq, + BerElement *ber ) +{ + LDAPControl *c; + int rc, i; + + rc = LDAP_ENCODING_ERROR; /* the most popular error */ + + /* if no controls were passed in, use global list from LDAP * */ + LDAP_MUTEX_LOCK( ld, LDAP_CTRL_LOCK ); + if ( ctrls == NULL ) { + ctrls = ld->ld_servercontrols; + } + + /* if there are no controls then we are done */ + if ( ctrls == NULL || ctrls[ 0 ] == NULL ) { + goto clean_exit; + } + + /* + * If we're using LDAPv2 or earlier we can't send any controls, so + * we just ignore them unless one is marked critical, in which case + * we return an error. + */ + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + for ( i = 0; ctrls != NULL && ctrls[i] != NULL; i++ ) { + if ( ctrls[i]->ldctl_iscritical ) { + rc = LDAP_NOT_SUPPORTED; + goto error_exit; + } + } + goto clean_exit; + } + + /* + * encode the controls as a Sequence of Sequence + */ + if ( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) { + goto error_exit; + } + + for ( i = 0; ctrls[i] != NULL; i++ ) { + c = ctrls[i]; + + if ( ber_printf( ber, "{s", c->ldctl_oid ) == -1 ) { + goto error_exit; + } + + /* criticality is "BOOLEAN DEFAULT FALSE" */ + /* therefore, it should only be encoded if it exists AND is TRUE */ + if ( c->ldctl_iscritical ) { + if ( ber_printf( ber, "b", (int)c->ldctl_iscritical ) + == -1 ) { + goto error_exit; + } + } + + if ( c->ldctl_value.bv_val != NULL ) { + if ( ber_printf( ber, "o", c->ldctl_value.bv_val, + c->ldctl_value.bv_len ) + == -1 ) { + goto error_exit; + } + } + + if ( ber_put_seq( ber ) == -1 ) { + goto error_exit; + } + } + + if ( ber_put_seq( ber ) == -1 ) { + goto error_exit; + } + +clean_exit: + LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK ); + if ( closeseq && ber_put_seq( ber ) == -1 ) { + goto error_exit; + } + return( LDAP_SUCCESS ); + +error_exit: + LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK ); + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + + +/* + * Pull controls out of "ber" (if any present) and return them in "controlsp." + * Returns an LDAP error code. + */ +int +nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp ) +{ + LDAPControl *newctrl; + ber_tag_t tag; + ber_len_t len; + int rc, maxcontrols, curcontrols; + char *last; + + /* + * Each LDAPMessage can have a set of controls appended + * to it. Controls are used to extend the functionality + * of an LDAP operation (e.g., add an attribute size limit + * to the search operation). These controls look like this: + * + * Controls ::= SEQUENCE OF Control + * + * Control ::= SEQUENCE { + * controlType LDAPOID, + * criticality BOOLEAN DEFAULT FALSE, + * controlValue OCTET STRING + * } + */ + LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 ); + + *controlsp = NULL; + + /* + * check to see if controls were included + */ + if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) { + return( LDAP_DECODING_ERROR ); /* unexpected error */ + } + if ( len == 0 ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_get_controls no controls\n", 0, 0, 0 ); + return( LDAP_SUCCESS ); /* no controls */ + } + if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { + if ( tag == LBER_ERROR ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n", + 0, 0, 0 ); + return( LDAP_DECODING_ERROR ); /* decoding error */ + } + /* + * We found something other than controls. This should never + * happen in LDAPv3, but we don't treat this is a hard error -- + * we just ignore the extra stuff. + */ + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n", + tag, 0, 0 ); + return( LDAP_SUCCESS ); + } + + maxcontrols = curcontrols = 0; + for ( tag = ber_first_element( ber, &len, &last ); + tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; + tag = ber_next_element( ber, &len, last ) ) { + if ( curcontrols >= maxcontrols - 1 ) { +#define CONTROL_GRABSIZE 5 + maxcontrols += CONTROL_GRABSIZE; + *controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC( + (char *)*controlsp, maxcontrols * + sizeof(struct ldapcontrol *) ); + if ( *controlsp == NULL ) { + rc = LDAP_NO_MEMORY; + goto free_and_return; + } + } + if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1, + sizeof(LDAPControl))) == NULL ) { + rc = LDAP_NO_MEMORY; + goto free_and_return; + } + + (*controlsp)[curcontrols++] = newctrl; + (*controlsp)[curcontrols] = NULL; + + if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid ) + == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + + /* the criticality is optional */ + if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) { + int aint; + + if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + newctrl->ldctl_iscritical = (char)aint; /* XXX lossy cast */ + } else { + /* absent is synonomous with FALSE */ + newctrl->ldctl_iscritical = 0; + } + + /* the control value is optional */ + if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) { + if ( ber_scanf( ber, "o", &newctrl->ldctl_value ) + == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + } else { + (newctrl->ldctl_value).bv_val = NULL; + (newctrl->ldctl_value).bv_len = 0; + } + + } + + if ( tag == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 ); + return( LDAP_SUCCESS ); + +free_and_return:; + ldap_controls_free( *controlsp ); + *controlsp = NULL; + LDAPDebug( LDAP_DEBUG_TRACE, + "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 ); + return( rc ); +} + +/* + * Skips forward in a ber to find a control tag, then calls on + * nsldapi_get_controls() to parse them into an LDAPControl list. + * Returns an LDAP error code. + */ +int +nsldapi_find_controls( BerElement *ber, LDAPControl ***controlsp ) +{ + ber_tag_t tag; + ber_len_t len; + + if ( ber == NULLBER ) { + return( LDAP_DECODING_ERROR ); + } + + tag = ber_peek_tag( ber, &len ); + + while( tag != LDAP_TAG_CONTROLS && tag != LBER_DEFAULT ) { + tag = ber_skip_tag( ber, &len ); + /* Skip ahead to the next sequence */ + ber->ber_ptr += len; + tag = ber_peek_tag( ber, &len ); + } + + return( nsldapi_get_controls( ber, controlsp ) ); +} + + +void +LDAP_CALL +ldap_control_free( LDAPControl *ctrl ) +{ + if ( ctrl != NULL ) { + if ( ctrl->ldctl_oid != NULL ) { + NSLDAPI_FREE( ctrl->ldctl_oid ); + } + if ( ctrl->ldctl_value.bv_val != NULL ) { + NSLDAPI_FREE( ctrl->ldctl_value.bv_val ); + } + NSLDAPI_FREE( (char *)ctrl ); + } +} + + +void +LDAP_CALL +ldap_controls_free( LDAPControl **ctrls ) +{ + int i; + + if ( ctrls != NULL ) { + for ( i = 0; ctrls[i] != NULL; i++ ) { + ldap_control_free( ctrls[i] ); + } + NSLDAPI_FREE( (char *)ctrls ); + } +} + +LDAPControl * +LDAP_CALL +ldap_find_control( const char *oid, LDAPControl **ctrls ) +{ + int i, foundControl; + LDAPControl *Ctrlp = NULL; + + /* find the control in the list of controls if it exists */ + if ( ctrls == NULL ) { + return ( NULL ); + } + foundControl = 0; + for ( i = 0; (( ctrls[i] != NULL ) && ( !foundControl )); i++ ) { + foundControl = !strcmp( ctrls[i]->ldctl_oid, oid ); + } + if ( !foundControl ) { + return ( NULL ); + } else { + /* let local var point to the control */ + Ctrlp = ctrls[i-1]; + } + + return( Ctrlp ); +} + +#if 0 +LDAPControl ** +LDAP_CALL +ldap_control_append( LDAPControl **ctrl_src, LDAPControl *ctrl ) +{ + int nctrls = 0; + LDAPControl **ctrlp; + int i; + + if ( NULL == ctrl ) + return ( NULL ); + + /* Count the existing controls */ + if ( NULL != ctrl_src ) { + while( NULL != ctrl_src[nctrls] ) { + nctrls++; + } + } + + /* allocate the new control structure */ + if ( ( ctrlp = (LDAPControl **)NSLDAPI_MALLOC( sizeof(LDAPControl *) + * (nctrls + 2) ) ) == NULL ) { + return( NULL ); + } + memset( ctrlp, 0, sizeof(*ctrlp) * (nctrls + 2) ); + + for( i = 0; i < (nctrls + 1); i++ ) { + if ( i < nctrls ) { + ctrlp[i] = ldap_control_dup( ctrl_src[i] ); + } else { + ctrlp[i] = ldap_control_dup( ctrl ); + } + if ( NULL == ctrlp[i] ) { + ldap_controls_free( ctrlp ); + return( NULL ); + } + } + return ctrlp; +} +#endif /* 0 */ + + +/* + * Replace *ldctrls with a copy of newctrls. + * returns 0 if successful. + * return -1 if not and set error code inside LDAP *ld. + */ +int +nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, LDAPControl **newctrls ) +{ + int count; + + if ( *ldctrls != NULL ) { + ldap_controls_free( *ldctrls ); + } + + if ( newctrls == NULL || newctrls[0] == NULL ) { + *ldctrls = NULL; + return( 0 ); + } + + for ( count = 0; newctrls[ count ] != NULL; ++count ) { + ; + } + + if (( *ldctrls = (LDAPControl **)NSLDAPI_MALLOC(( count + 1 ) * + sizeof( LDAPControl *))) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + (*ldctrls)[ count ] = NULL; + + for ( count = 0; newctrls[ count ] != NULL; ++count ) { + if (( (*ldctrls)[ count ] = + ldap_control_dup( newctrls[ count ] )) == NULL ) { + ldap_controls_free( *ldctrls ); + *ldctrls = NULL; + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + } + + return( 0 ); +} + + +/* + * return a malloc'd copy of "ctrl" (NULL if memory allocation fails) + */ +static LDAPControl * +/* LDAP_CALL */ /* keep this routine internal for now */ +ldap_control_dup( LDAPControl *ctrl ) +{ + LDAPControl *rctrl; + + if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl ))) + == NULL ) { + return( NULL ); + } + + if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) { + NSLDAPI_FREE( rctrl ); + return( NULL ); + } + + return( rctrl ); +} + + +/* + * duplicate the contents of "ctrl_src" and place in "ctrl_dst" + */ +static int +/* LDAP_CALL */ /* keep this routine internal for now */ +ldap_control_copy_contents( LDAPControl *ctrl_dst, LDAPControl *ctrl_src ) +{ + size_t len; + + if ( NULL == ctrl_dst || NULL == ctrl_src ) { + return( LDAP_PARAM_ERROR ); + } + + ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical; + + /* fill in the fields of this new control */ + if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid )) + == NULL ) { + return( LDAP_NO_MEMORY ); + } + + len = (size_t)(ctrl_src->ldctl_value).bv_len; + if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) { + ctrl_dst->ldctl_value.bv_len = 0; + ctrl_dst->ldctl_value.bv_val = NULL; + } else { + ctrl_dst->ldctl_value.bv_len = len; + if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len )) + == NULL ) { + NSLDAPI_FREE( ctrl_dst->ldctl_oid ); + return( LDAP_NO_MEMORY ); + } + SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val, + ctrl_src->ldctl_value.bv_val, len ); + } + + return ( LDAP_SUCCESS ); +} + + + +/* + * build an allocated LDAPv3 control. Returns an LDAP error code. + */ +int +nsldapi_build_control( char *oid, BerElement *ber, int freeber, char iscritical, + LDAPControl **ctrlp ) +{ + int rc; + struct berval *bvp; + + if ( ber == NULL ) { + bvp = NULL; + } else { + /* allocate struct berval with contents of the BER encoding */ + rc = ber_flatten( ber, &bvp ); + if ( freeber ) { + ber_free( ber, 1 ); + } + if ( rc == -1 ) { + return( LDAP_NO_MEMORY ); + } + } + + /* allocate the new control structure */ + if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl))) + == NULL ) { + if ( bvp != NULL ) { + ber_bvfree( bvp ); + } + return( LDAP_NO_MEMORY ); + } + + /* fill in the fields of this new control */ + (*ctrlp)->ldctl_iscritical = iscritical; + if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) { + NSLDAPI_FREE( *ctrlp ); + if ( bvp != NULL ) { + ber_bvfree( bvp ); + } + return( LDAP_NO_MEMORY ); + } + + if ( bvp == NULL ) { + (*ctrlp)->ldctl_value.bv_len = 0; + (*ctrlp)->ldctl_value.bv_val = NULL; + } else { + (*ctrlp)->ldctl_value = *bvp; /* struct copy */ + NSLDAPI_FREE( bvp ); /* free container, not contents! */ + } + + return( LDAP_SUCCESS ); +} diff --git a/ldap/c-sdk/libldap/countvalues.c b/ldap/c-sdk/libldap/countvalues.c new file mode 100644 index 0000000000..90e9e0adc6 --- /dev/null +++ b/ldap/c-sdk/libldap/countvalues.c @@ -0,0 +1,67 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * countvalues.c + */ + +#include "ldap-int.h" + +int +LDAP_CALL +ldap_count_values( char **vals ) +{ + int i; + + if ( vals == NULL ) + return( 0 ); + + for ( i = 0; vals[i] != NULL; i++ ) + ; /* NULL */ + + return( i ); +} + +int +LDAP_CALL +ldap_count_values_len( struct berval **vals ) +{ + return( ldap_count_values( (char **) vals ) ); +} diff --git a/ldap/c-sdk/libldap/delete.c b/ldap/c-sdk/libldap/delete.c new file mode 100644 index 0000000000..531761371b --- /dev/null +++ b/ldap/c-sdk/libldap/delete.c @@ -0,0 +1,169 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * delete.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_delete - initiate an ldap delete operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to delete + * + * Example: + * msgid = ldap_delete( ld, dn ); + */ +int +LDAP_CALL +ldap_delete( LDAP *ld, const char *dn ) +{ + int msgid; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_delete\n", 0, 0, 0 ); + + if ( ldap_delete_ext( ld, dn, NULL, NULL, &msgid ) == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + +int +LDAP_CALL +ldap_delete_ext( LDAP *ld, const char *dn, LDAPControl **serverctrls, + LDAPControl **clientctrls, int *msgidp ) +{ + BerElement *ber; + int rc, lderr; + + /* + * A delete request looks like this: + * DelRequet ::= DistinguishedName, + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_delete_ext\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) + { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + if ( dn == NULL ) { + dn = ""; + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* see if we should add to the cache */ + if ( ld->ld_cache_on && ld->ld_cache_delete != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_delete)( ld, *msgidp, LDAP_REQ_DELETE, + dn )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* create a message to send */ + if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( lderr ); + } + + if ( ber_printf( ber, "{its", *msgidp, LDAP_REQ_DELETE, dn ) + == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( lderr ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_DELETE, + (char *)dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +int +LDAP_CALL +ldap_delete_s( LDAP *ld, const char *dn ) +{ + return( ldap_delete_ext_s( ld, dn, NULL, NULL )); +} + +int +LDAP_CALL +ldap_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + int err, msgid; + LDAPMessage *res; + + if (( err = ldap_delete_ext( ld, dn, serverctrls, clientctrls, + &msgid )) != LDAP_SUCCESS ) { + return( err ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + return( ldap_result2error( ld, res, 1 ) ); +} diff --git a/ldap/c-sdk/libldap/disptmpl.c b/ldap/c-sdk/libldap/disptmpl.c new file mode 100644 index 0000000000..17fc71944b --- /dev/null +++ b/ldap/c-sdk/libldap/disptmpl.c @@ -0,0 +1,770 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993, 1994 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. + */ +/* + * disptmpl.c: display template library routines for LDAP clients + */ + +#include "ldap-int.h" +#include "disptmpl.h" + +static void free_disptmpl( struct ldap_disptmpl *tmpl ); +static int read_next_tmpl( char **bufp, long *blenp, + struct ldap_disptmpl **tmplp, int dtversion ); + +static char *tmploptions[] = { + "addable", "modrdn", + "altview", + NULL +}; + + +static unsigned long tmploptvals[] = { + LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN, + LDAP_DTMPL_OPT_ALTVIEW, +}; + + +static char *itemtypes[] = { + "cis", "mls", "dn", + "bool", "jpeg", "jpegbtn", + "fax", "faxbtn", "audiobtn", + "time", "date", "url", + "searchact", "linkact", "adddnact", + "addact", "verifyact", "mail", + NULL +}; + +static unsigned long itemsynids[] = { + LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN, + LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON, + LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON, + LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL, + LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION, + LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR, +}; + + +static char *itemoptions[] = { + "ro", "sort", + "1val", "hide", + "required", "hideiffalse", + NULL +}; + + +static unsigned long itemoptvals[] = { + LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, + LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, + LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, +}; + + +#define ADDEF_CONSTANT "constant" +#define ADDEF_ADDERSDN "addersdn" + + +int +LDAP_CALL +ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) +{ + FILE *fp; + char *buf; + long rlen, len; + int rc, eof; + + *tmpllistp = NULLDISPTMPL; + + if (( fp = NSLDAPI_FOPEN( file, "r" )) == NULL ) { + return( LDAP_TMPL_ERR_FILE ); + } + + if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ + fclose( fp ); + return( LDAP_TMPL_ERR_FILE ); + } + + len = ftell( fp ); + + if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ + fclose( fp ); + return( LDAP_TMPL_ERR_FILE ); + } + + if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { + fclose( fp ); + return( LDAP_TMPL_ERR_MEM ); + } + + rlen = fread( buf, 1, (size_t)len, fp ); + eof = feof( fp ); + fclose( fp ); + + if ( rlen != len && !eof ) { /* error: didn't get the whole file */ + NSLDAPI_FREE( buf ); + return( LDAP_TMPL_ERR_FILE ); + } + + rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); + NSLDAPI_FREE( buf ); + + return( rc ); +} + + +int +LDAP_CALL +ldap_init_templates_buf( char *buf, long buflen, + struct ldap_disptmpl **tmpllistp ) +{ + int rc = 0, version; + char **toks; + struct ldap_disptmpl *prevtmpl, *tmpl; + + *tmpllistp = prevtmpl = NULLDISPTMPL; + + if ( nsldapi_next_line_tokens( &buf, &buflen, &toks ) != 2 || + strcasecmp( toks[ 0 ], "version" ) != 0 ) { + nsldapi_free_strarray( toks ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + version = atoi( toks[ 1 ] ); + nsldapi_free_strarray( toks ); + if ( version != LDAP_TEMPLATE_VERSION ) { + return( LDAP_TMPL_ERR_VERSION ); + } + + while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl, + version )) == 0 && tmpl != NULLDISPTMPL ) { + if ( prevtmpl == NULLDISPTMPL ) { + *tmpllistp = tmpl; + } else { + prevtmpl->dt_next = tmpl; + } + prevtmpl = tmpl; + } + + if ( rc != 0 ) { + ldap_free_templates( *tmpllistp ); + } + + return( rc ); +} + + + +void +LDAP_CALL +ldap_free_templates( struct ldap_disptmpl *tmpllist ) +{ + struct ldap_disptmpl *tp, *nexttp; + + if ( tmpllist != NULL ) { + for ( tp = tmpllist; tp != NULL; tp = nexttp ) { + nexttp = tp->dt_next; + free_disptmpl( tp ); + } + } +} + + +static void +free_disptmpl( struct ldap_disptmpl *tmpl ) +{ + if ( tmpl != NULL ) { + if ( tmpl->dt_name != NULL ) { + NSLDAPI_FREE( tmpl->dt_name ); + } + + if ( tmpl->dt_pluralname != NULL ) { + NSLDAPI_FREE( tmpl->dt_pluralname ); + } + + if ( tmpl->dt_iconname != NULL ) { + NSLDAPI_FREE( tmpl->dt_iconname ); + } + + if ( tmpl->dt_authattrname != NULL ) { + NSLDAPI_FREE( tmpl->dt_authattrname ); + } + + if ( tmpl->dt_defrdnattrname != NULL ) { + NSLDAPI_FREE( tmpl->dt_defrdnattrname ); + } + + if ( tmpl->dt_defaddlocation != NULL ) { + NSLDAPI_FREE( tmpl->dt_defaddlocation ); + } + + if ( tmpl->dt_oclist != NULL ) { + struct ldap_oclist *ocp, *nextocp; + + for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { + nextocp = ocp->oc_next; + nsldapi_free_strarray( ocp->oc_objclasses ); + NSLDAPI_FREE( ocp ); + } + } + + if ( tmpl->dt_adddeflist != NULL ) { + struct ldap_adddeflist *adp, *nextadp; + + for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) { + nextadp = adp->ad_next; + if( adp->ad_attrname != NULL ) { + NSLDAPI_FREE( adp->ad_attrname ); + } + if( adp->ad_value != NULL ) { + NSLDAPI_FREE( adp->ad_value ); + } + NSLDAPI_FREE( adp ); + } + } + + if ( tmpl->dt_items != NULL ) { + struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp; + + for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) { + nextrowp = rowp->ti_next_in_col; + for ( colp = rowp; colp != NULL; colp = nextcolp ) { + nextcolp = colp->ti_next_in_row; + if ( colp->ti_attrname != NULL ) { + NSLDAPI_FREE( colp->ti_attrname ); + } + if ( colp->ti_label != NULL ) { + NSLDAPI_FREE( colp->ti_label ); + } + if ( colp->ti_args != NULL ) { + nsldapi_free_strarray( colp->ti_args ); + } + NSLDAPI_FREE( colp ); + } + } + } + + NSLDAPI_FREE( tmpl ); + } +} + + +struct ldap_disptmpl * +LDAP_CALL +ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ) +{ + return( tmpllist ); +} + + +struct ldap_disptmpl * +LDAP_CALL +ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, + struct ldap_disptmpl *tmpl ) +{ + return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next ); +} + + +struct ldap_disptmpl * +LDAP_CALL +ldap_name2template( char *name, struct ldap_disptmpl *tmpllist ) +{ + struct ldap_disptmpl *dtp; + + for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; + dtp = ldap_next_disptmpl( tmpllist, dtp )) { + if ( strcasecmp( name, dtp->dt_name ) == 0 ) { + return( dtp ); + } + } + + return( NULLDISPTMPL ); +} + + +struct ldap_disptmpl * +LDAP_CALL +ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist ) +{ + struct ldap_disptmpl *dtp; + struct ldap_oclist *oclp; + int i, j, needcnt, matchcnt; + + if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) { + return( NULLDISPTMPL ); + } + + for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; + dtp = ldap_next_disptmpl( tmpllist, dtp )) { + for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST; + oclp = oclp->oc_next ) { + needcnt = matchcnt = 0; + for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) { + for ( j = 0; oclist[ j ] != NULL; ++j ) { + if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] ) + == 0 ) { + ++matchcnt; + } + } + ++needcnt; + } + + if ( matchcnt == needcnt ) { + return( dtp ); + } + } + } + + return( NULLDISPTMPL ); +} + + +struct ldap_tmplitem * +LDAP_CALL +ldap_first_tmplrow( struct ldap_disptmpl *tmpl ) +{ + return( tmpl->dt_items ); +} + + +struct ldap_tmplitem * +LDAP_CALL +ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) +{ + return( row == NULLTMPLITEM ? row : row->ti_next_in_col ); +} + + +struct ldap_tmplitem * +LDAP_CALL +ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) +{ + return( row ); +} + + +struct ldap_tmplitem * +LDAP_CALL +ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, + struct ldap_tmplitem *col ) +{ + return( col == NULLTMPLITEM ? col : col->ti_next_in_row ); +} + + +char ** +LDAP_CALL +ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, + int exclude, unsigned long syntaxmask ) +{ +/* + * this routine should filter out duplicate attributes... + */ + struct ldap_tmplitem *tirowp, *ticolp; + int i, attrcnt, memerr; + char **attrs; + + attrcnt = 0; + memerr = 0; + + if (( attrs = (char **)NSLDAPI_MALLOC( sizeof( char * ))) == NULL ) { + return( NULL ); + } + + if ( includeattrs != NULL ) { + for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { + if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) * + sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = + nsldapi_strdup( includeattrs[ i ] )) == NULL ) { + memerr = 1; + } else { + attrs[ attrcnt ] = NULL; + } + } + } + + for ( tirowp = ldap_first_tmplrow( tmpl ); + !memerr && tirowp != NULLTMPLITEM; + tirowp = ldap_next_tmplrow( tmpl, tirowp )) { + for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); + ticolp != NULLTMPLITEM; + ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { + + if ( syntaxmask != 0 ) { + if (( exclude && + ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || + ( !exclude && + ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { + continue; + } + } + + if ( ticolp->ti_attrname != NULL ) { + if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) + * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = + nsldapi_strdup( ticolp->ti_attrname )) == NULL ) { + memerr = 1; + } else { + attrs[ attrcnt ] = NULL; + } + } + } + } + + if ( memerr || attrcnt == 0 ) { + for ( i = 0; i < attrcnt; ++i ) { + if ( attrs[ i ] != NULL ) { + NSLDAPI_FREE( attrs[ i ] ); + } + } + + NSLDAPI_FREE( (char *)attrs ); + return( NULL ); + } + + return( attrs ); +} + + +static int +read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp, + int dtversion ) +{ + int i, j, tokcnt, samerow, adsource; + char **toks, *itemopts; + struct ldap_disptmpl *tmpl = NULL; + struct ldap_oclist *ocp = NULL, *prevocp = NULL; + struct ldap_adddeflist *adp = NULL, *prevadp = NULL; + struct ldap_tmplitem *rowp = NULL, *ip = NULL, *previp = NULL; + + /* + * template name comes first + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); + } + + if (( tmpl = (struct ldap_disptmpl *)NSLDAPI_CALLOC( 1, + sizeof( struct ldap_disptmpl ))) == NULL ) { + nsldapi_free_strarray( toks ); + return( LDAP_TMPL_ERR_MEM ); + } + tmpl->dt_name = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * template plural name comes next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + tmpl->dt_pluralname = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * template icon name is next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + tmpl->dt_iconname = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * template options come next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) < 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + for ( i = 0; toks[ i ] != NULL; ++i ) { + for ( j = 0; tmploptions[ j ] != NULL; ++j ) { + if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) { + tmpl->dt_options |= tmploptvals[ j ]; + } + } + } + nsldapi_free_strarray( toks ); + + /* + * object class list is next + */ + while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { + if (( ocp = (struct ldap_oclist *)NSLDAPI_CALLOC( 1, + sizeof( struct ldap_oclist ))) == NULL ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_MEM ); + } + ocp->oc_objclasses = toks; + if ( tmpl->dt_oclist == NULL ) { + tmpl->dt_oclist = ocp; + } else { + prevocp->oc_next = ocp; + } + prevocp = ocp; + } + if ( tokcnt < 0 ) { + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + + /* + * read name of attribute to authenticate as + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + if ( toks[ 0 ][ 0 ] != '\0' ) { + tmpl->dt_authattrname = toks[ 0 ]; + } else { + NSLDAPI_FREE( toks[ 0 ] ); + } + NSLDAPI_FREE( (char *)toks ); + + /* + * read default attribute to use for RDN + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + tmpl->dt_defrdnattrname = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * read default location for new entries + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + if ( toks[ 0 ][ 0 ] != '\0' ) { + tmpl->dt_defaddlocation = toks[ 0 ]; + } else { + NSLDAPI_FREE( toks[ 0 ] ); + } + NSLDAPI_FREE( (char *)toks ); + + /* + * read list of rules used to define default values for new entries + */ + while (( tokcnt = nsldapi_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 ) { + adsource = LDAP_ADSRC_ADDERSDN; + } else { + adsource = 0; + } + if ( adsource == 0 || tokcnt < 2 || + ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || + ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + + if (( adp = (struct ldap_adddeflist *)NSLDAPI_CALLOC( 1, + sizeof( struct ldap_adddeflist ))) == NULL ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_MEM ); + } + adp->ad_source = adsource; + adp->ad_attrname = toks[ 1 ]; + if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) { + adp->ad_value = toks[ 2 ]; + } + NSLDAPI_FREE( toks[ 0 ] ); + NSLDAPI_FREE( (char *)toks ); + + if ( tmpl->dt_adddeflist == NULL ) { + tmpl->dt_adddeflist = adp; + } else { + prevadp->ad_next = adp; + } + prevadp = adp; + } + + /* + * item list is next + */ + samerow = 0; + while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { + if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { + if ( tokcnt < 4 ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + + if (( ip = (struct ldap_tmplitem *)NSLDAPI_CALLOC( 1, + sizeof( struct ldap_tmplitem ))) == NULL ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_MEM ); + } + + /* + * find syntaxid from config file string + */ + while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) { + *itemopts++ = '\0'; + for ( i = 0; itemoptions[ i ] != NULL; ++i ) { + if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) { + break; + } + } + if ( itemoptions[ i ] == NULL ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + ip->ti_options |= itemoptvals[ i ]; + } + + for ( i = 0; itemtypes[ i ] != NULL; ++i ) { + if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) { + break; + } + } + if ( itemtypes[ i ] == NULL ) { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + + NSLDAPI_FREE( toks[ 0 ] ); + NSLDAPI_FREE( toks[ 1 ] ); + ip->ti_syntaxid = itemsynids[ i ]; + ip->ti_label = toks[ 2 ]; + if ( toks[ 3 ][ 0 ] == '\0' ) { + ip->ti_attrname = NULL; + NSLDAPI_FREE( toks[ 3 ] ); + } else { + ip->ti_attrname = toks[ 3 ]; + } + if ( toks[ 4 ] != NULL ) { /* extra args. */ + for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { + ; + } + if (( ip->ti_args = (char **)NSLDAPI_CALLOC( i + 1, + sizeof( char * ))) == NULL ) { + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_MEM ); + } + for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { + ip->ti_args[ i ] = toks[ i + 4 ]; + } + } + NSLDAPI_FREE( (char *)toks ); + + if ( tmpl->dt_items == NULL ) { + tmpl->dt_items = rowp = ip; + } else if ( samerow ) { + previp->ti_next_in_row = ip; + } else { + rowp->ti_next_in_col = ip; + rowp = ip; + } + previp = ip; + samerow = 0; + } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { + nsldapi_free_strarray( toks ); + samerow = 1; + } else { + nsldapi_free_strarray( toks ); + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + } + if ( tokcnt < 0 ) { + free_disptmpl( tmpl ); + return( LDAP_TMPL_ERR_SYNTAX ); + } + + *tmplp = tmpl; + return( 0 ); +} + + +struct tmplerror { + int e_code; + char *e_reason; +}; + +static struct tmplerror ldap_tmplerrlist[] = { + { LDAP_TMPL_ERR_VERSION, "Bad template version" }, + { LDAP_TMPL_ERR_MEM, "Out of memory" }, + { LDAP_TMPL_ERR_SYNTAX, "Bad template syntax" }, + { LDAP_TMPL_ERR_FILE, "File error reading template" }, + { -1, 0 } +}; + +char * +LDAP_CALL +ldap_tmplerr2string( int err ) +{ + int i; + + for ( i = 0; ldap_tmplerrlist[i].e_code != -1; i++ ) { + if ( err == ldap_tmplerrlist[i].e_code ) + return( ldap_tmplerrlist[i].e_reason ); + } + + return( "Unknown error" ); +} diff --git a/ldap/c-sdk/libldap/dllmain.c b/ldap/c-sdk/libldap/dllmain.c new file mode 100644 index 0000000000..b51c16caa4 --- /dev/null +++ b/ldap/c-sdk/libldap/dllmain.c @@ -0,0 +1,178 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Microsoft Windows specifics for LIBLDAP DLL + */ +#include "ldap.h" +#include "lber.h" + + +#ifdef _WIN32 +/* Lifted from Q125688 + * How to Port a 16-bit DLL to a Win32 DLL + * on the MSVC 4.0 CD + */ +BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + /* Code from LibMain inserted here. Return TRUE to keep the + DLL loaded or return FALSE to fail loading the DLL. + + You may have to modify the code in your original LibMain to + account for the fact that it may be called more than once. + You will get one DLL_PROCESS_ATTACH for each process that + loads the DLL. This is different from LibMain which gets + called only once when the DLL is loaded. The only time this + is critical is when you are using shared data sections. + If you are using shared data sections for statically + allocated data, you will need to be careful to initialize it + only once. Check your code carefully. + + Certain one-time initializations may now need to be done for + each process that attaches. You may also not need code from + your original LibMain because the operating system may now + be doing it for you. + */ + /* + * 16 bit code calls UnlockData() + * which is mapped to UnlockSegment in windows.h + * in 32 bit world UnlockData is not defined anywhere + * UnlockSegment is mapped to GlobalUnfix in winbase.h + * and the docs for both UnlockSegment and GlobalUnfix say + * ".. function is oboslete. Segments have no meaning + * in the 32-bit environment". So we do nothing here. + */ + /* If we are building a version that includes the security libraries, + * we have to initialize Winsock here. If not, we can defer until the + * first real socket call is made (in mozock.c). + */ +#ifdef LINK_SSL + { + WSADATA wsaData; + WSAStartup(0x0101, &wsaData); + } +#endif + + break; + + case DLL_THREAD_ATTACH: + /* Called each time a thread is created in a process that has + already loaded (attached to) this DLL. Does not get called + for each thread that exists in the process before it loaded + the DLL. + + Do thread-specific initialization here. + */ + break; + + case DLL_THREAD_DETACH: + /* Same as above, but called when a thread in the process + exits. + + Do thread-specific cleanup here. + */ + break; + + case DLL_PROCESS_DETACH: + /* Code from _WEP inserted here. This code may (like the + LibMain) not be necessary. Check to make certain that the + operating system is not doing it for you. + */ +#ifdef LINK_SSL + WSACleanup(); +#endif + + break; + } + /* The return value is only used for DLL_PROCESS_ATTACH; all other + conditions are ignored. */ + return TRUE; // successful DLL_PROCESS_ATTACH +} +#else +int CALLBACK +LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) +{ + /*UnlockData( 0 );*/ + return( 1 ); +} + +BOOL CALLBACK __loadds WEP(BOOL fSystemExit) +{ + WSACleanup(); + return TRUE; +} + +#endif + +#ifdef LDAP_DEBUG +#ifndef _WIN32 +#include +#include + +void LDAP_C LDAPDebug( int level, char* fmt, ... ) +{ + static char debugBuf[1024]; + + if (ldap_debug & level) + { + va_list ap; + va_start (ap, fmt); + _snprintf (debugBuf, sizeof(debugBuf), fmt, ap); + va_end (ap); + + OutputDebugString (debugBuf); + } +} +#endif +#endif + +#ifndef _WIN32 + +/* The 16-bit version of the RTL does not implement perror() */ + +#include + +void perror( const char *msg ) +{ + char buf[128]; + wsprintf( buf, "%s: error %d\n", msg, WSAGetLastError()) ; + OutputDebugString( buf ); +} + +#endif diff --git a/ldap/c-sdk/libldap/dsparse.c b/ldap/c-sdk/libldap/dsparse.c new file mode 100644 index 0000000000..22d411617c --- /dev/null +++ b/ldap/c-sdk/libldap/dsparse.c @@ -0,0 +1,227 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993, 1994 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. + */ +/* + * dsparse.c: parsing routines used by display template and search + * preference file library routines for LDAP clients. + * + */ + +#include "ldap-int.h" + +static int next_line( char **bufp, long *blenp, char **linep ); +static char *next_token( char ** sp ); + +int +nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp ) +{ + char *p, *line, *token, **toks; + int rc, tokcnt; + + *toksp = NULL; + + if (( rc = next_line( bufp, blenp, &line )) <= 0 ) { + return( rc ); + } + + if (( toks = (char **)NSLDAPI_CALLOC( 1, sizeof( char * ))) == NULL ) { + NSLDAPI_FREE( line ); + return( -1 ); + } + tokcnt = 0; + + p = line; + while (( token = next_token( &p )) != NULL ) { + if (( toks = (char **)NSLDAPI_REALLOC( toks, ( tokcnt + 2 ) * + sizeof( char * ))) == NULL ) { + NSLDAPI_FREE( (char *)toks ); + NSLDAPI_FREE( line ); + return( -1 ); + } + toks[ tokcnt ] = token; + toks[ ++tokcnt ] = NULL; + } + + if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) { + tokcnt = 0; + nsldapi_free_strarray( toks ); + toks = NULL; + } + + NSLDAPI_FREE( line ); + + if ( tokcnt == 0 ) { + if ( toks != NULL ) { + NSLDAPI_FREE( (char *)toks ); + } + } else { + *toksp = toks; + } + + return( tokcnt ); +} + + +static int +next_line( char **bufp, long *blenp, char **linep ) +{ + char *linestart, *line, *p; + long plen; + + linestart = *bufp; + p = *bufp; + plen = *blenp; + + do { + for ( linestart = p; plen > 0; ++p, --plen ) { + if ( *p == '\r' ) { + if ( plen > 1 && *(p+1) == '\n' ) { + ++p; + --plen; + } + break; + } + + if ( *p == '\n' ) { + if ( plen > 1 && *(p+1) == '\r' ) { + ++p; + --plen; + } + break; + } + } + ++p; + --plen; + } while ( plen > 0 && ( *linestart == '#' || linestart + 1 == p )); + + + *bufp = p; + *blenp = plen; + + + if ( plen <= 0 ) { + *linep = NULL; + return( 0 ); /* end of file */ + } + + if (( line = NSLDAPI_MALLOC( p - linestart )) == NULL ) { + *linep = NULL; + return( -1 ); /* fatal error */ + } + + SAFEMEMCPY( line, linestart, p - linestart ); + line[ p - linestart - 1 ] = '\0'; + *linep = line; + return( strlen( line )); +} + + +static char * +next_token( char **sp ) +{ + int in_quote = 0; + char *p, *tokstart, *t; + + if ( **sp == '\0' ) { + return( NULL ); + } + + p = *sp; + + while ( ldap_utf8isspace( p )) { /* skip leading white space */ + ++p; + } + + if ( *p == '\0' ) { + return( NULL ); + } + + if ( *p == '\"' ) { + in_quote = 1; + ++p; + } + t = tokstart = p; + + for ( ;; ) { + if ( *p == '\0' || ( ldap_utf8isspace( p ) && !in_quote )) { + if ( *p != '\0' ) { + ++p; + } + *t++ = '\0'; /* end of token */ + break; + } + + if ( *p == '\"' ) { + in_quote = !in_quote; + ++p; + } else { + *t++ = *p++; + } + } + + *sp = p; + + if ( t == tokstart ) { + return( NULL ); + } + + return( nsldapi_strdup( tokstart )); +} + + +void +nsldapi_free_strarray( char **sap ) +{ + int i; + + if ( sap != NULL ) { + for ( i = 0; sap[ i ] != NULL; ++i ) { + NSLDAPI_FREE( sap[ i ] ); + } + NSLDAPI_FREE( (char *)sap ); + } +} diff --git a/ldap/c-sdk/libldap/error.c b/ldap/c-sdk/libldap/error.c new file mode 100644 index 0000000000..82cbb56cb7 --- /dev/null +++ b/ldap/c-sdk/libldap/error.c @@ -0,0 +1,490 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +struct ldaperror { + int e_code; + char *e_reason; +}; + +static struct ldaperror ldap_errlist[] = { + { LDAP_SUCCESS, "Success" }, + { LDAP_OPERATIONS_ERROR, "Operations error" }, + { LDAP_PROTOCOL_ERROR, "Protocol error" }, + { LDAP_TIMELIMIT_EXCEEDED, "Timelimit exceeded" }, + { LDAP_SIZELIMIT_EXCEEDED, "Sizelimit exceeded" }, + { LDAP_COMPARE_FALSE, "Compare false" }, + { LDAP_COMPARE_TRUE, "Compare true" }, + { LDAP_STRONG_AUTH_NOT_SUPPORTED, "Authentication method not supported" }, + { LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required" }, + { LDAP_PARTIAL_RESULTS, "Partial results and referral received" }, + { LDAP_REFERRAL, "Referral received" }, + { LDAP_ADMINLIMIT_EXCEEDED, "Administrative limit exceeded" }, + { LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Unavailable critical extension" }, + { LDAP_CONFIDENTIALITY_REQUIRED, "Confidentiality required" }, + { LDAP_SASL_BIND_IN_PROGRESS, "SASL bind in progress" }, + + { LDAP_NO_SUCH_ATTRIBUTE, "No such attribute" }, + { LDAP_UNDEFINED_TYPE, "Undefined attribute type" }, + { LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching" }, + { LDAP_CONSTRAINT_VIOLATION, "Constraint violation" }, + { LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists" }, + { LDAP_INVALID_SYNTAX, "Invalid syntax" }, + + { 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_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" }, + + { LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" }, + { LDAP_INVALID_CREDENTIALS, "Invalid credentials" }, + { LDAP_INSUFFICIENT_ACCESS, "Insufficient access" }, + { LDAP_BUSY, "DSA is busy" }, + { LDAP_UNAVAILABLE, "DSA is unavailable" }, + { LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform" }, + { LDAP_LOOP_DETECT, "Loop detected" }, + { LDAP_SORT_CONTROL_MISSING, "Sort Control is missing" }, + { LDAP_INDEX_RANGE_ERROR, "Search results exceed the range specified by the offsets" }, + + { LDAP_NAMING_VIOLATION, "Naming violation" }, + { LDAP_OBJECT_CLASS_VIOLATION, "Object class violation" }, + { LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf" }, + { LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN" }, + { LDAP_ALREADY_EXISTS, "Already exists" }, + { LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class" }, + { LDAP_RESULTS_TOO_LARGE, "Results too large" }, + { LDAP_AFFECTS_MULTIPLE_DSAS, "Affects multiple servers" }, + + { LDAP_OTHER, "Unknown error" }, + { LDAP_SERVER_DOWN, "Can't contact LDAP server" }, + { LDAP_LOCAL_ERROR, "Local error" }, + { LDAP_ENCODING_ERROR, "Encoding error" }, + { LDAP_DECODING_ERROR, "Decoding error" }, + { LDAP_TIMEOUT, "Timed out" }, + { LDAP_AUTH_UNKNOWN, "Unknown authentication method" }, + { LDAP_FILTER_ERROR, "Bad search filter" }, + { LDAP_USER_CANCELLED, "User cancelled operation" }, + { LDAP_PARAM_ERROR, "Bad parameter to an ldap routine" }, + { LDAP_NO_MEMORY, "Out of memory" }, + { LDAP_CONNECT_ERROR, "Can't connect to the LDAP server" }, + { LDAP_NOT_SUPPORTED, "Not supported by this version of the LDAP protocol" }, + { LDAP_CONTROL_NOT_FOUND, "Requested LDAP control not found" }, + { LDAP_NO_RESULTS_RETURNED, "No results returned" }, + { LDAP_MORE_RESULTS_TO_RETURN, "More results to return" }, + { LDAP_CLIENT_LOOP, "Client detected loop" }, + { LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral hop limit exceeded" }, + { -1, 0 } +}; + +char * +LDAP_CALL +ldap_err2string( int err ) +{ + int i; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 ); + + for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { + if ( err == ldap_errlist[i].e_code ) + return( ldap_errlist[i].e_reason ); + } + + return( "Unknown error" ); +} + + +static char * +nsldapi_safe_strerror( int e ) +{ + char *s; + + if (( s = strerror( e )) == NULL ) { + s = "unknown error"; + } + + return( s ); +} + + +void +LDAP_CALL +ldap_perror( LDAP *ld, const char *s ) +{ + int i, err; + char *matched = NULL; + char *errmsg = NULL; + char *separator; + char msg[1024]; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 ); + + if ( s == NULL ) { + s = separator = ""; + } else { + separator = ": "; + } + + if ( ld == NULL ) { + snprintf( msg, sizeof( msg ), + "%s%s%s", s, separator, nsldapi_safe_strerror( errno ) ); + ber_err_print( msg ); + return; + } + + LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); + err = LDAP_GET_LDERRNO( ld, &matched, &errmsg ); + for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { + if ( err == ldap_errlist[i].e_code ) { + snprintf( msg, sizeof( msg ), + "%s%s%s", s, separator, ldap_errlist[i].e_reason ); + ber_err_print( msg ); + if ( err == LDAP_CONNECT_ERROR ) { + ber_err_print( " - " ); + ber_err_print( nsldapi_safe_strerror( + LDAP_GET_ERRNO( ld ))); + } + ber_err_print( "\n" ); + if ( matched != NULL && *matched != '\0' ) { + snprintf( msg, sizeof( msg ), + "%s%smatched: %s\n", s, separator, matched ); + ber_err_print( msg ); + } + if ( errmsg != NULL && *errmsg != '\0' ) { + snprintf( msg, sizeof( msg ), + "%s%sadditional info: %s\n", s, separator, errmsg ); + ber_err_print( msg ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); + return; + } + } + snprintf( msg, sizeof( msg ), + "%s%sNot an LDAP errno %d\n", s, separator, err ); + ber_err_print( msg ); + LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); +} + +int +LDAP_CALL +ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) +{ + int lderr_parse, lderr; + + lderr_parse = ldap_parse_result( ld, r, &lderr, NULL, NULL, NULL, + NULL, freeit ); + + if ( lderr_parse != LDAP_SUCCESS ) { + return( lderr_parse ); + } + + return( lderr ); +} + +int +LDAP_CALL +ldap_get_lderrno( LDAP *ld, char **m, char **s ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); /* punt */ + } + + if ( ld->ld_get_lderrno_fn == NULL ) { + if ( m != NULL ) { + *m = ld->ld_matched; + } + if ( s != NULL ) { + *s = ld->ld_error; + } + return( ld->ld_errno ); + } else { + return( ld->ld_get_lderrno_fn( m, s, ld->ld_lderrno_arg ) ); + } +} + + +/* + * Note: there is no need for callers of ldap_set_lderrno() to lock the + * ld mutex. If applications intend to share an LDAP session handle + * between threads they *must* perform their own locking around the + * session handle or they must install a "set lderrno" thread callback + * function. + * + */ +int +LDAP_CALL +ldap_set_lderrno( LDAP *ld, int e, char *m, char *s ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ld->ld_set_lderrno_fn != NULL ) { + ld->ld_set_lderrno_fn( e, m, s, ld->ld_lderrno_arg ); + } else { + LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); + ld->ld_errno = e; + if ( ld->ld_matched ) { + NSLDAPI_FREE( ld->ld_matched ); + } + ld->ld_matched = m; + if ( ld->ld_error ) { + NSLDAPI_FREE( ld->ld_error ); + } + ld->ld_error = s; + LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); + } + + return( LDAP_SUCCESS ); +} + + +/* + * Returns an LDAP error that says whether parse succeeded. The error code + * from the LDAP result itself is returned in the errcodep result parameter. + * If any of the result params. (errcodep, matchednp, errmsgp, referralsp, + * or serverctrlsp) are NULL we don't return that info. + */ +int +LDAP_CALL +ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep, char **matchednp, + char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, + int freeit ) +{ + LDAPMessage *lm; + int err, errcode; + char *m, *e; + m = e = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || + !NSLDAPI_VALID_LDAPMESSAGE_POINTER( res )) { + return( LDAP_PARAM_ERROR ); + } + + /* skip over entries and references to find next result in this chain */ + for ( lm = res; lm != NULL; lm = lm->lm_chain ) { + if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && + lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { + break; + } + } + + if ( lm == NULL ) { + err = LDAP_NO_RESULTS_RETURNED; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + err = nsldapi_parse_result( ld, lm->lm_msgtype, lm->lm_ber, &errcode, + &m, &e, referralsp, serverctrlsp ); + + if ( err == LDAP_SUCCESS ) { + if ( errcodep != NULL ) { + *errcodep = errcode; + } + if ( matchednp != NULL ) { + *matchednp = nsldapi_strdup( m ); + } + if ( errmsgp != NULL ) { + *errmsgp = nsldapi_strdup( e ); + } + + /* + * if there are more result messages in the chain, arrange to + * return the special LDAP_MORE_RESULTS_TO_RETURN "error" code. + */ + for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) { + if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && + lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { + err = LDAP_MORE_RESULTS_TO_RETURN; + break; + } + } + } else { + /* In this case, m and e were already freed by ber_scanf */ + m = e = NULL; + } + + if ( freeit ) { + ldap_msgfree( res ); + } + + LDAP_SET_LDERRNO( ld, ( err == LDAP_SUCCESS ) ? errcode : err, m, e ); + + /* nsldapi_parse_result set m and e, so we have to delete them if they exist. + Only delete them if they haven't been reused for matchednp or errmsgp. + if ( err == LDAP_SUCCESS ) { + if ( (m != NULL) && (matchednp == NULL) ) { + NSLDAPI_FREE( m ); + } + if ( (e != NULL) && (errmsgp == NULL) ) { + NSLDAPI_FREE( e ); + } + } */ + + return( err ); +} + +/* + * returns an LDAP error code indicating success or failure of parsing + * does NOT set any error information inside "ld" + */ +int +nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, int *errcodep, + char **matchednp, char **errmsgp, char ***referralsp, + LDAPControl ***serverctrlsp ) +{ + BerElement ber; + ber_len_t len; + ber_int_t errcode; + int berrc, err; + char *m, *e; + + /* + * Parse the result message. LDAPv3 result messages look like this: + * + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED { ... }, + * matchedDN LDAPDN, + * errorMessage LDAPString, + * referral [3] Referral OPTIONAL + * opSpecificStuff OPTIONAL + * } + * + * all wrapped up in an LDAPMessage sequence which looks like this: + * LDAPMessage ::= SEQUENCE { + * messageID MessageID, + * LDAPResult CHOICE { ... }, // message type + * controls [0] Controls OPTIONAL + * } + * + * LDAPv2 messages don't include referrals or controls. + * LDAPv1 messages don't include matchedDN, referrals, or controls. + * + * ldap_result() pulls out the message id, so by the time a result + * message gets here we are sitting at the start of the LDAPResult. + */ + + err = LDAP_SUCCESS; /* optimistic */ + m = e = NULL; + if ( matchednp != NULL ) { + *matchednp = NULL; + } + if ( errmsgp != NULL ) { + *errmsgp = NULL; + } + if ( referralsp != NULL ) { + *referralsp = NULL; + } + if ( serverctrlsp != NULL ) { + *serverctrlsp = NULL; + } + ber = *rber; /* struct copy */ + + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION2 ) { + berrc = ber_scanf( &ber, "{ia}", &errcode, &e ); + } else { + if (( berrc = ber_scanf( &ber, "{iaa", &errcode, &m, &e )) + != LBER_ERROR ) { + /* check for optional referrals */ + if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_REFERRAL ) { + if ( referralsp == NULL ) { + /* skip referrals */ + berrc = ber_scanf( &ber, "x" ); + } else { + /* suck out referrals */ + berrc = ber_scanf( &ber, "v", + referralsp ); + } + } else if ( referralsp != NULL ) { + *referralsp = NULL; + } + } + + if ( berrc != LBER_ERROR ) { + /* + * skip past optional operation-specific elements: + * bind results - serverSASLcreds + * extendedop results - OID plus value + */ + if ( msgtype == LDAP_RES_BIND ) { + if ( ber_peek_tag( &ber, &len ) == + LDAP_TAG_SASL_RES_CREDS ) { + berrc = ber_scanf( &ber, "x" ); + } + } else if ( msgtype == LDAP_RES_EXTENDED ) { + if ( ber_peek_tag( &ber, &len ) == + LDAP_TAG_EXOP_RES_OID ) { + berrc = ber_scanf( &ber, "x" ); + } + if ( berrc != LBER_ERROR && + ber_peek_tag( &ber, &len ) == + LDAP_TAG_EXOP_RES_VALUE ) { + berrc = ber_scanf( &ber, "x" ); + } + } + } + + /* pull out controls (if requested and any are present) */ + if ( berrc != LBER_ERROR && serverctrlsp != NULL && + ( berrc = ber_scanf( &ber, "}" )) != LBER_ERROR ) { + err = nsldapi_get_controls( &ber, serverctrlsp ); + } + } + + if ( berrc == LBER_ERROR && err == LDAP_SUCCESS ) { + err = LDAP_DECODING_ERROR; + } + + if ( errcodep != NULL ) { + *errcodep = errcode; + } + if ( matchednp != NULL ) { + *matchednp = m; + } else if ( m != NULL ) { + NSLDAPI_FREE( m ); + } + if ( errmsgp != NULL ) { + *errmsgp = e; + } else if ( e != NULL ) { + NSLDAPI_FREE( e ); + } + + return( err ); +} diff --git a/ldap/c-sdk/libldap/extendop.c b/ldap/c-sdk/libldap/extendop.c new file mode 100644 index 0000000000..f1a92afcd5 --- /dev/null +++ b/ldap/c-sdk/libldap/extendop.c @@ -0,0 +1,275 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +/* + * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation. + * the oid and data of the extended operation are supplied. Returns an + * LDAP error code. + * + * Example: + * struct berval exdata; + * char *exoid; + * int err, msgid; + * ... fill in oid and data ... + * err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid ); + */ + +int +LDAP_CALL +ldap_extended_operation( + LDAP *ld, + const char *exoid, + const struct berval *exdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp +) +{ + BerElement *ber; + int rc, msgid; + + /* + * the ldapv3 extended operation request looks like this: + * + * ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + * requestName LDAPOID, + * requestValue OCTET STRING + * } + * + * all wrapped up in an LDAPMessage sequence. + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + + /* only ldapv3 or higher can do extended operations */ + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + rc = LDAP_NOT_SUPPORTED; + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + } + + if ( msgidp == NULL || exoid == NULL || *exoid == '\0' ) { + rc = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + +#if 0 + if ( ld->ld_cache_on && ld->ld_cache_extendedop != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_extendedop)( ld, msgid, + LDAP_REQ_EXTENDED, exoid, cred )) != 0 ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( rc ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } +#endif + + /* create a message to send */ + if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( rc ); + } + + /* fill it in */ + if ( exdata ) { + if ( ber_printf( ber, "{it{tsto}", msgid, LDAP_REQ_EXTENDED, + LDAP_TAG_EXOP_REQ_OID, exoid, LDAP_TAG_EXOP_REQ_VALUE, + exdata->bv_val, exdata->bv_len ) == -1 ) { + rc = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + ber_free( ber, 1 ); + return( rc ); + } + } else { /* some implementations are pretty strict on empty values */ + if ( ber_printf( ber, "{it{ts}", msgid, LDAP_REQ_EXTENDED, + LDAP_TAG_EXOP_REQ_OID, exoid ) == -1 ) { + rc = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + ber_free( ber, 1 ); + return( rc ); + } + } + + if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( rc ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL, + ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + + +/* + * ldap_extended_operation_s - perform an arbitrary ldapv3 extended operation. + * the oid and data of the extended operation are supplied. LDAP_SUCCESS + * is returned upon success, the ldap error code otherwise. + * + * Example: + * struct berval exdata, exretval; + * char *exoid; + * int rc; + * ... fill in oid and data ... + * rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval ); + */ +int +LDAP_CALL +ldap_extended_operation_s( + LDAP *ld, + const char *requestoid, + const struct berval *requestdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + char **retoidp, + struct berval **retdatap +) +{ + int err, msgid; + LDAPMessage *result; + + if (( err = ldap_extended_operation( ld, requestoid, requestdata, + serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) { + return( err ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) + == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if (( err = ldap_parse_extended_result( ld, result, retoidp, retdatap, + 0 )) != LDAP_SUCCESS ) { + ldap_msgfree( result ); + return( err ); + } + + return( ldap_result2error( ld, result, 1 ) ); +} + + +/* + * Pull the oid returned by the server and the data out of an extended + * operation result. Return an LDAP error code. + */ +int +LDAP_CALL +ldap_parse_extended_result( + LDAP *ld, + LDAPMessage *res, + char **retoidp, /* may be NULL */ + struct berval **retdatap, /* may be NULL */ + int freeit +) +{ + struct berelement ber; + ber_len_t len; + ber_int_t err; + char *m, *e, *roid; + struct berval *rdata; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) { + return( LDAP_PARAM_ERROR ); + } + + m = e = NULL; + ber = *(res->lm_ber); + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) { + goto decoding_error; + } + roid = NULL; + if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { + if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) { + goto decoding_error; + } + } + if ( retoidp != NULL ) { + *retoidp = roid; + } else if ( roid != NULL ) { + NSLDAPI_FREE( roid ); + } + + rdata = NULL; + if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { + if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) { + goto decoding_error; + } + } + if ( retdatap != NULL ) { + *retdatap = rdata; + } else if ( rdata != NULL ) { + ber_bvfree( rdata ); + } + + LDAP_SET_LDERRNO( ld, err, m, e ); + + if ( freeit ) { + ldap_msgfree( res ); + } + + return( LDAP_SUCCESS ); + +decoding_error:; + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( LDAP_DECODING_ERROR ); +} diff --git a/ldap/c-sdk/libldap/free.c b/ldap/c-sdk/libldap/free.c new file mode 100644 index 0000000000..821ebad10c --- /dev/null +++ b/ldap/c-sdk/libldap/free.c @@ -0,0 +1,156 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1994 The Regents of the University of Michigan. + * All rights reserved. + */ +/* + * free.c - some free routines are included here to avoid having to + * link in lots of extra code when not using certain features + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +void +LDAP_CALL +ldap_getfilter_free( LDAPFiltDesc *lfdp ) +{ + LDAPFiltList *flp, *nextflp; + LDAPFiltInfo *fip, *nextfip; + + if ( lfdp == NULL ) { + return; + } + + for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = nextflp ) { + for ( fip = flp->lfl_ilist; fip != NULL; fip = nextfip ) { + nextfip = fip->lfi_next; + NSLDAPI_FREE( fip->lfi_filter ); + NSLDAPI_FREE( fip->lfi_desc ); + NSLDAPI_FREE( fip ); + } + nextflp = flp->lfl_next; + NSLDAPI_FREE( flp->lfl_pattern ); + NSLDAPI_FREE( flp->lfl_delims ); + NSLDAPI_FREE( flp->lfl_tag ); + NSLDAPI_FREE( flp ); + } + + if ( lfdp->lfd_curval != NULL ) { + NSLDAPI_FREE( lfdp->lfd_curval ); + } + if ( lfdp->lfd_curvalcopy != NULL ) { + NSLDAPI_FREE( lfdp->lfd_curvalcopy ); + } + if ( lfdp->lfd_curvalwords != NULL ) { + NSLDAPI_FREE( lfdp->lfd_curvalwords ); + } + if ( lfdp->lfd_filtprefix != NULL ) { + NSLDAPI_FREE( lfdp->lfd_filtprefix ); + } + if ( lfdp->lfd_filtsuffix != NULL ) { + NSLDAPI_FREE( lfdp->lfd_filtsuffix ); + } + + NSLDAPI_FREE( lfdp ); +} + + +/* + * free a null-terminated array of pointers to mod structures. the + * structures are freed, not the array itself, unless the freemods + * flag is set. + */ +void +LDAP_CALL +ldap_mods_free( LDAPMod **mods, int freemods ) +{ + int i; + + if ( !NSLDAPI_VALID_LDAPMOD_ARRAY( mods )) { + return; + } + + for ( i = 0; mods[i] != NULL; i++ ) { + if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) { + if ( mods[i]->mod_bvalues != NULL ) { + ber_bvecfree( mods[i]->mod_bvalues ); + } + } else if ( mods[i]->mod_values != NULL ) { + ldap_value_free( mods[i]->mod_values ); + } + if ( mods[i]->mod_type != NULL ) { + NSLDAPI_FREE( mods[i]->mod_type ); + } + NSLDAPI_FREE( (char *) mods[i] ); + } + + if ( freemods ) + NSLDAPI_FREE( (char *) mods ); +} + + +/* + * ldap_memfree() is needed to ensure that memory allocated by the C runtime + * assocated with libldap is freed by the same runtime code. + */ +void +LDAP_CALL +ldap_memfree( void *s ) +{ + if ( s != NULL ) { + NSLDAPI_FREE( s ); + } +} + + +/* + * ldap_ber_free() is just a cover for ber_free() + * ber_free() checks for ber == NULL, so we don't bother. + */ +void +LDAP_CALL +ldap_ber_free( BerElement *ber, int freebuf ) +{ + ber_free( ber, freebuf ); +} diff --git a/ldap/c-sdk/libldap/freevalues.c b/ldap/c-sdk/libldap/freevalues.c new file mode 100644 index 0000000000..29a0ea03f6 --- /dev/null +++ b/ldap/c-sdk/libldap/freevalues.c @@ -0,0 +1,73 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * freevalues.c + */ + +#include "ldap-int.h" + +void +LDAP_CALL +ldap_value_free( char **vals ) +{ + int i; + + if ( vals == NULL ) + return; + for ( i = 0; vals[i] != NULL; i++ ) + NSLDAPI_FREE( vals[i] ); + NSLDAPI_FREE( (char *) vals ); +} + +void +LDAP_CALL +ldap_value_free_len( struct berval **vals ) +{ + int i; + + if ( vals == NULL ) + return; + for ( i = 0; vals[i] != NULL; i++ ) { + NSLDAPI_FREE( vals[i]->bv_val ); + NSLDAPI_FREE( vals[i] ); + } + NSLDAPI_FREE( (char *) vals ); +} diff --git a/ldap/c-sdk/libldap/friendly.c b/ldap/c-sdk/libldap/friendly.c new file mode 100644 index 0000000000..d7b5dc65d7 --- /dev/null +++ b/ldap/c-sdk/libldap/friendly.c @@ -0,0 +1,151 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * friendly.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +char * +LDAP_CALL +ldap_friendly_name( char *filename, char *name, FriendlyMap *map ) +{ + int i, entries; + FILE *fp; + char *s; + char buf[BUFSIZ]; + + if ( map == NULL ) { + return( name ); + } + if ( NULL == name) + { + return (name); + } + + if ( *map == NULL ) { + if ( (fp = NSLDAPI_FOPEN( filename, "r" )) == NULL ) + return( name ); + + entries = 0; + while ( fgets( buf, sizeof(buf), fp ) != NULL ) { + if ( buf[0] != '#' ) + entries++; + } + rewind( fp ); + + if ( (*map = (FriendlyMap)NSLDAPI_MALLOC( (entries + 1) * + sizeof(struct friendly) )) == NULL ) { + fclose( fp ); + return( name ); + } + + i = 0; + while ( fgets( buf, sizeof(buf), fp ) != NULL && i < entries ) { + if ( buf[0] == '#' ) + continue; + + if ( (s = strchr( buf, '\n' )) != NULL ) + *s = '\0'; + + if ( (s = strchr( buf, '\t' )) == NULL ) + continue; + *s++ = '\0'; + + if ( *s == '"' ) { + int esc = 0, found = 0; + + for ( ++s; *s && !found; s++ ) { + switch ( *s ) { + case '\\': + esc = 1; + break; + case '"': + if ( !esc ) + found = 1; + /* FALL */ + default: + esc = 0; + break; + } + } + } + + (*map)[i].f_unfriendly = nsldapi_strdup( buf ); + (*map)[i].f_friendly = nsldapi_strdup( s ); + i++; + } + + fclose( fp ); + (*map)[i].f_unfriendly = NULL; + } + + for ( i = 0; (*map)[i].f_unfriendly != NULL; i++ ) { + if ( strcasecmp( name, (*map)[i].f_unfriendly ) == 0 ) + return( (*map)[i].f_friendly ); + } + return( name ); +} + + +void +LDAP_CALL +ldap_free_friendlymap( FriendlyMap *map ) +{ + struct friendly* pF; + + if ( map == NULL || *map == NULL ) { + return; + } + + for ( pF = *map; pF->f_unfriendly; pF++ ) { + NSLDAPI_FREE( pF->f_unfriendly ); + NSLDAPI_FREE( pF->f_friendly ); + } + NSLDAPI_FREE( *map ); + *map = NULL; +} diff --git a/ldap/c-sdk/libldap/getattr.c b/ldap/c-sdk/libldap/getattr.c new file mode 100644 index 0000000000..fbe688fea3 --- /dev/null +++ b/ldap/c-sdk/libldap/getattr.c @@ -0,0 +1,150 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * getattr.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + + +static unsigned long +bytes_remaining( BerElement *ber ) +{ + ber_len_t len; + + if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) { + return( 0 ); /* not sure what else to do.... */ + } + return( len ); +} + + +char * +LDAP_CALL +ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **ber ) +{ + char *attr; + int err; + ber_len_t seqlength; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULL ); /* punt */ + } + + if ( ber == NULL || !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( NULL ); + } + + if ( nsldapi_alloc_ber_with_options( ld, ber ) != LDAP_SUCCESS ) { + return( NULL ); + } + + **ber = *entry->lm_ber; + + attr = NULL; /* pessimistic */ + err = LDAP_DECODING_ERROR; /* ditto */ + + /* + * Skip past the sequence, dn, and sequence of sequence. + * Reset number of bytes remaining so we confine the rest of our + * decoding to the current sequence. + */ + if ( ber_scanf( *ber, "{xl{", &seqlength ) != LBER_ERROR && + ber_set_option( *ber, LBER_OPT_REMAINING_BYTES, &seqlength ) + == 0 ) { + /* snarf the attribute type, and skip the set of values, + * leaving us positioned right before the next attribute + * type/value sequence. + */ + if ( ber_scanf( *ber, "{ax}", &attr ) != LBER_ERROR || + bytes_remaining( *ber ) == 0 ) { + err = LDAP_SUCCESS; + } + } + + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + if ( attr == NULL || err != LDAP_SUCCESS ) { + ber_free( *ber, 0 ); + *ber = NULL; + } + return( attr ); +} + +/* ARGSUSED */ +char * +LDAP_CALL +ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) +{ + char *attr; + int err; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULL ); /* punt */ + } + + if ( ber == NULL || !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( NULL ); + } + + attr = NULL; /* pessimistic */ + err = LDAP_DECODING_ERROR; /* ditto */ + + /* skip sequence, snarf attribute type, skip values */ + if ( ber_scanf( ber, "{ax}", &attr ) != LBER_ERROR || + bytes_remaining( ber ) == 0 ) { + err = LDAP_SUCCESS; + } + + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( attr ); +} diff --git a/ldap/c-sdk/libldap/getdn.c b/ldap/c-sdk/libldap/getdn.c new file mode 100644 index 0000000000..4fab52cc6d --- /dev/null +++ b/ldap/c-sdk/libldap/getdn.c @@ -0,0 +1,371 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1994 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * getdn.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +char * +LDAP_CALL +ldap_get_dn( LDAP *ld, LDAPMessage *entry ) +{ + char *dn; + struct berelement tmp; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULL ); /* punt */ + } + + if ( !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( NULL ); + } + + tmp = *entry->lm_ber; /* struct copy */ + if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( NULL ); + } + + return( dn ); +} + +char * +LDAP_CALL +ldap_dn2ufn( const char *dn ) +{ + char *p, *ufn, *r; + size_t plen; + int state; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); + + if ( dn == NULL ) { + dn = ""; + } + + if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL ) + return( nsldapi_strdup( (char *)dn )); + + ufn = nsldapi_strdup( ++p ); + +#define INQUOTE 1 +#define OUTQUOTE 2 + state = OUTQUOTE; + for ( p = ufn, r = ufn; *p; p += plen ) { + plen = 1; + switch ( *p ) { + case '\\': + if ( *++p == '\0' ) + plen=0; + else { + *r++ = '\\'; + r += (plen = LDAP_UTF8COPY(r,p)); + } + break; + case '"': + if ( state == INQUOTE ) + state = OUTQUOTE; + else + state = INQUOTE; + *r++ = *p; + break; + case ';': + case ',': + if ( state == OUTQUOTE ) + *r++ = ','; + else + *r++ = *p; + break; + case '=': + if ( state == INQUOTE ) + *r++ = *p; + else { + char *rsave = r; + LDAP_UTF8DEC(r); + *rsave = '\0'; + while ( !ldap_utf8isspace( r ) && *r != ';' + && *r != ',' && r > ufn ) + LDAP_UTF8DEC(r); + LDAP_UTF8INC(r); + + if ( strcasecmp( r, "c" ) + && strcasecmp( r, "o" ) + && strcasecmp( r, "ou" ) + && strcasecmp( r, "st" ) + && strcasecmp( r, "l" ) + && strcasecmp( r, "dc" ) + && strcasecmp( r, "uid" ) + && strcasecmp( r, "cn" ) ) { + r = rsave; + *r++ = '='; + } + } + break; + default: + r += (plen = LDAP_UTF8COPY(r,p)); + break; + } + } + *r = '\0'; + + return( ufn ); +} + +char ** +LDAP_CALL +ldap_explode_dns( const char *dn ) +{ + int ncomps, maxcomps; + char *s, *cpydn; + char **rdns; +#ifdef HAVE_STRTOK_R /* defined in portable.h */ + char *lasts; +#endif + + if ( dn == NULL ) { + dn = ""; + } + + if ( (rdns = (char **)NSLDAPI_MALLOC( 8 * sizeof(char *) )) == NULL ) { + return( NULL ); + } + + maxcomps = 8; + ncomps = 0; + cpydn = nsldapi_strdup( (char *)dn ); + for ( s = STRTOK( cpydn, "@.", &lasts ); s != NULL; + s = STRTOK( NULL, "@.", &lasts ) ) { + if ( ncomps == maxcomps ) { + maxcomps *= 2; + if ( (rdns = (char **)NSLDAPI_REALLOC( rdns, maxcomps * + sizeof(char *) )) == NULL ) { + NSLDAPI_FREE( cpydn ); + return( NULL ); + } + } + rdns[ncomps++] = nsldapi_strdup( s ); + } + rdns[ncomps] = NULL; + NSLDAPI_FREE( cpydn ); + + return( rdns ); +} + +#define LDAP_DN 1 +#define LDAP_RDN 2 + +static char ** +ldap_explode( const char *dn, const int notypes, const int nametype ) +{ + char *p, *q, *rdnstart, **rdns = NULL; + size_t plen = 0; + int state = 0; + int count = 0; + int startquote = 0; + int endquote = 0; + int len = 0; + int goteq = 0; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_explode\n", 0, 0, 0 ); + + if ( dn == NULL ) { + dn = ""; + } + +#if 0 + if ( ldap_is_dns_dn( dn ) ) { + return( ldap_explode_dns( dn ) ); + } +#endif + + while ( ldap_utf8isspace( (char *)dn )) { /* ignore leading spaces */ + ++dn; + } + + p = rdnstart = (char *) dn; + state = OUTQUOTE; + + do { + p += plen; + plen = 1; + switch ( *p ) { + case '\\': + if ( *++p == '\0' ) + p--; + else + plen = LDAP_UTF8LEN(p); + break; + case '"': + if ( state == INQUOTE ) + state = OUTQUOTE; + else + state = INQUOTE; + break; + case '+': if ( nametype != LDAP_RDN ) break; + case ';': + case ',': + case '\0': + if ( state == OUTQUOTE ) { + /* + * semicolon and comma are not valid RDN + * separators. + */ + if ( nametype == LDAP_RDN && + ( *p == ';' || *p == ',' || !goteq)) { + ldap_charray_free( rdns ); + return NULL; + } + if ( (*p == ',' || *p == ';') && !goteq ) { + /* If we get here, we have a case similar + * to =,,= + * This is not a valid dn */ + ldap_charray_free( rdns ); + return NULL; + } + goteq = 0; + ++count; + if ( rdns == NULL ) { + if (( rdns = (char **)NSLDAPI_MALLOC( 8 + * sizeof( char *))) == NULL ) + return( NULL ); + } else if ( count >= 8 ) { + if (( rdns = (char **)NSLDAPI_REALLOC( + rdns, (count+1) * + sizeof( char *))) == NULL ) + return( NULL ); + } + rdns[ count ] = NULL; + endquote = 0; + if ( notypes ) { + for ( q = rdnstart; + q < p && *q != '='; ++q ) { + ; + } + if ( q < p ) { /* *q == '=' */ + rdnstart = ++q; + } + if ( *rdnstart == '"' ) { + startquote = 1; + ++rdnstart; + } + + if ( (*(p-1) == '"') && startquote ) { + endquote = 1; + --p; + } + } + + len = p - rdnstart; + if (( rdns[ count-1 ] = (char *)NSLDAPI_CALLOC( + 1, len + 1 )) != NULL ) { + SAFEMEMCPY( rdns[ count-1 ], rdnstart, + len ); + if ( !endquote ) { + /* trim trailing spaces unless + * they are properly escaped */ + while ( len > 0 && + ldap_utf8isspace( + &rdns[count-1][len-1] ) && + ((len == 1) || (rdns[count-1][len-2] != '\\'))) { + --len; + } + } + rdns[ count-1 ][ len ] = '\0'; + } + + /* + * Don't forget to increment 'p' back to where + * it should be. If we don't, then we will + * never get past an "end quote." + */ + if ( endquote == 1 ) + p++; + + rdnstart = *p ? p + 1 : p; + while ( ldap_utf8isspace( rdnstart )) + ++rdnstart; + } + break; + case '=': + if ( state == OUTQUOTE ) { + goteq = 1; + } + /* FALL */ + default: + plen = LDAP_UTF8LEN(p); + break; + } + } while ( *p ); + + return( rdns ); +} + +char ** +LDAP_CALL +ldap_explode_dn( const char *dn, const int notypes ) +{ + return( ldap_explode( dn, notypes, LDAP_DN ) ); +} + +char ** +LDAP_CALL +ldap_explode_rdn( const char *rdn, const int notypes ) +{ + return( ldap_explode( rdn, notypes, LDAP_RDN ) ); +} + +int +LDAP_CALL +ldap_is_dns_dn( const char *dn ) +{ + return( dn != NULL && dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL && + strchr( dn, ',' ) == NULL ); +} diff --git a/ldap/c-sdk/libldap/getdxbyname.c b/ldap/c-sdk/libldap/getdxbyname.c new file mode 100644 index 0000000000..d706144586 --- /dev/null +++ b/ldap/c-sdk/libldap/getdxbyname.c @@ -0,0 +1,279 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * nsldapi_getdxbyname - retrieve DX records from the DNS (from + * TXT records for now) + */ + +#include + +#ifdef LDAP_DNS + +XXX not MT-safe XXX + +#include +#include + +#ifdef macintosh +#include +#include "macos.h" +#endif /* macintosh */ + +#ifdef _WINDOWS +#include +#endif + +#if !defined(macintosh) && !defined(DOS) && !defined( _WINDOWS ) +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include "ldap-int.h" + +#if defined( DOS ) +#include "msdos.h" +#endif /* DOS */ + + +#ifdef NEEDPROTOS +static char ** decode_answer( unsigned char *answer, int len ); +#else /* NEEDPROTOS */ +static char **decode_answer(); +#endif /* NEEDPROTOS */ + +extern int h_errno; +extern char *h_errlist[]; + + +#define MAX_TO_SORT 32 + + +/* + * nsldapi_getdxbyname - lookup DNS DX records for domain and return an ordered + * array. + */ +char ** +nsldapi_getdxbyname( char *domain ) +{ + unsigned char buf[ PACKETSZ ]; + char **dxs; + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_getdxbyname( %s )\n", domain, 0, 0 ); + + memset( buf, 0, sizeof( buf )); + + /* XXX not MT safe XXX */ + if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0 + || ( rc > sizeof( buf )) + || ( dxs = decode_answer( buf, rc )) == NULL ) { + /* + * punt: return list consisting of the original domain name only + */ + if (( dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ))) == NULL || + ( dxs[ 0 ] = nsldapi_strdup( domain )) == NULL ) { + if ( dxs != NULL ) { + NSLDAPI_FREE( dxs ); + } + dxs = NULL; + } else { + dxs[ 1 ] = NULL; + } + } + + return( dxs ); +} + + +static char ** +decode_answer( unsigned char *answer, int 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 + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { +/* __p_query( answer ); */ + } +#endif /* LDAP_DEBUG */ + + dxs = NULL; + hp = (HEADER *)answer; + eom = answer + len; + + if ( len < sizeof( *hp ) ) { + h_errno = NO_RECOVERY; + return( NULL ); + } + + 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 */ + if ( p + 3 * INT16SZ + INT32SZ > eom ) { + err = NO_RECOVERY; + continue; + } + type = _getshort( p ); + p += INT16SZ; + class = _getshort( p ); + p += INT16SZ; + p += INT32SZ; /* skip over TTL */ + rr_len = _getshort( p ); + p += INT16SZ; + if ( p + rr_len > eom ) { + err = NO_RECOVERY; + continue; + } + if ( class == C_IN && type == T_TXT ) { + int i, n, 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( *r )) { + ++r; + --txt_len; + } + pref = 0; + while ( isdigit( *r )) { + pref *= 10; + pref += ( *r - '0' ); + ++r; + --txt_len; + } + if ( dx_count < MAX_TO_SORT - 1 ) { + dx_pref[ dx_count ] = pref; + } + while ( isspace( *r )) { + ++r; + --txt_len; + } + if ( dx_count == 0 ) { + dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * )); + } else { + dxs = (char **)NSLDAPI_REALLOC( dxs, + ( dx_count + 2 ) * sizeof( char * )); + } + if ( dxs == NULL || ( dxs[ dx_count ] = + (char *)NSLDAPI_CALLOC( 1, txt_len + 1 )) + == NULL ) { + err = NO_RECOVERY; + continue; + } + SAFEMEMCPY( 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_DNS */ diff --git a/ldap/c-sdk/libldap/geteffectiverightsctrl.c b/ldap/c-sdk/libldap/geteffectiverightsctrl.c new file mode 100644 index 0000000000..f03fdc4416 --- /dev/null +++ b/ldap/c-sdk/libldap/geteffectiverightsctrl.c @@ -0,0 +1,109 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_create_geteffectiveRights_control + + Create Effective Rights control. + + Parameters are + + ld LDAP pointer to the desired connection + + authzid RFC2829 section 9, eg "dn:". + NULL or empty string means get bound user's rights, + just "dn:" means get anonymous user's rights. + + attrlist additional attributes for which rights info is + requrested. NULL means "just the ones returned + with the search operation". + + ctl_iscritical Indicates whether the control is critical of not. If + this field is non-zero, the operation will only be car- + ried out if the control is recognized by the server + and/or client + + ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_geteffectiveRights_control ( + LDAP *ld, + const char *authzid, + const char **attrlist, + const char ctl_iscritical, + LDAPControl **ctrlp +) +{ + BerElement *ber; + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + if (NULL == authzid) + { + authzid = ""; + } + + /* create a ber package to hold the controlValue */ + if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + if ( LBER_ERROR == ber_printf( ber, "{s{v}}", authzid, attrlist ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, ber, 1, + ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + +} + + diff --git a/ldap/c-sdk/libldap/getentry.c b/ldap/c-sdk/libldap/getentry.c new file mode 100644 index 0000000000..fb999265b9 --- /dev/null +++ b/ldap/c-sdk/libldap/getentry.c @@ -0,0 +1,141 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * getentry.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +LDAPMessage * +LDAP_CALL +ldap_first_entry( LDAP *ld, LDAPMessage *chain ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || chain == NULLMSG ) { + return( NULLMSG ); + } + + if ( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { + return( chain ); + } + + return( ldap_next_entry( ld, chain )); +} + + +LDAPMessage * +LDAP_CALL +ldap_next_entry( LDAP *ld, LDAPMessage *entry ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || entry == NULLMSG ) { + return( NULLMSG ); + } + + for ( entry = entry->lm_chain; entry != NULLMSG; + entry = entry->lm_chain ) { + if ( entry->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { + return( entry ); + } + } + + return( NULLMSG ); +} + +int +LDAP_CALL +ldap_count_entries( LDAP *ld, LDAPMessage *chain ) +{ + int i; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); + } + + for ( i = 0; chain != NULL; chain = chain->lm_chain ) { + if ( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { + ++i; + } + } + + return( i ); +} + + +int +LDAP_CALL +ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry, + LDAPControl ***serverctrlsp ) +{ + int rc; + BerElement tmpber; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_entry_controls\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry ) + || serverctrlsp == NULL ) { + rc = LDAP_PARAM_ERROR; + goto report_error_and_return; + } + + *serverctrlsp = NULL; + tmpber = *entry->lm_ber; /* struct copy */ + + /* skip past dn and entire attribute/value list */ + if ( ber_scanf( &tmpber, "{xx" ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto report_error_and_return; + } + + rc = nsldapi_get_controls( &tmpber, serverctrlsp ); + +report_error_and_return: + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} diff --git a/ldap/c-sdk/libldap/getfilter.c b/ldap/c-sdk/libldap/getfilter.c new file mode 100644 index 0000000000..ff2ee77f91 --- /dev/null +++ b/ldap/c-sdk/libldap/getfilter.c @@ -0,0 +1,553 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * getfilter.c -- optional add-on to libldap + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" +#include "regex.h" + +static int break_into_words( char *str, char *delims, char ***wordsp ); + +#if !defined( macintosh ) && !defined( DOS ) +extern char * LDAP_CALL re_comp(); +#endif + +#define FILT_MAX_LINE_LEN 1024 + +LDAPFiltDesc * +LDAP_CALL +ldap_init_getfilter( char *fname ) +{ + FILE *fp; + char *buf; + long rlen, len; + int eof; + LDAPFiltDesc *lfdp; + + if (( fp = NSLDAPI_FOPEN( fname, "r" )) == NULL ) { + return( NULL ); + } + + if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ + fclose( fp ); + return( NULL ); + } + + len = ftell( fp ); + + if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ + fclose( fp ); + return( NULL ); + } + + if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { + fclose( fp ); + return( NULL ); + } + + rlen = fread( buf, 1, (size_t)len, fp ); + eof = feof( fp ); + fclose( fp ); + + if ( rlen != len && !eof ) { /* error: didn't get the whole file */ + NSLDAPI_FREE( buf ); + return( NULL ); + } + + + lfdp = ldap_init_getfilter_buf( buf, rlen ); + NSLDAPI_FREE( buf ); + + return( lfdp ); +} + + +LDAPFiltDesc * +LDAP_CALL +ldap_init_getfilter_buf( char *buf, long buflen ) +{ + LDAPFiltDesc *lfdp; + LDAPFiltList *flp, *nextflp; + LDAPFiltInfo *fip, *nextfip; + char *errmsg, *tag, **tok; + int tokcnt, i; + + if ( (buf == NULL) || (buflen < 0) || + ( lfdp = (LDAPFiltDesc *)NSLDAPI_CALLOC(1, sizeof( LDAPFiltDesc))) + == NULL ) { + return( NULL ); + } + + flp = nextflp = NULL; + fip = NULL; + tag = NULL; + + while ( buflen > 0 && ( tokcnt = nsldapi_next_line_tokens( &buf, &buflen, + &tok )) > 0 ) { + switch( tokcnt ) { + case 1: /* tag line */ + if ( tag != NULL ) { + NSLDAPI_FREE( tag ); + } + tag = tok[ 0 ]; + NSLDAPI_FREE( tok ); + break; + case 4: + case 5: /* start of filter info. list */ + if (( nextflp = (LDAPFiltList *)NSLDAPI_CALLOC( 1, + sizeof( LDAPFiltList ))) == NULL ) { + ldap_getfilter_free( lfdp ); + return( NULL ); + } + nextflp->lfl_tag = nsldapi_strdup( tag ); + nextflp->lfl_pattern = tok[ 0 ]; + if (( errmsg = re_comp( nextflp->lfl_pattern )) != NULL ) { + char msg[512]; + ldap_getfilter_free( lfdp ); + snprintf( msg, sizeof(msg), + "bad regular expression \"%s\" - %s\n", + nextflp->lfl_pattern, errmsg ); + ber_err_print( msg ); + nsldapi_free_strarray( tok ); + return( NULL ); + } + + nextflp->lfl_delims = tok[ 1 ]; + nextflp->lfl_ilist = NULL; + nextflp->lfl_next = NULL; + if ( flp == NULL ) { /* first one */ + lfdp->lfd_filtlist = nextflp; + } else { + flp->lfl_next = nextflp; + } + flp = nextflp; + fip = NULL; + for ( i = 2; i < 5; ++i ) { + tok[ i - 2 ] = tok[ i ]; + } + /* fall through */ + + case 2: + case 3: /* filter, desc, and optional search scope */ + if ( nextflp != NULL ) { /* add to info list */ + if (( nextfip = (LDAPFiltInfo *)NSLDAPI_CALLOC( 1, + sizeof( LDAPFiltInfo ))) == NULL ) { + ldap_getfilter_free( lfdp ); + nsldapi_free_strarray( tok ); + return( NULL ); + } + if ( fip == NULL ) { /* first one */ + nextflp->lfl_ilist = nextfip; + } else { + fip->lfi_next = nextfip; + } + fip = nextfip; + nextfip->lfi_next = NULL; + nextfip->lfi_filter = tok[ 0 ]; + nextfip->lfi_desc = tok[ 1 ]; + if ( tok[ 2 ] != NULL ) { + if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) { + nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; + } else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) { + nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL; + } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) { + nextfip->lfi_scope = LDAP_SCOPE_BASE; + } else { + nsldapi_free_strarray( tok ); + ldap_getfilter_free( lfdp ); + return( NULL ); + } + NSLDAPI_FREE( tok[ 2 ] ); + tok[ 2 ] = NULL; + } else { + nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */ + } + nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL && + strchr( tok[ 0 ], '~' ) == NULL ); + NSLDAPI_FREE( tok ); + } + break; + + default: + nsldapi_free_strarray( tok ); + ldap_getfilter_free( lfdp ); + return( NULL ); + } + } + + if ( tag != NULL ) { + NSLDAPI_FREE( tag ); + } + + return( lfdp ); +} + + +int +LDAP_CALL +ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix, char *suffix ) +{ + if ( lfdp == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + if ( lfdp->lfd_filtprefix != NULL ) { + NSLDAPI_FREE( lfdp->lfd_filtprefix ); + } + lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : nsldapi_strdup( prefix ); + + if ( lfdp->lfd_filtsuffix != NULL ) { + NSLDAPI_FREE( lfdp->lfd_filtsuffix ); + } + lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : nsldapi_strdup( suffix ); + + return( LDAP_SUCCESS ); +} + + +/* + * ldap_setfilteraffixes() is deprecated -- use ldap_set_filter_additions() + */ +void +LDAP_CALL +ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix ) +{ + (void)ldap_set_filter_additions( lfdp, prefix, suffix ); +} + + +LDAPFiltInfo * +LDAP_CALL +ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value ) +{ + LDAPFiltList *flp; + + if ( lfdp == NULL || tagpat == NULL || value == NULL ) { + return( NULL ); /* punt */ + } + + if ( lfdp->lfd_curvalcopy != NULL ) { + NSLDAPI_FREE( lfdp->lfd_curvalcopy ); + NSLDAPI_FREE( lfdp->lfd_curvalwords ); + } + + NSLDAPI_FREE(lfdp->lfd_curval); + if ((lfdp->lfd_curval = nsldapi_strdup(value)) == NULL) { + return( NULL ); + } + + lfdp->lfd_curfip = NULL; + + for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) { + if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1 + && re_comp( flp->lfl_pattern ) == NULL + && re_exec( lfdp->lfd_curval ) == 1 ) { + lfdp->lfd_curfip = flp->lfl_ilist; + break; + } + } + + if ( lfdp->lfd_curfip == NULL ) { + return( NULL ); + } + + if (( lfdp->lfd_curvalcopy = nsldapi_strdup( value )) == NULL ) { + return( NULL ); + } + + if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims, + &lfdp->lfd_curvalwords ) < 0 ) { + NSLDAPI_FREE( lfdp->lfd_curvalcopy ); + lfdp->lfd_curvalcopy = NULL; + return( NULL ); + } + + return( ldap_getnextfilter( lfdp )); +} + + +LDAPFiltInfo * +LDAP_CALL +ldap_getnextfilter( LDAPFiltDesc *lfdp ) +{ + LDAPFiltInfo *fip; + + if ( lfdp == NULL || ( fip = lfdp->lfd_curfip ) == NULL ) { + return( NULL ); + } + + lfdp->lfd_curfip = fip->lfi_next; + + ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter, + lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL, + lfdp->lfd_curval, lfdp->lfd_curvalwords ); + lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter; + lfdp->lfd_retfi.lfi_desc = fip->lfi_desc; + lfdp->lfd_retfi.lfi_scope = fip->lfi_scope; + lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact; + + return( &lfdp->lfd_retfi ); +} + + +static char* +filter_add_strn( char *f, char *flimit, char *v, size_t vlen ) + /* Copy v into f. If flimit is too small, return NULL; + * otherwise return (f + vlen). + */ +{ + auto size_t flen = flimit - f; + if ( vlen > flen ) { /* flimit is too small */ + if ( flen > 0 ) SAFEMEMCPY( f, v, flen ); + return NULL; + } + if ( vlen > 0 ) SAFEMEMCPY( f, v, vlen ); + return f + vlen; +} + +static char* +filter_add_value( char *f, char *flimit, char *v, int escape_all ) + /* Copy v into f, but with parentheses escaped. But only escape * and \ + * if escape_all is non-zero so that either "*" or "\2a" can be used in + * v, with different meanings. + * If flimit is too small, return NULL; otherwise + * return (f + the number of bytes copied). + */ +{ + auto char x[4]; + auto size_t slen; + while ( f && *v ) { + switch ( *v ) { + case '*': + if ( escape_all ) { + f = filter_add_strn( f, flimit, "\\2a", 3 ); + v++; + } else { + if ( f < flimit ) { + *f++ = *v++; + } else { + f = NULL; /* overflow */ + } + } + break; + + case '(': + case ')': + sprintf( x, "\\%02x", (unsigned)*v ); + f = filter_add_strn( f, flimit, x, 3 ); + v++; + break; + + case '\\': + if ( escape_all ) { + f = filter_add_strn( f, flimit, "\\5c", 3 ); + v++; + } else { + slen = (ldap_utf8isxdigit( v+1 ) && + ldap_utf8isxdigit( v+2 )) ? 3 : (v[1] ? 2 : 1); + f = filter_add_strn( f, flimit, v, slen ); + v += slen; + } + break; + + default: + if ( f < flimit ) { + *f++ = *v++; + } else { + f = NULL; /* overflow */ + } + break; + } + } + return f; +} + +int +LDAP_CALL +ldap_create_filter( char *filtbuf, unsigned long buflen, char *pattern, + char *prefix, char *suffix, char *attr, char *value, char **valwords ) +{ + char *p, *f, *flimit; + int i, wordcount, wordnum, endwordnum, escape_all; + + /* + * there is some confusion on what to create for a filter if + * attr or value are null pointers. For now we just leave them + * as TO BE DEALT with + */ + + if ( filtbuf == NULL || buflen == 0 || pattern == NULL ){ + return( LDAP_PARAM_ERROR ); + } + + if ( valwords == NULL ) { + wordcount = 0; + } else { + for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) { + ; + } + } + + f = filtbuf; + flimit = filtbuf + buflen - 1; + + if ( prefix != NULL ) { + f = filter_add_strn( f, flimit, prefix, strlen( prefix )); + } + + for ( p = pattern; f != NULL && *p != '\0'; ++p ) { + if ( *p == '%' ) { + ++p; + if ( *p == 'v' || *p == 'e' ) { + escape_all = ( *p == 'e' ); + if ( ldap_utf8isdigit( p+1 )) { + ++p; + wordnum = *p - '1'; + if ( *(p+1) == '-' ) { + ++p; + if ( ldap_utf8isdigit( p+1 )) { + ++p; + endwordnum = *p - '1'; /* e.g., "%v2-4" */ + if ( endwordnum > wordcount - 1 ) { + endwordnum = wordcount - 1; + } + } else { + endwordnum = wordcount - 1; /* e.g., "%v2-" */ + } + } else { + endwordnum = wordnum; /* e.g., "%v2" */ + } + + if ( wordcount > 0 ) { + for ( i = wordnum; i <= endwordnum; ++i ) { + if ( i > wordnum ) { /* add blank btw words */ + f = filter_add_strn( f, flimit, " ", 1 ); + if ( f == NULL ) break; + } + f = filter_add_value( f, flimit, valwords[ i ], + escape_all ); + if ( f == NULL ) break; + } + } + } else if ( *(p+1) == '$' ) { + ++p; + if ( wordcount > 0 ) { + wordnum = wordcount - 1; + f = filter_add_value( f, flimit, + valwords[ wordnum ], escape_all ); + } + } else if ( value != NULL ) { + f = filter_add_value( f, flimit, value, escape_all ); + } + } else if ( *p == 'a' && attr != NULL ) { + f = filter_add_strn( f, flimit, attr, strlen( attr )); + } else { + *f++ = *p; + } + } else { + *f++ = *p; + } + if ( f > flimit ) { /* overflow */ + f = NULL; + } + } + + if ( suffix != NULL && f != NULL) { + f = filter_add_strn( f, flimit, suffix, strlen( suffix )); + } + + if ( f == NULL ) { + *flimit = '\0'; + return( LDAP_SIZELIMIT_EXCEEDED ); + } + *f = '\0'; + return( LDAP_SUCCESS ); +} + + +/* + * ldap_build_filter() is deprecated -- use ldap_create_filter() instead + */ +void +LDAP_CALL +ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern, + char *prefix, char *suffix, char *attr, char *value, char **valwords ) +{ + (void)ldap_create_filter( filtbuf, buflen, pattern, prefix, suffix, attr, + value, valwords ); +} + + +static int +break_into_words( char *str, char *delims, char ***wordsp ) +{ + char *word, **words; + int count; + char *lasts; + + if (( words = (char **)NSLDAPI_CALLOC( 1, sizeof( char * ))) == NULL ) { + return( -1 ); + } + count = 0; + words[ count ] = NULL; + + word = ldap_utf8strtok_r( str, delims, &lasts ); + while ( word != NULL ) { + if (( words = (char **)NSLDAPI_REALLOC( words, + ( count + 2 ) * sizeof( char * ))) == NULL ) { + return( -1 ); + } + + words[ count ] = word; + words[ ++count ] = NULL; + word = ldap_utf8strtok_r( NULL, delims, &lasts ); + } + + *wordsp = words; + return( count ); +} diff --git a/ldap/c-sdk/libldap/getoption.c b/ldap/c-sdk/libldap/getoption.c new file mode 100644 index 0000000000..73e21a2dc9 --- /dev/null +++ b/ldap/c-sdk/libldap/getoption.c @@ -0,0 +1,475 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +#define LDAP_GET_BITOPT( ld, bit ) \ + ((ld)->ld_options & bit ) != 0 ? 1 : 0 + +static int nsldapi_get_api_info( LDAPAPIInfo *aip ); +static int nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ); + + +int +LDAP_CALL +ldap_get_option( LDAP *ld, int option, void *optdata ) +{ + int rc = 0; + + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + + /* + * optdata MUST be a valid pointer... + */ + if (NULL == optdata) + { + return(LDAP_PARAM_ERROR); + } + /* + * process global options (not associated with an LDAP session handle) + */ + if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) { + /* struct copy */ + *((struct ldap_memalloc_fns *)optdata) = nsldapi_memalloc_fns; + return( 0 ); + } + + if ( option == LDAP_OPT_API_INFO ) { + rc = nsldapi_get_api_info( (LDAPAPIInfo *)optdata ); + if ( rc != LDAP_SUCCESS ) { + if ( ld != NULL ) { + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + } + return( -1 ); + } + return( 0 ); + } + /* + * LDAP_OPT_DEBUG_LEVEL is global + */ + if (LDAP_OPT_DEBUG_LEVEL == option) + { +#ifdef LDAP_DEBUG + *((int *) optdata) = ldap_debug; +#endif /* LDAP_DEBUG */ + return ( 0 ); + } + + /* + * if ld is NULL, arrange to return options from our default settings + */ + if ( ld == NULL ) { + ld = &nsldapi_ld_defaults; + } + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); /* punt */ + } + + + if (ld != &nsldapi_ld_defaults) + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + switch( option ) { +#ifdef LDAP_DNS + case LDAP_OPT_DNS: + *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_DNS ); + break; +#endif + + case LDAP_OPT_REFERRALS: + *((int *) optdata) = + LDAP_GET_BITOPT( ld, LDAP_BITOPT_REFERRALS ); + break; + + case LDAP_OPT_SSL: + *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_SSL ); + break; + + case LDAP_OPT_RESTART: + *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_RESTART ); + break; + + case LDAP_OPT_RECONNECT: + *((int *) optdata) = + LDAP_GET_BITOPT( ld, LDAP_BITOPT_RECONNECT ); + break; + + case LDAP_OPT_NOREBIND: + *((int *) optdata) = + LDAP_GET_BITOPT( ld, LDAP_BITOPT_NOREBIND ); + break; + +#ifdef LDAP_ASYNC_IO + case LDAP_OPT_ASYNC_CONNECT: + *((int *) optdata) = + LDAP_GET_BITOPT( ld, LDAP_BITOPT_ASYNC ); + break; +#endif /* LDAP_ASYNC_IO */ + + /* stuff in the sockbuf */ + case LDAP_X_OPT_SOCKBUF: + *((Sockbuf **) optdata) = ld->ld_sbp; + break; + + case LDAP_OPT_DESC: + if ( ber_sockbuf_get_option( ld->ld_sbp, + LBER_SOCKBUF_OPT_DESC, optdata ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + rc = -1; + } + break; + + /* fields in the LDAP structure */ + case LDAP_OPT_DEREF: + *((int *) optdata) = ld->ld_deref; + break; + case LDAP_OPT_SIZELIMIT: + *((int *) optdata) = ld->ld_sizelimit; + break; + case LDAP_OPT_TIMELIMIT: + *((int *) optdata) = ld->ld_timelimit; + break; + case LDAP_OPT_REFERRAL_HOP_LIMIT: + *((int *) optdata) = ld->ld_refhoplimit; + break; + case LDAP_OPT_PROTOCOL_VERSION: + *((int *) optdata) = ld->ld_version; + break; + case LDAP_OPT_SERVER_CONTROLS: + /* fall through */ + case LDAP_OPT_CLIENT_CONTROLS: + *((LDAPControl ***)optdata) = NULL; + /* nsldapi_dup_controls returns -1 and sets lderrno on error */ + rc = nsldapi_dup_controls( ld, (LDAPControl ***)optdata, + ( option == LDAP_OPT_SERVER_CONTROLS ) ? + ld->ld_servercontrols : ld->ld_clientcontrols ); + break; + + /* rebind proc */ + case LDAP_OPT_REBIND_FN: + *((LDAP_REBINDPROC_CALLBACK **) optdata) = ld->ld_rebind_fn; + break; + case LDAP_OPT_REBIND_ARG: + *((void **) optdata) = ld->ld_rebind_arg; + break; + + /* i/o function pointers */ + case LDAP_OPT_IO_FN_PTRS: + if ( ld->ld_io_fns_ptr == NULL ) { + memset( optdata, 0, sizeof( struct ldap_io_fns )); + } else { + /* struct copy */ + *((struct ldap_io_fns *)optdata) = *(ld->ld_io_fns_ptr); + } + break; + + /* extended i/o function pointers */ + case LDAP_X_OPT_EXTIO_FN_PTRS: + if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) { + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close = ld->ld_extclose_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect = ld->ld_extconnect_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read = ld->ld_extread_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write = ld->ld_extwrite_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll = ld->ld_extpoll_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle = ld->ld_extnewhandle_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle = ld->ld_extdisposehandle_fn; + ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg = ld->ld_ext_session_arg; + } else if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == + LDAP_X_EXTIO_FNS_SIZE ) { + /* struct copy */ + *((struct ldap_x_ext_io_fns *) optdata) = ld->ld_ext_io_fns; + } else { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + rc = -1; + } + break; + + /* get socketargp in extended i/o function */ + case LDAP_X_OPT_SOCKETARG: + if ( ber_sockbuf_get_option( ld->ld_sbp,LBER_SOCKBUF_OPT_SOCK_ARG, optdata) + != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + rc = -1; + } + break; + + /* thread function pointers */ + case LDAP_OPT_THREAD_FN_PTRS: + /* struct copy */ + *((struct ldap_thread_fns *) optdata) = ld->ld_thread; + break; + + /* extra thread function pointers */ + case LDAP_OPT_EXTRA_THREAD_FN_PTRS: + /* struct copy */ + *((struct ldap_extra_thread_fns *) optdata) = ld->ld_thread2; + break; + + /* DNS function pointers */ + case LDAP_OPT_DNS_FN_PTRS: + /* struct copy */ + *((struct ldap_dns_fns *) optdata) = ld->ld_dnsfn; + break; + + /* cache function pointers */ + case LDAP_OPT_CACHE_FN_PTRS: + /* struct copy */ + *((struct ldap_cache_fns *) optdata) = ld->ld_cache; + break; + case LDAP_OPT_CACHE_STRATEGY: + *((int *) optdata) = ld->ld_cache_strategy; + break; + case LDAP_OPT_CACHE_ENABLE: + *((int *) optdata) = ld->ld_cache_on; + break; + + case LDAP_OPT_ERROR_NUMBER: + *((int *) optdata) = LDAP_GET_LDERRNO( ld, NULL, NULL ); + break; + + case LDAP_OPT_ERROR_STRING: + (void)LDAP_GET_LDERRNO( ld, NULL, (char **)optdata ); + *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); + break; + + case LDAP_OPT_MATCHED_DN: + (void)LDAP_GET_LDERRNO( ld, (char **)optdata, NULL ); + *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); + break; + + case LDAP_OPT_PREFERRED_LANGUAGE: + if ( NULL != ld->ld_preferred_language ) { + *((char **) optdata) = + nsldapi_strdup(ld->ld_preferred_language); + } else { + *((char **) optdata) = NULL; + } + break; + + case LDAP_OPT_API_FEATURE_INFO: + rc = nsldapi_get_feature_info( (LDAPAPIFeatureInfo *)optdata ); + if ( rc != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + rc = -1; + } + break; + + case LDAP_OPT_HOST_NAME: + *((char **) optdata) = nsldapi_strdup( ld->ld_defhost ); + break; + + case LDAP_X_OPT_CONNECT_TIMEOUT: + *((int *) optdata) = ld->ld_connect_timeout; + break; + +#ifdef LDAP_SASLIO_HOOKS + /* SASL options */ + case LDAP_OPT_X_SASL_MECH: + *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_mech); + break; + case LDAP_OPT_X_SASL_REALM: + *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_realm); + break; + case LDAP_OPT_X_SASL_AUTHCID: + *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authcid); + break; + case LDAP_OPT_X_SASL_AUTHZID: + *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authzid); + break; + case LDAP_OPT_X_SASL_SSF: + { + int sc; + sasl_ssf_t *ssf; + sasl_conn_t *ctx; + if( ld->ld_defconn == NULL ) { + return -1; + } + ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sasl_ctx); + if ( ctx == NULL ) { + return -1; + } + sc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); + if ( sc != SASL_OK ) { + return -1; + } + *((sasl_ssf_t *) optdata) = *ssf; + } + break; + case LDAP_OPT_X_SASL_SSF_MIN: + *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.min_ssf; + break; + case LDAP_OPT_X_SASL_SSF_MAX: + *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.max_ssf; + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.maxbufsize; + break; + case LDAP_OPT_X_SASL_SSF_EXTERNAL: + case LDAP_OPT_X_SASL_SECPROPS: + /* + * These options are write only. Making these options + * read/write would expose semi-private interfaces of libsasl + * for which there are no cross platform/standardized + * definitions. + */ + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + rc = -1; + break; +#endif + + default: + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + rc = -1; + } + if (ld != &nsldapi_ld_defaults) + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + return( rc ); +} + + +/* + * Table of extended API features we support. + * The first field is the version of the info. strcuture itself; we do not + * use the ones from this table so it is okay to leave as zero. + */ +static LDAPAPIFeatureInfo nsldapi_extensions[] = { + { 0, "SERVER_SIDE_SORT", LDAP_API_FEATURE_SERVER_SIDE_SORT }, + { 0, "VIRTUAL_LIST_VIEW", LDAP_API_FEATURE_VIRTUAL_LIST_VIEW }, + { 0, "PERSISTENT_SEARCH", LDAP_API_FEATURE_PERSISTENT_SEARCH }, + { 0, "PROXY_AUTHORIZATION", LDAP_API_FEATURE_PROXY_AUTHORIZATION }, + { 0, "X_LDERRNO", LDAP_API_FEATURE_X_LDERRNO }, + { 0, "X_MEMCACHE", LDAP_API_FEATURE_X_MEMCACHE }, + { 0, "X_IO_FUNCTIONS", LDAP_API_FEATURE_X_IO_FUNCTIONS }, + { 0, "X_EXTIO_FUNCTIONS", LDAP_API_FEATURE_X_EXTIO_FUNCTIONS }, + { 0, "X_DNS_FUNCTIONS", LDAP_API_FEATURE_X_DNS_FUNCTIONS }, + { 0, "X_MEMALLOC_FUNCTIONS", LDAP_API_FEATURE_X_MEMALLOC_FUNCTIONS }, + { 0, "X_THREAD_FUNCTIONS", LDAP_API_FEATURE_X_THREAD_FUNCTIONS }, + { 0, "X_EXTHREAD_FUNCTIONS", LDAP_API_FEATURE_X_EXTHREAD_FUNCTIONS }, + { 0, "X_GETLANGVALUES", LDAP_API_FEATURE_X_GETLANGVALUES }, + { 0, "X_CLIENT_SIDE_SORT", LDAP_API_FEATURE_X_CLIENT_SIDE_SORT }, + { 0, "X_URL_FUNCTIONS", LDAP_API_FEATURE_X_URL_FUNCTIONS }, + { 0, "X_FILTER_FUNCTIONS", LDAP_API_FEATURE_X_FILTER_FUNCTIONS }, +}; + +#define NSLDAPI_EXTENSIONS_COUNT \ + (sizeof(nsldapi_extensions)/sizeof(LDAPAPIFeatureInfo)) + +/* + * Retrieve information about this implementation of the LDAP API. + * Returns an LDAP error code. + */ +static int +nsldapi_get_api_info( LDAPAPIInfo *aip ) +{ + int i; + + if ( aip == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + aip->ldapai_api_version = LDAP_API_VERSION; + + if ( aip->ldapai_info_version != LDAP_API_INFO_VERSION ) { + aip->ldapai_info_version = LDAP_API_INFO_VERSION; + return( LDAP_PARAM_ERROR ); + } + + aip->ldapai_protocol_version = LDAP_VERSION_MAX; + aip->ldapai_vendor_version = LDAP_VENDOR_VERSION; + + if (( aip->ldapai_vendor_name = nsldapi_strdup( LDAP_VENDOR_NAME )) + == NULL ) { + return( LDAP_NO_MEMORY ); + } + + if ( NSLDAPI_EXTENSIONS_COUNT < 1 ) { + aip->ldapai_extensions = NULL; + } else { + if (( aip->ldapai_extensions = NSLDAPI_CALLOC( + NSLDAPI_EXTENSIONS_COUNT + 1, sizeof(char *))) == NULL ) { + NSLDAPI_FREE( aip->ldapai_vendor_name ); + aip->ldapai_vendor_name = NULL; + return( LDAP_NO_MEMORY ); + } + + for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { + if (( aip->ldapai_extensions[i] = nsldapi_strdup( + nsldapi_extensions[i].ldapaif_name )) == NULL ) { + ldap_value_free( aip->ldapai_extensions ); + NSLDAPI_FREE( aip->ldapai_vendor_name ); + aip->ldapai_extensions = NULL; + aip->ldapai_vendor_name = NULL; + return( LDAP_NO_MEMORY ); + } + } + } + + return( LDAP_SUCCESS ); +} + + +/* + * Retrieves information about a specific extended feature of the LDAP API/ + * Returns an LDAP error code. + */ +static int +nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ) +{ + int i; + + if ( fip == NULL || fip->ldapaif_name == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + if ( fip->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION ) { + fip->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; + return( LDAP_PARAM_ERROR ); + } + + for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { + if ( strcmp( fip->ldapaif_name, + nsldapi_extensions[i].ldapaif_name ) == 0 ) { + fip->ldapaif_version = + nsldapi_extensions[i].ldapaif_version; + break; + } + } + + return(( i < NSLDAPI_EXTENSIONS_COUNT ) ? LDAP_SUCCESS + : LDAP_PARAM_ERROR ); +} diff --git a/ldap/c-sdk/libldap/getvalues.c b/ldap/c-sdk/libldap/getvalues.c new file mode 100644 index 0000000000..cae40d2cdf --- /dev/null +++ b/ldap/c-sdk/libldap/getvalues.c @@ -0,0 +1,480 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * getvalues.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + + +static void ** +internal_ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target, + int lencall ) +{ + struct berelement ber; + char *attr; + int rc; + void **vals; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULL ); /* punt */ + } + if ( target == NULL || + !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( NULL ); + } + + ber = *entry->lm_ber; + + /* skip sequence, dn, sequence of, and snag the first attr */ + if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( NULL ); + } + + rc = strcasecmp( (char *)target, attr ); + NSLDAPI_FREE( attr ); + if ( rc != 0 ) { + while ( 1 ) { + if ( ber_scanf( &ber, "x}{a", &attr ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, + NULL, NULL ); + return( NULL ); + } + + rc = strcasecmp( (char *)target, attr ); + if ( rc == 0 ) { + NSLDAPI_FREE( attr ); + break; + } + NSLDAPI_FREE( attr ); + } + } + + /* + * if we get this far, we've found the attribute and are sitting + * just before the set of values. + */ + + if ( lencall ) { + rc = ber_scanf( &ber, "[V]", &vals ); + } else { + rc = ber_scanf( &ber, "[v]", &vals ); + } + + if ( rc == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + } else { + rc = LDAP_SUCCESS; + } + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + + return(( rc == LDAP_SUCCESS ) ? vals : NULL ); +} + + +/* For language-sensitive attribute matching, we are looking for a + language tag that looks like one of the following: + + cn + cn;lang-en + cn;lang-en-us + cn;lang-ja + cn;lang-ja-JP-kanji + + The base language specification consists of two letters following + "lang-". After that, there may be additional language-specific + narrowings preceded by a "-". In our processing we go from the + specific to the general, preferring a complete subtype match, but + accepting a partial one. For example: + + For a request for "cn;lang-en-us", we would return cn;lang-en-us + if present, otherwise cn;lang-en if present, otherwise cn. + + Besides the language subtype, there may be other subtypes: + + cn;lang-ja;binary (Unlikely!) + cn;lang-ja;phonetic + + If not in the target, they are ignored. If they are in the target, + they must be in the attribute to match. +*/ +#define LANG_SUBTYPE_INDEX_NONE -1 +#define LANG_SUBTYPE_INDEX_DUPLICATE -2 + +typedef struct { + int start; + int length; +} _SubStringIndex; + +static int +parse_subtypes( const char *target, int *baseLenp, char **langp, + _SubStringIndex **subs, int *nsubtypes ) +{ + int nSubtypes = 0; + int ind = 0; + char *nextToken; + _SubStringIndex *result = NULL; + int langIndex; + int targetLen; + int subtypeStart; + + langIndex = LANG_SUBTYPE_INDEX_NONE; + *subs = NULL; + *langp = NULL; + *baseLenp = 0; + *nsubtypes = 0; + targetLen = strlen( target ); + + /* Parse past base attribute */ + nextToken = strchr( target, ';' ); + if ( NULL != nextToken ) { + subtypeStart = nextToken - target + 1; + *baseLenp = subtypeStart - 1; + } + else { + subtypeStart = targetLen; + *baseLenp = subtypeStart; + } + ind = subtypeStart; + + /* How many subtypes? */ + nextToken = (char *)target + subtypeStart; + while ( nextToken && *nextToken ) { + char *thisToken = nextToken; + nextToken = strchr( thisToken, ';' ); + if ( NULL != nextToken ) + nextToken++; + if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { + /* If there was a previous lang tag, this is illegal! */ + if ( langIndex != LANG_SUBTYPE_INDEX_NONE ) { + langIndex = LANG_SUBTYPE_INDEX_DUPLICATE; + return langIndex; + } + else { + langIndex = nSubtypes; + } + } else { + nSubtypes++; + } + } + /* No language subtype? */ + if ( langIndex < 0 ) + return langIndex; + + /* Allocate array of non-language subtypes */ + if ( nSubtypes > 0 ) { + result = (_SubStringIndex *)NSLDAPI_MALLOC( sizeof(*result) + * nSubtypes ); + memset( result, 0, sizeof(*result) * nSubtypes ); + } + ind = 0; + nSubtypes = 0; + ind = subtypeStart; + nextToken = (char *)target + subtypeStart; + while ( nextToken && *nextToken ) { + char *thisToken = nextToken; + int len; + nextToken = strchr( thisToken, ';' ); + if ( NULL != nextToken ) { + len = nextToken - thisToken; + nextToken++; + } + else { + nextToken = (char *)target + targetLen; + len = nextToken - thisToken; + } + if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { + int i; + *langp = (char *)NSLDAPI_MALLOC( len + 1 ); + for( i = 0; i < len; i++ ) + (*langp)[i] = toupper( target[ind+i] ); + (*langp)[len] = 0; + } + else { + result[nSubtypes].start = thisToken - target; + result[nSubtypes].length = len; + nSubtypes++; + } + } + *subs = result; + *nsubtypes = nSubtypes; + return langIndex; +} + + +static int +check_lang_match( const char *target, const char *baseTarget, + _SubStringIndex *targetTypes, + int ntargetTypes, char *targetLang, char *attr ) +{ + int langIndex; + _SubStringIndex *subtypes; + int baseLen; + char *lang; + int nsubtypes; + int mismatch = 0; + int match = -1; + int i; + + /* Get all subtypes in the attribute name */ + langIndex = parse_subtypes( attr, &baseLen, &lang, &subtypes, &nsubtypes ); + + /* Check if there any required non-language subtypes which are + not in this attribute */ + for( i = 0; i < ntargetTypes; i++ ) { + char *t = (char *)target+targetTypes[i].start; + int tlen = targetTypes[i].length; + int j; + for( j = 0; j < nsubtypes; j++ ) { + char *a = attr + subtypes[j].start; + int alen = subtypes[j].length; + if ( (tlen == alen) && !strncasecmp( t, a, tlen ) ) + break; + } + if ( j >= nsubtypes ) { + mismatch = 1; + break; + } + } + if ( mismatch ) { + if ( NULL != subtypes ) + NSLDAPI_FREE( subtypes ); + if ( NULL != lang ) + NSLDAPI_FREE( lang ); + return -1; + } + + /* If there was no language subtype... */ + if ( langIndex < 0 ) { + if ( NULL != subtypes ) + NSLDAPI_FREE( subtypes ); + if ( NULL != lang ) + NSLDAPI_FREE( lang ); + if ( LANG_SUBTYPE_INDEX_NONE == langIndex ) + return 0; + else + return -1; + } + + /* Okay, now check the language subtag */ + i = 0; + while( targetLang[i] && lang[i] && + (toupper(targetLang[i]) == toupper(lang[i])) ) + i++; + + /* The total length can't be longer than the requested subtype */ + if ( !lang[i] || (lang[i] == ';') ) { + /* If the found subtype is shorter than the requested one, the next + character in the requested one should be "-" */ + if ( !targetLang[i] || (targetLang[i] == '-') ) + match = i; + } + return match; +} + +static int check_base_match( const char *target, char *attr ) +{ + int i = 0; + int rc; + while( target[i] && attr[i] && (toupper(target[i]) == toupper(attr[i])) ) + i++; + rc = ( !target[i] && (!attr[i] || (';' == attr[i])) ); + return rc; +} + +static void ** +internal_ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, + const char *target, char **type, int lencall ) +{ + struct berelement ber; + char *attr = NULL; + int rc; + void **vals = NULL; + int langIndex; + _SubStringIndex *subtypes; + int nsubtypes; + char *baseTarget = NULL; + int bestMatch = 0; + char *lang = NULL; + int len; + int firstAttr = 1; + char *bestType = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULL ); + } + if ( (target == NULL) || + !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( NULL ); + } + + /* A language check was requested, so see if there really is a + language subtype in the attribute spec */ + langIndex = parse_subtypes( target, &len, &lang, + &subtypes, &nsubtypes ); + if ( langIndex < 0 ) { + if ( NULL != subtypes ) { + NSLDAPI_FREE( subtypes ); + subtypes = NULL; + } + vals = internal_ldap_get_values( ld, entry, target, lencall ); + if ( NULL != type ) + *type = nsldapi_strdup( target ); + return vals; + } else { + /* Get just the base attribute name */ + baseTarget = (char *)NSLDAPI_MALLOC( len + 1 ); + memcpy( baseTarget, target, len ); + baseTarget[len] = 0; + } + + ber = *entry->lm_ber; + + /* Process all attributes in the entry */ + while ( 1 ) { + int foundMatch = 0; + if ( NULL != attr ) + NSLDAPI_FREE( attr ); + if ( firstAttr ) { + firstAttr = 0; + /* skip sequence, dn, sequence of, and snag the first attr */ + if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) { + break; + } + } else { + if ( ber_scanf( &ber, "{a", &attr ) == LBER_ERROR ) { + break; + } + } + + if ( check_base_match( (const char *)baseTarget, attr ) ) { + int thisMatch = check_lang_match( target, baseTarget, + subtypes, nsubtypes, lang, attr ); + if ( thisMatch > bestMatch ) { + if ( vals ) + NSLDAPI_FREE( vals ); + foundMatch = 1; + bestMatch = thisMatch; + if ( NULL != bestType ) + NSLDAPI_FREE( bestType ); + bestType = attr; + attr = NULL; + } + } + if ( foundMatch ) { + if ( lencall ) { + rc = ber_scanf( &ber, "[V]}", &vals ); + } else { + rc = ber_scanf( &ber, "[v]}", &vals ); + } + } else { + ber_scanf( &ber, "x}" ); + } + } + + NSLDAPI_FREE( lang ); + NSLDAPI_FREE( baseTarget ); + NSLDAPI_FREE( subtypes ); + + if ( NULL != type ) + *type = bestType; + else if ( NULL != bestType ) + NSLDAPI_FREE( bestType ); + + if ( NULL == vals ) { + rc = LDAP_DECODING_ERROR; + } else { + rc = LDAP_SUCCESS; + } + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + + return( vals ); +} + + +char ** +LDAP_CALL +ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target ) +{ + return( (char **) internal_ldap_get_values( ld, entry, target, 0 ) ); +} + +struct berval ** +LDAP_CALL +ldap_get_values_len( LDAP *ld, LDAPMessage *entry, const char *target ) +{ + return( (struct berval **) internal_ldap_get_values( ld, entry, target, + 1 ) ); +} + +char ** +LDAP_CALL +ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, const char *target, + char **type ) +{ + return( (char **) internal_ldap_get_lang_values( ld, entry, + target, type, 0 ) ); +} + +struct berval ** +LDAP_CALL +ldap_get_lang_values_len( LDAP *ld, LDAPMessage *entry, const char *target, + char **type ) +{ + return( (struct berval **) internal_ldap_get_lang_values( ld, entry, + target, type, 1 ) ); +} + diff --git a/ldap/c-sdk/libldap/ldap-int.h b/ldap/c-sdk/libldap/ldap-int.h new file mode 100644 index 0000000000..f64d1b3d3a --- /dev/null +++ b/ldap/c-sdk/libldap/ldap-int.h @@ -0,0 +1,888 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef _LDAPINT_H +#define _LDAPINT_H + +#include +#include +#include +#include +#include +#include +#ifdef hpux +#include +#endif /* hpux */ + +#ifdef _WINDOWS +# define FD_SETSIZE 256 /* number of connections we support */ +# define WIN32_LEAN_AND_MEAN +# include +#elif defined(macintosh) +#include "ldap-macos.h" +#else /* _WINDOWS */ +# include +# include +# include +# include +#if !defined(XP_OS2) && !defined(XP_BEOS) +# include +#endif +# include +#if !defined(hpux) && !defined(SUNOS4) && !defined(XP_BEOS) +# include +#endif /* !defined(hpux) and others */ +#endif /* _WINDOWS */ + +#if defined(IRIX) +#include +#endif /* IRIX */ + +#ifdef XP_BEOS +#define NSLDAPI_AVOID_OS_SOCKETS +#endif + +#define NSLBERI_LBER_INT_FRIEND +#ifdef macintosh +#include "lber-int.h" +#else /* macintosh */ +#include "../liblber/lber-int.h" +#endif /* macintosh */ + +#include "ldap.h" +#include "ldaprot.h" +#include "ldaplog.h" +#include "portable.h" + +#ifdef LDAP_ASYNC_IO +#ifdef NEED_FILIO +#include /* to get FIONBIO for ioctl() call */ +#else /* NEED_FILIO */ +#if !defined( _WINDOWS) && !defined (macintosh) +#include /* to get FIONBIO for ioctl() call */ +#endif /* _WINDOWS && macintosh */ +#endif /* NEED_FILIO */ +#endif /* LDAP_ASYNC_IO */ + +#ifdef USE_SYSCONF +# include +#endif /* USE_SYSCONF */ + +#ifdef LDAP_SASLIO_HOOKS +#include +#define SASL_MAX_BUFF_SIZE 65536 +#define SASL_MIN_BUFF_SIZE 4096 +#endif + +#if !defined(_WINDOWS) && !defined(macintosh) && !defined(BSDI) && \ + !defined(XP_OS2) && !defined(XP_BEOS) && !defined(NTO) && \ + !defined(DARWIN) +#define NSLDAPI_HAVE_POLL 1 +#endif + +/* SSL version, or 0 if not built with SSL */ +#if defined(NET_SSL) +# define SSL_VERSION 3 +#else +# define SSL_VERSION 0 +#endif + + +#define LDAP_URL_URLCOLON "URL:" +#define LDAP_URL_URLCOLON_LEN 4 + +#define LDAP_LDAP_REF_STR LDAP_URL_PREFIX +#define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN +#define LDAP_LDAPS_REF_STR LDAPS_URL_PREFIX +#define LDAP_LDAPS_REF_STR_LEN LDAPS_URL_PREFIX_LEN + +/* default limit on nesting of referrals */ +#define LDAP_DEFAULT_REFHOPLIMIT 5 +#ifdef LDAP_DNS +#define LDAP_DX_REF_STR "dx://" +#define LDAP_DX_REF_STR_LEN 5 +#endif /* LDAP_DNS */ + +typedef enum { + LDAP_CACHE_LOCK, + LDAP_MEMCACHE_LOCK, + LDAP_MSGID_LOCK, + LDAP_REQ_LOCK, + LDAP_RESP_LOCK, + LDAP_ABANDON_LOCK, + LDAP_CTRL_LOCK, + LDAP_OPTION_LOCK, + LDAP_ERR_LOCK, + LDAP_CONN_LOCK, + LDAP_IOSTATUS_LOCK, /* serializes access to ld->ld_iostatus */ + LDAP_RESULT_LOCK, + LDAP_PEND_LOCK, + LDAP_THREADID_LOCK, +#ifdef LDAP_SASLIO_HOOKS + LDAP_SASL_LOCK, +#endif + LDAP_MAX_LOCK +} LDAPLock; + +/* + * This structure represents both ldap messages and ldap responses. + * These are really the same, except in the case of search responses, + * where a response has multiple messages. + */ + +struct ldapmsg { + int lm_msgid; /* the message id */ + ber_tag_t lm_msgtype; /* the message type */ + BerElement *lm_ber; /* the ber encoded message contents */ + struct ldapmsg *lm_chain; /* for search - next msg in the resp */ + struct ldapmsg *lm_next; /* next response */ + int lm_fromcache; /* memcache: origin of message */ +}; + +/* + * structure for tracking LDAP server host, ports, DNs, etc. + */ +typedef struct ldap_server { + char *lsrv_host; + char *lsrv_dn; /* if NULL, use default */ + int lsrv_port; + unsigned long lsrv_options; /* boolean options */ +#define LDAP_SRV_OPT_SECURE 0x01 + struct ldap_server *lsrv_next; +} LDAPServer; + +/* + * structure for representing an LDAP server connection + */ +typedef struct ldap_conn { + Sockbuf *lconn_sb; + BerElement *lconn_ber; /* non-NULL if in midst of msg. */ + int lconn_version; /* LDAP protocol version */ + int lconn_refcnt; + unsigned long lconn_lastused; /* time */ + int lconn_status; +#define LDAP_CONNST_CONNECTING 2 +#define LDAP_CONNST_CONNECTED 3 +#define LDAP_CONNST_DEAD 4 + LDAPServer *lconn_server; + char *lconn_binddn; /* DN of last successful bind */ + int lconn_bound; /* has a bind been done? */ + int lconn_pending_requests; /* count of unsent req*/ + char *lconn_krbinstance; +#ifdef LDAP_SASLIO_HOOKS + sasl_conn_t *lconn_sasl_ctx; /* the sasl connection context */ +#endif /* LDAP_SASLIO_HOOKS */ + struct ldap_conn *lconn_next; +} LDAPConn; + + +/* + * structure used to track outstanding requests + */ +typedef struct ldapreq { + int lr_msgid; /* the message id */ + int lr_status; /* status of request */ +#define LDAP_REQST_INPROGRESS 1 +#define LDAP_REQST_CHASINGREFS 2 +#define LDAP_REQST_WRITING 4 +#define LDAP_REQST_CONNDEAD 5 /* associated conn. has failed */ + int lr_outrefcnt; /* count of outstanding referrals */ + int lr_origid; /* original request's message id */ + int lr_parentcnt; /* count of parent requests */ + ber_tag_t lr_res_msgtype; /* result message type */ + int lr_expect_resp; /* if non-zero, expect a response */ + int lr_res_errno; /* result LDAP errno */ + char *lr_res_error; /* result error string */ + char *lr_res_matched;/* result matched DN string */ + BerElement *lr_ber; /* ber encoded request contents */ + LDAPConn *lr_conn; /* connection used to send request */ + char *lr_binddn; /* request is a bind for this DN */ + struct ldapreq *lr_parent; /* request that spawned this referral */ + struct ldapreq *lr_child; /* list of requests we spawned */ + struct ldapreq *lr_sibling; /* next referral spawned */ + struct ldapreq *lr_prev; /* ld->ld_requests previous request */ + struct ldapreq *lr_next; /* ld->ld_requests next request */ + LDAPControl **lr_res_ctrls; /* result controls */ +} LDAPRequest; + +typedef struct ldappend { + void *lp_sema; /* semaphore to post */ + int lp_msgid; /* message id */ + LDAPMessage *lp_result; /* result storage */ + struct ldappend *lp_prev; /* previous pending */ + struct ldappend *lp_next; /* next pending */ +} LDAPPend; + +/* + * forward declaration for I/O status structure (defined in os-ip.c) + */ +typedef struct nsldapi_iostatus_info NSLDAPIIOStatus; + +/* + * old extended IO structure (before writev callback was added) + */ +struct ldap_x_ext_io_fns_rev0 { + int lextiof_size; + LDAP_X_EXTIOF_CONNECT_CALLBACK *lextiof_connect; + LDAP_X_EXTIOF_CLOSE_CALLBACK *lextiof_close; + LDAP_X_EXTIOF_READ_CALLBACK *lextiof_read; + LDAP_X_EXTIOF_WRITE_CALLBACK *lextiof_write; + LDAP_X_EXTIOF_POLL_CALLBACK *lextiof_poll; + LDAP_X_EXTIOF_NEWHANDLE_CALLBACK *lextiof_newhandle; + LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lextiof_disposehandle; + void *lextiof_session_arg; +}; +#define LDAP_X_EXTIO_FNS_SIZE_REV0 sizeof(struct ldap_x_ext_io_fns_rev0) + + +/* + * Structure representing an ldap connection. + * + * This is an opaque struct; the fields are not visible to + * applications that use the LDAP API. + */ +struct ldap { + struct sockbuf *ld_sbp; /* pointer to socket desc. & buffer */ + char *ld_host; + int ld_version; /* LDAP protocol version */ + char ld_lberoptions; + int ld_deref; + + int ld_timelimit; + int ld_sizelimit; + + struct ldap_filt_desc *ld_filtd; /* from getfilter for ufn searches */ + char *ld_ufnprefix; /* for incomplete ufn's */ + + int ld_errno; + char *ld_error; + char *ld_matched; + int ld_msgid; + + /* Note: the ld_requests list is ordered old to new */ + LDAPRequest *ld_requests; /* list of outstanding requests */ + LDAPMessage *ld_responses; /* list of outstanding responses */ + int *ld_abandoned; /* array of abandoned requests */ + char *ld_cldapdn; /* DN used in connectionless search */ + + int ld_cldaptries; /* connectionless search retry count */ + int ld_cldaptimeout;/* time between retries */ + int ld_refhoplimit; /* limit on referral nesting */ + unsigned long ld_options; /* boolean options */ + +#define LDAP_BITOPT_REFERRALS 0x80000000 +#define LDAP_BITOPT_SSL 0x40000000 +#define LDAP_BITOPT_DNS 0x20000000 +#define LDAP_BITOPT_RESTART 0x10000000 +#define LDAP_BITOPT_RECONNECT 0x08000000 +#define LDAP_BITOPT_ASYNC 0x04000000 +#define LDAP_BITOPT_NOREBIND 0x02000000 + + char *ld_defhost; /* full name of default server */ + int ld_defport; /* port of default server */ + BERTranslateProc ld_lber_encode_translate_proc; + BERTranslateProc ld_lber_decode_translate_proc; + LDAPConn *ld_defconn; /* default connection */ + LDAPConn *ld_conns; /* list of all server connections */ + NSLDAPIIOStatus *ld_iostatus; /* status info. about network sockets */ + LDAP_REBINDPROC_CALLBACK *ld_rebind_fn; + void *ld_rebind_arg; + + /* function pointers, etc. for extended I/O */ + struct ldap_x_ext_io_fns ld_ext_io_fns; +#define ld_extio_size ld_ext_io_fns.lextiof_size +#define ld_extclose_fn ld_ext_io_fns.lextiof_close +#define ld_extconnect_fn ld_ext_io_fns.lextiof_connect +#define ld_extread_fn ld_ext_io_fns.lextiof_read +#define ld_extwrite_fn ld_ext_io_fns.lextiof_write +#define ld_extwritev_fn ld_ext_io_fns.lextiof_writev +#define ld_extpoll_fn ld_ext_io_fns.lextiof_poll +#define ld_extnewhandle_fn ld_ext_io_fns.lextiof_newhandle +#define ld_extdisposehandle_fn ld_ext_io_fns.lextiof_disposehandle +#define ld_ext_session_arg ld_ext_io_fns.lextiof_session_arg + + /* allocated pointer for older I/O functions */ + struct ldap_io_fns *ld_io_fns_ptr; +#define NSLDAPI_USING_CLASSIC_IO_FUNCTIONS( ld ) ((ld)->ld_io_fns_ptr != NULL) + + /* function pointers, etc. for DNS */ + struct ldap_dns_fns ld_dnsfn; +#define ld_dns_extradata ld_dnsfn.lddnsfn_extradata +#define ld_dns_bufsize ld_dnsfn.lddnsfn_bufsize +#define ld_dns_gethostbyname_fn ld_dnsfn.lddnsfn_gethostbyname +#define ld_dns_gethostbyaddr_fn ld_dnsfn.lddnsfn_gethostbyaddr +#define ld_dns_getpeername_fn ld_dnsfn.lddnsfn_getpeername + + /* function pointers, etc. for threading */ + struct ldap_thread_fns ld_thread; +#define ld_mutex_alloc_fn ld_thread.ltf_mutex_alloc +#define ld_mutex_free_fn ld_thread.ltf_mutex_free +#define ld_mutex_lock_fn ld_thread.ltf_mutex_lock +#define ld_mutex_unlock_fn ld_thread.ltf_mutex_unlock +#define ld_get_errno_fn ld_thread.ltf_get_errno +#define ld_set_errno_fn ld_thread.ltf_set_errno +#define ld_get_lderrno_fn ld_thread.ltf_get_lderrno +#define ld_set_lderrno_fn ld_thread.ltf_set_lderrno +#define ld_lderrno_arg ld_thread.ltf_lderrno_arg + void **ld_mutex; + + /* function pointers, etc. for caching */ + int ld_cache_on; + int ld_cache_strategy; + struct ldap_cache_fns ld_cache; +#define ld_cache_config ld_cache.lcf_config +#define ld_cache_bind ld_cache.lcf_bind +#define ld_cache_unbind ld_cache.lcf_unbind +#define ld_cache_search ld_cache.lcf_search +#define ld_cache_compare ld_cache.lcf_compare +#define ld_cache_add ld_cache.lcf_add +#define ld_cache_delete ld_cache.lcf_delete +#if 0 +#define ld_cache_rename ld_cache.lcf_rename +#endif +#define ld_cache_modify ld_cache.lcf_modify +#define ld_cache_modrdn ld_cache.lcf_modrdn +#define ld_cache_abandon ld_cache.lcf_abandon +#define ld_cache_result ld_cache.lcf_result +#define ld_cache_flush ld_cache.lcf_flush +#define ld_cache_arg ld_cache.lcf_arg + + /* ldapv3 controls */ + LDAPControl **ld_servercontrols; + LDAPControl **ld_clientcontrols; + + /* Preferred language */ + char *ld_preferred_language; + + /* MemCache */ + LDAPMemCache *ld_memcache; + + /* Pending results */ + LDAPPend *ld_pend; /* list of pending results */ + + /* extra thread function pointers */ + struct ldap_extra_thread_fns ld_thread2; + + /* + * With the 4.0 and later versions of the LDAP SDK, the extra thread + * functions except for the ld_threadid_fn have been disabled. + * Look at the release notes for the full explanation. + */ +#define ld_mutex_trylock_fn ld_thread2.ltf_mutex_trylock +#define ld_sema_alloc_fn ld_thread2.ltf_sema_alloc +#define ld_sema_free_fn ld_thread2.ltf_sema_free +#define ld_sema_wait_fn ld_thread2.ltf_sema_wait +#define ld_sema_post_fn ld_thread2.ltf_sema_post +#define ld_threadid_fn ld_thread2.ltf_threadid_fn + + /* extra data for mutex handling in referrals */ + void *ld_mutex_threadid[LDAP_MAX_LOCK]; + unsigned long ld_mutex_refcnt[LDAP_MAX_LOCK]; + + /* connect timeout value (milliseconds) */ + int ld_connect_timeout; + +#ifdef LDAP_SASLIO_HOOKS + /* SASL default option settings */ + char *ld_def_sasl_mech; + char *ld_def_sasl_realm; + char *ld_def_sasl_authcid; + char *ld_def_sasl_authzid; + /* SASL Security properties */ + struct sasl_security_properties ld_sasl_secprops; +#endif +}; + +/* allocate/free mutex */ +#define LDAP_MUTEX_ALLOC( ld ) \ + (((ld)->ld_mutex_alloc_fn != NULL) ? (ld)->ld_mutex_alloc_fn() : NULL) + +/* allocate/free mutex */ +#define LDAP_MUTEX_FREE( ld, m ) \ + if ( (ld)->ld_mutex_free_fn != NULL && m != NULL ) { \ + (ld)->ld_mutex_free_fn( m ); \ + } + +/* enter/exit critical sections */ +/* + * The locks assume that the locks are thread safe. XXXmcs: which means??? + * + * Note that we test for both ld_mutex_lock_fn != NULL AND ld_mutex != NULL. + * This is necessary because there is a window in ldap_init() between the + * time we set the ld_mutex_lock_fn pointer and the time we allocate the + * mutexes in which external code COULD be called which COULD make a call to + * something like ldap_get_option(), which uses LDAP_MUTEX_LOCK(). The + * libprldap code does this in its newhandle callback (prldap_newhandle). + */ + +#define LDAP_MUTEX_LOCK(ld, lock) \ + if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \ + if ((ld)->ld_threadid_fn != NULL) { \ + if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \ + (ld)->ld_mutex_refcnt[lock]++; \ + } else { \ + (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \ + (ld)->ld_mutex_threadid[lock] = ld->ld_threadid_fn(); \ + (ld)->ld_mutex_refcnt[lock] = 1; \ + } \ + } else { \ + (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \ + } \ + } + +#define LDAP_MUTEX_UNLOCK(ld, lock) \ + if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \ + if ((ld)->ld_threadid_fn != NULL) { \ + if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \ + (ld)->ld_mutex_refcnt[lock]--; \ + if ((ld)->ld_mutex_refcnt[lock] <= 0) { \ + (ld)->ld_mutex_threadid[lock] = (void *) -1; \ + (ld)->ld_mutex_refcnt[lock] = 0; \ + (ld)->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \ + } \ + } \ + } else { \ + ld->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \ + } \ + } + +/* Backward compatibility locks */ +#define LDAP_MUTEX_BC_LOCK( ld, i ) \ + /* the ld_mutex_trylock_fn is always set to NULL */ \ + /* in setoption.c as the extra thread functions were */ \ + /* turned off in the 4.0 SDK. This check will */ \ + /* always be true */ \ + if( (ld)->ld_mutex_trylock_fn == NULL ) { \ + LDAP_MUTEX_LOCK( ld, i ) ; \ + } +#define LDAP_MUTEX_BC_UNLOCK( ld, i ) \ + /* the ld_mutex_trylock_fn is always set to NULL */ \ + /* in setoption.c as the extra thread functions were */ \ + /* turned off in the 4.0 SDK. This check will */ \ + /* always be true */ \ + if( (ld)->ld_mutex_trylock_fn == NULL ) { \ + LDAP_MUTEX_UNLOCK( ld, i ) ; \ + } + +/* allocate/free semaphore */ +#define LDAP_SEMA_ALLOC( ld ) \ + (((ld)->ld_sema_alloc_fn != NULL) ? (ld)->ld_sema_alloc_fn() : NULL) +#define LDAP_SEMA_FREE( ld, m ) \ + if ( (ld)->ld_sema_free_fn != NULL && m != NULL ) { \ + (ld)->ld_sema_free_fn( m ); \ + } + +/* wait/post binary semaphore */ +#define LDAP_SEMA_WAIT( ld, lp ) \ + if ( (ld)->ld_sema_wait_fn != NULL ) { \ + (ld)->ld_sema_wait_fn( lp->lp_sema ); \ + } +#define LDAP_SEMA_POST( ld, lp ) \ + if ( (ld)->ld_sema_post_fn != NULL ) { \ + (ld)->ld_sema_post_fn( lp->lp_sema ); \ + } +#define POST( ld, y, z ) \ + /* the ld_mutex_trylock_fn is always set to NULL */ \ + /* in setoption.c as the extra thread functions were */ \ + /* turned off in the 4.0 SDK. This check will */ \ + /* always be false */ \ + if( (ld)->ld_mutex_trylock_fn != NULL ) { \ + nsldapi_post_result( ld, y, z ); \ + } + +/* get/set errno */ +#ifndef macintosh +#define LDAP_SET_ERRNO( ld, e ) \ + if ( (ld)->ld_set_errno_fn != NULL ) { \ + (ld)->ld_set_errno_fn( e ); \ + } else { \ + errno = e; \ + } +#define LDAP_GET_ERRNO( ld ) \ + (((ld)->ld_get_errno_fn != NULL) ? \ + (ld)->ld_get_errno_fn() : errno) +#else /* macintosh */ +#define LDAP_SET_ERRNO( ld, e ) \ + if ( (ld)->ld_set_errno_fn != NULL ) { \ + (ld)->ld_set_errno_fn( e ); \ + } +#define LDAP_GET_ERRNO( ld ) \ + (((ld)->ld_get_errno_fn != NULL) ? \ + (ld)->ld_get_errno_fn() : 0) +#endif + + +/* get/set ldap-specific errno */ +#define LDAP_SET_LDERRNO( ld, e, m, s ) ldap_set_lderrno( ld, e, m, s ) +#define LDAP_GET_LDERRNO( ld, m, s ) ldap_get_lderrno( ld, m, s ) + +/* + * your standard "mimimum of two values" macro + */ +#define NSLDAPI_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +/* + * handy macro to check whether LDAP struct is set up for CLDAP or not + */ +#define LDAP_IS_CLDAP( ld ) ( ld->ld_sbp->sb_naddr > 0 ) + +/* + * Some Unix error defs. Under CW 7, we can't define OTUNIXERRORS because + * it generates many conflicts with errno.h. Define what we need here. + * These need to be in sync with OpenTransport.h + */ + +#if defined(macintosh) +#define EWOULDBLOCK 35 +#define EHOSTUNREACH 65 +#endif + +/* + * handy macro to check errno "e" for an "in progress" sort of error + */ +#if defined(macintosh) || defined(_WINDOWS) +#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EAGAIN) +#else +#ifdef EAGAIN +#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EINPROGRESS || (e) == EAGAIN) +#else /* EAGAIN */ +#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EINPROGRESS) +#endif /* EAGAIN */ +#endif /* macintosh || _WINDOWS*/ + +/* + * macro to return the LDAP protocol version we are using + */ +#define NSLDAPI_LDAP_VERSION( ld ) ( (ld)->ld_defconn == NULL ? \ + (ld)->ld_version : \ + (ld)->ld_defconn->lconn_version ) + +/* + * Structures used for handling client filter lists. + */ +#define LDAP_FILT_MAXSIZ 1024 + +struct ldap_filt_list { + char *lfl_tag; + char *lfl_pattern; + char *lfl_delims; + struct ldap_filt_info *lfl_ilist; + struct ldap_filt_list *lfl_next; +}; + +struct ldap_filt_desc { + LDAPFiltList *lfd_filtlist; + LDAPFiltInfo *lfd_curfip; + LDAPFiltInfo lfd_retfi; + char lfd_filter[ LDAP_FILT_MAXSIZ ]; + char *lfd_curval; + char *lfd_curvalcopy; + char **lfd_curvalwords; + char *lfd_filtprefix; + char *lfd_filtsuffix; +}; + +/* + * "internal" globals used to track defaults and memory allocation callbacks: + * (the actual definitions are in open.c) + */ +extern struct ldap nsldapi_ld_defaults; +extern struct ldap_memalloc_fns nsldapi_memalloc_fns; +extern int nsldapi_initialized; + + +/* + * Memory allocation done in liblber should all go through one of the + * following macros. This is so we can plug-in alternative memory + * allocators, etc. as the need arises. + */ +#define NSLDAPI_MALLOC( size ) ldap_x_malloc( size ) +#define NSLDAPI_CALLOC( nelem, elsize ) ldap_x_calloc( nelem, elsize ) +#define NSLDAPI_REALLOC( ptr, size ) ldap_x_realloc( ptr, size ) +#define NSLDAPI_FREE( ptr ) ldap_x_free( ptr ) + + +/* + * macros used to check validity of data structures and parameters + */ +#define NSLDAPI_VALID_LDAP_POINTER( ld ) \ + ( (ld) != NULL ) + +#define NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm ) \ + ( (lm) != NULL ) + +#define NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( lm ) \ + ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) + +#define NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( lm ) \ + ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) + +#define NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( lm ) \ + ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_BIND ) + +#define NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( lm ) \ + ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_EXTENDED ) + +#define NSLDAPI_VALID_LDAPMOD_ARRAY( mods ) \ + ( (mods) != NULL ) + +#define NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods ) \ + ( (mods) != NULL && (mods)[0] != NULL ) + +#define NSLDAPI_IS_SEARCH_ENTRY( code ) \ + ((code) == LDAP_RES_SEARCH_ENTRY) + +#define NSLDAPI_IS_SEARCH_RESULT( code ) \ + ((code) == LDAP_RES_SEARCH_RESULT) + +#define NSLDAPI_SEARCH_RELATED_RESULT( code ) \ + (NSLDAPI_IS_SEARCH_RESULT( code ) || NSLDAPI_IS_SEARCH_ENTRY( code )) + +/* + * in bind.c + */ +char *nsldapi_get_binddn( LDAP *ld ); + +/* + * in cache.c + */ +void nsldapi_add_result_to_cache( LDAP *ld, LDAPMessage *result ); + +/* + * in dsparse.c + */ +int nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp ); +void nsldapi_free_strarray( char **sap ); + +/* + * in error.c + */ +int nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, + int *errcodep, char **matchednp, char **errmsgp, char ***referralsp, + LDAPControl ***serverctrlsp ); + +/* + * in open.c + */ +void nsldapi_initialize_defaults( void ); +void nsldapi_mutex_alloc_all( LDAP *ld ); +void nsldapi_mutex_free_all( LDAP *ld ); +int nsldapi_open_ldap_defconn( LDAP *ld ); +char *nsldapi_strdup( const char *s ); /* if s is NULL, returns NULL */ + +/* + * in os-ip.c + */ +int nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, + int port, int secure, char **krbinstancep ); +void nsldapi_close_connection( LDAP *ld, Sockbuf *sb ); + +int nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout ); +void nsldapi_iostatus_free( LDAP *ld ); +int nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb ); +int nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb ); +int nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb ); +int nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb ); +int nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb ); +int nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb ); +int nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns ); + +/* + * if referral.c + */ +int nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp, + LDAPControl ***serverctrlsp ); + + +/* + * in result.c + */ +int ldap_msgdelete( LDAP *ld, int msgid ); +int nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted, + struct timeval *timeout, LDAPMessage **result ); +int nsldapi_wait_result( LDAP *ld, int msgid, int all, struct timeval *timeout, + LDAPMessage **result ); +int nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result ); + +/* + * in request.c + */ +int nsldapi_send_initial_request( LDAP *ld, int msgid, unsigned long msgtype, + char *dn, BerElement *ber ); +int nsldapi_send_pending_requests_nolock( LDAP *ld, LDAPConn *lc ); +int nsldapi_alloc_ber_with_options( LDAP *ld, BerElement **berp ); +void nsldapi_set_ber_options( LDAP *ld, BerElement *ber ); +int nsldapi_send_ber_message( LDAP *ld, Sockbuf *sb, BerElement *ber, + int freeit, int epipe_handler ); +int nsldapi_send_server_request( LDAP *ld, BerElement *ber, int msgid, + LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc, + char *bindreqdn, int bind ); +LDAPConn *nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, + int connect, int bind ); +LDAPRequest *nsldapi_find_request_by_msgid( LDAP *ld, int msgid ); +LDAPRequest *nsldapi_new_request( LDAPConn *lc, BerElement *ber, int msgid, + int expect_resp ); +void nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn ); +void nsldapi_queue_request_nolock( LDAP *ld, LDAPRequest *lr ); +void nsldapi_free_connection( LDAP *ld, LDAPConn *lc, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int force, int unbind ); +void nsldapi_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); +void nsldapi_dump_requests_and_responses( LDAP *ld ); +int nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, + int *totalcountp, int *chasingcountp ); +int nsldapi_chase_v3_refs( LDAP *ld, LDAPRequest *lr, char **refs, + int is_reference, int *totalcountp, int *chasingcountp ); +int nsldapi_append_referral( LDAP *ld, char **referralsp, char *s ); +void nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb ); + +#ifdef LDAP_SASLIO_HOOKS +/* + * in saslbind.c + */ +int nsldapi_sasl_is_inited(); +int nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg ); +int nsldapi_sasl_secprops( const char *in, + sasl_security_properties_t *secprops ); + +/* + * in saslio.c + */ +int nsldapi_sasl_install( LDAP *ld, LDAPConn *lconn ); +int nsldapi_sasl_open( LDAP *ld, LDAPConn *lconn, sasl_conn_t **ctx, sasl_ssf_t ssf ); + +#endif /* LDAP_SASLIO_HOOKS */ + +/* + * in search.c + */ +int nsldapi_build_search_req( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int timelimit, int sizelimit, int msgid, BerElement **berp ); + +/* + * in unbind.c + */ +int ldap_ld_free( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls, int close ); +int nsldapi_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **serverctrls, + LDAPControl **clientctrls ); + +#ifdef LDAP_DNS +/* + * in getdxbyname.c + */ +char **nsldapi_getdxbyname( char *domain ); + +#endif /* LDAP_DNS */ + +/* + * in unescape.c + */ +void nsldapi_hex_unescape( char *s ); + +/* + * in compat.c + */ +#ifdef hpux +char *nsldapi_compat_ctime_r( const time_t *clock, char *buf, int buflen ); +struct hostent *nsldapi_compat_gethostbyname_r( const char *name, + struct hostent *result, char *buffer, int buflen, int *h_errnop ); +#endif /* hpux */ + +/* + * in control.c + */ +int nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq, + BerElement *ber ); +int nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp ); +int nsldapi_find_controls( BerElement *ber, LDAPControl ***controlsp ); +int nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, + LDAPControl **newctrls ); +int nsldapi_build_control( char *oid, BerElement *ber, int freeber, + char iscritical, LDAPControl **ctrlp ); + + +/* + * in url.c + */ +int nsldapi_url_parse( const char *inurl, LDAPURLDesc **ludpp, + int dn_required ); + + +/* + * in charset.c + * + * If we ever want to expose character set translation functionality to + * users of libldap, all of these prototypes will need to be moved to ldap.h + */ +#ifdef STR_TRANSLATION +void ldap_set_string_translators( LDAP *ld, + BERTranslateProc encode_proc, BERTranslateProc decode_proc ); +int ldap_translate_from_t61( LDAP *ld, char **bufp, + unsigned long *lenp, int free_input ); +int ldap_translate_to_t61( LDAP *ld, char **bufp, + unsigned long *lenp, int free_input ); +void ldap_enable_translation( LDAP *ld, LDAPMessage *entry, + int enable ); +#ifdef LDAP_CHARSET_8859 +int ldap_t61_to_8859( char **bufp, unsigned long *buflenp, + int free_input ); +int ldap_8859_to_t61( char **bufp, unsigned long *buflenp, + int free_input ); +#endif /* LDAP_CHARSET_8859 */ +#endif /* STR_TRANSLATION */ + +/* + * in memcache.h + */ +int ldap_memcache_createkey( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + unsigned long *keyp ); +int ldap_memcache_result( LDAP *ld, int msgid, unsigned long key ); +int ldap_memcache_new( LDAP *ld, int msgid, unsigned long key, + const char *basedn ); +int ldap_memcache_append( LDAP *ld, int msgid, int bLast, LDAPMessage *result ); +int ldap_memcache_abandon( LDAP *ld, int msgid ); + +/* + * in sbind.c + */ +void nsldapi_handle_reconnect( LDAP *ld ); + +#endif /* _LDAPINT_H */ diff --git a/ldap/c-sdk/libldap/libldap.def b/ldap/c-sdk/libldap/libldap.def new file mode 100644 index 0000000000..dd79389a27 --- /dev/null +++ b/ldap/c-sdk/libldap/libldap.def @@ -0,0 +1,352 @@ +; +; ***** BEGIN LICENSE BLOCK ***** +; Version: MPL 1.1/GPL 2.0/LGPL 2. +; +; The contents of this file are subject to the Mozilla Public License Version +; 1.1 (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" basis, +; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +; for the specific language governing rights and limitations under the +; License. +; +; The Original Code is Mozilla Communicator client code. +; +; The Initial Developer of the Original Code is +; Netscape Communications Corporation. +; Portions created by the Initial Developer are Copyright (C) 1996-1999 +; the Initial Developer. All Rights Reserved. +; +; Contributor(s): +; +; Alternatively, the contents of this file may be used under the terms of +; either of the GNU General Public License Version 2 or later (the "GPL"), +; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +; in which case the provisions of the GPL or the LGPL are applicable instead +; of those above. If you wish to allow use of your version of this file only +; under the terms of either the GPL or the LGPL, and not to allow others to +; use your version of this file under the terms of the MPL, indicate your +; decision by deleting the provisions above and replace them with the notice +; and other provisions required by the GPL or the LGPL. If you do not delete +; the provisions above, a recipient may use your version of this file under +; the terms of any one of the MPL, the GPL or the LGPL. +; +; ***** END LICENSE BLOCK ***** + +LIBRARY LDAP60 +VERSION 6.0 +HEAPSIZE 4096 + +EXPORTS +; exports list (generated by genexports.pl) +; + ldap_abandon + ldap_add + ldap_unbind + +; ldap_enable_cache +; ldap_disable_cache +; ldap_destroy_cache +; ldap_flush_cache +; ldap_uncache_entry + + ldap_compare + ldap_delete + ldap_result2error + ldap_err2string + ldap_modify + ldap_modrdn + ldap_open + ldap_first_entry + ldap_next_entry + ldap_get_dn + ldap_dn2ufn + ldap_first_attribute + ldap_next_attribute + ldap_get_values + ldap_get_values_len + ldap_count_entries + ldap_count_values + ldap_value_free + ldap_explode_dn + ldap_result + ldap_msgfree + ldap_search + ldap_add_s + ldap_bind_s + ldap_unbind_s + ldap_delete_s + ldap_modify_s + ldap_modrdn_s + ldap_search_s + ldap_search_st + ldap_compare_s + ldap_ufn_search_c + ldap_ufn_search_s + ldap_init_getfilter + ldap_getfilter_free + ldap_getfirstfilter + ldap_getnextfilter + ldap_simple_bind + ldap_simple_bind_s + ldap_bind + ldap_friendly_name + ldap_free_friendlymap + ldap_ufn_search_ct + +; ldap_set_cache_options +; ldap_uncache_request + + ldap_modrdn2 + ldap_modrdn2_s + ldap_ufn_setfilter + ldap_ufn_setprefix + ldap_ufn_timeout + ldap_init_getfilter_buf + ldap_setfilteraffixes + ldap_sort_entries + ldap_sort_values + ldap_sort_strcasecmp + ldap_count_values_len + ldap_name2template + ldap_value_free_len + +; manually comment and uncomment these five as necessary +; ldap_kerberos_bind1 +; ldap_kerberos_bind2 +; ldap_kerberos_bind_s +; ldap_kerberos_bind1_s +; ldap_kerberos_bind2_s + + ldap_init + ldap_is_dns_dn + ldap_explode_dns + ldap_mods_free + + ldap_is_ldap_url + ldap_free_urldesc + ldap_url_parse + ldap_url_search + ldap_url_search_s + ldap_url_search_st + ldap_set_rebind_proc + ber_skip_tag + ber_peek_tag + ber_get_int + ber_get_stringb + ber_get_stringa + ber_get_stringal + ber_get_bitstringa + ber_get_null + ber_get_boolean + ber_first_element + ber_next_element + ber_scanf + ber_bvfree + ber_bvecfree + ber_put_int + ber_put_ostring + ber_put_string + ber_put_bitstring + ber_put_null + ber_put_boolean + ber_start_seq + ber_start_set + ber_put_seq + ber_put_set + ber_printf + ber_read + ber_write + ber_free + ber_flush + ber_alloc + ber_dup + ber_get_next + ber_get_tag + ber_put_enum + der_alloc + ber_alloc_t + ber_bvdup + ber_init_w_nullchar + ber_reset + ber_get_option + ber_set_option + ber_sockbuf_alloc + ber_sockbuf_get_option + ber_sockbuf_set_option + ber_init + ber_flatten + ber_special_alloc + ber_special_free + ber_get_next_buffer + ber_err_print + ber_sockbuf_free + ber_get_next_buffer_ext + ber_svecfree + ber_get_buf_datalen + ber_get_buf_databegin + ber_stack_init + ber_sockbuf_free_data + + ldap_memfree + ldap_ber_free + + ldap_init_searchprefs + ldap_init_searchprefs_buf + ldap_free_searchprefs + ldap_first_searchobj + ldap_next_searchobj + ldap_build_filter + + 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_entry2text_search + ldap_entry2text + ldap_vals2text + ldap_entry2html + ldap_entry2html_search + ldap_vals2html + ldap_tmplerr2string + ldap_set_option + ldap_get_option + ldap_charray_merge + ldap_get_lderrno + ldap_set_lderrno + ldap_perror + ldap_set_filter_additions + ldap_create_filter + ldap_version + ldap_multisort_entries + ldap_msgid + ldap_explode_rdn + ldap_msgtype + ldap_cache_flush + ldap_str2charray + ldap_charray_add + ldap_charray_dup + ldap_charray_free + +; Windows ordinals 450-469 are reserved for SSL routines + + ldap_charray_inlist + ldap_charray_position + ldap_rename + ldap_rename_s + ldap_utf8len + ldap_utf8next + ldap_utf8prev + ldap_utf8copy + ldap_utf8characters + ldap_utf8strtok_r + ldap_utf8isalnum + ldap_utf8isalpha + ldap_utf8isdigit + ldap_utf8isxdigit + ldap_utf8isspace + ldap_control_free + ldap_controls_free + ldap_sasl_bind + ldap_sasl_bind_s + ldap_parse_sasl_bind_result + ldap_sasl_interactive_bind_s + ldap_sasl_interactive_bind_ext_s +; LDAPv3 simple paging controls are not supported by Netscape at this time. +; 490 ldap_create_page_control +; 491 ldap_parse_page_control + ldap_create_sort_control + ldap_parse_sort_control +; an LDAPv3 language control was proposed but then retracted. +; 494 ldap_create_language_control + ldap_get_lang_values + ldap_get_lang_values_len + ldap_free_sort_keylist + ldap_create_sort_keylist + ldap_utf8getcc + ldap_get_entry_controls + ldap_create_persistentsearch_control + ldap_parse_entrychange_control + ldap_parse_result + ldap_parse_extended_result + ldap_parse_reference + ldap_abandon_ext + ldap_add_ext + ldap_add_ext_s + ldap_modify_ext + ldap_modify_ext_s + ldap_first_message + ldap_next_message + ldap_compare_ext + ldap_compare_ext_s + ldap_delete_ext + ldap_delete_ext_s + ldap_search_ext + ldap_search_ext_s + ldap_extended_operation + ldap_extended_operation_s + ldap_first_reference + ldap_next_reference + ldap_count_references + ldap_count_messages + ldap_create_virtuallist_control + ldap_parse_virtuallist_control + ldap_create_proxyauth_control + ldap_unbind_ext + ldap_x_hostlist_first + ldap_x_hostlist_next + ldap_x_hostlist_statusfree + ldap_x_malloc + ldap_x_calloc + ldap_x_realloc + ldap_x_free +; + ldap_create_proxiedauth_control +; + ldap_create_geteffectiveRights_control +; + ldap_find_control +; + ldap_url_parse_no_defaults +; + ldap_create_userstatus_control + ldap_parse_userstatus_control +; + ldap_create_passwordpolicy_control + ldap_create_passwordpolicy_control_ext + ldap_parse_passwordpolicy_control + ldap_parse_passwordpolicy_control_ext + ldap_passwordpolicy_err2txt +; + ldap_passwd + ldap_parse_passwd + ldap_passwd_s +; + ldap_delete_result_entry + ldap_add_result_entry +; + ldap_whoami + ldap_parse_whoami + ldap_whoami_s +; + ldap_create_authzid_control + ldap_parse_authzid_control +; + ldap_memcache_init + ldap_memcache_set + ldap_memcache_get + ldap_memcache_flush + ldap_memcache_destroy + ldap_memcache_update + ldap_keysort_entries +; +; end of generated exports list. diff --git a/ldap/c-sdk/libldap/memcache.c b/ldap/c-sdk/libldap/memcache.c new file mode 100644 index 0000000000..78943408aa --- /dev/null +++ b/ldap/c-sdk/libldap/memcache.c @@ -0,0 +1,2244 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * + * memcache.c - routines that implement an in-memory cache. + * + * To Do: 1) ber_dup_ext(). + * 2) referrals and reference? + */ + +#include +#include "ldap-int.h" + +/* + * Extra size allocated to BerElement. + * XXXmcs: must match EXBUFSIZ in liblber/io.c? + */ +#define EXTRA_SIZE 1024 + +/* Mode constants for function memcache_access() */ +#define MEMCACHE_ACCESS_ADD 0 +#define MEMCACHE_ACCESS_APPEND 1 +#define MEMCACHE_ACCESS_APPEND_LAST 2 +#define MEMCACHE_ACCESS_FIND 3 +#define MEMCACHE_ACCESS_DELETE 4 +#define MEMCACHE_ACCESS_DELETE_ALL 5 +#define MEMCACHE_ACCESS_UPDATE 6 +#define MEMCACHE_ACCESS_FLUSH 7 +#define MEMCACHE_ACCESS_FLUSH_ALL 8 +#define MEMCACHE_ACCESS_FLUSH_LRU 9 +#define MEMCACHE_ACCESS_FLUSH_RESULTS 10 + +/* Mode constants for function memcache_adj_size */ +#define MEMCACHE_SIZE_DEDUCT 0 +#define MEMCACHE_SIZE_ADD 1 + +#define MEMCACHE_SIZE_ENTRIES 1 +#define MEMCACHE_SIZE_NON_ENTRIES 2 + +/* Size used for calculation if given size of cache is 0 */ +#define MEMCACHE_DEF_SIZE 131072 /* 128K bytes */ + +/* Index into different list structure */ +#define LIST_TTL 0 +#define LIST_LRU 1 +#define LIST_TMP 2 +#define LIST_TOTAL 3 + +/* Macros to make code more readable */ +#define NSLDAPI_VALID_MEMCACHE_POINTER( cp ) ( (cp) != NULL ) +#define NSLDAPI_STR_NONNULL( s ) ( (s) ? (s) : "" ) +#define NSLDAPI_SAFE_STRLEN( s ) ( (s) ? strlen((s)) + 1 : 1 ) + +/* Macros dealing with mutex */ +#define LDAP_MEMCACHE_MUTEX_LOCK( c ) \ + if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_lock ) { \ + ((c)->ldmemc_lock_fns).ltf_mutex_lock( (c)->ldmemc_lock ); \ + } + +#define LDAP_MEMCACHE_MUTEX_UNLOCK( c ) \ + if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_unlock ) { \ + ((c)->ldmemc_lock_fns).ltf_mutex_unlock( (c)->ldmemc_lock ); \ + } + +#define LDAP_MEMCACHE_MUTEX_ALLOC( c ) \ + ((c) && ((c)->ldmemc_lock_fns).ltf_mutex_alloc ? \ + ((c)->ldmemc_lock_fns).ltf_mutex_alloc() : NULL) + +#define LDAP_MEMCACHE_MUTEX_FREE( c ) \ + if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_free ) { \ + ((c)->ldmemc_lock_fns).ltf_mutex_free( (c)->ldmemc_lock ); \ + } + +/* Macros used for triming unnecessary spaces in a basedn */ +#define NSLDAPI_IS_SPACE( c ) \ + (((c) == ' ') || ((c) == '\t') || ((c) == '\n')) + +#define NSLDAPI_IS_SEPARATER( c ) \ + ((c) == ',') + +/* Hash table callback function pointer definition */ +typedef int (*HashFuncPtr)(int table_size, void *key); +typedef int (*PutDataPtr)(void **ppTableData, void *key, void *pData); +typedef int (*GetDataPtr)(void *pTableData, void *key, void **ppData); +typedef int (*RemoveDataPtr)(void **ppTableData, void *key, void **ppData); +typedef int (*MiscFuncPtr)(void **ppTableData, void *key, void *pData); +typedef void (*ClrTableNodePtr)(void **ppTableData, void *pData); + +/* Structure of a node in a hash table */ +typedef struct HashTableNode_struct { + void *pData; +} HashTableNode; + +/* Structure of a hash table */ +typedef struct HashTable_struct { + HashTableNode *table; + int size; + HashFuncPtr hashfunc; + PutDataPtr putdata; + GetDataPtr getdata; + MiscFuncPtr miscfunc; + RemoveDataPtr removedata; + ClrTableNodePtr clrtablenode; +} HashTable; + +/* Structure uniquely identifies a search request */ +typedef struct ldapmemcacheReqId_struct { + LDAP *ldmemcrid_ld; + int ldmemcrid_msgid; +} ldapmemcacheReqId; + +/* Structure representing a ldap handle associated to memcache */ +typedef struct ldapmemcacheld_struct { + LDAP *ldmemcl_ld; + struct ldapmemcacheld_struct *ldmemcl_next; +} ldapmemcacheld; + +/* Structure representing header of a search result */ +typedef struct ldapmemcacheRes_struct { + char *ldmemcr_basedn; + unsigned long ldmemcr_crc_key; + unsigned long ldmemcr_resSize; + unsigned long ldmemcr_timestamp; + LDAPMessage *ldmemcr_resHead; + LDAPMessage *ldmemcr_resTail; + ldapmemcacheReqId ldmemcr_req_id; + struct ldapmemcacheRes_struct *ldmemcr_next[LIST_TOTAL]; + struct ldapmemcacheRes_struct *ldmemcr_prev[LIST_TOTAL]; + struct ldapmemcacheRes_struct *ldmemcr_htable_next; +} ldapmemcacheRes; + +/* Structure for memcache statistics */ +typedef struct ldapmemcacheStats_struct { + unsigned long ldmemcstat_tries; + unsigned long ldmemcstat_hits; +} ldapmemcacheStats; + +/* Structure of a memcache object */ +struct ldapmemcache { + unsigned long ldmemc_ttl; + unsigned long ldmemc_size; + unsigned long ldmemc_size_used; + unsigned long ldmemc_size_entries; + char **ldmemc_basedns; + void *ldmemc_lock; + ldapmemcacheld *ldmemc_lds; + HashTable *ldmemc_resTmp; + HashTable *ldmemc_resLookup; + ldapmemcacheRes *ldmemc_resHead[LIST_TOTAL]; + ldapmemcacheRes *ldmemc_resTail[LIST_TOTAL]; + struct ldap_thread_fns ldmemc_lock_fns; + ldapmemcacheStats ldmemc_stats; +}; + +/* Function prototypes */ +static int memcache_exist(LDAP *ld); +static int memcache_add_to_ld(LDAP *ld, int msgid, LDAPMessage *pMsg); +static int memcache_compare_dn(const char *main_dn, const char *dn, int scope); +static int memcache_dup_message(LDAPMessage *res, int msgid, int fromcache, + LDAPMessage **ppResCopy, unsigned long *pSize); +static BerElement* memcache_ber_dup(BerElement* pBer, unsigned long *pSize); + +static void memcache_trim_basedn_spaces(char *basedn); +static int memcache_validate_basedn(LDAPMemCache *cache, const char *basedn); +static int memcache_get_ctrls_len(LDAPControl **ctrls); +static void memcache_append_ctrls(char *buf, LDAPControl **serverCtrls, + LDAPControl **clientCtrls); +static int memcache_adj_size(LDAPMemCache *cache, unsigned long size, + int usageFlags, int bAdd); +static int memcache_free_entry(LDAPMemCache *cache, ldapmemcacheRes *pRes); +static int memcache_expired(LDAPMemCache *cache, ldapmemcacheRes *pRes, + unsigned long curTime); +static int memcache_add_to_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, + int index); +static int memcache_add_res_to_list(ldapmemcacheRes *pRes, LDAPMessage *pMsg, + unsigned long size); +static int memcache_free_from_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, + int index); +static int memcache_search(LDAP *ld, unsigned long key, LDAPMessage **ppRes); +static int memcache_add(LDAP *ld, unsigned long key, int msgid, + const char *basedn); +static int memcache_append(LDAP *ld, int msgid, LDAPMessage *pRes); +static int memcache_append_last(LDAP *ld, int msgid, LDAPMessage *pRes); +static int memcache_remove(LDAP *ld, int msgid); +#if 0 /* function not used */ +static int memcache_remove_all(LDAP *ld); +#endif /* 0 */ +static int memcache_access(LDAPMemCache *cache, int mode, + void *pData1, void *pData2, void *pData3); +static void memcache_flush(LDAPMemCache *cache, char *dn, int scope, + int flushresults); +#ifdef LDAP_DEBUG +static void memcache_print_list( LDAPMemCache *cache, int index ); +static void memcache_report_statistics( LDAPMemCache *cache ); +#endif /* LDAP_DEBUG */ + +static int htable_calculate_size(int sizelimit); +static int htable_sizeinbytes(HashTable *pTable); +static int htable_put(HashTable *pTable, void *key, void *pData); +static int htable_get(HashTable *pTable, void *key, void **ppData); +static int htable_misc(HashTable *pTable, void *key, void *pData); +static int htable_remove(HashTable *pTable, void *key, void **ppData); +static int htable_removeall(HashTable *pTable, void *pData); +static int htable_create(int size_limit, HashFuncPtr hashf, + PutDataPtr putDataf, GetDataPtr getDataf, + RemoveDataPtr removeDataf, ClrTableNodePtr clrNodef, + MiscFuncPtr miscOpf, HashTable **ppTable); +static int htable_free(HashTable *pTable); + +static int msgid_hashf(int table_size, void *key); +static int msgid_putdata(void **ppTableData, void *key, void *pData); +static int msgid_getdata(void *pTableData, void *key, void **ppData); +static int msgid_removedata(void **ppTableData, void *key, void **ppData); +static int msgid_clear_ld_items(void **ppTableData, void *key, void *pData); +static void msgid_clearnode(void **ppTableData, void *pData); + +static int attrkey_hashf(int table_size, void *key); +static int attrkey_putdata(void **ppTableData, void *key, void *pData); +static int attrkey_getdata(void *pTableData, void *key, void **ppData); +static int attrkey_removedata(void **ppTableData, void *key, void **ppData); +static void attrkey_clearnode(void **ppTableData, void *pData); + +static unsigned long crc32_convert(char *buf, int len); + +/* Create a memcache object. */ +int +LDAP_CALL +ldap_memcache_init( unsigned long ttl, unsigned long size, + char **baseDNs, struct ldap_thread_fns *thread_fns, + LDAPMemCache **cachep ) +{ + unsigned long total_size = 0; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_init\n", 0, 0, 0 ); + + if ( cachep == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + if ((*cachep = (LDAPMemCache*)NSLDAPI_CALLOC(1, + sizeof(LDAPMemCache))) == NULL) { + return ( LDAP_NO_MEMORY ); + } + + total_size += sizeof(LDAPMemCache); + + (*cachep)->ldmemc_ttl = ttl; + (*cachep)->ldmemc_size = size; + (*cachep)->ldmemc_lds = NULL; + + /* Non-zero default size needed for calculating size of hash tables */ + size = (size ? size : MEMCACHE_DEF_SIZE); + + if (thread_fns) { + memcpy(&((*cachep)->ldmemc_lock_fns), thread_fns, + sizeof(struct ldap_thread_fns)); + } else { + memset(&((*cachep)->ldmemc_lock_fns), 0, + sizeof(struct ldap_thread_fns)); + } + + (*cachep)->ldmemc_lock = LDAP_MEMCACHE_MUTEX_ALLOC( *cachep ); + + /* Cache basedns */ + if (baseDNs != NULL) { + + int i; + + for (i = 0; baseDNs[i]; i++) { + ; + } + + (*cachep)->ldmemc_basedns = (char**)NSLDAPI_CALLOC(i + 1, + sizeof(char*)); + + if ((*cachep)->ldmemc_basedns == NULL) { + ldap_memcache_destroy(*cachep); + *cachep = NULL; + return ( LDAP_NO_MEMORY ); + } + + total_size += (i + 1) * sizeof(char*); + + for (i = 0; baseDNs[i]; i++) { + (*cachep)->ldmemc_basedns[i] = nsldapi_strdup(baseDNs[i]); + total_size += strlen(baseDNs[i]) + 1; + } + + (*cachep)->ldmemc_basedns[i] = NULL; + } + + /* Create hash table for temporary cache */ + if (htable_create(size, msgid_hashf, msgid_putdata, msgid_getdata, + msgid_removedata, msgid_clearnode, msgid_clear_ld_items, + &((*cachep)->ldmemc_resTmp)) != LDAP_SUCCESS) { + ldap_memcache_destroy(*cachep); + *cachep = NULL; + return( LDAP_NO_MEMORY ); + } + + total_size += htable_sizeinbytes((*cachep)->ldmemc_resTmp); + + /* Create hash table for primary cache */ + if (htable_create(size, attrkey_hashf, attrkey_putdata, + attrkey_getdata, attrkey_removedata, attrkey_clearnode, + NULL, &((*cachep)->ldmemc_resLookup)) != LDAP_SUCCESS) { + ldap_memcache_destroy(*cachep); + *cachep = NULL; + return( LDAP_NO_MEMORY ); + } + + total_size += htable_sizeinbytes((*cachep)->ldmemc_resLookup); + + /* See if there is enough room so far */ + if (memcache_adj_size(*cachep, total_size, MEMCACHE_SIZE_NON_ENTRIES, + MEMCACHE_SIZE_ADD) != LDAP_SUCCESS) { + ldap_memcache_destroy(*cachep); + *cachep = NULL; + return( LDAP_SIZELIMIT_EXCEEDED ); + } + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_init new cache 0x%p\n", + *cachep, 0, 0 ); + + return( LDAP_SUCCESS ); +} + +/* Associates a ldap handle to a memcache object. */ +int +LDAP_CALL +ldap_memcache_set( LDAP *ld, LDAPMemCache *cache ) +{ + int nRes = LDAP_SUCCESS; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_set\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) + return( LDAP_PARAM_ERROR ); + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + + if (ld->ld_memcache != cache) { + + LDAPMemCache *c = ld->ld_memcache; + ldapmemcacheld *pCur = NULL; + ldapmemcacheld *pPrev = NULL; + + /* First dissociate handle from old cache */ + + LDAP_MEMCACHE_MUTEX_LOCK( c ); + + pCur = (c ? c->ldmemc_lds : NULL); + for (; pCur; pCur = pCur->ldmemcl_next) { + if (pCur->ldmemcl_ld == ld) + break; + pPrev = pCur; + } + + if (pCur) { + + ldapmemcacheReqId reqid; + + reqid.ldmemcrid_ld = ld; + reqid.ldmemcrid_msgid = -1; + htable_misc(c->ldmemc_resTmp, (void*)&reqid, (void*)c); + + if (pPrev) + pPrev->ldmemcl_next = pCur->ldmemcl_next; + else + c->ldmemc_lds = pCur->ldmemcl_next; + NSLDAPI_FREE(pCur); + pCur = NULL; + + memcache_adj_size(c, sizeof(ldapmemcacheld), + MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_DEDUCT); + } + + LDAP_MEMCACHE_MUTEX_UNLOCK( c ); + + ld->ld_memcache = NULL; + + /* Exit if no new cache is specified */ + if (cache == NULL) { + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + return( LDAP_SUCCESS ); + } + + /* Then associate handle with new cache */ + + LDAP_MEMCACHE_MUTEX_LOCK( cache ); + + if ((nRes = memcache_adj_size(cache, sizeof(ldapmemcacheld), + MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_ADD)) != LDAP_SUCCESS) { + LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + return nRes; + } + + pCur = (ldapmemcacheld*)NSLDAPI_CALLOC(1, sizeof(ldapmemcacheld)); + if (pCur == NULL) { + memcache_adj_size(cache, sizeof(ldapmemcacheld), + MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_DEDUCT); + nRes = LDAP_NO_MEMORY; + } else { + pCur->ldmemcl_ld = ld; + pCur->ldmemcl_next = cache->ldmemc_lds; + cache->ldmemc_lds = pCur; + ld->ld_memcache = cache; + } + + LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return nRes; +} + +/* Retrieves memcache with which the ldap handle has been associated. */ +int +LDAP_CALL +ldap_memcache_get( LDAP *ld, LDAPMemCache **cachep ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_get ld: 0x%p\n", ld, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || cachep == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + *cachep = ld->ld_memcache; + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return( LDAP_SUCCESS ); +} + +/* + * Function that stays inside libldap and proactively expires items from + * the given cache. This should be called from a newly created thread since + * it will not return until after ldap_memcache_destroy() is called. + */ +void +LDAP_CALL +ldap_memcache_update( LDAPMemCache *cache ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_update: cache 0x%p\n", + cache, 0, 0 ); + + if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { + return; + } + + LDAP_MEMCACHE_MUTEX_LOCK( cache ); + memcache_access(cache, MEMCACHE_ACCESS_UPDATE, NULL, NULL, NULL); + LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); +} + +/* Removes specified entries from given memcache. Only clears out search + results that included search entries. */ +void +LDAP_CALL +ldap_memcache_flush( LDAPMemCache *cache, char *dn, int scope ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_flush( cache: 0x%p, dn: %s, scope: %d)\n", + cache, ( dn == NULL ) ? "(null)" : dn, scope ); + memcache_flush(cache, dn, scope, 0 /* Don't use result flush mode */); +} + +/* Removes specified entries from given memcache, including search + results that returned no entries. */ +void +LDAP_CALL +ldap_memcache_flush_results( LDAPMemCache *cache, char *dn, int scope ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_flush_results( cache: 0x%p, dn: %s, scope: %d)\n", + cache, ( dn == NULL ) ? "(null)" : dn, scope ); + memcache_flush(cache, dn, scope, 1 /* Use result flush mode */); +} + +/* Destroys the given memcache. */ +void +LDAP_CALL +ldap_memcache_destroy( LDAPMemCache *cache ) +{ + int i = 0; + unsigned long size = sizeof(LDAPMemCache); + ldapmemcacheld *pNode = NULL, *pNextNode = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_destroy( 0x%p )\n", + cache, 0, 0 ); + + if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { + return; + } + + /* Dissociate all ldap handes from this cache. */ + LDAP_MEMCACHE_MUTEX_LOCK( cache ); + + for (pNode = cache->ldmemc_lds; pNode; pNode = pNextNode, i++) { + LDAP_MUTEX_LOCK( pNode->ldmemcl_ld, LDAP_MEMCACHE_LOCK ); + cache->ldmemc_lds = pNode->ldmemcl_next; + pNode->ldmemcl_ld->ld_memcache = NULL; + LDAP_MUTEX_UNLOCK( pNode->ldmemcl_ld, LDAP_MEMCACHE_LOCK ); + pNextNode = pNode->ldmemcl_next; + NSLDAPI_FREE(pNode); + } + + size += i * sizeof(ldapmemcacheld); + + LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); + + /* Free array of basedns */ + if (cache->ldmemc_basedns) { + for (i = 0; cache->ldmemc_basedns[i]; i++) { + size += strlen(cache->ldmemc_basedns[i]) + 1; + NSLDAPI_FREE(cache->ldmemc_basedns[i]); + } + size += (i + 1) * sizeof(char*); + NSLDAPI_FREE(cache->ldmemc_basedns); + } + + /* Free hash table used for temporary cache */ + if (cache->ldmemc_resTmp) { + size += htable_sizeinbytes(cache->ldmemc_resTmp); + memcache_access(cache, MEMCACHE_ACCESS_DELETE_ALL, NULL, NULL, NULL); + htable_free(cache->ldmemc_resTmp); + } + + /* Free hash table used for primary cache */ + if (cache->ldmemc_resLookup) { + size += htable_sizeinbytes(cache->ldmemc_resLookup); + memcache_access(cache, MEMCACHE_ACCESS_FLUSH_ALL, NULL, NULL, NULL); + htable_free(cache->ldmemc_resLookup); + } + + memcache_adj_size(cache, size, MEMCACHE_SIZE_NON_ENTRIES, + MEMCACHE_SIZE_DEDUCT); + + LDAP_MEMCACHE_MUTEX_FREE( cache ); + + NSLDAPI_FREE(cache); +} + +/************************* Internal API Functions ****************************/ + +/* Creates an integer key by applying the Cyclic Reduntency Check algorithm on + a long string formed by concatenating all the search parameters plus the + current bind DN. The key is used in the cache for looking up cached + entries. It is assumed that the CRC algorithm will generate + different integers from different byte strings. */ +int +ldap_memcache_createkey(LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, + int attrsonly, LDAPControl **serverctrls, + LDAPControl **clientctrls, unsigned long *keyp) +{ + int nRes, i, j, i_smallest; + int len; + int defport; + char buf[50]; + char *tmp, *defhost, *binddn, *keystr, *tmpbase; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (keyp == NULL) ) + return( LDAP_PARAM_ERROR ); + + *keyp = 0; + + if (!memcache_exist(ld)) + return( LDAP_LOCAL_ERROR ); + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); + nRes = memcache_validate_basedn(ld->ld_memcache, base); + LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + if (nRes != LDAP_SUCCESS) + return nRes; + + defhost = NSLDAPI_STR_NONNULL(ld->ld_defhost); + defport = ld->ld_defport; + tmpbase = nsldapi_strdup(NSLDAPI_STR_NONNULL(base)); + memcache_trim_basedn_spaces(tmpbase); + + if ((binddn = nsldapi_get_binddn(ld)) == NULL) + binddn = ""; + + sprintf(buf, "%i\n%i\n%i\n", defport, scope, (attrsonly ? 1 : 0)); + len = NSLDAPI_SAFE_STRLEN(buf) + NSLDAPI_SAFE_STRLEN(tmpbase) + + NSLDAPI_SAFE_STRLEN(filter) + NSLDAPI_SAFE_STRLEN(defhost) + + NSLDAPI_SAFE_STRLEN(binddn); + + if (attrs) { + for (i = 0; attrs[i]; i++) { + + for (i_smallest = j = i; attrs[j]; j++) { + if (strcasecmp(attrs[i_smallest], attrs[j]) > 0) + i_smallest = j; + } + + if (i != i_smallest) { + tmp = attrs[i]; + attrs[i] = attrs[i_smallest]; + attrs[i_smallest] = tmp; + } + + len += NSLDAPI_SAFE_STRLEN(attrs[i]); + } + } else { + len += 1; + } + + len += memcache_get_ctrls_len(serverctrls) + + memcache_get_ctrls_len(clientctrls) + 1; + + if ((keystr = (char*)NSLDAPI_CALLOC(len, sizeof(char))) == NULL) { + NSLDAPI_FREE(defhost); + return( LDAP_NO_MEMORY ); + } + + sprintf(keystr, "%s\n%s\n%s\n%s\n%s\n", binddn, tmpbase, + NSLDAPI_STR_NONNULL(defhost), NSLDAPI_STR_NONNULL(filter), + NSLDAPI_STR_NONNULL(buf)); + + if (attrs) { + for (i = 0; attrs[i]; i++) { + strcat(keystr, NSLDAPI_STR_NONNULL(attrs[i])); + strcat(keystr, "\n"); + } + } else { + strcat(keystr, "\n"); + } + + for (tmp = keystr; *tmp; + *tmp += (*tmp >= 'a' && *tmp <= 'z' ? 'A'-'a' : 0), tmp++) { + ; + } + + memcache_append_ctrls(keystr, serverctrls, clientctrls); + + /* CRC algorithm */ + *keyp = crc32_convert(keystr, len); + + NSLDAPI_FREE(keystr); + NSLDAPI_FREE(tmpbase); + + return LDAP_SUCCESS; +} + +/* Searches the cache for the right cached entries, and if found, attaches + them to the given ldap handle. This function relies on locking by the + caller. */ +int +ldap_memcache_result(LDAP *ld, int msgid, unsigned long key) +{ + int nRes; + LDAPMessage *pMsg = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_result( ld: 0x%p, msgid: %d, key: 0x%8.8lx)\n", + ld, msgid, key ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (msgid < 0) ) { + return( LDAP_PARAM_ERROR ); + } + + if (!memcache_exist(ld)) { + return( LDAP_LOCAL_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); + + /* Search the cache and append the results to ld if found */ + ++ld->ld_memcache->ldmemc_stats.ldmemcstat_tries; + if ((nRes = memcache_search(ld, key, &pMsg)) == LDAP_SUCCESS) { + nRes = memcache_add_to_ld(ld, msgid, pMsg); + ++ld->ld_memcache->ldmemc_stats.ldmemcstat_hits; + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_result: key 0x%8.8lx found in cache\n", + key, 0, 0 ); + } else { + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_result: key 0x%8.8lx not found in cache\n", + key, 0, 0 ); + } + +#ifdef LDAP_DEBUG + memcache_print_list( ld->ld_memcache, LIST_LRU ); + memcache_report_statistics( ld->ld_memcache ); +#endif /* LDAP_DEBUG */ + + LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return nRes; +} + +/* Creates a new header in the cache so that entries arriving from the + directory server can later be cached under the header. */ +int +ldap_memcache_new(LDAP *ld, int msgid, unsigned long key, const char *basedn) +{ + int nRes; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + + if (!memcache_exist(ld)) { + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + return( LDAP_LOCAL_ERROR ); + } + + LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); + nRes = memcache_add(ld, key, msgid, basedn); + LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return nRes; +} + +/* Appends a chain of entries to an existing cache header. Parameter "bLast" + indicates whether there will be more entries arriving for the search in + question. */ +int +ldap_memcache_append(LDAP *ld, int msgid, int bLast, LDAPMessage *result) +{ + int nRes = LDAP_SUCCESS; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_append( ld: 0x%p, ", ld, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "msgid %d, bLast: %d, result: 0x%p)\n", + msgid, bLast, result ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || !result ) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + + if (!memcache_exist(ld)) { + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + return( LDAP_LOCAL_ERROR ); + } + + LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); + + if (!bLast) + nRes = memcache_append(ld, msgid, result); + else + nRes = memcache_append_last(ld, msgid, result); + + LDAPDebug( LDAP_DEBUG_TRACE, + "ldap_memcache_append: %s result for msgid %d\n", + ( nRes == LDAP_SUCCESS ) ? "added" : "failed to add", msgid , 0 ); + + LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return nRes; +} + +/* Removes partially cached results for a search as a result of calling + ldap_abandon() by the client. */ +int +ldap_memcache_abandon(LDAP *ld, int msgid) +{ + int nRes; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (msgid < 0) ) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); + + if (!memcache_exist(ld)) { + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + return( LDAP_LOCAL_ERROR ); + } + + LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); + nRes = memcache_remove(ld, msgid); + LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); + LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); + + return nRes; +} + +/*************************** helper functions *******************************/ + +/* Removes extraneous spaces in a basedn so that basedns differ by only those + spaces will be treated as equal. Extraneous spaces are those that + precedes the basedn and those that follow a comma. */ +/* + * XXXmcs: this is a bit too agressive... we need to deal with the fact that + * commas and spaces may be quoted, in which case it is wrong to remove them. + */ +static void +memcache_trim_basedn_spaces(char *basedn) +{ + char *pRead, *pWrite; + + if (!basedn) + return; + + for (pWrite = pRead = basedn; *pRead; ) { + for (; *pRead && NSLDAPI_IS_SPACE(*pRead); pRead++) { + ; + } + for (; *pRead && !NSLDAPI_IS_SEPARATER(*pRead); + *(pWrite++) = *(pRead++)) { + ; + } + *(pWrite++) = (*pRead ? *(pRead++) : *pRead); + } +} + +/* Verifies whether the results of a search should be cached or not by + checking if the search's basedn falls under any of the basedns for which + the memcache is responsible. */ +static int +memcache_validate_basedn(LDAPMemCache *cache, const char *basedn) +{ + int i; + + if ( cache->ldmemc_basedns == NULL ) { + return( LDAP_SUCCESS ); + } + +#if 1 + if (basedn == NULL) { + basedn = ""; + } +#else + /* XXXmcs: I do not understand this code... */ + if (basedn == NULL) + return (cache->ldmemc_basedns && cache->ldmemc_basedns[0] ? + LDAP_OPERATIONS_ERROR : LDAP_SUCCESS); + } +#endif + + for (i = 0; cache->ldmemc_basedns[i]; i++) { + if (memcache_compare_dn(basedn, cache->ldmemc_basedns[i], + LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE) { + return( LDAP_SUCCESS ); + } + } + + return( LDAP_OPERATIONS_ERROR ); +} + +/* Calculates the length of the buffer needed to concatenate the contents of + a ldap control. */ +static int +memcache_get_ctrls_len(LDAPControl **ctrls) +{ + int len = 0, i; + + if (ctrls) { + for (i = 0; ctrls[i]; i++) { + len += strlen(NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)) + + (ctrls[i]->ldctl_value).bv_len + 4; + } + } + + return len; +} + +/* Contenates the contents of client and server controls to a buffer. */ +static void +memcache_append_ctrls(char *buf, LDAPControl **serverCtrls, + LDAPControl **clientCtrls) +{ + int i, j; + char *pCh = buf + strlen(buf); + LDAPControl **ctrls; + + for (j = 0; j < 2; j++) { + + if ((ctrls = (j ? clientCtrls : serverCtrls)) == NULL) + continue; + + for (i = 0; ctrls[i]; i++) { + sprintf(pCh, "%s\n", NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)); + pCh += strlen(NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)) + 1; + if ((ctrls[i]->ldctl_value).bv_len > 0) { + memcpy(pCh, (ctrls[i]->ldctl_value).bv_val, + (ctrls[i]->ldctl_value).bv_len); + pCh += (ctrls[i]->ldctl_value).bv_len; + } + sprintf(pCh, "\n%i\n", (ctrls[i]->ldctl_iscritical ? 1 : 0)); + pCh += 3; + } + } +} + +/* Increases or decreases the size (in bytes) the given memcache currently + uses. If the size goes over the limit, the function returns an error. */ +static int +memcache_adj_size(LDAPMemCache *cache, unsigned long size, + int usageFlags, int bAdd) +{ + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_adj_size: attempting to %s %ld %s bytes...\n", + bAdd ? "add" : "remove", size, + ( usageFlags & MEMCACHE_SIZE_ENTRIES ) ? "entry" : "non-entry" ); + + if (bAdd) { + cache->ldmemc_size_used += size; + if ((cache->ldmemc_size > 0) && + (cache->ldmemc_size_used > cache->ldmemc_size)) { + + if (size > cache->ldmemc_size_entries) { + cache->ldmemc_size_used -= size; + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_adj_size: failed (size > size_entries %ld).\n", + cache->ldmemc_size_entries, 0, 0 ); + return( LDAP_SIZELIMIT_EXCEEDED ); + } + + while (cache->ldmemc_size_used > cache->ldmemc_size) { + if (memcache_access(cache, MEMCACHE_ACCESS_FLUSH_LRU, + NULL, NULL, NULL) != LDAP_SUCCESS) { + cache->ldmemc_size_used -= size; + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_adj_size: failed (LRU flush failed).\n", + 0, 0, 0 ); + return( LDAP_SIZELIMIT_EXCEEDED ); + } + } + } + if (usageFlags & MEMCACHE_SIZE_ENTRIES) + cache->ldmemc_size_entries += size; + } else { + cache->ldmemc_size_used -= size; + assert(cache->ldmemc_size_used >= 0); + if (usageFlags & MEMCACHE_SIZE_ENTRIES) + cache->ldmemc_size_entries -= size; + } + +#ifdef LDAP_DEBUG + if ( cache->ldmemc_size == 0 ) { /* no size limit */ + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_adj_size: succeeded (new size: %ld bytes).\n", + cache->ldmemc_size_used, 0, 0 ); + } else { + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_adj_size: succeeded (new size: %ld bytes, " + "free space: %ld bytes).\n", cache->ldmemc_size_used, + cache->ldmemc_size - cache->ldmemc_size_used, 0 ); + } +#endif /* LDAP_DEBUG */ + + return( LDAP_SUCCESS ); +} + +/* Searches the cache for results for a particular search identified by + parameter "key", which was generated ldap_memcache_createkey(). */ +static int +memcache_search(LDAP *ld, unsigned long key, LDAPMessage **ppRes) +{ + int nRes; + ldapmemcacheRes *pRes; + + *ppRes = NULL; + + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + nRes = memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_FIND, + (void*)&key, (void*)(&pRes), NULL); + + if (nRes != LDAP_SUCCESS) + return nRes; + + *ppRes = pRes->ldmemcr_resHead; + assert((pRes->ldmemcr_req_id).ldmemcrid_msgid == -1); + + return( LDAP_SUCCESS ); +} + +/* Adds a new header into the cache as a place holder for entries + arriving later. */ +static int +memcache_add(LDAP *ld, unsigned long key, int msgid, + const char *basedn) +{ + ldapmemcacheReqId reqid; + + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + reqid.ldmemcrid_msgid = msgid; + reqid.ldmemcrid_ld = ld; + + return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_ADD, + (void*)&key, (void*)&reqid, (void*)basedn); +} + +/* Appends search entries arriving from the dir server to the cache. */ +static int +memcache_append(LDAP *ld, int msgid, LDAPMessage *pRes) +{ + ldapmemcacheReqId reqid; + + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + reqid.ldmemcrid_msgid = msgid; + reqid.ldmemcrid_ld = ld; + + return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_APPEND, + (void*)&reqid, (void*)pRes, NULL); +} + +/* Same as memcache_append(), but the entries being appended are the + last from the dir server. Once all entries for a search have arrived, + the entries are moved from secondary to primary cache, and a time + stamp is given to the entries. */ +static int +memcache_append_last(LDAP *ld, int msgid, LDAPMessage *pRes) +{ + ldapmemcacheReqId reqid; + + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + reqid.ldmemcrid_msgid = msgid; + reqid.ldmemcrid_ld = ld; + + return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_APPEND_LAST, + (void*)&reqid, (void*)pRes, NULL); +} + +/* Removes entries from the temporary cache. */ +static int +memcache_remove(LDAP *ld, int msgid) +{ + ldapmemcacheReqId reqid; + + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + reqid.ldmemcrid_msgid = msgid; + reqid.ldmemcrid_ld = ld; + + return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_DELETE, + (void*)&reqid, NULL, NULL); +} + +#if 0 /* this function is not used */ +/* Wipes out everything in the temporary cache directory. */ +static int +memcache_remove_all(LDAP *ld) +{ + if (!memcache_exist(ld)) + return LDAP_LOCAL_ERROR; + + return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_DELETE_ALL, + NULL, NULL, NULL); +} +#endif /* 0 */ + +/* Returns TRUE or FALSE */ +static int +memcache_exist(LDAP *ld) +{ + return (ld->ld_memcache != NULL); +} + +/* Attaches cached entries to an ldap handle. */ +static int +memcache_add_to_ld(LDAP *ld, int msgid, LDAPMessage *pMsg) +{ + int nRes = LDAP_SUCCESS; + LDAPMessage **r; + LDAPMessage *pCopy; + + nRes = memcache_dup_message(pMsg, msgid, 1, &pCopy, NULL); + if (nRes != LDAP_SUCCESS) + return nRes; + + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + + for (r = &(ld->ld_responses); *r; r = &((*r)->lm_next)) + if ((*r)->lm_msgid == msgid) + break; + + if (*r) + for (r = &((*r)->lm_chain); *r; r = &((*r)->lm_chain)) { + ; + } + + *r = pCopy; + + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + + return nRes; +} + +/* Check if main_dn is included in {dn, scope} */ +static int +memcache_compare_dn(const char *main_dn, const char *dn, int scope) +{ + int nRes; + char **components = NULL; + char **main_components = NULL; + + components = ldap_explode_dn(dn, 0); + main_components = ldap_explode_dn(main_dn, 0); + + if (!components || !main_components) { + nRes = LDAP_COMPARE_TRUE; + } + else { + + int i, main_i; + + main_i = ldap_count_values(main_components) - 1; + i = ldap_count_values(components) - 1; + + for (; i >= 0 && main_i >= 0; i--, main_i--) { + if (strcasecmp(main_components[main_i], components[i])) + break; + } + + if (i >= 0 && main_i >= 0) { + nRes = LDAP_COMPARE_FALSE; + } + else if (i < 0 && main_i < 0) { + if (scope != LDAP_SCOPE_ONELEVEL) + nRes = LDAP_COMPARE_TRUE; + else + nRes = LDAP_COMPARE_FALSE; + } + else if (main_i < 0) { + nRes = LDAP_COMPARE_FALSE; + } + else { + if (scope == LDAP_SCOPE_BASE) + nRes = LDAP_COMPARE_FALSE; + else if (scope == LDAP_SCOPE_SUBTREE) + nRes = LDAP_COMPARE_TRUE; + else if (main_i == 0) + nRes = LDAP_COMPARE_TRUE; + else + nRes = LDAP_COMPARE_FALSE; + } + } + + if (components) + ldap_value_free(components); + + if (main_components) + ldap_value_free(main_components); + + return nRes; +} + +/* Dup a complete separate copy of a berelement, including the buffers + the berelement points to. */ +static BerElement* +memcache_ber_dup(BerElement* pBer, unsigned long *pSize) +{ + BerElement *p = ber_dup(pBer); + + *pSize = 0; + + if (p) { + + *pSize += sizeof(BerElement) + EXTRA_SIZE; + + if (p->ber_len <= EXTRA_SIZE) { + p->ber_flags |= LBER_FLAG_NO_FREE_BUFFER; + p->ber_buf = (char*)p + sizeof(BerElement); + } else { + p->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; + p->ber_buf = (char*)NSLDAPI_CALLOC(1, p->ber_len); + *pSize += (p->ber_buf ? p->ber_len : 0); + } + + if (p->ber_buf) { + p->ber_ptr = p->ber_buf + (pBer->ber_ptr - pBer->ber_buf); + p->ber_end = p->ber_buf + p->ber_len; + memcpy(p->ber_buf, pBer->ber_buf, p->ber_len); + } else { + ber_free(p, 0); + p = NULL; + *pSize = 0; + } + } + + return p; +} + +/* Dup a entry or a chain of entries. */ +static int +memcache_dup_message(LDAPMessage *res, int msgid, int fromcache, + LDAPMessage **ppResCopy, unsigned long *pSize) +{ + int nRes = LDAP_SUCCESS; + unsigned long ber_size; + LDAPMessage *pCur; + LDAPMessage **ppCurNew; + + *ppResCopy = NULL; + + if (pSize) + *pSize = 0; + + /* Make a copy of res */ + for (pCur = res, ppCurNew = ppResCopy; pCur; + pCur = pCur->lm_chain, ppCurNew = &((*ppCurNew)->lm_chain)) { + + if ((*ppCurNew = (LDAPMessage*)NSLDAPI_CALLOC(1, + sizeof(LDAPMessage))) == NULL) { + nRes = LDAP_NO_MEMORY; + break; + } + + memcpy(*ppCurNew, pCur, sizeof(LDAPMessage)); + (*ppCurNew)->lm_next = NULL; + (*ppCurNew)->lm_ber = memcache_ber_dup(pCur->lm_ber, &ber_size); + (*ppCurNew)->lm_msgid = msgid; + (*ppCurNew)->lm_fromcache = (fromcache != 0); + + if (pSize) + *pSize += sizeof(LDAPMessage) + ber_size; + } + + if ((nRes != LDAP_SUCCESS) && (*ppResCopy != NULL)) { + ldap_msgfree(*ppResCopy); + *ppResCopy = NULL; + if (pSize) + *pSize = 0; + } + + return nRes; +} + +/************************* Cache Functions ***********************/ + +/* Frees a cache header. */ +static int +memcache_free_entry(LDAPMemCache *cache, ldapmemcacheRes *pRes) +{ + if (pRes) { + + unsigned long size = sizeof(ldapmemcacheRes); + + if (pRes->ldmemcr_basedn) { + size += strlen(pRes->ldmemcr_basedn) + 1; + NSLDAPI_FREE(pRes->ldmemcr_basedn); + } + + if (pRes->ldmemcr_resHead) { + size += pRes->ldmemcr_resSize; + ldap_msgfree(pRes->ldmemcr_resHead); + } + + NSLDAPI_FREE(pRes); + + memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, + MEMCACHE_SIZE_DEDUCT); + } + + return( LDAP_SUCCESS ); +} + +/* Detaches a cache header from the list of headers. */ +static int +memcache_free_from_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, int index) +{ + if (pRes->ldmemcr_prev[index]) + pRes->ldmemcr_prev[index]->ldmemcr_next[index] = + pRes->ldmemcr_next[index]; + + if (pRes->ldmemcr_next[index]) + pRes->ldmemcr_next[index]->ldmemcr_prev[index] = + pRes->ldmemcr_prev[index]; + + if (cache->ldmemc_resHead[index] == pRes) + cache->ldmemc_resHead[index] = pRes->ldmemcr_next[index]; + + if (cache->ldmemc_resTail[index] == pRes) + cache->ldmemc_resTail[index] = pRes->ldmemcr_prev[index]; + + pRes->ldmemcr_prev[index] = NULL; + pRes->ldmemcr_next[index] = NULL; + + return( LDAP_SUCCESS ); +} + +/* Inserts a new cache header to a list of headers. */ +static int +memcache_add_to_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, int index) +{ + if (cache->ldmemc_resHead[index]) + cache->ldmemc_resHead[index]->ldmemcr_prev[index] = pRes; + else + cache->ldmemc_resTail[index] = pRes; + + pRes->ldmemcr_prev[index] = NULL; + pRes->ldmemcr_next[index] = cache->ldmemc_resHead[index]; + cache->ldmemc_resHead[index] = pRes; + + return( LDAP_SUCCESS ); +} + +/* Appends a chain of entries to the given cache header. */ +static int +memcache_add_res_to_list(ldapmemcacheRes *pRes, LDAPMessage *pMsg, + unsigned long size) +{ + if (pRes->ldmemcr_resTail) + pRes->ldmemcr_resTail->lm_chain = pMsg; + else + pRes->ldmemcr_resHead = pMsg; + + for (pRes->ldmemcr_resTail = pMsg; + pRes->ldmemcr_resTail->lm_chain; + pRes->ldmemcr_resTail = pRes->ldmemcr_resTail->lm_chain) { + ; + } + + pRes->ldmemcr_resSize += size; + + return( LDAP_SUCCESS ); +} + + +#ifdef LDAP_DEBUG +static void +memcache_print_list( LDAPMemCache *cache, int index ) +{ + char *name; + ldapmemcacheRes *restmp; + + switch( index ) { + case LIST_TTL: + name = "TTL"; + break; + case LIST_LRU: + name = "LRU"; + break; + case LIST_TMP: + name = "TMP"; + break; + case LIST_TOTAL: + name = "TOTAL"; + break; + default: + name = "unknown"; + } + + LDAPDebug( LDAP_DEBUG_TRACE, "memcache 0x%p %s list:\n", + cache, name, 0 ); + for ( restmp = cache->ldmemc_resHead[index]; restmp != NULL; + restmp = restmp->ldmemcr_next[index] ) { + LDAPDebug( LDAP_DEBUG_TRACE, + " key: 0x%8.8lx, ld: 0x%p, msgid: %d\n", + restmp->ldmemcr_crc_key, + restmp->ldmemcr_req_id.ldmemcrid_ld, + restmp->ldmemcr_req_id.ldmemcrid_msgid ); + } + LDAPDebug( LDAP_DEBUG_TRACE, "memcache 0x%p end of %s list.\n", + cache, name, 0 ); +} +#endif /* LDAP_DEBUG */ + +/* Tells whether a cached result has expired. */ +static int +memcache_expired(LDAPMemCache *cache, ldapmemcacheRes *pRes, + unsigned long curTime) +{ + if (!cache->ldmemc_ttl) + return 0; + + return ((unsigned long)difftime( + (time_t)curTime, + (time_t)(pRes->ldmemcr_timestamp)) >= + cache->ldmemc_ttl); +} + +/* Operates the cache in a central place. */ +static int +memcache_access(LDAPMemCache *cache, int mode, + void *pData1, void *pData2, void *pData3) +{ + int nRes = LDAP_SUCCESS; + unsigned long size = 0; + + /* Add a new cache header to the cache. */ + if (mode == MEMCACHE_ACCESS_ADD) { + unsigned long key = *((unsigned long*)pData1); + char *basedn = (char*)pData3; + ldapmemcacheRes *pRes = NULL; + void* hashResult = NULL; + + nRes = htable_get(cache->ldmemc_resTmp, pData2, &hashResult); + if (nRes == LDAP_SUCCESS) + return( LDAP_ALREADY_EXISTS ); + + pRes = (ldapmemcacheRes*)NSLDAPI_CALLOC(1, sizeof(ldapmemcacheRes)); + if (pRes == NULL) + return( LDAP_NO_MEMORY ); + + pRes->ldmemcr_crc_key = key; + pRes->ldmemcr_req_id = *((ldapmemcacheReqId*)pData2); + pRes->ldmemcr_basedn = (basedn ? nsldapi_strdup(basedn) : NULL); + + size += sizeof(ldapmemcacheRes) + strlen(basedn) + 1; + nRes = memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, + MEMCACHE_SIZE_ADD); + if (nRes == LDAP_SUCCESS) + nRes = htable_put(cache->ldmemc_resTmp, pData2, (void*)pRes); + if (nRes == LDAP_SUCCESS) + memcache_add_to_list(cache, pRes, LIST_TMP); + else + memcache_free_entry(cache, pRes); + } + /* Append entries to an existing cache header. */ + else if ((mode == MEMCACHE_ACCESS_APPEND) || + (mode == MEMCACHE_ACCESS_APPEND_LAST)) { + + LDAPMessage *pMsg = (LDAPMessage*)pData2; + LDAPMessage *pCopy = NULL; + ldapmemcacheRes *pRes = NULL; + void* hashResult = NULL; + + nRes = htable_get(cache->ldmemc_resTmp, pData1, &hashResult); + if (nRes != LDAP_SUCCESS) + return nRes; + + pRes = (ldapmemcacheRes*) hashResult; + nRes = memcache_dup_message(pMsg, pMsg->lm_msgid, 0, &pCopy, &size); + if (nRes != LDAP_SUCCESS) { + nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TMP); + memcache_free_entry(cache, pRes); + return nRes; + } + + nRes = memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, + MEMCACHE_SIZE_ADD); + if (nRes != LDAP_SUCCESS) { + ldap_msgfree(pCopy); + nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TMP); + memcache_free_entry(cache, pRes); + return nRes; + } + + memcache_add_res_to_list(pRes, pCopy, size); + + if (mode == MEMCACHE_ACCESS_APPEND) + return( LDAP_SUCCESS ); + + nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TMP); + (pRes->ldmemcr_req_id).ldmemcrid_ld = NULL; + (pRes->ldmemcr_req_id).ldmemcrid_msgid = -1; + pRes->ldmemcr_timestamp = (unsigned long)time(NULL); + + if ((nRes = htable_put(cache->ldmemc_resLookup, + (void*)&(pRes->ldmemcr_crc_key), + (void*)pRes)) == LDAP_SUCCESS) { + memcache_add_to_list(cache, pRes, LIST_TTL); + memcache_add_to_list(cache, pRes, LIST_LRU); + } else { + memcache_free_entry(cache, pRes); + } + } + /* Search for cached entries for a particular search. */ + else if (mode == MEMCACHE_ACCESS_FIND) { + + ldapmemcacheRes **ppRes = (ldapmemcacheRes**)pData2; + + nRes = htable_get(cache->ldmemc_resLookup, pData1, (void**)ppRes); + if (nRes != LDAP_SUCCESS) + return nRes; + + if (!memcache_expired(cache, *ppRes, (unsigned long)time(0))) { + memcache_free_from_list(cache, *ppRes, LIST_LRU); + memcache_add_to_list(cache, *ppRes, LIST_LRU); + return( LDAP_SUCCESS ); + } + + nRes = htable_remove(cache->ldmemc_resLookup, pData1, NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, *ppRes, LIST_TTL); + memcache_free_from_list(cache, *ppRes, LIST_LRU); + memcache_free_entry(cache, *ppRes); + nRes = LDAP_NO_SUCH_OBJECT; + *ppRes = NULL; + } + /* Remove cached entries in the temporary cache. */ + else if (mode == MEMCACHE_ACCESS_DELETE) { + + void* hashResult = NULL; + + if ((nRes = htable_remove(cache->ldmemc_resTmp, pData1, + &hashResult)) == LDAP_SUCCESS) { + ldapmemcacheRes *pCurRes = (ldapmemcacheRes*) hashResult; + memcache_free_from_list(cache, pCurRes, LIST_TMP); + memcache_free_entry(cache, pCurRes); + } + } + /* Wipe out the temporary cache. */ + else if (mode == MEMCACHE_ACCESS_DELETE_ALL) { + + nRes = htable_removeall(cache->ldmemc_resTmp, (void*)cache); + } + /* Remove expired entries from primary cache. */ + else if (mode == MEMCACHE_ACCESS_UPDATE) { + + ldapmemcacheRes *pCurRes = cache->ldmemc_resTail[LIST_TTL]; + unsigned long curTime = (unsigned long)time(NULL); + + for (; pCurRes; pCurRes = cache->ldmemc_resTail[LIST_TTL]) { + + if (!memcache_expired(cache, pCurRes, curTime)) + break; + + nRes = htable_remove(cache->ldmemc_resLookup, + (void*)&(pCurRes->ldmemcr_crc_key), NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pCurRes, LIST_TTL); + memcache_free_from_list(cache, pCurRes, LIST_LRU); + memcache_free_entry(cache, pCurRes); + } + } + /* Wipe out the primary cache. */ + else if (mode == MEMCACHE_ACCESS_FLUSH_ALL) { + + ldapmemcacheRes *pCurRes = cache->ldmemc_resHead[LIST_TTL]; + + nRes = htable_removeall(cache->ldmemc_resLookup, (void*)cache); + + for (; pCurRes; pCurRes = cache->ldmemc_resHead[LIST_TTL]) { + memcache_free_from_list(cache, pCurRes, LIST_LRU); + cache->ldmemc_resHead[LIST_TTL] = + cache->ldmemc_resHead[LIST_TTL]->ldmemcr_next[LIST_TTL]; + memcache_free_entry(cache, pCurRes); + } + cache->ldmemc_resTail[LIST_TTL] = NULL; + } + /* Remove cached entries in both primary and temporary cache. */ + else if ((mode == MEMCACHE_ACCESS_FLUSH) || + (mode == MEMCACHE_ACCESS_FLUSH_RESULTS)) { + + int i, list_id, bDone; + int scope = (int)pData2; + char *dn = (char*)pData1; + char *dnTmp; + BerElement ber; + LDAPMessage *pMsg; + ldapmemcacheRes *pRes; + + if (cache->ldmemc_basedns) { + for (i = 0; cache->ldmemc_basedns[i]; i++) { + if ((memcache_compare_dn(cache->ldmemc_basedns[i], dn, + LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE) || + (memcache_compare_dn(dn, cache->ldmemc_basedns[i], + LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE)) + break; + } + if (cache->ldmemc_basedns[i] == NULL) + return( LDAP_SUCCESS ); + } + + for (i = 0; i < 2; i++) { + + list_id = (i == 0 ? LIST_TTL : LIST_TMP); + + for (pRes = cache->ldmemc_resHead[list_id]; pRes != NULL; + pRes = pRes->ldmemcr_next[list_id]) { + + int foundentries = 0; + + if ((memcache_compare_dn(pRes->ldmemcr_basedn, dn, + LDAP_SCOPE_SUBTREE) != LDAP_COMPARE_TRUE) && + (memcache_compare_dn(dn, pRes->ldmemcr_basedn, + LDAP_SCOPE_SUBTREE) != LDAP_COMPARE_TRUE)) + continue; + + for (pMsg = pRes->ldmemcr_resHead, bDone = 0; + !bDone && pMsg; pMsg = pMsg->lm_chain) { + + if (!NSLDAPI_IS_SEARCH_ENTRY( pMsg->lm_msgtype )) + continue; + foundentries = 1; + ber = *(pMsg->lm_ber); + if (ber_scanf(&ber, "{a", &dnTmp) != LBER_ERROR) { + bDone = (memcache_compare_dn(dnTmp, dn, scope) == + LDAP_COMPARE_TRUE); + ldap_memfree(dnTmp); + } + } + + /* If we're in the result flush mode, and the base matched, and + there were no entries in the result, we'll flush this cache + slot, as opposed to the MEMCACHE_ACCESS_FLUSH mode which does + not flush negative results. */ + if ((mode == MEMCACHE_ACCESS_FLUSH_RESULTS) && !foundentries) { + bDone = 1; + } + + if (!bDone) + continue; + + if (list_id == LIST_TTL) { + nRes = htable_remove(cache->ldmemc_resLookup, + (void*)&(pRes->ldmemcr_crc_key), NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TTL); + memcache_free_from_list(cache, pRes, LIST_LRU); + } else { + nRes = htable_remove(cache->ldmemc_resTmp, + (void*)&(pRes->ldmemcr_req_id), NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TMP); + } + memcache_free_entry(cache, pRes); + } + } + } + /* Flush least recently used entries from cache */ + else if (mode == MEMCACHE_ACCESS_FLUSH_LRU) { + + ldapmemcacheRes *pRes = cache->ldmemc_resTail[LIST_LRU]; + + if (pRes == NULL) + return LDAP_NO_SUCH_OBJECT; + + LDAPDebug( LDAP_DEBUG_TRACE, + "memcache_access FLUSH_LRU: removing key 0x%8.8lx\n", + pRes->ldmemcr_crc_key, 0, 0 ); + nRes = htable_remove(cache->ldmemc_resLookup, + (void*)&(pRes->ldmemcr_crc_key), NULL); + assert(nRes == LDAP_SUCCESS); + memcache_free_from_list(cache, pRes, LIST_TTL); + memcache_free_from_list(cache, pRes, LIST_LRU); + memcache_free_entry(cache, pRes); + } + /* Unknown command */ + else { + nRes = LDAP_PARAM_ERROR; + } + + return nRes; +} + +static void +memcache_flush( LDAPMemCache *cache, char *dn, int scope, int flushresults ) +{ + if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { + return; + } + + LDAP_MEMCACHE_MUTEX_LOCK( cache ); + + if (!dn) { + memcache_access(cache, MEMCACHE_ACCESS_FLUSH_ALL, NULL, NULL, NULL); + } else { + if (flushresults) { + memcache_access(cache, MEMCACHE_ACCESS_FLUSH_RESULTS, + (void*)dn, (void*)scope, NULL); + } else { + memcache_access(cache, MEMCACHE_ACCESS_FLUSH, + (void*)dn, (void*)scope, NULL); + } + } + + LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); +} + + +#ifdef LDAP_DEBUG +static void +memcache_report_statistics( LDAPMemCache *cache ) +{ + unsigned long hitrate; + + if ( cache->ldmemc_stats.ldmemcstat_tries == 0 ) { + hitrate = 0; + } else { + hitrate = ( 100L * cache->ldmemc_stats.ldmemcstat_hits ) / + cache->ldmemc_stats.ldmemcstat_tries; + } + LDAPDebug( LDAP_DEBUG_STATS, "memcache 0x%p:\n", cache, 0, 0 ); + LDAPDebug( LDAP_DEBUG_STATS, " tries: %ld hits: %ld hitrate: %ld%%\n", + cache->ldmemc_stats.ldmemcstat_tries, + cache->ldmemc_stats.ldmemcstat_hits, hitrate ); + if ( cache->ldmemc_size <= 0 ) { /* no size limit */ + LDAPDebug( LDAP_DEBUG_STATS, " memory bytes used: %ld\n", + cache->ldmemc_size_used, 0, 0 ); + } else { + LDAPDebug( LDAP_DEBUG_STATS, " memory bytes used: %ld free: %ld\n", + cache->ldmemc_size_used, + cache->ldmemc_size - cache->ldmemc_size_used, 0 ); + } +} +#endif /* LDAP_DEBUG */ + +/************************ Hash Table Functions *****************************/ + +/* Calculates size (# of entries) of hash table given the size limit for + the cache. */ +static int +htable_calculate_size(int sizelimit) +{ + int i, j; + int size = (int)(((double)sizelimit / + (double)(sizeof(BerElement) + EXTRA_SIZE)) / 1.5); + + /* Get a prime # */ + size = (size & 0x1 ? size : size + 1); + for (i = 3, j = size / 2; i < j; i++) { + if ((size % i) == 0) { + size += 2; + i = 3; + j = size / 2; + } + } + + return size; +} + +/* Returns the size in bytes of the given hash table. */ +static int +htable_sizeinbytes(HashTable *pTable) +{ + if (!pTable) + return 0; + + return (pTable->size * sizeof(HashTableNode)); +} + +/* Inserts an item into the hash table. */ +static int +htable_put(HashTable *pTable, void *key, void *pData) +{ + int index = pTable->hashfunc(pTable->size, key); + + if (index >= 0 && index < pTable->size) + return pTable->putdata(&(pTable->table[index].pData), key, pData); + + return( LDAP_OPERATIONS_ERROR ); +} + +/* Retrieves an item from the hash table. */ +static int +htable_get(HashTable *pTable, void *key, void **ppData) +{ + int index = pTable->hashfunc(pTable->size, key); + + *ppData = NULL; + + if (index >= 0 && index < pTable->size) + return pTable->getdata(pTable->table[index].pData, key, ppData); + + return( LDAP_OPERATIONS_ERROR ); +} + +/* Performs a miscellaneous operation on a hash table entry. */ +static int +htable_misc(HashTable *pTable, void *key, void *pData) +{ + if (pTable->miscfunc) { + int index = pTable->hashfunc(pTable->size, key); + if (index >= 0 && index < pTable->size) + return pTable->miscfunc(&(pTable->table[index].pData), key, pData); + } + + return( LDAP_OPERATIONS_ERROR ); +} + +/* Removes an item from the hash table. */ +static int +htable_remove(HashTable *pTable, void *key, void **ppData) +{ + int index = pTable->hashfunc(pTable->size, key); + + if (ppData) + *ppData = NULL; + + if (index >= 0 && index < pTable->size) + return pTable->removedata(&(pTable->table[index].pData), key, ppData); + + return( LDAP_OPERATIONS_ERROR ); +} + +/* Removes everything in the hash table. */ +static int +htable_removeall(HashTable *pTable, void *pData) +{ + int i; + + for (i = 0; i < pTable->size; i++) + pTable->clrtablenode(&(pTable->table[i].pData), pData); + + return( LDAP_SUCCESS ); +} + +/* Creates a new hash table. */ +static int +htable_create(int size_limit, HashFuncPtr hashf, + PutDataPtr putDataf, GetDataPtr getDataf, + RemoveDataPtr removeDataf, ClrTableNodePtr clrNodef, + MiscFuncPtr miscOpf, HashTable **ppTable) +{ + size_limit = htable_calculate_size(size_limit); + + if ((*ppTable = (HashTable*)NSLDAPI_CALLOC(1, sizeof(HashTable))) == NULL) + return( LDAP_NO_MEMORY ); + + (*ppTable)->table = (HashTableNode*)NSLDAPI_CALLOC(size_limit, + sizeof(HashTableNode)); + if ((*ppTable)->table == NULL) { + NSLDAPI_FREE(*ppTable); + *ppTable = NULL; + return( LDAP_NO_MEMORY ); + } + + (*ppTable)->size = size_limit; + (*ppTable)->hashfunc = hashf; + (*ppTable)->putdata = putDataf; + (*ppTable)->getdata = getDataf; + (*ppTable)->miscfunc = miscOpf; + (*ppTable)->removedata = removeDataf; + (*ppTable)->clrtablenode = clrNodef; + + return( LDAP_SUCCESS ); +} + +/* Destroys a hash table. */ +static int +htable_free(HashTable *pTable) +{ + NSLDAPI_FREE(pTable->table); + NSLDAPI_FREE(pTable); + return( LDAP_SUCCESS ); +} + +/**************** Hash table callbacks for temporary cache ****************/ + +/* Hash function */ +static int +msgid_hashf(int table_size, void *key) +{ + unsigned code = (unsigned)((ldapmemcacheReqId*)key)->ldmemcrid_ld; + return (((code << 20) + (code >> 12)) % table_size); +} + +/* Called by hash table to insert an item. */ +static int +msgid_putdata(void **ppTableData, void *key, void *pData) +{ + ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; + ldapmemcacheRes *pRes = (ldapmemcacheRes*)pData; + ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; + ldapmemcacheRes *pCurRes = *ppHead; + ldapmemcacheRes *pPrev = NULL; + + for (; pCurRes; pCurRes = pCurRes->ldmemcr_htable_next) { + if ((pCurRes->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) + break; + pPrev = pCurRes; + } + + if (pCurRes) { + for (; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { + if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == + pReqId->ldmemcrid_msgid) + return( LDAP_ALREADY_EXISTS ); + pPrev = pCurRes; + } + pPrev->ldmemcr_next[LIST_TTL] = pRes; + pRes->ldmemcr_prev[LIST_TTL] = pPrev; + pRes->ldmemcr_next[LIST_TTL] = NULL; + } else { + if (pPrev) + pPrev->ldmemcr_htable_next = pRes; + else + *ppHead = pRes; + pRes->ldmemcr_htable_next = NULL; + } + + return( LDAP_SUCCESS ); +} + +/* Called by hash table to retrieve an item. */ +static int +msgid_getdata(void *pTableData, void *key, void **ppData) +{ + ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; + ldapmemcacheRes *pCurRes = (ldapmemcacheRes*)pTableData; + + *ppData = NULL; + + for (; pCurRes; pCurRes = pCurRes->ldmemcr_htable_next) { + if ((pCurRes->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) + break; + } + + if (!pCurRes) + return( LDAP_NO_SUCH_OBJECT ); + + for (; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { + if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == + pReqId->ldmemcrid_msgid) { + *ppData = (void*)pCurRes; + return( LDAP_SUCCESS ); + } + } + + return( LDAP_NO_SUCH_OBJECT ); +} + +/* Called by hash table to remove an item. */ +static int +msgid_removedata(void **ppTableData, void *key, void **ppData) +{ + ldapmemcacheRes *pHead = *((ldapmemcacheRes**)ppTableData); + ldapmemcacheRes *pCurRes = NULL; + ldapmemcacheRes *pPrev = NULL; + ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; + + if (ppData) + *ppData = NULL; + + for (; pHead; pHead = pHead->ldmemcr_htable_next) { + if ((pHead->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) + break; + pPrev = pHead; + } + + if (!pHead) + return( LDAP_NO_SUCH_OBJECT ); + + for (pCurRes = pHead; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { + if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == + pReqId->ldmemcrid_msgid) + break; + } + + if (!pCurRes) + return( LDAP_NO_SUCH_OBJECT ); + + if (ppData) { + pCurRes->ldmemcr_next[LIST_TTL] = NULL; + pCurRes->ldmemcr_prev[LIST_TTL] = NULL; + pCurRes->ldmemcr_htable_next = NULL; + *ppData = (void*)pCurRes; + } + + if (pCurRes != pHead) { + if (pCurRes->ldmemcr_prev[LIST_TTL]) + pCurRes->ldmemcr_prev[LIST_TTL]->ldmemcr_next[LIST_TTL] = + pCurRes->ldmemcr_next[LIST_TTL]; + if (pCurRes->ldmemcr_next[LIST_TTL]) + pCurRes->ldmemcr_next[LIST_TTL]->ldmemcr_prev[LIST_TTL] = + pCurRes->ldmemcr_prev[LIST_TTL]; + return( LDAP_SUCCESS ); + } + + if (pPrev) { + if (pHead->ldmemcr_next[LIST_TTL]) { + pPrev->ldmemcr_htable_next = pHead->ldmemcr_next[LIST_TTL]; + pHead->ldmemcr_next[LIST_TTL]->ldmemcr_htable_next = + pHead->ldmemcr_htable_next; + } else { + pPrev->ldmemcr_htable_next = pHead->ldmemcr_htable_next; + } + } else { + if (pHead->ldmemcr_next[LIST_TTL]) { + *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_next[LIST_TTL]; + pHead->ldmemcr_next[LIST_TTL]->ldmemcr_htable_next = + pHead->ldmemcr_htable_next; + } else { + *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_htable_next; + } + } + + return( LDAP_SUCCESS ); +} + +/* Called by hash table to remove all cached entries associated to searches + being performed using the given ldap handle. */ +static int +msgid_clear_ld_items(void **ppTableData, void *key, void *pData) +{ + LDAPMemCache *cache = (LDAPMemCache*)pData; + ldapmemcacheRes *pHead = *((ldapmemcacheRes**)ppTableData); + ldapmemcacheRes *pPrev = NULL; + ldapmemcacheRes *pCurRes = NULL; + ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; + + for (; pHead; pHead = pHead->ldmemcr_htable_next) { + if ((pHead->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) + break; + pPrev = pHead; + } + + if (!pHead) + return( LDAP_NO_SUCH_OBJECT ); + + if (pPrev) + pPrev->ldmemcr_htable_next = pHead->ldmemcr_htable_next; + else + *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_htable_next; + + for (pCurRes = pHead; pHead; pCurRes = pHead) { + pHead = pHead->ldmemcr_next[LIST_TTL]; + memcache_free_from_list(cache, pCurRes, LIST_TMP); + memcache_free_entry(cache, pCurRes); + } + + return( LDAP_SUCCESS ); +} + +/* Called by hash table for removing all items in the table. */ +static void +msgid_clearnode(void **ppTableData, void *pData) +{ + LDAPMemCache *cache = (LDAPMemCache*)pData; + ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; + ldapmemcacheRes *pSubHead = *ppHead; + ldapmemcacheRes *pCurRes = NULL; + + for (; *ppHead; pSubHead = *ppHead) { + ppHead = &((*ppHead)->ldmemcr_htable_next); + for (pCurRes = pSubHead; pSubHead; pCurRes = pSubHead) { + pSubHead = pSubHead->ldmemcr_next[LIST_TTL]; + memcache_free_from_list(cache, pCurRes, LIST_TMP); + memcache_free_entry(cache, pCurRes); + } + } +} + +/********************* Hash table for primary cache ************************/ + +/* Hash function */ +static int +attrkey_hashf(int table_size, void *key) +{ + return ((*((unsigned long*)key)) % table_size); +} + +/* Called by hash table to insert an item. */ +static int +attrkey_putdata(void **ppTableData, void *key, void *pData) +{ + unsigned long attrkey = *((unsigned long*)key); + ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; + ldapmemcacheRes *pRes = *ppHead; + + for (; pRes; pRes = pRes->ldmemcr_htable_next) { + if (pRes->ldmemcr_crc_key == attrkey) + return( LDAP_ALREADY_EXISTS ); + } + + pRes = (ldapmemcacheRes*)pData; + pRes->ldmemcr_htable_next = *ppHead; + *ppHead = pRes; + + return( LDAP_SUCCESS ); +} + +/* Called by hash table to retrieve an item. */ +static int +attrkey_getdata(void *pTableData, void *key, void **ppData) +{ + unsigned long attrkey = *((unsigned long*)key); + ldapmemcacheRes *pRes = (ldapmemcacheRes*)pTableData; + + for (; pRes; pRes = pRes->ldmemcr_htable_next) { + if (pRes->ldmemcr_crc_key == attrkey) { + *ppData = (void*)pRes; + return( LDAP_SUCCESS ); + } + } + + *ppData = NULL; + + return( LDAP_NO_SUCH_OBJECT ); +} + +/* Called by hash table to remove an item. */ +static int +attrkey_removedata(void **ppTableData, void *key, void **ppData) +{ + unsigned long attrkey = *((unsigned long*)key); + ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; + ldapmemcacheRes *pRes = *ppHead; + ldapmemcacheRes *pPrev = NULL; + + for (; pRes; pRes = pRes->ldmemcr_htable_next) { + if (pRes->ldmemcr_crc_key == attrkey) { + if (ppData) + *ppData = (void*)pRes; + if (pPrev) + pPrev->ldmemcr_htable_next = pRes->ldmemcr_htable_next; + else + *ppHead = pRes->ldmemcr_htable_next; + pRes->ldmemcr_htable_next = NULL; + return( LDAP_SUCCESS ); + } + pPrev = pRes; + } + + if (ppData) + *ppData = NULL; + + return( LDAP_NO_SUCH_OBJECT ); +} + +/* Called by hash table for removing all items in the table. */ +static void +attrkey_clearnode(void **ppTableData, void *pData) +{ + ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; + ldapmemcacheRes *pRes = *ppHead; + + (void)pData; + + for (; *ppHead; pRes = *ppHead) { + ppHead = &((*ppHead)->ldmemcr_htable_next); + pRes->ldmemcr_htable_next = NULL; + } +} + +/***************************** CRC algorithm ********************************/ + +/* From http://www.faqs.org/faqs/compression-faq/part1/section-25.html */ + +/* + * Build auxiliary table for parallel byte-at-a-time CRC-32. + */ +#define NSLDAPI_CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ + +static nsldapi_uint_32 crc32_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; + +/* Initialized first time "crc32()" is called. If you prefer, you can + * statically initialize it at compile time. [Another exercise.] + */ + +static unsigned long +crc32_convert(char *buf, int len) +{ + unsigned char *p; + nsldapi_uint_32 crc; + + crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ + for (p = (unsigned char *)buf; len > 0; ++p, --len) + crc = ((crc << 8) ^ crc32_table[(crc >> 24) ^ *p]) & 0xffffffff; + + return (unsigned long) ~crc; /* transmit complement, per CRC-32 spec */ +} diff --git a/ldap/c-sdk/libldap/message.c b/ldap/c-sdk/libldap/message.c new file mode 100644 index 0000000000..bfbd200f87 --- /dev/null +++ b/ldap/c-sdk/libldap/message.c @@ -0,0 +1,105 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +int +LDAP_CALL +ldap_msgid( LDAPMessage *lm ) +{ + if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm )) { + return( -1 ); + } + + return( lm->lm_msgid ); +} + +int +LDAP_CALL +ldap_msgtype( LDAPMessage *lm ) +{ + if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm )) { + return( -1 ); + } + + return( lm->lm_msgtype ); +} + + +LDAPMessage * +LDAP_CALL +ldap_first_message( LDAP *ld, LDAPMessage *chain ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULLMSG ); /* punt */ + } + + return( chain ); +} + + +LDAPMessage * +LDAP_CALL +ldap_next_message( LDAP *ld, LDAPMessage *msg ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( NULLMSG ); /* punt */ + } + + if ( msg == NULLMSG || msg->lm_chain == NULLMSG ) { + return( NULLMSG ); + } + + return( msg->lm_chain ); +} + + +int +LDAP_CALL +ldap_count_messages( LDAP *ld, LDAPMessage *chain ) +{ + int i; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); + } + + for ( i = 0; chain != NULL; chain = chain->lm_chain ) { + i++; + } + + return( i ); +} diff --git a/ldap/c-sdk/libldap/modify.c b/ldap/c-sdk/libldap/modify.c new file mode 100644 index 0000000000..ea81102c4c --- /dev/null +++ b/ldap/c-sdk/libldap/modify.c @@ -0,0 +1,226 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * modify.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_modify - initiate an ldap modify operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to modify + * mods List of modifications to make. This is null-terminated + * array of struct ldapmod's, specifying the modifications + * to perform. + * + * Example: + * LDAPMod *mods[] = { + * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, + * { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } }, + * 0 + * } + * msgid = ldap_modify( ld, dn, mods ); + */ +int +LDAP_CALL +ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods ) +{ + int msgid; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 ); + + if ( ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid ) + == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + +int +LDAP_CALL +ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods, + LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) +{ + BerElement *ber; + int i, rc, lderr; + + /* + * A modify request looks like this: + * ModifyRequet ::= SEQUENCE { + * object DistinguishedName, + * modifications SEQUENCE OF SEQUENCE { + * operation ENUMERATED { + * add (0), + * delete (1), + * replace (2) + * }, + * modification SEQUENCE { + * type AttributeType, + * values SET OF AttributeValue + * } + * } + * } + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) + { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods )) { + lderr = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + return( lderr ); + } + if ( dn == NULL ) { + dn = ""; + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* see if we should add to the cache */ + if ( ld->ld_cache_on && ld->ld_cache_modify != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_modify)( ld, *msgidp, LDAP_REQ_MODIFY, + dn, mods )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* create a message to send */ + if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( lderr ); + } + + if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_MODIFY, dn ) + == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + /* for each modification to be performed... */ + for ( i = 0; mods[i] != NULL; i++ ) { + if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { + rc = ber_printf( ber, "{e{s[V]}}", + mods[i]->mod_op & ~LDAP_MOD_BVALUES, + mods[i]->mod_type, mods[i]->mod_bvalues ); + } else { + rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op, + mods[i]->mod_type, mods[i]->mod_values ); + } + + if ( rc == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + } + + if ( ber_printf( ber, "}}" ) == -1 ) { + lderr = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + ber_free( ber, 1 ); + return( lderr ); + } + + if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( lderr ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODIFY, + (char *)dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +int +LDAP_CALL +ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods ) +{ + return( ldap_modify_ext_s( ld, dn, mods, NULL, NULL )); +} + +int +LDAP_CALL +ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods, + LDAPControl **serverctrls, LDAPControl **clientctrls ) +{ + int msgid, err; + LDAPMessage *res; + + if (( err = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls, + &msgid )) != LDAP_SUCCESS ) { + return( err ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + return( ldap_result2error( ld, res, 1 ) ); +} diff --git a/ldap/c-sdk/libldap/moz.build b/ldap/c-sdk/libldap/moz.build new file mode 100644 index 0000000000..35fbd8fb61 --- /dev/null +++ b/ldap/c-sdk/libldap/moz.build @@ -0,0 +1,88 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include('../common.mozbuild') + +SharedLibrary('ldap60') + +SOURCES += [ + 'abandon.c', + 'add.c', + 'authzidctrl.c', + 'bind.c', + 'cache.c', + 'charray.c', + 'charset.c', + 'compare.c', + 'compat.c', + 'control.c', + 'countvalues.c', + 'delete.c', + 'disptmpl.c', + 'dsparse.c', + 'error.c', + 'extendop.c', + 'free.c', + 'freevalues.c', + 'friendly.c', + 'getattr.c', + 'getdn.c', + 'getdxbyname.c', + 'geteffectiverightsctrl.c', + 'getentry.c', + 'getfilter.c', + 'getoption.c', + 'getvalues.c', + 'memcache.c', + 'message.c', + 'modify.c', + 'open.c', + 'os-ip.c', + 'proxyauthctrl.c', + 'psearch.c', + 'pwmodext.c', + 'pwpctrl.c', + 'referral.c', + 'regex.c', + 'rename.c', + 'request.c', + 'reslist.c', + 'result.c', + 'saslbind.c', + 'sbind.c', + 'search.c', + 'setoption.c', + 'sort.c', + 'sortctrl.c', + 'srchpref.c', + 'tmplout.c', + 'ufn.c', + 'unbind.c', + 'unescape.c', + 'url.c', + 'userstatusctrl.c', + 'utf8.c', + 'vlistctrl.c', + 'whoami.c', +] + +if CONFIG['OS_TARGET'] == 'WINNT': + SOURCES += [ + 'dllmain.c', + 'mozock.c', + ] + DEFFILE = SRCDIR + '/libldap.def' + +if CONFIG['OS_TARGET'] != 'WINNT': + DEFINES['USE_WAITPID'] = True + DEFINES['USE_PTHREADS'] = True + +DEFINES['NEEDPROTOS'] = True + +LOCAL_INCLUDES += [ + '../include' +] + +USE_LIBS += ['lber60'] diff --git a/ldap/c-sdk/libldap/mozock.c b/ldap/c-sdk/libldap/mozock.c new file mode 100644 index 0000000000..4f0bc57501 --- /dev/null +++ b/ldap/c-sdk/libldap/mozock.c @@ -0,0 +1,714 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef _WINDOWS +#define FD_SETSIZE 30000 +#endif + +#include +#include +#include + +// Purpose of this file is to implement an intermediate layer to our network +// services, the winsock. +// This intermediate layer will be able to function with and without a working +// winsock being present. +// The attempt to activate the winsock happens as would normally be expected, +// through the calling application's entry point to us, WSAStartup. + + +// Name of the winsock we would like to load. +// Diffs between OSs, Win32s is out in the cold if running 32 bits unless +// they also have a winsock name wsock32.dll. +#ifndef _WIN32 +#define SZWINSOCK "winsock.dll" +#else +#define SZWINSOCK "wsock32.dll" +#endif + +// Here is the enumeration for the winsock functions we have currently +// overridden (needed to run). Add more when needed. +// We use these to access proc addresses, and to hold a table of strings +// to obtain the proc addresses. +enum SockProc { + sp_WSAAsyncGetHostByName = 0, + sp_WSAAsyncSelect, + sp_WSACleanup, + sp_WSAGetLastError, + sp_WSASetLastError, + sp_WSAStartup, + sp___WSAFDIsSet, + sp_accept, + sp_bind, + sp_closesocket, + sp_connect, + sp_gethostbyname, + sp_gethostbyaddr, + sp_gethostname, + sp_getpeername, + sp_getsockname, + sp_getsockopt, + sp_getprotobyname, + sp_htonl, + sp_htons, + sp_inet_addr, + sp_ioctlsocket, + sp_listen, + sp_ntohl, + sp_ntohs, + sp_recv, + sp_select, + sp_send, + sp_setsockopt, + sp_shutdown, + sp_socket, + sp_inet_ntoa, + + sp_MaxProcs // Total count. +}; + +// Array of function names used in GetProcAddress to fill in our +// proc array when needed. +// This array must match the enumerations exactly. +char *spName[(int)sp_MaxProcs] = { + "WSAAsyncGetHostByName", + "WSAAsyncSelect", + "WSACleanup", + "WSAGetLastError", + "WSASetLastError", + "WSAStartup", + "__WSAFDIsSet", + "accept", + "bind", + "closesocket", + "connect", + "gethostbyname", + "gethostbyaddr", + "gethostname", + "getpeername", + "getsockname", + "getsockopt", + "getprotobyname", + "htonl", + "htons", + "inet_addr", + "ioctlsocket", + "listen", + "ntohl", + "ntohs", + "recv", + "select", + "send", + "setsockopt", + "shutdown", + "socket", + "inet_ntoa" +}; + +// Array of proc addresses to the winsock functions. +// These can be NULL, indicating their absence (as in the case we couldn't +// load the winsock.dll or one of the functions wasn't loaded). +// The procs assigned in must corellate with the enumerations exactly. +FARPROC spArray[(int)sp_MaxProcs]; + +// Typedef all the different types of functions that we must cast the +// procs to in order to call without the compiler barfing. +// Prefix is always sp. +// Retval is next, spelled out. +// Parameters in their order are next, spelled out. +typedef int (PASCAL FAR *sp_int_WORD_LPWSADATA)(WORD, LPWSADATA); +typedef int (PASCAL FAR *sp_int_void)(void); +typedef HANDLE (PASCAL FAR *sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)(HWND, unsigned int, const char FAR *, char FAR *, int); +typedef int (PASCAL FAR *sp_int_SOCKET_HWND_uint_long)(SOCKET, HWND, unsigned int, long); +typedef void (PASCAL FAR *sp_void_int)(int); +typedef int (PASCAL FAR *sp_int_SOCKET_fdsetFARp)(SOCKET, fd_set FAR *); +typedef SOCKET(PASCAL FAR *sp_SOCKET_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *); +typedef int (PASCAL FAR *sp_int_SOCKET_csockaddrFARp_int)(SOCKET, const struct sockaddr FAR *, int); +typedef int (PASCAL FAR *sp_int_SOCKET)(SOCKET); +typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp)(const char FAR *); +typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp_int_int)(const char FAR *, int, int); +typedef int (PASCAL FAR *sp_int_charFARp_int)(char FAR *, int); +typedef int (PASCAL FAR *sp_int_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *); +typedef int (PASCAL FAR *sp_int_SOCKET_int_int_charFARp_intFARp)(SOCKET, int, int, char FAR *, int FAR *); +typedef u_long (PASCAL FAR *sp_ulong_ulong)(u_long); +typedef u_short (PASCAL FAR *sp_ushort_ushort)(u_short); +typedef unsigned long (PASCAL FAR *sp_ulong_ccharFARp)(const char FAR *); +typedef int (PASCAL FAR *sp_int_SOCKET_long_ulongFARp)(SOCKET, long, u_long FAR *); +typedef int (PASCAL FAR *sp_int_SOCKET_int)(SOCKET, int); +typedef int (PASCAL FAR *sp_int_SOCKET_charFARp_int_int)(SOCKET, char FAR *, int, int); +typedef int (PASCAL FAR *sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)(int,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR*); +typedef int (PASCAL FAR *sp_int_SOCKET_ccharFARp_int_int)(SOCKET, const char FAR *, int, int); +typedef int (PASCAL FAR *sp_int_SOCKET_int_int_ccharFARp_int)(SOCKET, int, int, const char FAR *, int); +typedef SOCKET (PASCAL FAR *sp_SOCKET_int_int_int)(int, int, int); +typedef char FAR * (PASCAL FAR *sp_charFARp_in_addr)(struct in_addr in); +typedef struct protoent FAR * (PASCAL FAR *sp_protoentFARcchar)(const char FAR *); + +// Handle to the winsock, if loaded. +HINSTANCE hWinsock = NULL; + +#ifndef _WIN32 +// Last error code for the winsock. +int ispError = 0; +#endif + + +BOOL IsWinsockLoaded (int sp) +{ + if (hWinsock == NULL) + { + WSADATA wsaData; +#ifdef _WIN32 + static LONG sc_init = 0; + static DWORD sc_done = 0; + static CRITICAL_SECTION sc; +#endif + /* We need to wait here because another thread might be + in the routine already */ +#ifdef _WIN32 + if (0 == InterlockedExchange(&sc_init,1)) { + InitializeCriticalSection(&sc); + sc_done = 1; + } + while (0 == sc_done) Sleep(0); + EnterCriticalSection(&sc); + if (hWinsock == NULL) { +#endif + WSAStartup(0x0101, &wsaData); +#ifdef _WIN32 + } + LeaveCriticalSection(&sc); +#endif + } +// Quick macro to tell if the winsock has actually loaded for a particular +// function. +// Debug version is a little more strict to make sure you get the names right. +#ifdef DEBUG + return hWinsock != NULL && spArray[(int)(sp)] != NULL; +#else // A little faster + return hWinsock != NULL; +#endif +} + +// Here are the functions that we have taken over by not directly linking +// with the winsock import library or importing through the def file. + +/* In win16 we simulate blocking commands as follows. Prior to issuing the + * command we make the socket not-blocking (WSAAsyncSelect does that). + * We then issue the command and see if it would have blocked. If so, we + * yield the processor and go to sleep until an event occurs that unblocks + * us (WSAAsyncSelect allowed us to register what that condition is). We + * keep repeating until we do not get a would-block indication when issuing + * the command. At that time we unregister the notification condition and + * return the result of the command to the caller. + */ + +//#ifndef _WIN32 +#if 0 +#define NON_BLOCKING(command,condition,index,type) \ + type iret; \ + HWND hWndFrame = AfxGetApp()->m_pMainWnd->m_hWnd; \ + while (TRUE) { \ + if (WSAAsyncSelect(s, hWndFrame, msg_NetActivity, condition) \ + == SOCKET_ERROR) { \ + break; \ + } \ + if(IsWinsockLoaded(index)) { \ + iret=command; \ + if (!(iret==SOCKET_ERROR && WSAGetLastError()==WSAEWOULDBLOCK)) { \ + WSAAsyncSelect(s, hWndFrame, msg_NetActivity, 0); \ + return iret; \ + } \ + PR_Yield(); \ + } else { \ + break; \ + } \ + } +#else +#define NON_BLOCKING(command,condition,index,type) \ + if(IsWinsockLoaded(index)) { \ + return command; \ + } +#endif + +int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) { + // Our default return value is failure, though we change this regardless. + int iRetval = WSAVERNOTSUPPORTED; + HINSTANCE MyHandle; + + // Before doing anything, clear out our proc array. + memset(spArray, 0, sizeof(spArray)); + + // attempt to load the real winsock. + MyHandle = LoadLibrary(SZWINSOCK); +#ifdef _WIN32 + if(MyHandle != NULL) { +#else + if(MyHandle > HINSTANCE_ERROR) { +#endif + // Winsock was loaded. + // Get the proc addresses for each needed function next. + int spTraverse; + for(spTraverse = 0; spTraverse < (int)sp_MaxProcs; spTraverse++) { + spArray[spTraverse] = GetProcAddress(MyHandle, spName[spTraverse]); + if ( NULL == spArray[spTraverse] ) + return iRetval;// Bad winsock? Bad function name? + } + + hWinsock = MyHandle; + // AllRight, attempt to make our first proxied call. + if(IsWinsockLoaded(sp_WSAStartup)) { + iRetval = ((sp_int_WORD_LPWSADATA)spArray[sp_WSAStartup])(wVersionRequested, lpWSAData); + } + + // If the return value is still an error at this point, we unload the DLL, + // so that we can act as though nothing happened and the user + // gets no network access. + if(iRetval != 0) { + // Clear out our proc array. + memset(spArray, 0, sizeof(spArray)); + + // Free up the winsock. + FreeLibrary(MyHandle); + MyHandle = NULL; + } + } +#ifndef _WIN32 + else { + // Failed to load. + // Set this to NULL so it is clear. + hWinsock = NULL; + } +#endif + + + // Check our return value, if it isn't success, then we need to fake + // our own winsock implementation. + if(iRetval != 0) { + // We always return success. + iRetval = 0; + + // Fill in the structure. + // Return the version requested as the version supported. + lpWSAData->wVersion = wVersionRequested; + lpWSAData->wHighVersion = wVersionRequested; + + // Fill in a discription. + strcpy(lpWSAData->szDescription, "Mozock DLL internal implementation."); + strcpy(lpWSAData->szSystemStatus, "Winsock running, allowing no network access."); + + // Report a nice round number for sockets and datagram sizes. + lpWSAData->iMaxSockets = 4096; + lpWSAData->iMaxUdpDg = 4096; + + // No vendor information. + lpWSAData->lpVendorInfo = NULL; + } + + return(iRetval); +} + +int PASCAL FAR WSACleanup(void) { + int iRetval = 0; + + // Handling normally or internally. + // When IsWinsockLoaded() is called and hWinsock is NULL, it winds up calling WSAStartup + // which wedges rpcrt4.dll on win95 with some winsock implementations. Bug: 81359. + if(hWinsock && IsWinsockLoaded(sp_WSACleanup)) { + // Call their cleanup routine. + // We could set the return value here, but it is meaning less. + // We always return success. + iRetval = ((sp_int_void)spArray[sp_WSACleanup])(); + //ASSERT(iRetval == 0); + iRetval = 0; + } + + // Wether or not it succeeded, we free off the library here. + // Clear out our proc table too. + memset(spArray, 0, sizeof(spArray)); + if(hWinsock != NULL) { + FreeLibrary(hWinsock); + hWinsock = NULL; + } + + return(iRetval); +} + +HANDLE PASCAL FAR WSAAsyncGetHostByName(HWND hWnd, unsigned int wMsg, const char FAR *name, char FAR *buf, int buflen) { + // Normal or shim. + if(IsWinsockLoaded(sp_WSAAsyncGetHostByName)) { + return(((sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)spArray[sp_WSAAsyncGetHostByName])(hWnd, wMsg, name, buf, buflen)); + } + + // Must return error here. + // Set our last error value to be that the net is down. + WSASetLastError(WSAENETDOWN); + return(NULL); +} + +int PASCAL FAR WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent) { + // Normal or shim. + if(IsWinsockLoaded(sp_WSAAsyncSelect)) { + return(((sp_int_SOCKET_HWND_uint_long)spArray[sp_WSAAsyncSelect])(s, hWnd, wMsg, lEvent)); + } + + // Must return error here. + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR WSAGetLastError(void) { + // See if someone else can handle. + if(IsWinsockLoaded(sp_WSAGetLastError)) { + return(((sp_int_void)spArray[sp_WSAGetLastError])()); + } + +#ifndef _WIN32 + { + // Fake it. + int iRetval = ispError; + ispError = 0; + return(iRetval); + } +#else + // Use default OS handler. + return(GetLastError()); +#endif +} + +void PASCAL FAR WSASetLastError(int iError) { + // See if someone else can handle. + if(IsWinsockLoaded(sp_WSASetLastError)) { + ((sp_void_int)spArray[sp_WSASetLastError])(iError); + return; + } + +#ifndef _WIN32 + // Fake it. + ispError = iError; + return; +#else + // Use default OS handler. + SetLastError(iError); + return; +#endif +} + +int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set) { + int i; + + // See if someone else will handle. + if(IsWinsockLoaded(sp___WSAFDIsSet)) { + return(((sp_int_SOCKET_fdsetFARp)spArray[sp___WSAFDIsSet])(fd, set)); + } + + // Default implementation. + i = set->fd_count; + while (i--) { + if (set->fd_array[i] == fd) { + return 1; + } + } + return 0; +} + +SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen) { + // Internally or shim + NON_BLOCKING( + (((sp_SOCKET_SOCKET_sockaddrFARp_intFARp)spArray[sp_accept])(s, addr, addrlen)), + FD_ACCEPT, sp_accept, SOCKET); + + // Fail. + WSASetLastError(WSAENETDOWN); + return(INVALID_SOCKET); +} + +int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR *name, int namelen) { + // Internally or shim + if(IsWinsockLoaded(sp_bind)) { + return(((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_bind])(s, name, namelen)); + } + + // Fail. + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR closesocket(SOCKET s) { + // Internally or shim. + NON_BLOCKING( + (((sp_int_SOCKET)spArray[sp_closesocket])(s)), + FD_CLOSE, sp_closesocket, int); + + // Error. + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR *name, int namelen) { + // Internally or shim. + if(IsWinsockLoaded(sp_connect)) { + /* This could block and so it would seem that the NON_BLOCK + * macro should be used here. However it was causing a crash + * and so it was decided to allow blocking here instead + */ + return (((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_connect])(s, name, namelen)); + } + + // Err. + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +struct hostent FAR * PASCAL FAR gethostbyname(const char FAR *name) { + if(IsWinsockLoaded(sp_gethostbyname)) { + return(((sp_hostentFARp_ccharFARp)spArray[sp_gethostbyname])(name)); + } + + WSASetLastError(WSAENETDOWN); + return(NULL); +} + +struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR *addr, int len, int type) { + if(IsWinsockLoaded(sp_gethostbyaddr)) { + return(((sp_hostentFARp_ccharFARp_int_int)spArray[sp_gethostbyaddr])(addr, len, type)); + } + + WSASetLastError(WSAENETDOWN); + return(NULL); +} + +int PASCAL FAR gethostname(char FAR *name, int namelen) { + if(IsWinsockLoaded(sp_gethostname)) { + return(((sp_int_charFARp_int)spArray[sp_gethostname])(name, namelen)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR getpeername(SOCKET s, struct sockaddr FAR *name, int FAR *namelen) { + if(IsWinsockLoaded(sp_getpeername)) { + return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getpeername])(s, name, namelen)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR getsockname(SOCKET s, struct sockaddr FAR *name, int FAR *namelen) { + if(IsWinsockLoaded(sp_getsockname)) { + return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getsockname])(s, name, namelen)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR getsockopt(SOCKET s, int level, int optname, char FAR *optval, int FAR *optlen) { + if(IsWinsockLoaded(sp_getsockopt)) { + return(((sp_int_SOCKET_int_int_charFARp_intFARp)spArray[sp_getsockopt])(s, level, optname, optval, optlen)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +struct protoent FAR * PASCAL getprotobyname(const char FAR * name) { + if(IsWinsockLoaded(sp_getprotobyname)) { + return(((sp_protoentFARcchar)spArray[sp_getprotobyname])(name)); + } + + WSASetLastError(WSAENETDOWN); + return NULL; +} + +u_long PASCAL FAR htonl(u_long hostlong) { + if(IsWinsockLoaded(sp_htonl)) { + return(((sp_ulong_ulong)spArray[sp_htonl])(hostlong)); + } + +#ifndef _WIN32 + return + (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) + + ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24)); + +#else + // Just return what was passed in. + return(hostlong); +#endif +} + +u_short PASCAL FAR htons(u_short hostshort) { + if(IsWinsockLoaded(sp_htons)) { + return(((sp_ushort_ushort)spArray[sp_htons])(hostshort)); + } + +#ifndef _WIN32 + return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8)); + +#else + // Just return what was passed in. + return(hostshort); +#endif +} + +u_long PASCAL FAR ntohl(u_long hostlong) { + if(IsWinsockLoaded(sp_ntohl)) { + return(((sp_ulong_ulong)spArray[sp_ntohl])(hostlong)); + } + +#ifndef _WIN32 + return + (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) + + ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24)); + +#else + // Just return what was passed in. + return(hostlong); +#endif +} + +u_short PASCAL FAR ntohs(u_short hostshort) { + if(IsWinsockLoaded(sp_ntohs)) { + return(((sp_ushort_ushort)spArray[sp_ntohs])(hostshort)); + } + +#ifndef _WIN32 + return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8)); + +#else + // Just return what was passed in. + return(hostshort); +#endif +} + +unsigned long PASCAL FAR inet_addr(const char FAR *cp) { + if(IsWinsockLoaded(sp_inet_addr)) { + return(((sp_ulong_ccharFARp)spArray[sp_inet_addr])(cp)); + } + + return(INADDR_NONE); +} + +int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) { + if(IsWinsockLoaded(sp_ioctlsocket)) { + return(((sp_int_SOCKET_long_ulongFARp)spArray[sp_ioctlsocket])(s, cmd, argp)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR listen(SOCKET s, int backlog) { + if(IsWinsockLoaded(sp_listen)) { + return(((sp_int_SOCKET_int)spArray[sp_listen])(s, backlog)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags) { + NON_BLOCKING( + (((sp_int_SOCKET_charFARp_int_int)spArray[sp_recv])(s, buf, len, flags)), + FD_READ, sp_recv, int); + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout) { + // If there's nothing to do, stop now before we go off into dll land. + // Optimization, boyz. + if((readfds && readfds->fd_count) || (writefds && writefds->fd_count) || (exceptfds && exceptfds->fd_count)) { + if(IsWinsockLoaded(sp_select)) { + return(((sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)spArray[sp_select])(nfds,readfds,writefds,exceptfds,timeout)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); + } + + // No need to go to the DLL, there is nothing to do. + return(0); +} + +int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags) { + NON_BLOCKING( + + (((sp_int_SOCKET_ccharFARp_int_int)spArray[sp_send])(s, buf, len, flags)), + FD_WRITE, sp_send, int); + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR setsockopt(SOCKET s, int level, int optname, const char FAR *optval, int optlen) { + if(IsWinsockLoaded(sp_setsockopt)) { + return(((sp_int_SOCKET_int_int_ccharFARp_int)spArray[sp_setsockopt])(s, level, optname, optval, optlen)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +int PASCAL FAR shutdown(SOCKET s, int how) { + if(IsWinsockLoaded(sp_shutdown)) { + return(((sp_int_SOCKET_int)spArray[sp_shutdown])(s, how)); + } + + WSASetLastError(WSAENETDOWN); + return(SOCKET_ERROR); +} + +SOCKET PASCAL FAR socket(int af, int type, int protocol) { + if(IsWinsockLoaded(sp_socket)) { + return(((sp_SOCKET_int_int_int)spArray[sp_socket])(af, type, protocol)); + } + + WSASetLastError(WSAENETDOWN); + return(INVALID_SOCKET); +} + +char FAR * PASCAL FAR inet_ntoa(struct in_addr in) { + if(IsWinsockLoaded(sp_inet_ntoa)) { + return ((sp_charFARp_in_addr)spArray[sp_inet_ntoa])(in); + } + + WSASetLastError(WSAENETDOWN); + return NULL; +} diff --git a/ldap/c-sdk/libldap/nsprthreadtest.c b/ldap/c-sdk/libldap/nsprthreadtest.c new file mode 100644 index 0000000000..f9af68b423 --- /dev/null +++ b/ldap/c-sdk/libldap/nsprthreadtest.c @@ -0,0 +1,621 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include +#include +#include + +#define NAME "cn=Directory Manager" +#define PASSWORD "secret99" +#define BASE "dc=example,dc=com" + +static int simplebind( LDAP *ld, char *msg, int tries ); +static void search_thread( void * ); +static void modify_thread( void * ); +static void add_thread( void * ); +static void delete_thread( void * ); +static void set_ld_error(); +static int get_ld_error(); +static void set_errno(); +static int get_errno(); +static void tsd_setup(); +static void *my_mutex_alloc( void ); +static void my_mutex_free( void * ); +static int my_mutex_lock( void * ); +static int my_mutex_unlock( void * ); +static LDAPHostEnt *my_gethostbyname( const char *name, LDAPHostEnt *result, + char *buffer, int buflen, int *statusp, void *extradata ); +static LDAPHostEnt *my_gethostbyaddr( const char *addr, int length, + int type, LDAPHostEnt *result, char *buffer, int buflen, + int *statusp, void *extradata ); +static LDAPHostEnt *copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp, + PRHostEnt *prhp ); + +typedef struct ldapmsgwrapper { + LDAPMessage *lmw_messagep; + struct ldapmsgwrapper *lmw_next; +} ldapmsgwrapper; + + +#define CONNECTION_ERROR( lderr ) ( (lderr) == LDAP_SERVER_DOWN || \ + (lderr) == LDAP_CONNECT_ERROR ) + + +LDAP *ld; +PRUintn tsdindex; +#ifdef LDAP_MEMCACHE +LDAPMemCache *memcache = NULL; +#define MEMCACHE_SIZE (256*1024) /* 256K bytes */ +#define MEMCACHE_TTL (15*60) /* 15 minutes */ +#endif + + +main( int argc, char **argv ) +{ + PRThread *search_tid, *search_tid2, *search_tid3; + PRThread *search_tid4, *modify_tid, *add_tid; + PRThread *delete_tid; + struct ldap_thread_fns tfns; + struct ldap_dns_fns dnsfns; + int rc; + + if ( argc != 3 ) { + fprintf( stderr, "usage: %s host port\n", argv[0] ); + exit( 1 ); + } + + PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0 ); + if ( PR_NewThreadPrivateIndex( &tsdindex, NULL ) != PR_SUCCESS ) { + perror( "PR_NewThreadPrivateIndex" ); + exit( 1 ); + } + tsd_setup(); /* for main thread */ + + if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) { + perror( "ldap_open" ); + exit( 1 ); + } + + /* set thread function pointers */ + memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); + tfns.ltf_mutex_alloc = my_mutex_alloc; + tfns.ltf_mutex_free = my_mutex_free; + tfns.ltf_mutex_lock = my_mutex_lock; + tfns.ltf_mutex_unlock = my_mutex_unlock; + tfns.ltf_get_errno = get_errno; + tfns.ltf_set_errno = set_errno; + tfns.ltf_get_lderrno = get_ld_error; + tfns.ltf_set_lderrno = set_ld_error; + tfns.ltf_lderrno_arg = NULL; + if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns ) + != 0 ) { + ldap_perror( ld, "ldap_set_option: thread functions" ); + exit( 1 ); + } + + /* set DNS function pointers */ + memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) ); + dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; + dnsfns.lddnsfn_gethostbyname = my_gethostbyname; + dnsfns.lddnsfn_gethostbyaddr = my_gethostbyaddr; + if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) + != 0 ) { + ldap_perror( ld, "ldap_set_option: DNS functions" ); + exit( 1 ); + } + +#ifdef LDAP_MEMCACHE + /* create the in-memory cache */ + if (( rc = ldap_memcache_init( MEMCACHE_TTL, MEMCACHE_SIZE, NULL, + &tfns, &memcache )) != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_memcache_init failed - %s\n", + ldap_err2string( rc )); + exit( 1 ); + } + if (( rc = ldap_memcache_set( ld, memcache )) != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_memcache_set failed - %s\n", + ldap_err2string( rc )); + exit( 1 ); + } +#endif + + /* + * set option so that the next call to ldap_simple_bind_s() after + * the server connection is lost will attempt to reconnect. + */ + if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) != 0 ) { + ldap_perror( ld, "ldap_set_option: reconnect" ); + exit( 1 ); + } + + /* initial bind */ + if ( simplebind( ld, "ldap_simple_bind_s/main", 1 ) != LDAP_SUCCESS ) { + exit( 1 ); + } + + /* create the operation threads */ + if ( (search_tid = PR_CreateThread( PR_USER_THREAD, search_thread, + "1", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread search_thread" ); + exit( 1 ); + } + if ( (modify_tid = PR_CreateThread( PR_USER_THREAD, modify_thread, + "2", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread modify_thread" ); + exit( 1 ); + } + if ( (search_tid2 = PR_CreateThread( PR_USER_THREAD, search_thread, + "3", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread search_thread 2" ); + exit( 1 ); + } + if ( (add_tid = PR_CreateThread( PR_USER_THREAD, add_thread, + "4", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread add_thread" ); + exit( 1 ); + } + if ( (search_tid3 = PR_CreateThread( PR_USER_THREAD, search_thread, + "5", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread search_thread 3" ); + exit( 1 ); + } + if ( (delete_tid = PR_CreateThread( PR_USER_THREAD, delete_thread, + "6", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread delete_thread" ); + exit( 1 ); + } + if ( (search_tid4 = PR_CreateThread( PR_USER_THREAD, search_thread, + "7", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + 0 )) == NULL ) { + perror( "PR_CreateThread search_thread 4" ); + exit( 1 ); + } + + PR_Cleanup(); + return( 0 ); +} + + +static int +simplebind( LDAP *ld, char *msg, int tries ) +{ + int rc; + + while ( tries-- > 0 ) { + rc = ldap_simple_bind_s( ld, NAME, PASSWORD ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, msg ); + } + if ( tries == 0 || !CONNECTION_ERROR( rc )) { + return( rc ); + } + fprintf( stderr, + "%s: sleeping for 5 secs - will try %d more time(s)...\n", + msg, tries ); + sleep( 5 ); + } + + return( rc ); +} + + +static void +search_thread( void *arg1 ) +{ + LDAPMessage *res; + LDAPMessage *e; + char *a; + char **v; + char *dn; + BerElement *ber; + int i, rc, msgid; + void *tsd; + char *id = arg1; + + printf( "search_thread\n" ); + tsd_setup(); + for ( ;; ) { + printf( "%sSearching...\n", id ); + if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, + "(objectclass=*)", NULL, 0 )) == -1 ) { + ldap_perror( ld, "ldap_search_s" ); + rc = ldap_get_lderrno( ld, NULL, NULL ); + if ( CONNECTION_ERROR( rc ) && simplebind( ld, + "bind-search_thread", 5 ) != LDAP_SUCCESS ) { + return; + } + continue; + } + while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) + == LDAP_RES_SEARCH_ENTRY ) { + for ( e = ldap_first_entry( ld, res ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + dn = ldap_get_dn( ld, e ); + /* printf( "%sdn: %s\n", id, dn ); */ + free( dn ); + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, + ber ) ) { + v = ldap_get_values( ld, e, a ); + for ( i = 0; v && v[i] != 0; i++ ) { + /* + printf( "%s%s: %s\n", id, a, + v[i] ); + */ + } + ldap_value_free( v ); + ldap_memfree( a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( res ); + /* printf( "%s\n", id ); */ + } + + if ( rc == -1 || ldap_result2error( ld, res, 0 ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search" ); + } else { + printf( "%sDone with one round\n", id ); + } + + if ( rc == -1 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + if ( CONNECTION_ERROR( rc ) && simplebind( ld, + "bind-search_thread", 5 ) != LDAP_SUCCESS ) { + return; + } + } + } +} + +static void +modify_thread( void *arg1 ) +{ + LDAPMessage *res; + LDAPMessage *e; + int i, modentry, entries, msgid, rc; + LDAPMod mod; + LDAPMod *mods[2]; + char *vals[2]; + char *dn; + char *id = arg1; + ldapmsgwrapper *list, *lmwp, *lastlmwp; + + printf( "modify_thread\n" ); + tsd_setup(); + if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, + "(objectclass=*)", NULL, 0 )) == -1 ) { + ldap_perror( ld, "ldap_search_s" ); + exit( 1 ); + } + entries = 0; + list = lastlmwp = NULL; + while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) + == LDAP_RES_SEARCH_ENTRY ) { + entries++; + if (( lmwp = (ldapmsgwrapper *) + malloc( sizeof( ldapmsgwrapper ))) == NULL ) { + perror( "modify_thread: malloc" ); + exit( 1 ); + } + lmwp->lmw_messagep = res; + lmwp->lmw_next = NULL; + if ( lastlmwp == NULL ) { + list = lastlmwp = lmwp; + } else { + lastlmwp->lmw_next = lmwp; + } + lastlmwp = lmwp; + } + if ( rc == -1 || ldap_result2error( ld, res, 0 ) != LDAP_SUCCESS ) { + ldap_perror( ld, "modify_thread: ldap_search" ); + exit( 1 ); + } else { + entries++; + printf( "%sModify got %d entries\n", id, entries ); + } + + mods[0] = &mod; + mods[1] = NULL; + vals[0] = "bar"; + vals[1] = NULL; + for ( ;; ) { + modentry = rand() % entries; + for ( i = 0, lmwp = list; lmwp != NULL && i < modentry; + i++, lmwp = lmwp->lmw_next ) { + /* NULL */ + } + + if ( lmwp == NULL ) { + fprintf( stderr, + "%sModify could not find entry %d of %d\n", + id, modentry, entries ); + continue; + } + e = lmwp->lmw_messagep; + printf( "%sPicked entry %d of %d\n", id, i, entries ); + dn = ldap_get_dn( ld, e ); + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = "description"; + mod.mod_values = vals; + printf( "%sModifying (%s)\n", id, dn ); + if (( rc = ldap_modify_s( ld, dn, mods )) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_modify_s" ); + if ( CONNECTION_ERROR( rc ) && simplebind( ld, + "bind-modify_thread", 5 ) != LDAP_SUCCESS ) { + return; + } + } + free( dn ); + } +} + +static void +add_thread( void *arg1 ) +{ + LDAPMod mod[5]; + LDAPMod *mods[6]; + char dn[BUFSIZ], name[40]; + char *cnvals[2], *snvals[2], *ocvals[2]; + int i, rc; + char *id = arg1; + + printf( "add_thread\n" ); + tsd_setup(); + for ( i = 0; i < 5; i++ ) { + mods[i] = &mod[i]; + } + mods[5] = NULL; + mod[0].mod_op = 0; + mod[0].mod_type = "cn"; + mod[0].mod_values = cnvals; + cnvals[1] = NULL; + mod[1].mod_op = 0; + mod[1].mod_type = "sn"; + mod[1].mod_values = snvals; + snvals[1] = NULL; + mod[2].mod_op = 0; + mod[2].mod_type = "objectclass"; + mod[2].mod_values = ocvals; + ocvals[0] = "person"; + ocvals[1] = NULL; + mods[3] = NULL; + + for ( ;; ) { + sprintf( name, "%d", rand() ); + sprintf( dn, "cn=%s, " BASE, name ); + cnvals[0] = name; + snvals[0] = name; + + printf( "%sAdding entry (%s)\n", id, dn ); + if (( rc = ldap_add_s( ld, dn, mods )) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_add_s" ); + if ( CONNECTION_ERROR( rc ) && simplebind( ld, + "bind-add_thread", 5 ) != LDAP_SUCCESS ) { + return; + } + } + } +} + +static void +delete_thread( void *arg1 ) +{ + LDAPMessage *res; + char dn[BUFSIZ], name[40]; + int entries, msgid, rc; + char *id = arg1; + + printf( "delete_thread\n" ); + tsd_setup(); + if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, + "(objectclass=*)", NULL, 0 )) == -1 ) { + ldap_perror( ld, "delete_thread: ldap_search_s" ); + exit( 1 ); + } + entries = 0; + while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) + == LDAP_RES_SEARCH_ENTRY ) { + entries++; + ldap_msgfree( res ); + } + entries++; + if ( rc == -1 || ldap_result2error( ld, res, 1 ) != LDAP_SUCCESS ) { + ldap_perror( ld, "delete_thread: ldap_search" ); + } else { + printf( "%sDelete got %d entries\n", id, entries ); + } + + for ( ;; ) { + sprintf( name, "%d", rand() ); + sprintf( dn, "cn=%s, " BASE, name ); + + printf( "%sDeleting entry (%s)\n", id, dn ); + if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_delete_s" ); + if ( CONNECTION_ERROR( rc ) && simplebind( ld, + "bind-delete_thread", 5 ) != LDAP_SUCCESS ) { + return; + } + } + } +} + +struct ldap_error { + int le_errno; + char *le_matched; + char *le_errmsg; +}; + +static void +tsd_setup() +{ + void *tsd; + + tsd = (void *) PR_GetThreadPrivate( tsdindex ); + if ( tsd != NULL ) { + fprintf( stderr, "tsd non-null!\n" ); + exit( 1 ); + } + tsd = (void *) calloc( 1, sizeof(struct ldap_error) ); + if ( PR_SetThreadPrivate( tsdindex, tsd ) != 0 ) { + perror( "PR_SetThreadPrivate" ); + exit( 1 ); + } +} + +static void +set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + struct ldap_error *le; + + le = (void *) PR_GetThreadPrivate( tsdindex ); + le->le_errno = err; + if ( le->le_matched != NULL ) { + ldap_memfree( le->le_matched ); + } + le->le_matched = matched; + if ( le->le_errmsg != NULL ) { + ldap_memfree( le->le_errmsg ); + } + le->le_errmsg = errmsg; +} + +static int +get_ld_error( char **matchedp, char **errmsgp, void *dummy ) +{ + struct ldap_error *le; + + le = PR_GetThreadPrivate( tsdindex ); + if ( matchedp != NULL ) { + *matchedp = le->le_matched; + } + if ( errmsgp != NULL ) { + *errmsgp = le->le_errmsg; + } + return( le->le_errno ); +} + +static void +set_errno( int oserrno ) +{ + /* XXXmcs: should this be PR_SetError( oserrno, 0 )? */ + PR_SetError( PR_UNKNOWN_ERROR, oserrno ); +} + +static int +get_errno( void ) +{ + /* XXXmcs: should this be PR_GetError()? */ + return( PR_GetOSError()); +} + +static void * +my_mutex_alloc( void ) +{ + return( (void *)PR_NewLock()); +} + +static void +my_mutex_free( void *mutex ) +{ + PR_DestroyLock( (PRLock *)mutex ); +} + +static int +my_mutex_lock( void *mutex ) +{ + PR_Lock( (PRLock *)mutex ); + return( 0 ); +} + +static int +my_mutex_unlock( void *mutex ) +{ + if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) { + return( -1 ); + } + + return( 0 ); +} + +static LDAPHostEnt * +my_gethostbyname( const char *name, LDAPHostEnt *result, + char *buffer, int buflen, int *statusp, void *extradata ) +{ + PRHostEnt prhent; + + if ( PR_GetHostByName( name, buffer, buflen, + &prhent ) != PR_SUCCESS ) { + return( NULL ); + } + + return( copyPRHostEnt2LDAPHostEnt( result, &prhent )); +} + +static LDAPHostEnt * +my_gethostbyaddr( const char *addr, int length, int type, LDAPHostEnt *result, + char *buffer, int buflen, int *statusp, void *extradata ) +{ + PRHostEnt prhent; + + if ( PR_GetHostByAddr( (PRNetAddr *)addr, buffer, buflen, + &prhent ) != PR_SUCCESS ) { + return( NULL ); + } + + return( copyPRHostEnt2LDAPHostEnt( result, &prhent )); +} + +static LDAPHostEnt * +copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp, PRHostEnt *prhp ) +{ + ldhp->ldaphe_name = prhp->h_name; + ldhp->ldaphe_aliases = prhp->h_aliases; + ldhp->ldaphe_addrtype = prhp->h_addrtype; + ldhp->ldaphe_length = prhp->h_length; + ldhp->ldaphe_addr_list = prhp->h_addr_list; + return( ldhp ); +} diff --git a/ldap/c-sdk/libldap/open.c b/ldap/c-sdk/libldap/open.c new file mode 100644 index 0000000000..06cb629cbb --- /dev/null +++ b/ldap/c-sdk/libldap/open.c @@ -0,0 +1,912 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * open.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" +#ifdef LDAP_SASLIO_HOOKS +/* Valid for any ANSI C compiler */ +#include +extern sasl_callback_t client_callbacks[]; +#endif + +#define VI_PRODUCTVERSION 3 + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK ((unsigned long) 0x7f000001) +#endif + +#ifdef LDAP_DEBUG +int ldap_debug = 0; +#endif + +#ifdef _WINDOWS +#define USE_WINDOWS_TLS /* thread local storage */ +#endif + +/* + * global defaults for callbacks are stored here. callers of the API set + * these by passing a NULL "ld" to ldap_set_option(). Everything in + * nsldapi_ld_defaults can be overridden on a per-ld basis as well (the + * memory allocation functions are global to all ld's). + */ +struct ldap nsldapi_ld_defaults; +struct ldap_memalloc_fns nsldapi_memalloc_fns = { 0, 0, 0, 0 }; +int nsldapi_initialized = 0; + +#ifdef USE_PTHREADS +#include +#ifdef VMS +/* +** pthread_self() is not a routine on OpenVMS; it's inline assembler code. +** Since we need a real address which we can stuff away into a table, we need +** to make sure that pthread_self maps to the real pthread_self routine (yes, +** we do have one fortunately). +*/ +#undef pthread_self +#define pthread_self PTHREAD_SELF +extern pthread_t pthread_self (void); +#endif +static pthread_key_t nsldapi_key; +static pthread_mutex_t nsldapi_init_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct nsldapi_ldap_error { + int le_errno; + char *le_matched; + char *le_errmsg; +}; +#elif defined (USE_WINDOWS_TLS) +static DWORD dwTlsIndex; +struct nsldapi_ldap_error { + int le_errno; + char *le_matched; + char *le_errmsg; +}; +#elif defined (_WINDOWS) /* use static tls */ +__declspec ( thread ) int nsldapi_gldaperrno; +__declspec ( thread ) char *nsldapi_gmatched = NULL; +__declspec ( thread ) char *nsldapi_gldaperror = NULL; +#endif /* USE_WINDOWS_TLS */ + + +#ifdef _WINDOWS +#define LDAP_MUTEX_T HANDLE +static LDAP_MUTEX_T nsldapi_init_mutex; + +int +pthread_mutex_init( LDAP_MUTEX_T *mp, void *attr) +{ + if ( (*mp = CreateMutex(NULL, FALSE, NULL)) == NULL ) + return( 1 ); + else + return( 0 ); +} + +static void * +pthread_mutex_alloc( void ) +{ + LDAP_MUTEX_T *mutexp; + + if ( (mutexp = malloc( sizeof(LDAP_MUTEX_T) )) != NULL ) { + pthread_mutex_init( mutexp, NULL ); + } + return( mutexp ); +} + +int +pthread_mutex_destroy( LDAP_MUTEX_T *mp ) +{ + if ( !(CloseHandle(*mp)) ) + return( 1 ); + else + return( 0 ); +} + +static void +pthread_mutex_free( void *mutexp ) +{ + pthread_mutex_destroy( (LDAP_MUTEX_T *) mutexp ); + free( mutexp ); +} + +int +pthread_mutex_lock( LDAP_MUTEX_T *mp ) +{ + if ( (WaitForSingleObject(*mp, INFINITE) != WAIT_OBJECT_0) ) + return( 1 ); + else + return( 0 ); +} + +int +pthread_mutex_unlock( LDAP_MUTEX_T *mp ) +{ + if ( !(ReleaseMutex(*mp)) ) + return( 1 ); + else + return( 0 ); +} + +static int +get_errno( void ) +{ + return errno; +} + +static void +set_errno( int Errno ) +{ + errno = Errno; +} + +#ifdef USE_WINDOWS_TLS +static void +set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + struct nsldapi_ldap_error *le; + void *tsd; + + le = TlsGetValue( dwTlsIndex ); + + if (le == NULL) { + tsd = (void *)calloc(1, sizeof(struct nsldapi_ldap_error)); + TlsSetValue( dwTlsIndex, tsd ); + } + + le = TlsGetValue ( dwTlsIndex ); + + if (le == NULL) + return; + + le->le_errno = err; + + if ( le->le_matched != NULL ) { + ldap_memfree( le->le_matched ); + } + le->le_matched = matched; + + if ( le->le_errmsg != NULL ) { + ldap_memfree( le->le_errmsg ); + } + le->le_errmsg = errmsg; +} + +static int +get_ld_error ( char **matched, char **errmsg, void *dummy ) +{ + struct nsldapi_ldap_error *le; + + le = TlsGetValue( dwTlsIndex ); + if ( matched != NULL ) { + *matched = le->le_matched; + } + + if ( errmsg != NULL ) { + *errmsg = le->le_errmsg; + } + + return( le->le_errno ); +} +#else +static int +get_ld_error( char **LDMatched, char **LDError, void * Args ) +{ + if ( LDMatched != NULL ) + { + *LDMatched = nsldapi_gmatched; + } + if ( LDError != NULL ) + { + *LDError = nsldapi_gldaperror; + } + return nsldapi_gldaperrno; +} + +static void +set_ld_error( int LDErrno, char * LDMatched, char * LDError, + void * Args ) +{ + /* Clean up any previous string storage. */ + if ( nsldapi_gmatched != NULL ) + { + ldap_memfree( nsldapi_gmatched ); + } + if ( nsldapi_gldaperror != NULL ) + { + ldap_memfree( nsldapi_gldaperror ); + } + + nsldapi_gldaperrno = LDErrno; + nsldapi_gmatched = LDMatched; + nsldapi_gldaperror = LDError; +} +#endif /* USE_WINDOWS_TLS */ +#endif /* ! _WINDOWS */ + +#ifdef USE_PTHREADS +static void * +pthread_mutex_alloc( void ) +{ + pthread_mutex_t *mutexp; + + if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { + pthread_mutex_init( mutexp, NULL ); + } + return( mutexp ); +} + +static void +pthread_mutex_free( void *mutexp ) +{ + pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); + free( mutexp ); +} + +static void +set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + struct nsldapi_ldap_error *le; + void *tsd; + + le = pthread_getspecific( nsldapi_key ); + + if (le == NULL) { + tsd = (void *)calloc(1, sizeof(struct nsldapi_ldap_error)); + pthread_setspecific( nsldapi_key, tsd ); + } + + le = pthread_getspecific( nsldapi_key ); + + if (le == NULL) + return; + + le->le_errno = err; + + if ( le->le_matched != NULL ) { + ldap_memfree( le->le_matched ); + } + le->le_matched = matched; + + if ( le->le_errmsg != NULL ) { + ldap_memfree( le->le_errmsg ); + } + le->le_errmsg = errmsg; +} + +static int +get_ld_error( char **matched, char **errmsg, void *dummy ) +{ + struct nsldapi_ldap_error *le; + + le = pthread_getspecific( nsldapi_key ); + + if (le == NULL) + return( LDAP_SUCCESS ); + + if ( matched != NULL ) { + *matched = le->le_matched; + } + if ( errmsg != NULL ) { + *errmsg = le->le_errmsg; + } + return( le->le_errno ); +} + +static void +set_errno( int err ) +{ + errno = err; +} + +static int +get_errno( void ) +{ + return( errno ); +} +#endif /* use_pthreads */ + +#if defined(USE_PTHREADS) || defined(_WINDOWS) +static struct ldap_thread_fns + nsldapi_default_thread_fns = { + (void *(*)(void))pthread_mutex_alloc, + (void (*)(void *))pthread_mutex_free, + (int (*)(void *))pthread_mutex_lock, + (int (*)(void *))pthread_mutex_unlock, + (int (*)(void))get_errno, + (void (*)(int))set_errno, + (int (*)(char **, char **, void *))get_ld_error, + (void (*)(int, char *, char *, void *))set_ld_error, + 0 }; + +static struct ldap_extra_thread_fns + nsldapi_default_extra_thread_fns = { + 0, 0, 0, 0, 0, +#ifdef _WINDOWS + 0 +#else + (void *(*)(void))pthread_self +#endif /* _WINDOWS */ + }; +#endif /* use_pthreads || _windows */ + +void +nsldapi_initialize_defaults( void ) +{ +#ifdef _WINDOWS + pthread_mutex_init( &nsldapi_init_mutex, NULL ); +#endif /* _WINDOWS */ + +#if defined(USE_PTHREADS) || defined(_WINDOWS) + pthread_mutex_lock( &nsldapi_init_mutex ); + + if ( nsldapi_initialized ) { + pthread_mutex_unlock( &nsldapi_init_mutex ); + return; + } +#else + if ( nsldapi_initialized ) { + return; + } +#endif /* use_pthreads || _windows */ + +#ifdef USE_PTHREADS + if ( pthread_key_create(&nsldapi_key, free ) != 0) { + perror("pthread_key_create"); + } +#elif defined(USE_WINDOWS_TLS) + dwTlsIndex = TlsAlloc(); +#endif /* USE_WINDOWS_TLS */ + + memset( &nsldapi_memalloc_fns, 0, sizeof( nsldapi_memalloc_fns )); + memset( &nsldapi_ld_defaults, 0, sizeof( nsldapi_ld_defaults )); + nsldapi_ld_defaults.ld_options = LDAP_BITOPT_REFERRALS; + nsldapi_ld_defaults.ld_version = LDAP_VERSION3; + nsldapi_ld_defaults.ld_lberoptions = LBER_OPT_USE_DER; + nsldapi_ld_defaults.ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; + +#ifdef LDAP_SASLIO_HOOKS + /* SASL default option settings */ + nsldapi_ld_defaults.ld_def_sasl_mech = NULL; + nsldapi_ld_defaults.ld_def_sasl_realm = NULL; + nsldapi_ld_defaults.ld_def_sasl_authcid = NULL; + nsldapi_ld_defaults.ld_def_sasl_authzid = NULL; + /* SASL Security properties */ + nsldapi_ld_defaults.ld_sasl_secprops.max_ssf = UINT_MAX; + nsldapi_ld_defaults.ld_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE; + nsldapi_ld_defaults.ld_sasl_secprops.security_flags = + SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; + + /* SASL mutex function callbacks */ + sasl_set_mutex( + (sasl_mutex_alloc_t *)nsldapi_default_thread_fns.ltf_mutex_alloc, + (sasl_mutex_lock_t *)nsldapi_default_thread_fns.ltf_mutex_lock, + (sasl_mutex_unlock_t *)nsldapi_default_thread_fns.ltf_mutex_unlock, + (sasl_mutex_free_t *)nsldapi_default_thread_fns.ltf_mutex_free ); + + /* SASL memory allocation function callbacks */ + sasl_set_alloc( + (sasl_malloc_t *)ldap_x_malloc, + (sasl_calloc_t *)ldap_x_calloc, + (sasl_realloc_t *)ldap_x_realloc, + (sasl_free_t *)ldap_x_free ); + + /* SASL library initialization */ + if ( sasl_client_init( client_callbacks ) != SASL_OK ) { + nsldapi_initialized = 0; + pthread_mutex_unlock( &nsldapi_init_mutex ); + return; + } +#endif + +#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET ) + nsldapi_ld_defaults.ld_lberoptions |= LBER_OPT_TRANSLATE_STRINGS; +#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET + ldap_set_string_translators( &nsldapi_ld_defaults, ldap_8859_to_t61, + ldap_t61_to_8859 ); +#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */ +#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */ + + /* set default connect timeout (in milliseconds) */ + /* this was picked as it is the standard tcp timeout as well */ + nsldapi_ld_defaults.ld_connect_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; + +#if defined(USE_PTHREADS) || defined(_WINDOWS) + /* load up default platform specific locking routines */ + if (ldap_set_option( &nsldapi_ld_defaults, LDAP_OPT_THREAD_FN_PTRS, + (void *)&nsldapi_default_thread_fns) != LDAP_SUCCESS) { + nsldapi_initialized = 0; + pthread_mutex_unlock( &nsldapi_init_mutex ); + return; + } + +#ifndef _WINDOWS + /* load up default threadid function */ + if (ldap_set_option( &nsldapi_ld_defaults, LDAP_OPT_EXTRA_THREAD_FN_PTRS, + (void *)&nsldapi_default_extra_thread_fns) != LDAP_SUCCESS) { + nsldapi_initialized = 0; + pthread_mutex_unlock( &nsldapi_init_mutex ); + return; + } +#endif /* _WINDOWS */ + nsldapi_initialized = 1; + pthread_mutex_unlock( &nsldapi_init_mutex ); +#else + nsldapi_initialized = 1; +#endif /* use_pthreads || _windows */ +} + + +/* + * ldap_version - report version levels for important properties + * This function is deprecated. Use ldap_get_option( ..., LDAP_OPT_API_INFO, + * ... ) instead. + * + * Example: + * LDAPVersion ver; + * ldap_version( &ver ); + * if ( (ver.sdk_version < 100) || (ver.SSL_version < 300) ) + * fprintf( stderr, "LDAP SDK level insufficient\n" ); + * + * or: + * if ( ldap_version(NULL) < 100 ) + * fprintf( stderr, "LDAP SDK level insufficient\n" ); + * + */ + +int +LDAP_CALL +ldap_version( LDAPVersion *ver ) +{ + if ( NULL != ver ) + { + memset( ver, 0, sizeof(*ver) ); + ver->sdk_version = (int)(VI_PRODUCTVERSION * 100); + ver->protocol_version = LDAP_VERSION_MAX * 100; + ver->SSL_version = SSL_VERSION * 100; + /* + * set security to none by default + */ + + ver->security_level = LDAP_SECURITY_NONE; +#if defined(LINK_SSL) +#if defined(NS_DOMESTIC) + ver->security_level = 128; +#elif defined(NSS_EXPORT) + ver->security_level = 40; +#endif +#endif + + } + return (int)(VI_PRODUCTVERSION * 100); +} + +/* + * ldap_open - initialize and connect to an ldap server. 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( hostname, port ); + */ + +LDAP * +LDAP_CALL +ldap_open( const char *host, int port ) +{ + LDAP *ld; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 ); + + if (( ld = ldap_init( host, port )) == NULL ) { + return( NULL ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + ldap_ld_free( ld, NULL, NULL, 0 ); + return( NULL ); + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n", + ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); + + return( ld ); +} + + +/* + * ldap_init - initialize the LDAP library. A magic cookie to be used for + * future communication is returned on success, NULL on failure. + * "defhost" may be a space-separated list of hosts or IP addresses + * + * NOTE: If you want to use IPv6, you must use prldap creating a LDAP handle + * with prldap_init instead of ldap_init. Or install the NSPR functions + * by calling prldap_install_routines. (See the nspr samples in examples) + * + * Example: + * LDAP *ld; + * ld = ldap_init( default_hostname, default_port ); + */ +LDAP * +LDAP_CALL +ldap_init( const char *defhost, int defport ) +{ + LDAP *ld; + + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + + if ( defport < 0 || defport > LDAP_PORT_MAX ) { + LDAPDebug( LDAP_DEBUG_ANY, + "ldap_init: port %d is invalid (port numbers must range from 1 to %d)\n", + defport, LDAP_PORT_MAX, 0 ); +#if !defined( macintosh ) && !defined( DOS ) && !defined( BEOS ) + errno = EINVAL; +#endif + return( NULL ); + } + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); + + if ( (ld = (LDAP*)NSLDAPI_MALLOC( sizeof(struct ldap) )) == NULL ) { + return( NULL ); + } + + /* copy defaults */ + SAFEMEMCPY( ld, &nsldapi_ld_defaults, sizeof( struct ldap )); + if ( nsldapi_ld_defaults.ld_io_fns_ptr != NULL ) { + if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_MALLOC( + sizeof( struct ldap_io_fns ))) == NULL ) { + NSLDAPI_FREE( (char *)ld ); + return( NULL ); + } + /* struct copy */ + *(ld->ld_io_fns_ptr) = *(nsldapi_ld_defaults.ld_io_fns_ptr); + } + + /* call the new handle I/O callback if one is defined */ + if ( ld->ld_extnewhandle_fn != NULL ) { + /* + * We always pass the session extended I/O argument to + * the new handle callback. + */ + if ( ld->ld_extnewhandle_fn( ld, ld->ld_ext_session_arg ) + != LDAP_SUCCESS ) { + NSLDAPI_FREE( (char*)ld ); + return( NULL ); + } + } + + /* allocate session-specific resources */ + if (( ld->ld_sbp = ber_sockbuf_alloc()) == NULL || + ( defhost != NULL && + ( ld->ld_defhost = nsldapi_strdup( defhost )) == NULL ) || + ((ld->ld_mutex = (void **) NSLDAPI_CALLOC( LDAP_MAX_LOCK, sizeof(void *))) == NULL )) { + if ( ld->ld_sbp != NULL ) { + ber_sockbuf_free( ld->ld_sbp ); + } + if( ld->ld_mutex != NULL ) { + NSLDAPI_FREE( ld->ld_mutex ); + } + NSLDAPI_FREE( (char*)ld ); + return( NULL ); + } + + /* install Sockbuf I/O functions if set in LDAP * */ + if ( ld->ld_extread_fn != NULL || ld->ld_extwrite_fn != NULL ) { + struct lber_x_ext_io_fns lberiofns; + + memset( &lberiofns, 0, sizeof( lberiofns )); + + lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + lberiofns.lbextiofn_read = ld->ld_extread_fn; + lberiofns.lbextiofn_write = ld->ld_extwrite_fn; + lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; + lberiofns.lbextiofn_socket_arg = NULL; + ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&lberiofns ); + } + + /* allocate mutexes */ + nsldapi_mutex_alloc_all( ld ); + + /* set default port */ + ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport; + + return( ld ); +} + + +void +nsldapi_mutex_alloc_all( LDAP *ld ) +{ + int i; + + if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { + for ( i = 0; ild_mutex[i] = LDAP_MUTEX_ALLOC( ld ); + ld->ld_mutex_threadid[i] = (void *) -1; + ld->ld_mutex_refcnt[i] = 0; + } + } +} + + +void +nsldapi_mutex_free_all( LDAP *ld ) +{ + int i; + + if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { + for ( i = 0; ild_mutex[i] ); + } + } +} + + +/* returns 0 if connection opened and -1 if an error occurs */ +int +nsldapi_open_ldap_defconn( LDAP *ld ) +{ + LDAPServer *srv; + + if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == + NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = + nsldapi_strdup( ld->ld_defhost )) == NULL )) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + srv->lsrv_port = ld->ld_defport; + + if (( ld->ld_options & LDAP_BITOPT_SSL ) != 0 ) { + srv->lsrv_options |= LDAP_SRV_OPT_SECURE; + } + + if (( ld->ld_defconn = nsldapi_new_connection( ld, &srv, 1, 1, 0 )) + == NULL ) { + if ( ld->ld_defhost != NULL ) { + NSLDAPI_FREE( srv->lsrv_host ); + } + NSLDAPI_FREE( (char *)srv ); + return( -1 ); + } + ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ + + return( 0 ); +} + + +struct ldap_x_hostlist_status { + char *lhs_hostlist; + char *lhs_nexthost; + int lhs_defport; +}; + +/* + * Return the first host and port in hostlist (setting *hostp and *portp). + * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). + * Note that a NULL or zero-length hostlist causes the host "127.0.0.1" to + * be returned. + */ +int LDAP_CALL +ldap_x_hostlist_first( const char *hostlist, int defport, char **hostp, + int *portp, struct ldap_x_hostlist_status **statusp ) +{ + + if ( NULL == hostp || NULL == portp || NULL == statusp ) { + return( LDAP_PARAM_ERROR ); + } + + if ( NULL == hostlist || *hostlist == '\0' ) { + *hostp = nsldapi_strdup( "127.0.0.1" ); + if ( NULL == *hostp ) { + return( LDAP_NO_MEMORY ); + } + *portp = defport; + *statusp = NULL; + return( LDAP_SUCCESS ); + } + + *statusp = NSLDAPI_CALLOC( 1, sizeof( struct ldap_x_hostlist_status )); + if ( NULL == *statusp ) { + return( LDAP_NO_MEMORY ); + } + (*statusp)->lhs_hostlist = nsldapi_strdup( hostlist ); + if ( NULL == (*statusp)->lhs_hostlist ) { + return( LDAP_NO_MEMORY ); + } + (*statusp)->lhs_nexthost = (*statusp)->lhs_hostlist; + (*statusp)->lhs_defport = defport; + return( ldap_x_hostlist_next( hostp, portp, *statusp )); +} + +/* + * Return the next host and port in hostlist (setting *hostp and *portp). + * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). + * If no more hosts are available, LDAP_SUCCESS is returned but *hostp is set + * to NULL. + */ +int LDAP_CALL +ldap_x_hostlist_next( char **hostp, int *portp, + struct ldap_x_hostlist_status *status ) +{ + char *q; + int squarebrackets = 0; + + if ( NULL == hostp || NULL == portp ) { + return( LDAP_PARAM_ERROR ); + } + + if ( NULL == status || NULL == status->lhs_nexthost ) { + *hostp = NULL; + return( LDAP_SUCCESS ); + } + + /* + * skip past leading '[' if present (IPv6 addresses may be surrounded + * with square brackets, e.g., [fe80::a00:20ff:fee5:c0b4]:389 + */ + if ( status->lhs_nexthost[0] == '[' ) { + ++status->lhs_nexthost; + squarebrackets = 1; + } + + /* copy host into *hostp */ + if ( NULL != ( q = strchr( status->lhs_nexthost, ' ' ))) { + size_t len = q - status->lhs_nexthost; + *hostp = NSLDAPI_MALLOC( len + 1 ); + if ( NULL == *hostp ) { + return( LDAP_NO_MEMORY ); + } + strncpy( *hostp, status->lhs_nexthost, len ); + (*hostp)[len] = '\0'; + status->lhs_nexthost += ( len + 1 ); + } else { /* last host */ + *hostp = nsldapi_strdup( status->lhs_nexthost ); + if ( NULL == *hostp ) { + return( LDAP_NO_MEMORY ); + } + status->lhs_nexthost = NULL; + } + + /* + * Look for closing ']' and skip past it before looking for port. + */ + if ( squarebrackets && NULL != ( q = strchr( *hostp, ']' ))) { + *q++ = '\0'; + } else { + q = *hostp; + } + + /* determine and set port */ + if ( NULL != ( q = strchr( q, ':' ))) { + *q++ = '\0'; + *portp = atoi( q ); + } else { + *portp = status->lhs_defport; + } + + return( LDAP_SUCCESS ); +} + + +void LDAP_CALL +ldap_x_hostlist_statusfree( struct ldap_x_hostlist_status *status ) +{ + if ( NULL != status ) { + if ( NULL != status->lhs_hostlist ) { + NSLDAPI_FREE( status->lhs_hostlist ); + } + NSLDAPI_FREE( status ); + } +} + + + +/* + * memory allocation functions. we include these in open.c since every + * LDAP application is likely to pull the rest of the code in this file + * in anyways. + */ +void * +ldap_x_malloc( size_t size ) +{ + return( nsldapi_memalloc_fns.ldapmem_malloc == NULL ? + malloc( size ) : + nsldapi_memalloc_fns.ldapmem_malloc( size )); +} + + +void * +ldap_x_calloc( size_t nelem, size_t elsize ) +{ + return( nsldapi_memalloc_fns.ldapmem_calloc == NULL ? + calloc( nelem, elsize ) : + nsldapi_memalloc_fns.ldapmem_calloc( nelem, elsize )); +} + + +void * +ldap_x_realloc( void *ptr, size_t size ) +{ + return( nsldapi_memalloc_fns.ldapmem_realloc == NULL ? + realloc( ptr, size ) : + nsldapi_memalloc_fns.ldapmem_realloc( ptr, size )); +} + + +void +ldap_x_free( void *ptr ) +{ + if ( nsldapi_memalloc_fns.ldapmem_free == NULL ) { + free( ptr ); + } else { + nsldapi_memalloc_fns.ldapmem_free( ptr ); + } +} + + +/* if s is NULL, returns NULL */ +char * +nsldapi_strdup( const char *s ) +{ + char *p; + + if ( s == NULL || + (p = (char *)NSLDAPI_MALLOC( strlen( s ) + 1 )) == NULL ) + return( NULL ); + + strcpy( p, s ); + + return( p ); +} diff --git a/ldap/c-sdk/libldap/os-ip.c b/ldap/c-sdk/libldap/os-ip.c new file mode 100644 index 0000000000..2e70139be3 --- /dev/null +++ b/ldap/c-sdk/libldap/os-ip.c @@ -0,0 +1,1862 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * os-ip.c -- platform-specific TCP & UDP related code + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +/* + * On platforms where poll() does not exist, we use select(). + * Therefore, we should increase the number of file descriptors + * we can use by #defining FD_SETSIZE to a large number before + * we include or its equivalent. We do not need + * to do this for Windows, because on that platform there is no + * relationship between FD_SETSIZE and the highest numbered file + * descriptor we can use. See the document fdsetsize.txt in + * this directory for a description of the setting of FD_SETSIZE + * for the OS'es we care about. + */ +#ifndef NSLDAPI_HAVE_POLL +/* XXX value for BSDI? */ +/* XXX value for macintosh (if applicable)? */ +#endif + +#include "ldap-int.h" +#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED +#include +#endif + +#ifdef NSLDAPI_HAVE_POLL +#include +#endif + + +#ifdef _WINDOWS +#define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) == INVALID_SOCKET) +#else +#define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) < 0 ) +#endif + + +#define NSLDAPI_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ + + +/* + * Structures and union for tracking status of network sockets + */ +#ifdef NSLDAPI_HAVE_POLL +struct nsldapi_os_statusinfo { /* used with native OS poll() */ + struct pollfd *ossi_pollfds; + int ossi_pollfds_size; +}; +#else /* NSLDAPI_HAVE_POLL */ +struct nsldapi_os_statusinfo { /* used with native OS select() */ + fd_set ossi_readfds; + fd_set ossi_writefds; + fd_set ossi_use_readfds; + fd_set ossi_use_writefds; +}; +#endif /* else NSLDAPI_HAVE_POLL */ + +struct nsldapi_cb_statusinfo { /* used with ext. I/O poll() callback */ + LDAP_X_PollFD *cbsi_pollfds; + int cbsi_pollfds_size; +}; + +/* + * NSLDAPI_CB_POLL_MATCH() evaluates to non-zero (true) if the Sockbuf *sdp + * matches the LDAP_X_PollFD pollfd. + */ +#ifdef _WINDOWS +#define NSLDAPI_CB_POLL_SD_CAST (unsigned int) +#else +#define NSLDAPI_CB_POLL_SD_CAST +#endif +#define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \ + ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd) && \ + (sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) + + +struct nsldapi_iostatus_info { + int ios_type; +#define NSLDAPI_IOSTATUS_TYPE_OSNATIVE 1 /* poll() or select() */ +#define NSLDAPI_IOSTATUS_TYPE_CALLBACK 2 /* poll()-like */ + int ios_read_count; + int ios_write_count; + union { + struct nsldapi_os_statusinfo ios_osinfo; + struct nsldapi_cb_statusinfo ios_cbinfo; + } ios_status; +}; + +#ifndef NSLDAPI_AVOID_OS_SOCKETS +#ifdef NSLDAPI_HAVE_POLL +static int nsldapi_add_to_os_pollfds( int fd, + struct nsldapi_os_statusinfo *pip, short events ); +static int nsldapi_clear_from_os_pollfds( int fd, + struct nsldapi_os_statusinfo *pip, short events ); +static int nsldapi_find_in_os_pollfds( int fd, + struct nsldapi_os_statusinfo *pip, short revents ); +#endif /* NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + +static int nsldapi_iostatus_init_nolock( LDAP *ld ); +static int nsldapi_add_to_cb_pollfds( Sockbuf *sb, + struct nsldapi_cb_statusinfo *pip, short events ); +static int nsldapi_clear_from_cb_pollfds( Sockbuf *sb, + struct nsldapi_cb_statusinfo *pip, short events ); +static int nsldapi_find_in_cb_pollfds( Sockbuf *sb, + struct nsldapi_cb_statusinfo *pip, short revents ); + + +#ifdef irix +#ifndef _PR_THREADS +/* + * XXXmcs: on IRIX NSPR's poll() and select() wrappers will crash if NSPR + * has not been initialized. We work around the problem by bypassing + * the NSPR wrapper functions and going directly to the OS' functions. + */ +#define NSLDAPI_POLL _poll +#define NSLDAPI_SELECT _select +extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); +extern int _select(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout); +#else /* _PR_THREADS */ +#define NSLDAPI_POLL poll +#define NSLDAPI_SELECT select +#endif /* else _PR_THREADS */ +#else /* irix */ +#define NSLDAPI_POLL poll +#define NSLDAPI_SELECT select +#endif /* else irix */ + + +static LBER_SOCKET nsldapi_os_socket( LDAP *ld, int secure, int domain, + int type, int protocol ); +static int nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp ); +static int nsldapi_os_connect_with_to( LBER_SOCKET s, struct sockaddr *name, + int namelen, int msec_timeout ); +#if defined(KERBEROS) +char * nsldapi_host_connected_to( LDAP *ld, Sockbuf *sb ); +#endif + +/* + * Function typedefs used by nsldapi_try_each_host() + */ +typedef LBER_SOCKET (NSLDAPI_SOCKET_FN)( LDAP *ld, int secure, int domain, + int type, int protocol ); +typedef int (NSLDAPI_IOCTL_FN)( LBER_SOCKET s, int option, int *statusp ); +typedef int (NSLDAPI_CONNECT_WITH_TO_FN )( LBER_SOCKET s, struct sockaddr *name, + int namelen, int msec_timeout ); +typedef int (NSLDAPI_CONNECT_FN )( LBER_SOCKET s, struct sockaddr *name, + int namelen ); +typedef int (NSLDAPI_CLOSE_FN )( LBER_SOCKET s ); + +static int nsldapi_try_each_host( LDAP *ld, const char *hostlist, int defport, + int secure, NSLDAPI_SOCKET_FN *socketfn, NSLDAPI_IOCTL_FN *ioctlfn, + NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn, + NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn ); + + +static int +nsldapi_os_closesocket( LBER_SOCKET s ) +{ + int rc; + +#ifdef NSLDAPI_AVOID_OS_SOCKETS + rc = -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef _WINDOWS + rc = closesocket( s ); +#else /* _WINDOWS */ + rc = close( s ); +#endif /* _WINDOWS */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + return( rc ); +} + + +static LBER_SOCKET +nsldapi_os_socket( LDAP *ld, int secure, int domain, int type, int protocol ) +{ +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ + int s, invalid_socket; + char *errmsg = NULL; + + if ( secure ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, + nsldapi_strdup( "secure mode not supported" )); + return( -1 ); + } + + s = socket( domain, type, protocol ); + + /* + * if the socket() call failed or it returned a socket larger + * than we can deal with, return a "local error." + */ + if ( NSLDAPI_INVALID_OS_SOCKET( s )) { + errmsg = "unable to create a socket"; + invalid_socket = 1; + } else { /* valid socket -- check for overflow */ + invalid_socket = 0; +#if !defined(NSLDAPI_HAVE_POLL) && !defined(_WINDOWS) + /* not on Windows and do not have poll() */ + if ( s >= FD_SETSIZE ) { + errmsg = "can't use socket >= FD_SETSIZE"; + } +#endif + } + + if ( errmsg != NULL ) { /* local socket error */ + if ( !invalid_socket ) { + nsldapi_os_closesocket( s ); + } + errmsg = nsldapi_strdup( errmsg ); + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, errmsg ); + return( -1 ); + } + + return( s ); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ +} + + + +/* + * Non-blocking connect call function + */ +static int +nsldapi_os_connect_with_to(LBER_SOCKET sockfd, struct sockaddr *saptr, + int salen, int msec) +{ +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ + int n, error; + int len; +#if defined(_WINDOWS) || defined(XP_OS2) + int nonblock = 1; + int block = 0; +#else + int flags; +#endif /* _WINDOWS */ +#ifdef NSLDAPI_HAVE_POLL + struct pollfd pfd; +#else + struct timeval tval; + fd_set rset, wset; +#ifdef _WINDOWS + fd_set eset; +#endif +#endif /* NSLDAPI_HAVE_POLL */ + + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_nonblock timeout: %d (msec)\n", + msec, 0, 0); + +#ifdef _WINDOWS + ioctlsocket(sockfd, FIONBIO, &nonblock); +#elif defined(XP_OS2) + ioctl( sockfd, FIONBIO, &nonblock, sizeof(nonblock) ); +#else + flags = fcntl(sockfd, F_GETFL, 0); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); +#endif /* _WINDOWS */ + + error = 0; + if ((n = connect(sockfd, saptr, salen)) < 0) +#ifdef _WINDOWS + if ((n != SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) { +#else + if (errno != EINPROGRESS) { +#endif /* _WINDOWS */ +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_TRACE ) { + perror("connect"); + } +#endif + return (-1); + } + + /* success */ + if (n == 0) + goto done; + +#ifdef NSLDAPI_HAVE_POLL + pfd.fd = sockfd; + pfd.events = POLLOUT; +#else + FD_ZERO(&rset); + FD_SET(sockfd, &rset); + wset = rset; + +#ifdef _WINDOWS + eset = rset; +#endif /* _WINDOWS */ +#endif /* NSLDAPI_HAVE_POLL */ + + if (msec < 0 && msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) { + LDAPDebug( LDAP_DEBUG_TRACE, "Invalid timeout value detected.." + "resetting connect timeout to default value " + "(LDAP_X_IO_TIMEOUT_NO_TIMEOUT\n", 0, 0, 0); + msec = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; +#ifndef NSLDAPI_HAVE_POLL + } else { + if (msec != 0) { + tval.tv_sec = msec / 1000; + tval.tv_usec = 1000 * ( msec % 1000 ); + } else { + tval.tv_sec = 0; + tval.tv_usec = 0; + } +#endif /* NSLDAPI_HAVE_POLL */ + } + +#ifdef NSLDAPI_HAVE_POLL + if ((n = poll(&pfd, 1, + (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? msec : -1)) == 0) { + errno = ETIMEDOUT; + return (-1); + } + if (pfd.revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { + len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) + < 0) + return (-1); +#ifdef LDAP_DEBUG + } else if ( ldap_debug & LDAP_DEBUG_TRACE ) { + perror("poll error: sockfd not set"); +#endif + } + +#else /* NSLDAPI_HAVE_POLL */ + /* if timeval structure == NULL, select will block indefinitely */ + /* != NULL, and value == 0, select will */ + /* not block */ + /* Windows is a bit quirky on how it behaves w.r.t nonblocking */ + /* connects. If the connect fails, the exception fd, eset, is */ + /* set to show the failure. The first argument in select is */ + /* ignored */ + +#ifdef _WINDOWS + if ((n = select(sockfd +1, &rset, &wset, &eset, + (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) { + errno = WSAETIMEDOUT; + return (-1); + } + /* if wset is set, the connect worked */ + if (FD_ISSET(sockfd, &wset) || FD_ISSET(sockfd, &rset)) { + len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) + < 0) + return (-1); + goto done; + } + + /* if eset is set, the connect failed */ + if (FD_ISSET(sockfd, &eset)) { + return (-1); + } + + /* failure on select call */ + if (n == SOCKET_ERROR) { + perror("select error: SOCKET_ERROR returned"); + return (-1); + } +#else + if ((n = select(sockfd +1, &rset, &wset, NULL, + (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) { + errno = ETIMEDOUT; + return (-1); + } + if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { + len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) + < 0) + return (-1); +#ifdef LDAP_DEBUG + } else if ( ldap_debug & LDAP_DEBUG_TRACE ) { + perror("select error: sockfd not set"); +#endif + } +#endif /* _WINDOWS */ +#endif /* NSLDAPI_HAVE_POLL */ + +done: +#ifdef _WINDOWS + ioctlsocket(sockfd, FIONBIO, &block); +#elif defined(XP_OS2) + ioctl( sockfd, FIONBIO, &nonblock, sizeof(block) ); +#else + fcntl(sockfd, F_SETFL, flags); +#endif /* _WINDOWS */ + + if (error) { + errno = error; + return (-1); + } + + return (0); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ +} + + +static int +nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp ) +{ +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ + int err; +#if defined(_WINDOWS) || defined(XP_OS2) + u_long iostatus; +#endif + + if ( FIONBIO != option ) { + return( -1 ); + } + +#ifdef _WINDOWS + iostatus = *(u_long *)statusp; + err = ioctlsocket( s, FIONBIO, &iostatus ); +#else +#ifdef XP_OS2 + err = ioctl( s, FIONBIO, (caddr_t)&iostatus, sizeof(iostatus) ); +#else + err = ioctl( s, FIONBIO, (caddr_t)statusp ); +#endif +#endif + + return( err ); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ +} + + +int +nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *hostlist, + int defport, int secure, char **krbinstancep ) +/* + * "defport" must be in host byte order + * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS + * if -1 is returned, ld_errno is set + */ +{ + int s; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_to_host: %s, port: %d\n", + NULL == hostlist ? "NULL" : hostlist, defport, 0 ); + + /* + * If an extended I/O connect callback has been defined, just use it. + */ + if ( NULL != ld->ld_extconnect_fn ) { + unsigned long connect_opts = 0; + + if ( ld->ld_options & LDAP_BITOPT_ASYNC) { + connect_opts |= LDAP_X_EXTIOF_OPT_NONBLOCKING; + } + if ( secure ) { + connect_opts |= LDAP_X_EXTIOF_OPT_SECURE; + } + s = ld->ld_extconnect_fn( hostlist, defport, + ld->ld_connect_timeout, connect_opts, + ld->ld_ext_session_arg, + &sb->sb_ext_io_fns.lbextiofn_socket_arg ); + + } else { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return( -1 ); +#else /* NSLDAPI_AVOID_OS_SOCKETS */ + s = nsldapi_try_each_host( ld, hostlist, + defport, secure, nsldapi_os_socket, + nsldapi_os_ioctl, nsldapi_os_connect_with_to, + NULL, nsldapi_os_closesocket ); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + } + + if ( s < 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL ); + return( -1 ); + } + + sb->sb_sd = s; + + /* + * Set krbinstancep (canonical name of host for use by Kerberos). + */ +#ifdef KERBEROS + char *p; + + if (( *krbinstancep = nsldapi_host_connected_to( sb )) != NULL + && ( p = strchr( *krbinstancep, '.' )) != NULL ) { + *p = '\0'; + } +#else /* KERBEROS */ + *krbinstancep = NULL; +#endif /* KERBEROS */ + + return( 0 ); +} + + +/* + * Returns a socket number if successful and -1 if an error occurs. + */ +static int +nsldapi_try_each_host( LDAP *ld, const char *hostlist, + int defport, int secure, NSLDAPI_SOCKET_FN *socketfn, + NSLDAPI_IOCTL_FN *ioctlfn, NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn, + NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn ) +{ +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ + int rc = -1; + int s = 0; + int i, err, connected, use_hp; + int parse_err, port; + struct sockaddr_in sin; + nsldapi_in_addr_t address; + char **addrlist, *ldhpbuf, *ldhpbuf_allocd = NULL; + char *host; + LDAPHostEnt ldhent, *ldhp; + struct hostent *hp; + struct ldap_x_hostlist_status *status; +#ifdef GETHOSTBYNAME_BUF_T + GETHOSTBYNAME_BUF_T hbuf; + struct hostent hent; +#endif /* GETHOSTBYNAME_BUF_T */ + + connected = 0; + parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, + &status ); + while ( !connected && LDAP_SUCCESS == parse_err && host != NULL ) { + ldhpbuf_allocd = NULL; + ldhp = NULL; + hp = NULL; + s = 0; + use_hp = 0; + addrlist = NULL; + + + if (( address = inet_addr( host )) == -1 ) { + if ( ld->ld_dns_gethostbyname_fn == NULL ) { +#ifdef GETHOSTBYNAME_R_RETURNS_INT + (void)GETHOSTBYNAME( host, &hent, hbuf, + sizeof(hbuf), &hp, &err ); +#else + hp = GETHOSTBYNAME( host, &hent, hbuf, + sizeof(hbuf), &err ); +#endif + if ( hp != NULL ) { + addrlist = hp->h_addr_list; + } + } else { + /* + * DNS callback installed... use it. + */ +#ifdef GETHOSTBYNAME_buf_t + /* avoid allocation by using hbuf if large enough */ + if ( sizeof( hbuf ) < ld->ld_dns_bufsize ) { + ldhpbuf = ldhpbuf_allocd + = NSLDAPI_MALLOC( ld->ld_dns_bufsize ); + } else { + ldhpbuf = (char *)hbuf; + } +#else /* GETHOSTBYNAME_buf_t */ + ldhpbuf = ldhpbuf_allocd = NSLDAPI_MALLOC( + ld->ld_dns_bufsize ); +#endif /* else GETHOSTBYNAME_buf_t */ + + if ( ldhpbuf == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, + NULL, NULL ); + ldap_memfree( host ); + ldap_x_hostlist_statusfree( status ); + return( -1 ); + } + + if (( ldhp = ld->ld_dns_gethostbyname_fn( host, + &ldhent, ldhpbuf, ld->ld_dns_bufsize, &err, + ld->ld_dns_extradata )) != NULL ) { + addrlist = ldhp->ldaphe_addr_list; + } + } + + if ( addrlist == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL ); + LDAP_SET_ERRNO( ld, EHOSTUNREACH ); /* close enough */ + if ( ldhpbuf_allocd != NULL ) { + NSLDAPI_FREE( ldhpbuf_allocd ); + } + ldap_memfree( host ); + ldap_x_hostlist_statusfree( status ); + return( -1 ); + } + use_hp = 1; + } + + rc = -1; + for ( i = 0; !use_hp || ( addrlist[ i ] != 0 ); i++ ) { + if ( -1 == ( s = (*socketfn)( ld, secure, AF_INET, + SOCK_STREAM, 0 ))) { + if ( ldhpbuf_allocd != NULL ) { + NSLDAPI_FREE( ldhpbuf_allocd ); + } + ldap_memfree( host ); + ldap_x_hostlist_statusfree( status ); + return( -1 ); + } + + if ( ld->ld_options & LDAP_BITOPT_ASYNC ) { + int iostatus = 1; + + err = (*ioctlfn)( s, FIONBIO, &iostatus ); + if ( err == -1 ) { + LDAPDebug( LDAP_DEBUG_ANY, + "FIONBIO ioctl failed on %d\n", + s, 0, 0 ); + } + } + + (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); + sin.sin_family = AF_INET; + sin.sin_port = htons( (unsigned short)port ); + + SAFEMEMCPY( (char *) &sin.sin_addr.s_addr, + ( use_hp ? (char *) addrlist[ i ] : + (char *) &address ), sizeof( sin.sin_addr.s_addr) ); + + { +#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED +/* + * Block all of the signals that might interrupt connect() since + * there is an OS bug that causes connect() to fail if it is restarted. + * Look in ../../include/portable.h for the definition of + * NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED. + */ + sigset_t ints_off, oldset; + + sigemptyset( &ints_off ); + sigaddset( &ints_off, SIGALRM ); + sigaddset( &ints_off, SIGIO ); + sigaddset( &ints_off, SIGCLD ); + + NSLDAPI_MT_SAFE_SIGPROCMASK( SIG_BLOCK, &ints_off, &oldset ); +#endif /* NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED */ + + if ( NULL != connectwithtofn ) { + err = (*connectwithtofn)(s, + (struct sockaddr *)&sin, + sizeof(struct sockaddr_in), + ld->ld_connect_timeout); + } else { + err = (*connectfn)(s, + (struct sockaddr *)&sin, + sizeof(struct sockaddr_in)); + } +#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED +/* + * restore original signal mask + */ + NSLDAPI_MT_SAFE_SIGPROCMASK( SIG_SETMASK, &oldset, 0 ); +#endif /* NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED */ + + } + if ( err >= 0 ) { + connected = 1; + rc = 0; + break; + } else { + if ( ld->ld_options & LDAP_BITOPT_ASYNC) { +#ifdef _WINDOWS + if (err == -1 && WSAGetLastError() == WSAEWOULDBLOCK) + LDAP_SET_ERRNO( ld, EWOULDBLOCK ); +#endif /* _WINDOWS */ + err = LDAP_GET_ERRNO( ld ); + if ( NSLDAPI_ERRNO_IO_INPROGRESS( err )) { + LDAPDebug( LDAP_DEBUG_TRACE, "connect would block...\n", + 0, 0, 0 ); + rc = -2; + break; + } + } + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_TRACE ) { + perror( (char *)inet_ntoa( sin.sin_addr )); + } +#endif + (*closefn)( s ); + if ( !use_hp ) { + break; + } + } + } + + ldap_memfree( host ); + parse_err = ldap_x_hostlist_next( &host, &port, status ); + } + + if ( ldhpbuf_allocd != NULL ) { + NSLDAPI_FREE( ldhpbuf_allocd ); + } + ldap_memfree( host ); + ldap_x_hostlist_statusfree( status ); + + if ( connected ) { + LDAPDebug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n", + s, inet_ntoa( sin.sin_addr ), 0 ); + } + + return( rc == 0 ? s : -1 ); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ +} + +void +nsldapi_close_connection( LDAP *ld, Sockbuf *sb ) +{ + if ( ld->ld_extclose_fn == NULL ) { +#ifndef NSLDAPI_AVOID_OS_SOCKETS + nsldapi_os_closesocket( sb->sb_sd ); +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + } else { + ld->ld_extclose_fn( sb->sb_sd, + sb->sb_ext_io_fns.lbextiofn_socket_arg ); + } +} + + +#ifdef KERBEROS +char * +nsldapi_host_connected_to( LDAP *ld, Sockbuf *sb ) +{ + struct hostent *hp; + char *p; + int len; + struct sockaddr_in sin; + + (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); + len = sizeof( sin ); + if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) { + return( NULL ); + } + + /* + * do a reverse lookup on the addr to get the official hostname. + * this is necessary for kerberos to work right, since the official + * hostname is used as the kerberos instance. + */ +#error XXXmcs: need to use DNS callbacks here + if (( hp = (struct hostent *)gethostbyaddr( (char *) &sin.sin_addr, + sizeof( sin.sin_addr ), AF_INET )) != NULL ) { + if ( hp->h_name != NULL ) { + return( nsldapi_strdup( hp->h_name )); + } + } + + return( NULL ); +} +#endif /* KERBEROS */ + + +/* + * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) + * Also allocates initializes ld->ld_iostatus if needed.. + */ +int +nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb ) +{ + int rc = 0; + NSLDAPIIOStatus *iosp; + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + + if ( ld->ld_iostatus == NULL + && nsldapi_iostatus_init_nolock( ld ) < 0 ) { + rc = -1; + goto unlock_and_return; + } + + iosp = ld->ld_iostatus; + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + rc = -1; + goto unlock_and_return; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef NSLDAPI_HAVE_POLL + if ( nsldapi_add_to_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, POLLOUT )) { + ++iosp->ios_write_count; + } +#else /* NSLDAPI_HAVE_POLL */ + if ( !FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_writefds )) { + FD_SET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_writefds ); + ++iosp->ios_write_count; + } +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + if ( nsldapi_add_to_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) { + ++iosp->ios_write_count; + } + + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_interest_write: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + } + +unlock_and_return: + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + + +/* + * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) + * Also allocates initializes ld->ld_iostatus if needed.. + */ +int +nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb ) +{ + int rc = 0; + NSLDAPIIOStatus *iosp; + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + + if ( ld->ld_iostatus == NULL + && nsldapi_iostatus_init_nolock( ld ) < 0 ) { + rc = -1; + goto unlock_and_return; + } + + iosp = ld->ld_iostatus; + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + rc = -1; + goto unlock_and_return; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef NSLDAPI_HAVE_POLL + if ( nsldapi_add_to_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, POLLIN )) { + ++iosp->ios_read_count; + } +#else /* NSLDAPI_HAVE_POLL */ + if ( !FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_readfds )) { + FD_SET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_readfds ); + ++iosp->ios_read_count; + } +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + if ( nsldapi_add_to_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) { + ++iosp->ios_read_count; + } + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_interest_read: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + } + +unlock_and_return: + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + + +/* + * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) + * Also allocates initializes ld->ld_iostatus if needed.. + */ +int +nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb ) +{ + int rc = 0; + NSLDAPIIOStatus *iosp; + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + + if ( ld->ld_iostatus == NULL + && nsldapi_iostatus_init_nolock( ld ) < 0 ) { + rc = -1; + goto unlock_and_return; + } + + iosp = ld->ld_iostatus; + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + rc = -1; + goto unlock_and_return; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef NSLDAPI_HAVE_POLL + if ( nsldapi_clear_from_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, POLLOUT )) { + --iosp->ios_write_count; + } + if ( nsldapi_clear_from_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, POLLIN )) { + --iosp->ios_read_count; + } +#else /* NSLDAPI_HAVE_POLL */ + if ( FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_writefds )) { + FD_CLR( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_writefds ); + --iosp->ios_write_count; + } + if ( FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_readfds )) { + FD_CLR( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_readfds ); + --iosp->ios_read_count; + } +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + if ( nsldapi_clear_from_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) { + --iosp->ios_write_count; + } + if ( nsldapi_clear_from_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) { + --iosp->ios_read_count; + } + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_interest_clear: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + } + +unlock_and_return: + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + + +/* + * Return a non-zero value if sb is ready for write. + */ +int +nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb ) +{ + int rc = 0; + NSLDAPIIOStatus *iosp; + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + iosp = ld->ld_iostatus; + if ( iosp == NULL ) { + goto unlock_and_return; + } + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + goto unlock_and_return; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef NSLDAPI_HAVE_POLL + /* + * if we are using poll() we do something a little tricky: if + * any bits in the socket's returned events field other than + * POLLIN (ready for read) are set, we return true. This + * is done so we notice when a server closes a connection + * or when another error occurs. The actual error will be + * noticed later when we call write() or send(). + */ + rc = nsldapi_find_in_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, ~POLLIN ); + +#else /* NSLDAPI_HAVE_POLL */ + rc = FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_use_writefds ); +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + rc = nsldapi_find_in_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLIN ); + + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_is_write_ready: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + rc = 0; + } + +unlock_and_return: + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + + +/* + * Return a non-zero value if sb is ready for read. + */ +int +nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb ) +{ + int rc = 0; + NSLDAPIIOStatus *iosp; + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + iosp = ld->ld_iostatus; + if ( iosp == NULL ) { + goto unlock_and_return; + } + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_AVOID_OS_SOCKETS + goto unlock_and_return; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef NSLDAPI_HAVE_POLL + /* + * if we are using poll() we do something a little tricky: if + * any bits in the socket's returned events field other than + * POLLOUT (ready for write) are set, we return true. This + * is done so we notice when a server closes a connection + * or when another error occurs. The actual error will be + * noticed later when we call read() or recv(). + */ + rc = nsldapi_find_in_os_pollfds( sb->sb_sd, + &iosp->ios_status.ios_osinfo, ~POLLOUT ); + +#else /* NSLDAPI_HAVE_POLL */ + rc = FD_ISSET( sb->sb_sd, + &iosp->ios_status.ios_osinfo.ossi_use_readfds ); +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + rc = nsldapi_find_in_cb_pollfds( sb, + &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLOUT ); + + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_is_read_ready: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + rc = 0; + } + +unlock_and_return: + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + + +/* + * Allocate and initialize ld->ld_iostatus if not already done. + * Should be called with LDAP_IOSTATUS_LOCK locked. + * Returns 0 if all goes well and -1 if not (sets error in ld) + */ +static int +nsldapi_iostatus_init_nolock( LDAP *ld ) +{ + NSLDAPIIOStatus *iosp; + + if ( ld->ld_iostatus != NULL ) { + return( 0 ); + } + + if (( iosp = (NSLDAPIIOStatus *)NSLDAPI_CALLOC( 1, + sizeof( NSLDAPIIOStatus ))) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + + if ( ld->ld_extpoll_fn == NULL ) { + iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_OSNATIVE; +#ifdef NSLDAPI_AVOID_OS_SOCKETS + return( -1 ); +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifndef NSLDAPI_HAVE_POLL + FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_readfds ); + FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_writefds ); +#endif /* !NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else { + iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_CALLBACK; + } + + ld->ld_iostatus = iosp; + return( 0 ); +} + + +void +nsldapi_iostatus_free( LDAP *ld ) +{ + if ( ld == NULL ) { + return; + } + + + /* clean up classic I/O compatibility glue */ + if ( ld->ld_io_fns_ptr != NULL ) { + if ( ld->ld_ext_session_arg != NULL ) { + NSLDAPI_FREE( ld->ld_ext_session_arg ); + } + NSLDAPI_FREE( ld->ld_io_fns_ptr ); + } + + /* clean up I/O status tracking info. */ + if ( ld->ld_iostatus != NULL ) { + NSLDAPIIOStatus *iosp = ld->ld_iostatus; + + if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifdef NSLDAPI_HAVE_POLL + if ( iosp->ios_status.ios_osinfo.ossi_pollfds + != NULL ) { + NSLDAPI_FREE( + iosp->ios_status.ios_osinfo.ossi_pollfds ); + } +#endif /* NSLDAPI_HAVE_POLL */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + if ( iosp->ios_status.ios_cbinfo.cbsi_pollfds + != NULL ) { + NSLDAPI_FREE( + iosp->ios_status.ios_cbinfo.cbsi_pollfds ); + } + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_free: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + } + + NSLDAPI_FREE( iosp ); + } +} + + + +#if !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) +static int +nsldapi_get_select_table_size( void ) +{ + static int tblsize = 0; /* static */ + + if ( tblsize == 0 ) { +#if defined(_WINDOWS) || defined(XP_OS2) + tblsize = FOPEN_MAX; /* ANSI spec. */ +#else +#ifdef USE_SYSCONF + tblsize = sysconf( _SC_OPEN_MAX ); +#else /* USE_SYSCONF */ + tblsize = getdtablesize(); +#endif /* else USE_SYSCONF */ +#endif /* else _WINDOWS */ + + if ( tblsize >= FD_SETSIZE ) { + /* + * clamp value so we don't overrun the fd_set structure + */ + tblsize = FD_SETSIZE - 1; + } + } + + return( tblsize ); +} +#endif /* !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) */ + + +static int +nsldapi_tv2ms( struct timeval *tv ) +{ + if ( tv == NULL ) { + return( -1 ); /* infinite timout for poll() */ + } + + return( tv->tv_sec * 1000 + tv->tv_usec / 1000 ); +} + + +int +nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout ) +{ + int rc; + NSLDAPIIOStatus *iosp; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_iostatus_poll\n", 0, 0, 0 ); + + LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); + iosp = ld->ld_iostatus; + + if ( iosp == NULL || + ( iosp->ios_read_count <= 0 && iosp->ios_write_count <= 0 )) { + rc = 0; /* simulate a timeout */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { +#ifndef NSLDAPI_AVOID_OS_SOCKETS +#ifdef NSLDAPI_HAVE_POLL + + rc = NSLDAPI_POLL( iosp->ios_status.ios_osinfo.ossi_pollfds, + iosp->ios_status.ios_osinfo.ossi_pollfds_size, + nsldapi_tv2ms( timeout )); + +#else /* NSLDAPI_HAVE_POLL */ + + /* two (potentially large) struct copies */ + iosp->ios_status.ios_osinfo.ossi_use_readfds + = iosp->ios_status.ios_osinfo.ossi_readfds; + iosp->ios_status.ios_osinfo.ossi_use_writefds + = iosp->ios_status.ios_osinfo.ossi_writefds; + +#ifdef HPUX9 + rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(), + (int *)&iosp->ios_status.ios_osinfo.ossi_use_readfds + (int *)&iosp->ios_status.ios_osinfo.ossi_use_writefds, + NULL, timeout ); +#else + rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(), + &iosp->ios_status.ios_osinfo.ossi_use_readfds, + &iosp->ios_status.ios_osinfo.ossi_use_writefds, + NULL, timeout ); +#endif /* else HPUX9 */ +#endif /* else NSLDAPI_HAVE_POLL */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + + } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { + /* + * We always pass the session extended I/O argument to + * the extended poll() callback. + */ + rc = ld->ld_extpoll_fn( + iosp->ios_status.ios_cbinfo.cbsi_pollfds, + iosp->ios_status.ios_cbinfo.cbsi_pollfds_size, + nsldapi_tv2ms( timeout ), ld->ld_ext_session_arg ); + + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_poll: unknown I/O type %d\n", + iosp->ios_type, 0, 0 ); + rc = 0; /* simulate a timeout (what else to do?) */ + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); + return( rc ); +} + +#if defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) +/* + * returns 1 if "fd" was added to pollfds. + * returns 1 if some of the bits in "events" were added to pollfds. + * returns 0 if no changes were made. + */ +static int +nsldapi_add_to_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, + short events ) +{ + int i, openslot; + + /* first we check to see if "fd" is already in our pollfds */ + openslot = -1; + for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { + if ( pip->ossi_pollfds[ i ].fd == fd ) { + if (( pip->ossi_pollfds[ i ].events & events ) + != events ) { + pip->ossi_pollfds[ i ].events |= events; + return( 1 ); + } else { + return( 0 ); + } + } + if ( pip->ossi_pollfds[ i ].fd == -1 && openslot == -1 ) { + openslot = i; /* remember for later */ + } + } + + /* + * "fd" is not currently being poll'd on -- add to array. + * if we need to expand the pollfds array, we do it in increments of + * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file). + */ + if ( openslot == -1 ) { + struct pollfd *newpollfds; + + if ( pip->ossi_pollfds_size == 0 ) { + newpollfds = (struct pollfd *)NSLDAPI_MALLOC( + NSLDAPI_POLL_ARRAY_GROWTH + * sizeof( struct pollfd )); + } else { + newpollfds = (struct pollfd *)NSLDAPI_REALLOC( + pip->ossi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH + + pip->ossi_pollfds_size) + * sizeof( struct pollfd )); + } + if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */ + return( 0 ); + } + pip->ossi_pollfds = newpollfds; + openslot = pip->ossi_pollfds_size; + pip->ossi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH; + for ( i = openslot + 1; i < pip->ossi_pollfds_size; ++i ) { + pip->ossi_pollfds[ i ].fd = -1; + pip->ossi_pollfds[ i ].events = + pip->ossi_pollfds[ i ].revents = 0; + } + } + pip->ossi_pollfds[ openslot ].fd = fd; + pip->ossi_pollfds[ openslot ].events = events; + pip->ossi_pollfds[ openslot ].revents = 0; + return( 1 ); +} + + +/* + * returns 1 if any "events" from "fd" were removed from pollfds + * returns 0 of "fd" wasn't in pollfds or if events did not overlap. + */ +static int +nsldapi_clear_from_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, + short events ) +{ + int i; + + for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { + if ( pip->ossi_pollfds[i].fd == fd ) { + if (( pip->ossi_pollfds[ i ].events & events ) != 0 ) { + pip->ossi_pollfds[ i ].events &= ~events; + if ( pip->ossi_pollfds[ i ].events == 0 ) { + pip->ossi_pollfds[i].fd = -1; + } + return( 1 ); /* events overlap */ + } else { + return( 0 ); /* events do not overlap */ + } + } + } + + return( 0 ); /* "fd" was not found */ +} + + +/* + * returns 1 if any "revents" from "fd" were set in pollfds revents field. + * returns 0 if not. + */ +static int +nsldapi_find_in_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, + short revents ) +{ + int i; + + for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { + if ( pip->ossi_pollfds[i].fd == fd ) { + if (( pip->ossi_pollfds[ i ].revents & revents ) != 0 ) { + return( 1 ); /* revents overlap */ + } else { + return( 0 ); /* revents do not overlap */ + } + } + } + + return( 0 ); /* "fd" was not found */ +} +#endif /* !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) */ + +/* + * returns 1 if "sb" was added to pollfds. + * returns 1 if some of the bits in "events" were added to pollfds. + * returns 0 if no changes were made. + */ +static int +nsldapi_add_to_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip, + short events ) +{ + int i, openslot; + + /* first we check to see if "sb" is already in our pollfds */ + openslot = -1; + for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { + if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { + if (( pip->cbsi_pollfds[ i ].lpoll_events & events ) + != events ) { + pip->cbsi_pollfds[ i ].lpoll_events |= events; + return( 1 ); + } else { + return( 0 ); + } + } + if ( pip->cbsi_pollfds[ i ].lpoll_fd == -1 && openslot == -1 ) { + openslot = i; /* remember for later */ + } + } + + /* + * "sb" is not currently being poll'd on -- add to array. + * if we need to expand the pollfds array, we do it in increments of + * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file). + */ + if ( openslot == -1 ) { + LDAP_X_PollFD *newpollfds; + + if ( pip->cbsi_pollfds_size == 0 ) { + newpollfds = (LDAP_X_PollFD *)NSLDAPI_MALLOC( + NSLDAPI_POLL_ARRAY_GROWTH + * sizeof( LDAP_X_PollFD )); + } else { + newpollfds = (LDAP_X_PollFD *)NSLDAPI_REALLOC( + pip->cbsi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH + + pip->cbsi_pollfds_size) + * sizeof( LDAP_X_PollFD )); + } + if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */ + return( 0 ); + } + pip->cbsi_pollfds = newpollfds; + openslot = pip->cbsi_pollfds_size; + pip->cbsi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH; + for ( i = openslot + 1; i < pip->cbsi_pollfds_size; ++i ) { + pip->cbsi_pollfds[ i ].lpoll_fd = -1; + pip->cbsi_pollfds[ i ].lpoll_socketarg = NULL; + pip->cbsi_pollfds[ i ].lpoll_events = + pip->cbsi_pollfds[ i ].lpoll_revents = 0; + } + } + pip->cbsi_pollfds[ openslot ].lpoll_fd = sb->sb_sd; + pip->cbsi_pollfds[ openslot ].lpoll_socketarg = + sb->sb_ext_io_fns.lbextiofn_socket_arg; + pip->cbsi_pollfds[ openslot ].lpoll_events = events; + pip->cbsi_pollfds[ openslot ].lpoll_revents = 0; + return( 1 ); +} + + +/* + * returns 1 if any "events" from "sb" were removed from pollfds + * returns 0 of "sb" wasn't in pollfds or if events did not overlap. + */ +static int +nsldapi_clear_from_cb_pollfds( Sockbuf *sb, + struct nsldapi_cb_statusinfo *pip, short events ) +{ + int i; + + for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { + if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { + if (( pip->cbsi_pollfds[ i ].lpoll_events + & events ) != 0 ) { + pip->cbsi_pollfds[ i ].lpoll_events &= ~events; + if ( pip->cbsi_pollfds[ i ].lpoll_events + == 0 ) { + pip->cbsi_pollfds[i].lpoll_fd = -1; + } + return( 1 ); /* events overlap */ + } else { + return( 0 ); /* events do not overlap */ + } + } + } + + return( 0 ); /* "sb" was not found */ +} + + +/* + * returns 1 if any "revents" from "sb" were set in pollfds revents field. + * returns 0 if not. + */ +static int +nsldapi_find_in_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip, + short revents ) +{ + int i; + + for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { + if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { + if (( pip->cbsi_pollfds[ i ].lpoll_revents + & revents ) != 0 ) { + return( 1 ); /* revents overlap */ + } else { + return( 0 ); /* revents do not overlap */ + } + } + } + + return( 0 ); /* "sb" was not found */ +} + + +/* + * Install read and write functions into lber layer / sb + */ +int +nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb ) +{ + struct lber_x_ext_io_fns lberiofns; + + if ( NULL != sb ) { + lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + lberiofns.lbextiofn_read = ld->ld_extread_fn; + lberiofns.lbextiofn_write = ld->ld_extwrite_fn; + lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; + lberiofns.lbextiofn_socket_arg = ld->ld_ext_session_arg; + + if ( ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, + &lberiofns ) != 0 ) { + return( LDAP_LOCAL_ERROR ); + } + } + + return( LDAP_SUCCESS ); +} + + +/* + ****************************************************************************** + * One struct and several functions to bridge the gap between new extended + * I/O functions that are installed using ldap_set_option( ..., + * LDAP_OPT_EXTIO_FN_PTRS, ... ) and the original "classic" I/O functions + * (installed using LDAP_OPT_IO_FN_PTRS) follow. + * + * Our basic strategy is to use the new extended arg to hold a pointer to a + * structure that contains a pointer to the LDAP * (which contains pointers + * to the old functions so we can call them) as well as a pointer to an + * LBER_SOCKET to hold the socket used by the classic functions (the new + * functions use a simple int for the socket). + */ +typedef struct nsldapi_compat_socket_info { + LBER_SOCKET csi_socket; + LDAP *csi_ld; +} NSLDAPICompatSocketInfo; + +static int LDAP_CALLBACK +nsldapi_ext_compat_read( int s, void *buf, int len, + struct lextiof_socket_private *arg ) +{ + NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; + struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; + + return( iofns->liof_read( csip->csi_socket, buf, len )); +} + + +static int LDAP_CALLBACK +nsldapi_ext_compat_write( int s, const void *buf, int len, + struct lextiof_socket_private *arg ) +{ + NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; + struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; + + return( iofns->liof_write( csip->csi_socket, buf, len )); +} + + +static int LDAP_CALLBACK +nsldapi_ext_compat_poll( LDAP_X_PollFD fds[], int nfds, int timeout, + struct lextiof_session_private *arg ) +{ + NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; + struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; + fd_set readfds, writefds; + int i, rc, maxfd = 0; + struct timeval tv, *tvp; + + /* + * Prepare fd_sets for select() + */ + FD_ZERO( &readfds ); + FD_ZERO( &writefds ); + for ( i = 0; i < nfds; ++i ) { + if ( fds[ i ].lpoll_fd < 0 ) { + continue; + } + + if ( fds[ i ].lpoll_fd >= FD_SETSIZE ) { + LDAP_SET_ERRNO( csip->csi_ld, EINVAL ); + return( -1 ); + } + + if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )) { + FD_SET( fds[i].lpoll_fd, &readfds ); + } + + if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )) { + FD_SET( fds[i].lpoll_fd, &writefds ); + } + + fds[i].lpoll_revents = 0; /* clear revents */ + + if ( fds[i].lpoll_fd >= maxfd ) { + maxfd = fds[i].lpoll_fd; + } + } + + /* + * select() using callback. + */ + ++maxfd; + if ( timeout == -1 ) { + tvp = NULL; + } else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = 1000 * ( timeout - tv.tv_sec * 1000 ); + tvp = &tv; + } + rc = iofns->liof_select( maxfd, &readfds, &writefds, NULL, tvp ); + if ( rc <= 0 ) { /* timeout or fatal error */ + return( rc ); + } + + /* + * Use info. in fd_sets to populate poll() revents. + */ + for ( i = 0; i < nfds; ++i ) { + if ( fds[ i ].lpoll_fd < 0 ) { + continue; + } + + if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN ) + && FD_ISSET( fds[i].lpoll_fd, &readfds )) { + fds[i].lpoll_revents |= LDAP_X_POLLIN; + } + + if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT ) + && FD_ISSET( fds[i].lpoll_fd, &writefds )) { + fds[i].lpoll_revents |= LDAP_X_POLLOUT; + } + + /* XXXmcs: any other cases to deal with? LDAP_X_POLLERR? */ + } + + return( rc ); +} + + +static LBER_SOCKET +nsldapi_compat_socket( LDAP *ld, int secure, int domain, int type, + int protocol ) +{ + int s; + + s = ld->ld_io_fns_ptr->liof_socket( domain, type, protocol ); + + if ( s >= 0 ) { + char *errmsg = NULL; + +#ifdef NSLDAPI_HAVE_POLL + if ( ld->ld_io_fns_ptr->liof_select != NULL + && s >= FD_SETSIZE ) { + errmsg = "can't use socket >= FD_SETSIZE"; + } +#elif !defined(_WINDOWS) /* not on Windows and do not have poll() */ + if ( s >= FD_SETSIZE ) { + errmsg = "can't use socket >= FD_SETSIZE"; + } +#endif + + if ( NULL == errmsg && secure && + ld->ld_io_fns_ptr->liof_ssl_enable( s ) < 0 ) { + errmsg = "failed to enable secure mode"; + } + + if ( NULL != errmsg ) { + if ( NULL == ld->ld_io_fns_ptr->liof_close ) { + nsldapi_os_closesocket( s ); + } else { + ld->ld_io_fns_ptr->liof_close( s ); + } + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, + nsldapi_strdup( errmsg )); + return( -1 ); + } + } + + return( s ); +} + + +/* + * Note: timeout is ignored because we have no way to pass it via + * the old I/O callback interface. + */ +static int LDAP_CALLBACK +nsldapi_ext_compat_connect( const char *hostlist, int defport, int timeout, + unsigned long options, struct lextiof_session_private *sessionarg, + struct lextiof_socket_private **socketargp ) +{ + NSLDAPICompatSocketInfo *defcsip; + struct ldap_io_fns *iofns; + int s, secure; + NSLDAPI_SOCKET_FN *socketfn; + NSLDAPI_IOCTL_FN *ioctlfn; + NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn; + NSLDAPI_CONNECT_FN *connectfn; + NSLDAPI_CLOSE_FN *closefn; + + defcsip = (NSLDAPICompatSocketInfo *)sessionarg; + iofns = defcsip->csi_ld->ld_io_fns_ptr; + + if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { + if ( NULL == iofns->liof_ssl_enable ) { + LDAP_SET_ERRNO( defcsip->csi_ld, EINVAL ); + return( -1 ); + } + secure = 1; + } else { + secure = 0; + } + + socketfn = ( iofns->liof_socket == NULL ) ? + nsldapi_os_socket : nsldapi_compat_socket; + ioctlfn = ( iofns->liof_ioctl == NULL ) ? + nsldapi_os_ioctl : (NSLDAPI_IOCTL_FN *)(iofns->liof_ioctl); + if ( NULL == iofns->liof_connect ) { + connectwithtofn = nsldapi_os_connect_with_to; + connectfn = NULL; + } else { + connectwithtofn = NULL; + connectfn = iofns->liof_connect; + } + closefn = ( iofns->liof_close == NULL ) ? + nsldapi_os_closesocket : iofns->liof_close; + + s = nsldapi_try_each_host( defcsip->csi_ld, hostlist, defport, + secure, socketfn, ioctlfn, connectwithtofn, + connectfn, closefn ); + + if ( s >= 0 ) { + NSLDAPICompatSocketInfo *csip; + + if (( csip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1, + sizeof( NSLDAPICompatSocketInfo ))) == NULL ) { + (*closefn)( s ); + LDAP_SET_LDERRNO( defcsip->csi_ld, LDAP_NO_MEMORY, + NULL, NULL ); + return( -1 ); + } + + csip->csi_socket = s; + csip->csi_ld = defcsip->csi_ld; + *socketargp = (void *)csip; + + /* + * We always return 1, which is a valid but not unique socket + * (file descriptor) number. The extended I/O functions only + * require that the combination of the void *arg and the int + * socket be unique. Since we allocate the + * NSLDAPICompatSocketInfo that we assign to arg, we meet + * that requirement. + */ + s = 1; + } + + return( s ); +} + + +static int LDAP_CALLBACK +nsldapi_ext_compat_close( int s, struct lextiof_socket_private *arg ) +{ + NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; + struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; + int rc; + + rc = iofns->liof_close( csip->csi_socket ); + + NSLDAPI_FREE( csip ); + + return( rc ); +} + +/* + * Install the I/O functions. + * Return an LDAP error code (LDAP_SUCCESS if all goes well). + */ +int +nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns ) +{ + NSLDAPICompatSocketInfo *defcsip; + + if (( defcsip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1, + sizeof( NSLDAPICompatSocketInfo ))) == NULL ) { + return( LDAP_NO_MEMORY ); + } + + defcsip->csi_socket = -1; + defcsip->csi_ld = ld; + + if ( ld->ld_io_fns_ptr != NULL ) { + (void)memset( (char *)ld->ld_io_fns_ptr, 0, + sizeof( struct ldap_io_fns )); + } else if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_CALLOC( + 1, sizeof( struct ldap_io_fns ))) == NULL ) { + NSLDAPI_FREE( defcsip ); + return( LDAP_NO_MEMORY ); + } + + /* struct copy */ + *(ld->ld_io_fns_ptr) = *iofns; + + ld->ld_extio_size = LBER_X_EXTIO_FNS_SIZE; + ld->ld_ext_session_arg = defcsip; + ld->ld_extread_fn = nsldapi_ext_compat_read; + ld->ld_extwrite_fn = nsldapi_ext_compat_write; + ld->ld_extpoll_fn = nsldapi_ext_compat_poll; + ld->ld_extconnect_fn = nsldapi_ext_compat_connect; + ld->ld_extclose_fn = nsldapi_ext_compat_close; + + return( nsldapi_install_lber_extiofns( ld, ld->ld_sbp )); +} +/* + * end of compat I/O functions + ****************************************************************************** + */ diff --git a/ldap/c-sdk/libldap/proxyauthctrl.c b/ldap/c-sdk/libldap/proxyauthctrl.c new file mode 100644 index 0000000000..e8e80cb144 --- /dev/null +++ b/ldap/c-sdk/libldap/proxyauthctrl.c @@ -0,0 +1,164 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +/* ldap_create_proxyauth_control + + Create a "version 1" proxied authorization control. + + Parameters are + + ld LDAP pointer to the desired connection + + dn The dn used in the proxy auth + + ctl_iscritical Indicates whether the control is critical of not. If + this field is non-zero, the operation will only be car- + ried out if the control is recognized by the server + and/or client + + ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_proxyauth_control ( + LDAP *ld, + const char *dn, + const char ctl_iscritical, + LDAPControl **ctrlp +) +{ + BerElement *ber; + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + if (NULL == dn) + { + dn = ""; + } + + /* create a ber package to hold the controlValue */ + if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + + + if ( LBER_ERROR == ber_printf( ber, + "{s}", + dn ) ) + { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_PROXYAUTH, ber, 1, + ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + +} + + +/* ldap_create_proxiedauth_control + + Create a "version 2" proxied authorization control. + + Parameters are + + ld LDAP pointer to the desired connection + + authzid The authorization identity used in the proxy auth, + e.g., dn:uid=bjensen,dc=example,dc=com + + ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_proxiedauth_control ( + LDAP *ld, + const char *authzid, + LDAPControl **ctrlp +) +{ + BerElement *ber; + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL || authzid == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + /* create a ber package to hold the controlValue */ + if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + + + if ( LBER_ERROR == ber_printf( ber, + "s", + authzid ) ) + { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_PROXIEDAUTH, ber, 1, 1, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + +} diff --git a/ldap/c-sdk/libldap/psearch.c b/ldap/c-sdk/libldap/psearch.c new file mode 100644 index 0000000000..71b9da90dd --- /dev/null +++ b/ldap/c-sdk/libldap/psearch.c @@ -0,0 +1,190 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * psearch.c - Persistent search and "Entry Change Notification" support. + */ +#include "ldap-int.h" + + +int +LDAP_CALL +ldap_create_persistentsearch_control( LDAP *ld, int changetypes, + int changesonly, int return_echg_ctls, char ctl_iscritical, + LDAPControl **ctrlp ) +{ + BerElement *ber; + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL || ( changetypes & ~LDAP_CHANGETYPE_ANY ) != 0 ) { + rc = LDAP_PARAM_ERROR; + goto report_error_and_return; + } + + /* + * create a Persistent Search control. The control value looks like this: + * + * PersistentSearch ::= SEQUENCE { + * changeTypes INTEGER, + * -- the changeTypes field is the logical OR of + * -- one or more of these values: add (1), delete (2), + * -- modify (4), modDN (8). It specifies which types of + * -- changes will cause an entry to be returned. + * changesOnly BOOLEAN, -- skip initial search? + * returnECs BOOLEAN, -- return "Entry Change" controls? + * } + */ + if (( nsldapi_alloc_ber_with_options( ld, &ber )) != LDAP_SUCCESS ) { + rc = LDAP_NO_MEMORY; + goto report_error_and_return; + } + + if ( ber_printf( ber, "{ibb}", changetypes, changesonly, + return_echg_ctls ) == -1 ) { + ber_free( ber, 1 ); + rc = LDAP_ENCODING_ERROR; + goto report_error_and_return; + } + + rc = nsldapi_build_control( LDAP_CONTROL_PERSISTENTSEARCH, ber, 1, + ctl_iscritical, ctrlp ); + +report_error_and_return: + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + + +int +LDAP_CALL +ldap_parse_entrychange_control( LDAP *ld, LDAPControl **ctrls, ber_int_t *chgtypep, + char **prevdnp, int *chgnumpresentp, ber_int_t *chgnump ) +{ + BerElement *ber; + int rc, i; + ber_int_t changetype; + ber_len_t len; + ber_int_t along; + char *previousdn; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + /* + * find the entry change notification in the list of controls + */ + for ( i = 0; ctrls != NULL && ctrls[i] != NULL; ++i ) { + if ( strcmp( ctrls[i]->ldctl_oid, LDAP_CONTROL_ENTRYCHANGE ) == 0 ) { + break; + } + } + + if ( ctrls == NULL || ctrls[i] == NULL ) { + rc = LDAP_CONTROL_NOT_FOUND; + goto report_error_and_return; + } + + /* + * allocate a BER element from the control value and parse it. The control + * value should look like this: + * + * EntryChangeNotification ::= SEQUENCE { + * changeType ENUMERATED { + * add (1), -- these values match the + * delete (2), -- values used for changeTypes + * modify (4), -- in the PersistentSearch control. + * modDN (8), + * }, + * previousDN LDAPDN OPTIONAL, -- modDN ops. only + * changeNumber INTEGER OPTIONAL, -- if supported + * } + */ + if (( ber = ber_init( &(ctrls[i]->ldctl_value))) == NULL ) { + rc = LDAP_NO_MEMORY; + goto report_error_and_return; + } + + if ( ber_scanf( ber, "{e", &along ) == LBER_ERROR ) { + ber_free( ber, 1 ); + rc = LDAP_DECODING_ERROR; + goto report_error_and_return; + } + changetype = along; + + if ( changetype == LDAP_CHANGETYPE_MODDN ) { + if ( ber_scanf( ber, "a", &previousdn ) == LBER_ERROR ) { + ber_free( ber, 1 ); + rc = LDAP_DECODING_ERROR; + goto report_error_and_return; + } + } else { + previousdn = NULL; + } + + if ( chgtypep != NULL ) { + *chgtypep = changetype; + } + if ( prevdnp != NULL ) { + *prevdnp = previousdn; + } else if ( previousdn != NULL ) { + NSLDAPI_FREE( previousdn ); + } + + if ( chgnump != NULL ) { /* check for optional changenumber */ + if ( ber_peek_tag( ber, &len ) == LBER_INTEGER + && ber_get_int( ber, chgnump ) != LBER_ERROR ) { + if ( chgnumpresentp != NULL ) { + *chgnumpresentp = 1; + } + } else { + if ( chgnumpresentp != NULL ) { + *chgnumpresentp = 0; + } + } + } + + ber_free( ber, 1 ); + rc = LDAP_SUCCESS; + +report_error_and_return: + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} diff --git a/ldap/c-sdk/libldap/pthreadtest.c b/ldap/c-sdk/libldap/pthreadtest.c new file mode 100644 index 0000000000..fa913f6919 --- /dev/null +++ b/ldap/c-sdk/libldap/pthreadtest.c @@ -0,0 +1,1028 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Authentication and search information. */ +#define NAME "cn=Directory Manager" +#define PASSWORD "rtfm11111" +#define BASE "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE + +static void *modify_thread(); +static void *add_thread(); +static void *delete_thread(); +static void *bind_thread(); +static void *compare_thread(); +static void *search_thread(); +static void *my_mutex_alloc(); +static void my_mutex_free(); +void *my_sema_alloc( void ); +void my_sema_free( void * ); +int my_sema_wait( void * ); +int my_sema_post( void * ); +static void set_ld_error(); +static int get_ld_error(); +static void set_errno(); +static int get_errno(); +static void tsd_setup(); +static void tsd_cleanup(); +static int get_random_id( void ); +static char *get_id_str( int id ); + +/* Linked list of LDAPMessage structs for search results. */ +typedef struct ldapmsgwrapper { + LDAPMessage *lmw_messagep; + struct ldapmsgwrapper *lmw_next; +} ldapmsgwrapper; + +LDAP *ld; +pthread_key_t key; +int maxid = MAXINT; +int maxops = 0; /* zero means no limit */ +int range_filters = 0; /* if non-zero use >= and >= filters */ + +main( int argc, char **argv ) + +{ + pthread_attr_t attr; + pthread_t *threadids; + void *status; + struct ldap_thread_fns tfns; + struct ldap_extra_thread_fns extrafns; + int rc, c, errflg, i, inited_attr; + int doadd, dodelete, domodify, docompare, dosearch, dobind; + int option_extthreads, option_restart; + int each_thread_count, thread_count; + extern int optind; + extern char *optarg; + + doadd = dodelete = domodify = docompare = dobind = dosearch = 0; + option_extthreads = option_restart = 0; + inited_attr = 0; + errflg = 0; + each_thread_count = 1; /* how many of each type of thread? */ + rc = LDAP_SUCCESS; /* optimistic */ + + while (( c = getopt( argc, argv, "abcdmrsERi:n:o:S:" )) != EOF ) { + switch( c ) { + case 'a': /* perform add operations */ + ++doadd; + break; + case 'b': /* perform bind operations */ + ++dobind; + break; + case 'c': /* perform compare operations */ + ++docompare; + break; + case 'd': /* perform delete operations */ + ++dodelete; + break; + case 'm': /* perform modify operations */ + ++domodify; + break; + case 'r': /* use range filters in searches */ + ++range_filters; + break; + case 's': /* perform search operations */ + ++dosearch; + break; + case 'E': /* use extended thread functions */ + ++option_extthreads; + break; + case 'R': /* turn on LDAP_OPT_RESTART */ + ++option_restart; + break; + case 'i': /* highest # used for entry names */ + maxid = atoi( optarg ); + break; + case 'n': /* # threads for each operation */ + if (( each_thread_count = atoi( optarg )) < 1 ) { + fprintf( stderr, "thread count must be > 0\n" ); + ++errflg; + } + break; + case 'o': /* operations to perform per thread */ + if (( maxops = atoi( optarg )) < 0 ) { + fprintf( stderr, + "operation limit must be >= 0\n" ); + ++errflg; + } + break; + case 'S': /* random number seed */ + if ( *optarg == 'r' ) { + int seed = (int)time( (time_t *)0 ); + srandom( seed ); + printf( "Random seed: %d\n", seed ); + } else { + srandom( atoi( optarg )); + } + break; + default: + ++errflg; + break; + } + } + + /* Check command-line syntax. */ + thread_count = each_thread_count * ( doadd + dodelete + domodify + + dobind + docompare + dosearch ); + if ( thread_count < 1 ) { + fprintf( stderr, + "Specify at least one of -a, -b, -c, -d, -m, or -s\n" ); + ++errflg; + } + + if ( errflg || argc - optind != 2 ) { + fprintf( stderr, "usage: %s [-abcdmrsER] [-i id] [-n thr]" + " [-o oplim] [-S sd] host port\n", argv[0] ); + fputs( "\nWhere:\n" + "\t\"id\" is the highest entry id (name) to use" + " (default is MAXINT)\n" + "\t\"thr\" is the number of threads for each operation" + " (default is 1)\n" + "\t\"oplim\" is the number of ops done by each thread" + " (default is infinite)\n" + "\t\"sd\" is a random() number seed (default is 1). Use" + " the letter r for\n" + "\t\tsd to seed random() using time of day.\n" + "\t\"host\" is the hostname of an LDAP directory server\n" + "\t\"port\" is the TCP port of the LDAP directory server\n" + , stderr ); + fputs( "\nAnd the single character options are:\n" + "\t-a\tstart thread(s) to perform add operations\n" + "\t-b\tstart thread(s) to perform bind operations\n" + "\t-c\tstart thread(s) to perform compare operations\n" + "\t-d\tstart thread(s) to perform delete operations\n" + "\t-m\tstart thread(s) to perform modify operations\n" + "\t-s\tstart thread(s) to perform search operations\n" + "\t-r\tuse range filters in searches\n" + "\t-E\tinstall LDAP_OPT_EXTRA_THREAD_FN_PTRS\n" + "\t-R\tturn on LDAP_OPT_RESTART\n", stderr ); + + return( LDAP_PARAM_ERROR ); + } + + /* Create a key. */ + if ( pthread_key_create( &key, free ) != 0 ) { + perror( "pthread_key_create" ); + } + tsd_setup(); + + /* Allocate space for thread ids */ + if (( threadids = (pthread_t *)calloc( thread_count, + sizeof( pthread_t ))) == NULL ) { + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + + + /* Initialize the LDAP session. */ + if (( ld = ldap_init( argv[optind], atoi( argv[optind+1] ))) == NULL ) { + perror( "ldap_init" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + + /* Set the function pointers for dealing with mutexes + and error information. */ + memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); + tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc; + tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free; + tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock; + tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock; + tfns.ltf_get_errno = get_errno; + tfns.ltf_set_errno = set_errno; + tfns.ltf_get_lderrno = get_ld_error; + tfns.ltf_set_lderrno = set_ld_error; + tfns.ltf_lderrno_arg = NULL; + + /* Set up this session to use those function pointers. */ + + rc = ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns ); + if ( rc < 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, + "ldap_set_option (LDAP_OPT_THREAD_FN_PTRS): %s\n", + ldap_err2string( rc ) ); + goto clean_up_and_return; + } + + if ( option_extthreads ) { + /* Set the function pointers for working with semaphores. */ + + memset( &extrafns, '\0', sizeof(struct ldap_extra_thread_fns) ); + extrafns.ltf_mutex_trylock = + (int (*)(void *)) pthread_mutex_trylock; + extrafns.ltf_sema_alloc = (void *(*)(void)) my_sema_alloc; + extrafns.ltf_sema_free = (void (*)(void *)) my_sema_free; + extrafns.ltf_sema_wait = (int (*)(void *)) my_sema_wait; + extrafns.ltf_sema_post = (int (*)(void *)) my_sema_post; + + /* Set up this session to use those function pointers. */ + + if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, + (void *) &extrafns ) != 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + ldap_perror( ld, "ldap_set_option" + " (LDAP_OPT_EXTRA_THREAD_FN_PTRS)" ); + goto clean_up_and_return; + } + } + + + if ( option_restart && ldap_set_option( ld, LDAP_OPT_RESTART, + LDAP_OPT_ON ) != 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + ldap_perror( ld, "ldap_set_option(LDAP_OPT_RESTART)" ); + goto clean_up_and_return; + } + + /* Attempt to bind to the server. */ + rc = ldap_simple_bind_s( ld, NAME, PASSWORD ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", + ldap_err2string( rc ) ); + goto clean_up_and_return; + } + + /* Initialize the attribute. */ + if ( pthread_attr_init( &attr ) != 0 ) { + perror( "pthread_attr_init" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++inited_attr; + + /* Specify that the threads are joinable. */ + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); + + /* Create all the requested threads */ + thread_count = 0; + if ( domodify ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + modify_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create modify_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + if ( doadd ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + add_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create add_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + if ( dodelete ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + delete_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create delete_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + if ( dobind ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + bind_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create bind_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + if ( docompare ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + compare_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create compare_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + if ( dosearch ) { + for ( i = 0; i < each_thread_count; ++i ) { + if ( pthread_create( &threadids[thread_count], &attr, + search_thread, get_id_str(thread_count) ) != 0 ) { + perror( "pthread_create search_thread" ); + rc = LDAP_LOCAL_ERROR; + goto clean_up_and_return; + } + ++thread_count; + } + } + + /* Wait until these threads exit. */ + for ( i = 0; i < thread_count; ++i ) { + pthread_join( threadids[i], &status ); + } + +clean_up_and_return: + if ( ld != NULL ) { + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + ldap_unbind( ld ); + } + if ( threadids != NULL ) { + free( threadids ); + } + if ( inited_attr ) { + pthread_attr_destroy( &attr ); + } + tsd_cleanup(); + + return( rc ); +} + + +static void * +modify_thread( char *id ) +{ + LDAPMessage *res; + LDAPMessage *e; + int i, modentry, num_entries, msgid, parse_rc, finished; + int rc, opcount; + LDAPMod mod; + LDAPMod *mods[2]; + char *vals[2]; + char *dn; + ldapmsgwrapper *list, *lmwp, *lastlmwp; + struct timeval zerotime; + void *voidrc = (void *)0; + + zerotime.tv_sec = zerotime.tv_usec = 0L; + + printf( "Starting modify_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: Modify thread: " + "ldap_search_ext: %s\n", id, ldap_err2string( rc ) ); + exit( 1 ); + } + list = lastlmwp = NULL; + finished = 0; + num_entries = 0; + while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + switch ( rc ) { + case -1: + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + exit( 1 ); + break; + case 0: + break; + /* Keep track of the number of entries found. */ + case LDAP_RES_SEARCH_ENTRY: + num_entries++; + if (( lmwp = (ldapmsgwrapper *) + malloc( sizeof( ldapmsgwrapper ))) == NULL ) { + fprintf( stderr, "Thread %s: Modify thread: Cannot malloc\n", id ); + exit( 1 ); + } + lmwp->lmw_messagep = res; + lmwp->lmw_next = NULL; + if ( lastlmwp == NULL ) { + list = lastlmwp = lmwp; + } else { + lastlmwp->lmw_next = lmwp; + } + lastlmwp = lmwp; + break; + case LDAP_RES_SEARCH_REFERENCE: + break; + case LDAP_RES_SEARCH_RESULT: + finished = 1; + parse_rc = ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, NULL, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: can't parse result code.\n", id ); + exit( 1 ); + } else { + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: ldap_search: %s\n", id, ldap_err2string( rc ) ); + } else { + printf( "Thread %s: Got %d results.\n", id, num_entries ); + } + } + break; + default: + break; + } + } + + mods[0] = &mod; + mods[1] = NULL; + vals[0] = "bar"; + vals[1] = NULL; + + for ( ;; ) { + modentry = random() % num_entries; + for ( i = 0, lmwp = list; lmwp != NULL && i < modentry; + i++, lmwp = lmwp->lmw_next ) { + /* NULL */ + } + + if ( lmwp == NULL ) { + fprintf( stderr, + "Thread %s: Modify thread could not find entry %d of %d\n", + id, modentry, num_entries ); + continue; + } + + e = lmwp->lmw_messagep; + printf( "Thread %s: Modify thread picked entry %d of %d\n", id, i, num_entries ); + dn = ldap_get_dn( ld, e ); + + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = "description"; + mod.mod_values = vals; + printf( "Thread %s: Modifying (%s)\n", id, dn ); + + rc = ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext_s: %s\n", + ldap_err2string( rc ) ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_modify_ext_s" ); + voidrc = (void *)1; + goto modify_cleanup_and_return; + } + } + free( dn ); + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +modify_cleanup_and_return: + printf( "Thread %s: attempted %d modify operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +add_thread( char *id ) +{ + LDAPMod mod[4]; + LDAPMod *mods[5]; + char dn[BUFSIZ], name[40]; + char *cnvals[2], *snvals[2], *pwdvals[2], *ocvals[3]; + int i, rc, opcount; + void *voidrc = (void *)0; + + printf( "Starting add_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + for ( i = 0; i < 4; i++ ) { + mods[i] = &mod[i]; + } + + mods[4] = NULL; + + mod[0].mod_op = 0; + mod[0].mod_type = "cn"; + mod[0].mod_values = cnvals; + cnvals[1] = NULL; + mod[1].mod_op = 0; + mod[1].mod_type = "sn"; + mod[1].mod_values = snvals; + snvals[1] = NULL; + mod[2].mod_op = 0; + mod[2].mod_type = "objectclass"; + mod[2].mod_values = ocvals; + ocvals[0] = "top"; + ocvals[1] = "person"; + ocvals[2] = NULL; + mod[3].mod_op = 0; + mod[3].mod_type = "userPassword"; + mod[3].mod_values = pwdvals; + pwdvals[1] = NULL; + mods[4] = NULL; + + for ( ;; ) { + sprintf( name, "%d", get_random_id() ); + sprintf( dn, "cn=%s, " BASE, name ); + cnvals[0] = name; + snvals[0] = name; + pwdvals[0] = name; + + printf( "Thread %s: Adding entry (%s)\n", id, dn ); + rc = ldap_add_ext_s( ld, dn, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext_s: %s\n", + ldap_err2string( rc ) ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_add_ext_s" ); + voidrc = (void *)1; + goto add_cleanup_and_return; + } + } + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +add_cleanup_and_return: + printf( "Thread %s: attempted %d add operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +delete_thread( char *id ) +{ + LDAPMessage *res; + char dn[BUFSIZ], name[40]; + int num_entries, msgid, rc, parse_rc, finished, opcount; + struct timeval zerotime; + void *voidrc = (void *)0; + + zerotime.tv_sec = zerotime.tv_usec = 0L; + + printf( "Starting delete_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: Delete thread: " + "ldap_search_ext: %s\n", id, ldap_err2string( rc ) ); + exit( 1 ); + } + + finished = 0; + num_entries = 0; + while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + switch ( rc ) { + case -1: + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + exit( 1 ); + break; + case 0: + break; + /* Keep track of the number of entries found. */ + case LDAP_RES_SEARCH_ENTRY: + num_entries++; + break; + case LDAP_RES_SEARCH_REFERENCE: + break; + case LDAP_RES_SEARCH_RESULT: + finished = 1; + parse_rc = ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, NULL, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: can't parse result code.\n", id ); + exit( 1 ); + } else { + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: ldap_search: %s\n", id, ldap_err2string( rc ) ); + } else { + printf( "Thread %s: Got %d results.\n", id, num_entries ); + } + } + break; + default: + break; + } + } + + for ( ;; ) { + sprintf( name, "%d", get_random_id() ); + sprintf( dn, "cn=%s, " BASE, name ); + printf( "Thread %s: Deleting entry (%s)\n", id, dn ); + + if (( rc = ldap_delete_ext_s( ld, dn, NULL, NULL )) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_delete_ext_s" ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_delete_ext_s" ); + voidrc = (void *)1; + goto delete_cleanup_and_return; + } + } + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +delete_cleanup_and_return: + printf( "Thread %s: attempted %d delete operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +bind_thread( char *id ) +{ + char dn[BUFSIZ], name[40]; + int rc, opcount; + void *voidrc = (void *)0; + + printf( "Starting bind_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + for ( ;; ) { + sprintf( name, "%d", get_random_id() ); + sprintf( dn, "cn=%s, " BASE, name ); + printf( "Thread %s: Binding as entry (%s)\n", id, dn ); + + if (( rc = ldap_simple_bind_s( ld, dn, name )) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_simple_bind_s" ); + voidrc = (void *)1; + goto bind_cleanup_and_return; + } + } else { + printf( "Thread %s: bound as entry (%s)\n", id, dn ); + } + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +bind_cleanup_and_return: + printf( "Thread %s: attempted %d bind operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +compare_thread( char *id ) +{ + char dn[BUFSIZ], name[40], cmpval[40]; + int rc, randval, opcount; + struct berval bv; + void *voidrc = (void *)0; + + printf( "Starting compare_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + for ( ;; ) { + randval = get_random_id(); + sprintf( name, "%d", randval ); + sprintf( dn, "cn=%s, " BASE, name ); + sprintf( cmpval, "%d", randval + random() % 3 ); + bv.bv_val = cmpval; + bv.bv_len = strlen( cmpval ); + + printf( "Thread %s: Comparing cn in entry (%s) with %s\n", + id, dn, cmpval ); + + rc = ldap_compare_ext_s( ld, dn, "cn", &bv, NULL, NULL ); + switch ( rc ) { + case LDAP_COMPARE_TRUE: + printf( "Thread %s: entry (%s) contains cn %s\n", + id, dn, cmpval ); + break; + case LDAP_COMPARE_FALSE: + printf( "Thread %s: entry (%s) doesn't contain cn %s\n", + id, dn, cmpval ); + break; + default: + ldap_perror( ld, "ldap_compare_ext_s" ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_compare_ext_s" ); + voidrc = (void *)1; + goto compare_cleanup_and_return; + } + } + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +compare_cleanup_and_return: + printf( "Thread %s: attempted %d compare operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +search_thread( char *id ) +{ + LDAPMessage *res, *entry; + char *dn, filter[40]; + int rc, opcount; + void *voidrc = (void *)0; + + printf( "Starting search_thread %s.\n", id ); + opcount = 0; + tsd_setup(); + + for ( ;; ) { + if ( range_filters ) { + switch( get_random_id() % 3 ) { + case 0: + sprintf( filter, "(cn>=%d)", get_random_id()); + break; + case 1: + sprintf( filter, "(cn<=%d)", get_random_id()); + break; + case 2: + sprintf( filter, "(&(cn>=%d)(cn<=%d))", + get_random_id(), get_random_id() ); + break; + } + } else { + sprintf( filter, "cn=%d", get_random_id() ); + } + + printf( "Thread %s: Searching for entry (%s)\n", id, filter ); + + res = NULL; + if (( rc = ldap_search_ext_s( ld, BASE, SCOPE, filter, NULL, 0, + NULL, NULL, NULL, 0, &res )) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_ext_s" ); + if ( rc == LDAP_SERVER_DOWN ) { + perror( "ldap_search_ext_s" ); + voidrc = (void *)1; + goto search_cleanup_and_return; + } + } + if ( res != NULL ) { + entry = ldap_first_entry( ld, res ); + if ( entry == NULL ) { + printf( "Thread %s: found no entries\n", id ); + } else { + dn = ldap_get_dn( ld, entry ); + printf( + "Thread %s: found entry (%s); %d total\n", + id, dn == NULL ? "(Null)" : dn, + ldap_count_entries( ld, res )); + ldap_memfree( dn ); + } + ldap_msgfree( res ); + } + + ++opcount; + if ( maxops != 0 && opcount >= maxops ) { + break; + } + } + +search_cleanup_and_return: + printf( "Thread %s: attempted %d search operations\n", id, opcount ); + set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ + tsd_cleanup(); + free( id ); + return voidrc; +} + + +static void * +my_mutex_alloc( void ) +{ + pthread_mutex_t *mutexp; + + if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { + pthread_mutex_init( mutexp, NULL ); + } + return( mutexp ); +} + + +void * +my_sema_alloc( void ) +{ + sema_t *semptr; + + if( (semptr = malloc( sizeof(sema_t) ) ) != NULL ) { + sema_init( semptr, 0, USYNC_THREAD, NULL ); + } + return ( semptr ); +} + + +static void +my_mutex_free( void *mutexp ) +{ + pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); + free( mutexp ); +} + + +void +my_sema_free( void *semptr ) +{ + sema_destroy( (sema_t *) semptr ); + free( semptr ); +} + + +int +my_sema_wait( void *semptr ) +{ + if( semptr != NULL ) + return( sema_wait( (sema_t *) semptr ) ); + else + return( -1 ); +} + + +int +my_sema_post( void *semptr ) +{ + if( semptr != NULL ) + return( sema_post( (sema_t *) semptr ) ); + else + return( -1 ); +} + + +struct ldap_error { + int le_errno; + char *le_matched; + char *le_errmsg; +}; + + +static void +tsd_setup() +{ + void *tsd; + tsd = pthread_getspecific( key ); + if ( tsd != NULL ) { + fprintf( stderr, "tsd non-null!\n" ); + pthread_exit( NULL ); + } + + tsd = (void *) calloc( 1, sizeof(struct ldap_error) ); + pthread_setspecific( key, tsd ); +} + + +static void +tsd_cleanup() +{ + void *tsd; + + if (( tsd = pthread_getspecific( key )) != NULL ) { + pthread_setspecific( key, NULL ); + free( tsd ); + } +} + + +static void +set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + struct ldap_error *le; + + le = pthread_getspecific( key ); + + le->le_errno = err; + + if ( le->le_matched != NULL ) { + ldap_memfree( le->le_matched ); + } + le->le_matched = matched; + + if ( le->le_errmsg != NULL ) { + ldap_memfree( le->le_errmsg ); + } + le->le_errmsg = errmsg; +} + + +static int +get_ld_error( char **matchedp, char **errmsgp, void *dummy ) +{ + struct ldap_error *le; + + le = pthread_getspecific( key ); + if ( matchedp != NULL ) { + *matchedp = le->le_matched; + } + if ( errmsgp != NULL ) { + *errmsgp = le->le_errmsg; + } + return( le->le_errno ); +} + + +static void +set_errno( int err ) +{ + errno = err; +} + + +static int +get_errno( void ) +{ + return( errno ); +} + + +static int +get_random_id() +{ + return( random() % maxid ); +} + + +static char * +get_id_str( int id ) +{ + char idstr[ 10 ]; + + sprintf( idstr, "%d", id ); + return( strdup( idstr )); +} diff --git a/ldap/c-sdk/libldap/pwmodext.c b/ldap/c-sdk/libldap/pwmodext.c new file mode 100644 index 0000000000..fd737c4a3f --- /dev/null +++ b/ldap/c-sdk/libldap/pwmodext.c @@ -0,0 +1,265 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): abobrov + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_passwd */ +int +LDAP_CALL +ldap_passwd ( + LDAP *ld, + struct berval *userid, + struct berval *oldpasswd, + struct berval *newpasswd, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp + ) +{ + int rc; + BerElement *ber = NULL; + struct berval *requestdata = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + requestdata = NSLDAPI_MALLOC( sizeof( struct berval ) ); + if ( requestdata == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* If the requestValue field is provided, it SHALL contain a + * PasswdModifyRequestValue with one or more fields present. + */ + if ( userid || oldpasswd || newpasswd ) { + if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) + != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* + * PasswdModifyRequestValue ::= SEQUENCE { + * userIdentity [0] OCTET STRING OPTIONAL + * oldPasswd [1] OCTET STRING OPTIONAL + * newPasswd [2] OCTET STRING OPTIONAL } + */ + if ( LBER_ERROR == ( ber_printf( ber, "{" ) ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + if ( userid && userid->bv_val && userid->bv_len ) { + if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_ID, + userid->bv_val, userid->bv_len ) ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + + if ( oldpasswd && oldpasswd->bv_val && oldpasswd->bv_len ) { + if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_OLD, + oldpasswd->bv_val, oldpasswd->bv_len ) ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + + if ( newpasswd && newpasswd->bv_val && newpasswd->bv_len ) { + if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_NEW, + newpasswd->bv_val, newpasswd->bv_len ) ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + + if ( LBER_ERROR == ( ber_printf( ber, "}" ) ) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + /* allocate struct berval with contents of the BER encoding */ + rc = ber_flatten( ber, &requestdata ); + if ( rc == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_NO_MEMORY ); + } + } else { + requestdata = NULL; + } + + rc = ldap_extended_operation( ld, LDAP_EXOP_MODIFY_PASSWD, requestdata, + serverctrls, clientctrls, msgidp ); + + /* the ber encoding is no longer needed */ + if ( requestdata ) { + ber_bvfree( requestdata ); + } + + if ( ber ) { + ber_free( ber, 1 ); + } + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + +/* ldap_parse_passwd */ +int +LDAP_CALL +ldap_parse_passwd ( + LDAP *ld, + LDAPMessage *result, + struct berval *genpasswd + ) +{ + int rc; + char *retoidp = NULL; + struct berval *retdatap = NULL; + BerElement *ber = NULL; + ber_len_t len; + ber_tag_t tag; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( !result ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( !genpasswd ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + rc = ldap_parse_extended_result( ld, result, &retoidp, &retdatap, 0 ); + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + rc = ldap_get_lderrno( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + if ( retdatap ) { + /* allocate a Ber element with the contents of the + * berval from the response. + */ + if ( ( ber = ber_init( retdatap ) ) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + if ( ( tag = ber_skip_tag( ber, &len ) ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + ldap_memfree( retoidp ); + return( LDAP_DECODING_ERROR ); + } + + if ( ( ( tag = ber_peek_tag( ber, &len ) ) == LBER_ERROR ) || + tag != LDAP_TAG_PWDMOD_RES_GEN ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + ldap_memfree( retoidp ); + return( LDAP_DECODING_ERROR ); + } + + if ( ber_scanf( ber, "o}", genpasswd ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + ldap_memfree( retoidp ); + return( LDAP_DECODING_ERROR ); + } + + /* the ber encoding is no longer needed */ + ber_free( ber,1 ); + } + + ldap_memfree( retoidp ); + return( LDAP_SUCCESS ); +} + +/* ldap_passwd_s */ +int +LDAP_CALL +ldap_passwd_s ( + LDAP *ld, + struct berval *userid, + struct berval *oldpasswd, + struct berval *newpasswd, + struct berval *genpasswd, + LDAPControl **serverctrls, + LDAPControl **clientctrls + ) +{ + int rc, msgid; + LDAPMessage *result = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + rc = ldap_passwd( ld, userid, oldpasswd, newpasswd, serverctrls, + clientctrls, &msgid ); + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( rc == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + rc = ldap_parse_passwd( ld, result, genpasswd ); + + ldap_msgfree( result ); + return( rc ); +} diff --git a/ldap/c-sdk/libldap/pwpctrl.c b/ldap/c-sdk/libldap/pwpctrl.c new file mode 100644 index 0000000000..26a3f1b2f6 --- /dev/null +++ b/ldap/c-sdk/libldap/pwpctrl.c @@ -0,0 +1,315 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): abobrov@sun.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_create_passwordpolicy_control: + +Parameters are + +ld LDAP pointer to the desired connection + +ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_passwordpolicy_control ( + LDAP *ld, + LDAPControl **ctrlp + ) +{ + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY, + NULL, 0, 0, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + +/* ldap_create_passwordpolicy_control_ext: + +Parameters are + +ld LDAP pointer to the desired connection + +ctl_iscritical Indicates whether the control is critical of not. If + this field is non-zero, the operation will only be car- + ried out if the control is recognized by the server + and/or client + +ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_passwordpolicy_control_ext ( + LDAP *ld, + const char ctl_iscritical, + LDAPControl **ctrlp + ) +{ + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY, + NULL, 0, ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + +/* ldap_parse_passwordpolicy_control: + +Parameters are + +ld LDAP pointer to the desired connection + +ctrlp pointer to LDAPControl structure, obtained from + calling ldap_find_control() or by other means. + +exptimep result parameter is filled in with the number of seconds before + the password will expire. + +gracep result parameter is filled in with the number of grace logins + after the password has expired. + +errorcodep result parameter is filled in with the error code of the + password operation. +*/ + +int +LDAP_CALL +ldap_parse_passwordpolicy_control ( + LDAP *ld, + LDAPControl *ctrlp, + ber_int_t *expirep, + ber_int_t *gracep, + LDAPPasswordPolicyError *errorp + ) +{ + ber_len_t len; + ber_tag_t tag; + ber_int_t pp_exp = -1; + ber_int_t pp_grace = -1; + ber_int_t pp_warning = -1; + ber_int_t pp_err = PP_noError; + BerElement *ber = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + + /* allocate a Ber element with the contents of the control's struct berval */ + if ( ( ber = ber_init( &ctrlp->ldctl_value ) ) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* + * The control value should look like this: + * + * PasswordPolicyResponseValue ::= SEQUENCE { + * warning [0] CHOICE { + * timeBeforeExpiration [0] INTEGER (0 .. maxInt), + * graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL + * error [1] ENUMERATED { + * passwordExpired (0), + * accountLocked (1), + * changeAfterReset (2), + * passwordModNotAllowed (3), + * mustSupplyOldPassword (4), + * insufficientPasswordQuality (5), + * passwordTooShort (6), + * passwordTooYoung (7), + * passwordInHistory (8) } OPTIONAL } + */ + + if ( ber_scanf( ber, "{" ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + + tag = ber_peek_tag( ber, &len ); + + while ( (tag != LBER_ERROR) && (tag != LBER_END_OF_SEQORSET) ) { + if ( tag == ( LBER_CONSTRUCTED | LBER_CLASS_CONTEXT ) ) { + ber_skip_tag( ber, &len ); + if ( ber_scanf( ber, "ti", &tag, &pp_warning ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + if ( tag == LBER_CLASS_CONTEXT ) { + pp_exp = pp_warning; + } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) { + pp_grace = pp_warning; + } + } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) { + if ( ber_scanf( ber, "ti", &tag, &pp_err ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + } + if ( tag == LBER_DEFAULT ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + tag = ber_skip_tag( ber, &len ); + } + + if (expirep) *expirep = pp_exp; + if (gracep) *gracep = pp_grace; + if (errorp) *errorp = pp_err; + + /* the ber encoding is no longer needed */ + ber_free( ber, 1 ); + return( LDAP_SUCCESS ); +} + +/* ldap_parse_passwordpolicy_control_ext: + +Parameters are + +ld LDAP pointer to the desired connection + +ctrlp An array of controls obtained from calling + ldap_parse_result on the set of results + returned by the server + +exptimep result parameter is filled in with the number of seconds before + the password will expire. + +gracep result parameter is filled in with the number of grace logins + after the password has expired. + +errorcodep result parameter is filled in with the error code of the + password operation. +*/ + +int +LDAP_CALL +ldap_parse_passwordpolicy_control_ext ( + LDAP *ld, + LDAPControl **ctrlp, + ber_int_t *expirep, + ber_int_t *gracep, + LDAPPasswordPolicyError *errorp + ) +{ + int i, foundPPControl; + LDAPControl *PPCtrlp = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { + return( LDAP_PARAM_ERROR ); + } + + /* find the control in the list of controls if it exists */ + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + foundPPControl = 0; + for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundPPControl )); i++ ) { + foundPPControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_PASSWD_POLICY ); + } + if ( !foundPPControl ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } else { + /* let local var point to the control */ + PPCtrlp = ctrlp[i-1]; + } + + return ( + ldap_parse_passwordpolicy_control( ld, PPCtrlp, expirep, gracep, errorp )); +} + +const char * +LDAP_CALL +ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err ) +{ + switch(err) { + case PP_passwordExpired: + return "Password expired"; + case PP_accountLocked: + return "Account locked"; + case PP_changeAfterReset: + return "Password must be changed"; + case PP_passwordModNotAllowed: + return "Policy prevents password modification"; + case PP_mustSupplyOldPassword: + return "Policy requires old password in order to change password"; + case PP_insufficientPasswordQuality: + return "Password fails quality checks"; + case PP_passwordTooShort: + return "Password is too short for policy"; + case PP_passwordTooYoung: + return "Password has been changed too recently"; + case PP_passwordInHistory: + return "New password is in list of old passwords"; + case PP_noError: + return "No error"; + default: + return "Unknown error code"; + } +} diff --git a/ldap/c-sdk/libldap/referral.c b/ldap/c-sdk/libldap/referral.c new file mode 100644 index 0000000000..742d3d9861 --- /dev/null +++ b/ldap/c-sdk/libldap/referral.c @@ -0,0 +1,177 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * referral.c - routines for handling LDAPv3 referrals and references. + */ + +#include "ldap-int.h" + + +LDAPMessage * +LDAP_CALL +ldap_first_reference( LDAP *ld, LDAPMessage *res ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || res == NULLMSG ) { + return( NULLMSG ); + } + + if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + return( res ); + } + + return( ldap_next_reference( ld, res )); +} + + +LDAPMessage * +LDAP_CALL +ldap_next_reference( LDAP *ld, LDAPMessage *ref ) +{ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || ref == NULLMSG ) { + return( NULLMSG ); /* punt */ + } + + for ( ref = ref->lm_chain; ref != NULLMSG; ref = ref->lm_chain ) { + if ( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + return( ref ); + } + } + + return( NULLMSG ); +} + + +int +LDAP_CALL +ldap_count_references( LDAP *ld, LDAPMessage *res ) +{ + int i; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); + } + + for ( i = 0; res != NULL; res = res->lm_chain ) { + if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + ++i; + } + } + + return( i ); +} + + +/* + * returns an LDAP error code. + */ +int +LDAP_CALL +ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp, + LDAPControl ***serverctrlsp, int freeit ) +{ + int err; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || + !NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( ref )) { + return( LDAP_PARAM_ERROR ); + } + + err = nsldapi_parse_reference( ld, ref->lm_ber, referralsp, + serverctrlsp ); + + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + + if ( freeit ) { + ldap_msgfree( ref ); + } + + return( err ); +} + + +/* + * returns an LDAP error code indicating success or failure of parsing + * does NOT set any error information inside "ld" + */ +int +nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp, + LDAPControl ***serverctrlsp ) +{ + int err; + BerElement ber; + char **refs; + + /* + * Parse a searchResultReference message. These are used in LDAPv3 + * and beyond and look like this: + * + * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL + * + * all wrapped up in an LDAPMessage sequence which looks like this: + * + * LDAPMessage ::= SEQUENCE { + * messageID MessageID, + * SearchResultReference + * controls [0] Controls OPTIONAL + * } + * + * ldap_result() pulls out the message id, so by the time a result + * message gets here we are conveniently sitting at the start of the + * SearchResultReference itself. + */ + err = LDAP_SUCCESS; /* optimistic */ + ber = *rber; /* struct copy */ + + if ( ber_scanf( &ber, "{v", &refs ) == LBER_ERROR ) { + err = LDAP_DECODING_ERROR; + } else if ( serverctrlsp != NULL ) { + /* pull out controls (if requested and any are present) */ + if ( ber_scanf( &ber, "}" ) == LBER_ERROR ) { + err = LDAP_DECODING_ERROR; + } else { + err = nsldapi_get_controls( &ber, serverctrlsp ); + } + } + + if ( referralsp == NULL ) { + ldap_value_free( refs ); + } else { + *referralsp = refs; + } + + return( err ); +} diff --git a/ldap/c-sdk/libldap/regex.c b/ldap/c-sdk/libldap/regex.c new file mode 100644 index 0000000000..4ba4ee08a1 --- /dev/null +++ b/ldap/c-sdk/libldap/regex.c @@ -0,0 +1,920 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" +#if defined( macintosh ) || defined( DOS ) || defined( _WINDOWS ) || defined( NEED_BSDREGEX ) || defined( XP_OS2) +#include "regex.h" + +/* + * regex - Regular expression pattern matching and replacement + * + * By: Ozan S. Yigit (oz) + * Dept. of Computer Science + * York University + * + * These routines are the PUBLIC DOMAIN equivalents of regex + * routines as found in 4.nBSD UN*X, with minor extensions. + * + * These routines are derived from various implementations found + * in software tools books, and Conroy's grep. They are NOT derived + * from licensed/restricted software. + * For more interesting/academic/complicated implementations, + * see Henry Spencer's regexp routines, or GNU Emacs pattern + * matching module. + * + * Use the actual CCL code in the CLO + * section of pmatch. No need for a recursive + * pmatch call. + * + * Use a bitmap table to set char bits in an + * 8-bit chunk. + * + * Interfaces: + * re_comp: compile a regular expression into a NFA. + * + * char *re_comp(s) + * char *s; + * + * re_exec: execute the NFA to match a pattern. + * + * int re_exec(s) + * char *s; + * + * re_modw change re_exec's understanding of what a "word" + * looks like (for \< and \>) by adding into the + * hidden word-syntax table. + * + * void re_modw(s) + * char *s; + * + * re_subs: substitute the matched portions in a new string. + * + * int re_subs(src, dst) + * char *src; + * char *dst; + * + * re_fail: failure routine for re_exec. + * + * void re_fail(msg, op) + * char *msg; + * char op; + * + * Regular Expressions: + * + * [1] char matches itself, unless it is a special + * character (metachar): . \ [ ] * + ^ $ + * + * [2] . matches any character. + * + * [3] \ matches the character following it, except + * when followed by a left or right round bracket, + * a digit 1 to 9 or a left or right angle bracket. + * (see [7], [8] and [9]) + * It is used as an escape character for all + * other meta-characters, and itself. When used + * in a set ([4]), it is treated as an ordinary + * character. + * + * [4] [set] matches one of the characters in the set. + * If the first character in the set is "^", + * it matches a character NOT in the set, i.e. + * complements the set. A shorthand S-E is + * used to specify a set of characters S upto + * E, inclusive. The special characters "]" and + * "-" have no special meaning if they appear + * as the first chars in the set. + * examples: match: + * + * [a-z] any lowercase alpha + * + * [^]-] any char except ] and - + * + * [^A-Z] any char except uppercase + * alpha + * + * [a-zA-Z] any alpha + * + * [5] * any regular expression form [1] to [4], followed by + * closure char (*) matches zero or more matches of + * that form. + * + * [6] + same as [5], except it matches one or more. + * + * [7] a regular expression in the form [1] to [10], enclosed + * as \(form\) matches what form matches. The enclosure + * creates a set of tags, used for [8] and for + * pattern substution. The tagged forms are numbered + * starting from 1. + * + * [8] a \ followed by a digit 1 to 9 matches whatever a + * previously tagged regular expression ([7]) matched. + * + * [9] \< a regular expression starting with a \< construct + * \> and/or ending with a \> construct, restricts the + * pattern matching to the beginning of a word, and/or + * the end of a word. A word is defined to be a character + * string beginning and/or ending with the characters + * A-Z a-z 0-9 and _. It must also be preceded and/or + * followed by any character outside those mentioned. + * + * [10] a composite regular expression xy where x and y + * are in the form [1] to [10] matches the longest + * match of x followed by a match for y. + * + * [11] ^ a regular expression starting with a ^ character + * $ and/or ending with a $ character, restricts the + * pattern matching to the beginning of the line, + * or the end of line. [anchors] Elsewhere in the + * pattern, ^ and $ are treated as ordinary characters. + * + * + * Acknowledgements: + * + * HCR's Hugh Redelmeier has been most helpful in various + * stages of development. He convinced me to include BOW + * and EOW constructs, originally invented by Rob Pike at + * the University of Toronto. + * + * References: + * Software tools Kernighan & Plauger + * Software tools in Pascal Kernighan & Plauger + * Grep [rsx-11 C dist] David Conroy + * ed - text editor Un*x Programmer's Manual + * Advanced editing on Un*x B. W. Kernighan + * RegExp routines Henry Spencer + * + * Notes: + * + * This implementation uses a bit-set representation for character + * classes for speed and compactness. Each character is represented + * by one bit in a 128-bit block. Thus, CCL always takes a + * constant 16 bytes in the internal nfa, and re_exec does a single + * bit comparison to locate the character in the set. + * + * Examples: + * + * pattern: foo*.* + * compile: CHR f CHR o CLO CHR o END CLO ANY END END + * matches: fo foo fooo foobar fobar foxx ... + * + * pattern: fo[ob]a[rz] + * compile: CHR f CHR o CCL bitset CHR a CCL bitset END + * matches: fobar fooar fobaz fooaz + * + * pattern: foo\\+ + * compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END + * matches: foo\ foo\\ foo\\\ ... + * + * pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo) + * compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END + * matches: foo1foo foo2foo foo3foo + * + * pattern: \(fo.*\)-\1 + * compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END + * matches: foo-foo fo-fo fob-fob foobar-foobar ... + */ + +#define MAXNFA 1024 +#define MAXTAG 10 + +#define OKP 1 +#define NOP 0 + +#define CHR 1 +#define ANY 2 +#define CCL 3 +#define BOL 4 +#define EOL 5 +#define BOT 6 +#define EOT 7 +#define BOW 8 +#define EOW 9 +#define REF 10 +#define CLO 11 + +#define END 0 + +/* + * The following defines are not meant to be changeable. + * They are for readability only. + */ +#define MAXCHR 128 +#define CHRBIT 8 +#define BITBLK MAXCHR/CHRBIT +#define BLKIND 0170 +#define BITIND 07 + +#define ASCIIB 0177 + +/* Plain char, on the other hand, may be signed or unsigned; it depends on + * the platform and perhaps a compiler option. A hard fact of life, in C. + * + * 6-April-1999 mcs@netscape.com: replaced CHAR with REGEXCHAR to avoid + * conflicts with system types on Win32. Changed typedef + * for REGEXCHAR to always be unsigned, which seems right. + */ +typedef unsigned char REGEXCHAR; + +static int tagstk[MAXTAG]; /* subpat tag stack..*/ +static REGEXCHAR nfa[MAXNFA]; /* automaton.. */ +static int sta = NOP; /* status of lastpat */ + +static REGEXCHAR bittab[BITBLK]; /* bit table for CCL */ + /* pre-set bits... */ +static REGEXCHAR bitarr[] = {1,2,4,8,16,32,64,128}; + +static void +chset(REGEXCHAR c) +{ + bittab[((c) & (unsigned)BLKIND) >> 3] |= bitarr[(c) & BITIND]; +} + +#define badpat(x) (*nfa = END, x) +#define store(x) *mp++ = x + +char * +LDAP_CALL +re_comp( const char *pat ) +{ + register REGEXCHAR *p; /* pattern pointer */ + register REGEXCHAR *mp=nfa; /* nfa pointer */ + register REGEXCHAR *lp; /* saved pointer.. */ + register REGEXCHAR *sp=nfa; /* another one.. */ + + register int tagi = 0; /* tag stack index */ + register int tagc = 1; /* actual tag count */ + + register int n; + register REGEXCHAR mask; /* xor mask -CCL/NCL */ + int c1, c2; + + if (!pat || !*pat) { + if (sta) { + return 0; + } else { + return badpat("No previous regular expression"); + } + } + sta = NOP; + + for (p = (REGEXCHAR*)pat; *p; p++) { + lp = mp; + switch(*p) { + + case '.': /* match any char.. */ + store(ANY); + break; + + case '^': /* match beginning.. */ + if (p == (REGEXCHAR*)pat) + store(BOL); + else { + store(CHR); + store(*p); + } + break; + + case '$': /* match endofline.. */ + if (!*(p+1)) + store(EOL); + else { + store(CHR); + store(*p); + } + break; + + case '[': /* match char class..*/ + store(CCL); + + if (*++p == '^') { + mask = 0377; + p++; + } + else + mask = 0; + + if (*p == '-') /* real dash */ + chset(*p++); + if (*p == ']') /* real brac */ + chset(*p++); + while (*p && *p != ']') { + if (*p == '-' && *(p+1) && *(p+1) != ']') { + p++; + c1 = *(p-2) + 1; + c2 = *p++; + while (c1 <= c2) + chset((REGEXCHAR)c1++); + } +#ifdef EXTEND + else if (*p == '\\' && *(p+1)) { + p++; + chset(*p++); + } +#endif + else + chset(*p++); + } + if (!*p) + return badpat("Missing ]"); + + for (n = 0; n < BITBLK; bittab[n++] = (REGEXCHAR) 0) + store(mask ^ bittab[n]); + + break; + + case '*': /* match 0 or more.. */ + case '+': /* match 1 or more.. */ + if (p == (REGEXCHAR*)pat) + return badpat("Empty closure"); + lp = sp; /* previous opcode */ + if (*lp == CLO) /* equivalence.. */ + break; + switch(*lp) { + + case BOL: + case BOT: + case EOT: + case BOW: + case EOW: + case REF: + return badpat("Illegal closure"); + default: + break; + } + + if (*p == '+') + for (sp = mp; lp < sp; lp++) + store(*lp); + + store(END); + store(END); + sp = mp; + while (--mp > lp) + *mp = mp[-1]; + store(CLO); + mp = sp; + break; + + case '\\': /* tags, backrefs .. */ + switch(*++p) { + + case '(': + if (tagc < MAXTAG) { + tagstk[++tagi] = tagc; + store(BOT); + store(tagc++); + } + else + return badpat("Too many \\(\\) pairs"); + break; + case ')': + if (*sp == BOT) + return badpat("Null pattern inside \\(\\)"); + if (tagi > 0) { + store(EOT); + store(tagstk[tagi--]); + } + else + return badpat("Unmatched \\)"); + break; + case '<': + store(BOW); + break; + case '>': + if (*sp == BOW) + return badpat("Null pattern inside \\<\\>"); + store(EOW); + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = *p-'0'; + if (tagi > 0 && tagstk[tagi] == n) + return badpat("Cyclical reference"); + if (tagc > n) { + store(REF); + store(n); + } + else + return badpat("Undetermined reference"); + break; +#ifdef EXTEND + case 'b': + store(CHR); + store('\b'); + break; + case 'n': + store(CHR); + store('\n'); + break; + case 'f': + store(CHR); + store('\f'); + break; + case 'r': + store(CHR); + store('\r'); + break; + case 't': + store(CHR); + store('\t'); + break; +#endif + default: + store(CHR); + store(*p); + } + break; + + default : /* an ordinary char */ + store(CHR); + store(*p); + break; + } + sp = lp; + } + if (tagi > 0) + return badpat("Unmatched \\("); + store(END); + sta = OKP; + return 0; +} + + +static REGEXCHAR *bol; +static REGEXCHAR *bopat[MAXTAG]; +static REGEXCHAR *eopat[MAXTAG]; +#ifdef NEEDPROTOS +static REGEXCHAR *pmatch( REGEXCHAR *lp, REGEXCHAR *ap ); +#else /* NEEDPROTOS */ +static REGEXCHAR *pmatch(); +#endif /* NEEDPROTOS */ + +/* + * re_exec: + * execute nfa to find a match. + * + * special cases: (nfa[0]) + * BOL + * Match only once, starting from the + * beginning. + * CHR + * First locate the character without + * calling pmatch, and if found, call + * pmatch for the remaining string. + * END + * re_comp failed, poor luser did not + * check for it. Fail fast. + * + * If a match is found, bopat[0] and eopat[0] are set + * to the beginning and the end of the matched fragment, + * respectively. + * + */ + +int +LDAP_CALL +re_exec( const char *lp ) +{ + register REGEXCHAR c; + register REGEXCHAR *ep = 0; + register REGEXCHAR *ap = nfa; + + bol = (REGEXCHAR*)lp; + + bopat[0] = 0; + bopat[1] = 0; + bopat[2] = 0; + bopat[3] = 0; + bopat[4] = 0; + bopat[5] = 0; + bopat[6] = 0; + bopat[7] = 0; + bopat[8] = 0; + bopat[9] = 0; + + switch(*ap) { + + case BOL: /* anchored: match from BOL only */ + ep = pmatch((REGEXCHAR*)lp,ap); + break; + case CHR: /* ordinary char: locate it fast */ + c = *(ap+1); + while (*lp && *(REGEXCHAR*)lp != c) + lp++; + if (!*lp) /* if EOS, fail, else fall thru. */ + return 0; + default: /* regular matching all the way. */ + do { + if ((ep = pmatch((REGEXCHAR*)lp,ap))) + break; + lp++; + } while (*lp); + + break; + case END: /* munged automaton. fail always */ + return 0; + } + if (!ep) + return 0; + + bopat[0] = (REGEXCHAR*)lp; + eopat[0] = ep; + return 1; +} + +/* + * pmatch: internal routine for the hard part + * + * This code is partly snarfed from an early grep written by + * David Conroy. The backref and tag stuff, and various other + * innovations are by oz. + * + * special case optimizations: (nfa[n], nfa[n+1]) + * CLO ANY + * We KNOW .* will match everything upto the + * end of line. Thus, directly go to the end of + * line, without recursive pmatch calls. As in + * the other closure cases, the remaining pattern + * must be matched by moving backwards on the + * string recursively, to find a match for xy + * (x is ".*" and y is the remaining pattern) + * where the match satisfies the LONGEST match for + * x followed by a match for y. + * CLO CHR + * We can again scan the string forward for the + * single char and at the point of failure, we + * execute the remaining nfa recursively, same as + * above. + * + * At the end of a successful match, bopat[n] and eopat[n] + * are set to the beginning and end of subpatterns matched + * by tagged expressions (n = 1 to 9). + * + */ + +#ifndef re_fail +extern void re_fail(); +#endif /* re_fail */ + +/* + * character classification table for word boundary operators BOW + * and EOW. the reason for not using ctype macros is that we can + * let the user add into our own table. see re_modw. This table + * is not in the bitset form, since we may wish to extend it in the + * future for other character classifications. + * + * TRUE for 0-9 A-Z a-z _ + */ +static char chrtyp[MAXCHR] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0 + }; + +#define HIBIT 0200 +#define inascii(x) (0177&(x)) +#define iswordc(x) chrtyp[inascii(x)] +#define isinset(x,y) (((y)&HIBIT)?0:((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])) + +/* + * skip values for CLO XXX to skip past the closure + */ + +#define ANYSKIP 2 /* [CLO] ANY END ... */ +#define CHRSKIP 3 /* [CLO] CHR chr END ... */ +#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */ + +static REGEXCHAR * +pmatch( REGEXCHAR *lp, REGEXCHAR *ap) +{ + register int op, c, n; + register REGEXCHAR *e; /* extra pointer for CLO */ + register REGEXCHAR *bp; /* beginning of subpat.. */ + register REGEXCHAR *ep; /* ending of subpat.. */ + REGEXCHAR *are; /* to save the line ptr. */ + + while ((op = *ap++) != END) + switch(op) { + + case CHR: + if (*lp++ != *ap++) + return 0; + break; + case ANY: + if (!*lp++) + return 0; + break; + case CCL: + c = *lp++; + if (!isinset(ap,c)) + return 0; + ap += BITBLK; + break; + case BOL: + if (lp != bol) + return 0; + break; + case EOL: + if (*lp) + return 0; + break; + case BOT: + bopat[*ap++] = lp; + break; + case EOT: + eopat[*ap++] = lp; + break; + case BOW: + if ((lp!=bol && iswordc(lp[-1])) || !iswordc(*lp)) + return 0; + break; + case EOW: + if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp)) + return 0; + break; + case REF: + n = *ap++; + bp = bopat[n]; + ep = eopat[n]; + while (bp < ep) + if (*bp++ != *lp++) + return 0; + break; + case CLO: + are = lp; + switch(*ap) { + + case ANY: + while (*lp) + lp++; + n = ANYSKIP; + break; + case CHR: + c = *(ap+1); + while (*lp && c == *lp) + lp++; + n = CHRSKIP; + break; + case CCL: + while ((c = *lp) && isinset(ap+1,c)) + lp++; + n = CCLSKIP; + break; + default: + re_fail("closure: bad nfa.", *ap); + return 0; + } + + ap += n; + + while (lp >= are) { + if ((e = pmatch(lp, ap))) + return e; + --lp; + } + return 0; + default: + re_fail("re_exec: bad nfa.", op); + return 0; + } + return lp; +} + +/* + * re_modw: + * add new characters into the word table to change re_exec's + * understanding of what a word should look like. Note that we + * only accept additions into the word definition. + * + * If the string parameter is 0 or null string, the table is + * reset back to the default containing A-Z a-z 0-9 _. [We use + * the compact bitset representation for the default table] + */ + +static REGEXCHAR deftab[16] = { + 0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207, + 0376, 0377, 0377, 007 +}; + +void +LDAP_CALL +re_modw( char *s ) +{ + register int i; + + if (!s || !*s) { + for (i = 0; i < MAXCHR; i++) + if (!isinset(deftab,i)) + iswordc(i) = 0; + } + else + while(*s) + iswordc(*s++) = 1; +} + +/* + * re_subs: + * substitute the matched portions of the src in dst. + * + * & substitute the entire matched pattern. + * + * \digit substitute a subpattern, with the given tag number. + * Tags are numbered from 1 to 9. If the particular + * tagged subpattern does not exist, null is substituted. + */ +int +LDAP_CALL +re_subs( char *src, char *dst) +{ + register char c; + register int pin; + register REGEXCHAR *bp; + register REGEXCHAR *ep; + + if (!*src || !bopat[0]) + return 0; + + while ((c = *src++)) { + switch(c) { + + case '&': + pin = 0; + break; + + case '\\': + c = *src++; + if (c >= '0' && c <= '9') { + pin = c - '0'; + break; + } + + default: + *dst++ = c; + continue; + } + + if ((bp = bopat[pin]) && (ep = eopat[pin])) { + while (*bp && bp < ep) + *dst++ = *(char*)bp++; + if (bp < ep) + return 0; + } + } + *dst = (char) 0; + return 1; +} + +#ifdef DEBUG + +/* No printf or exit in 16-bit Windows */ +#if defined( _WINDOWS ) && !defined( _WIN32 ) +static int LDAP_C printf( const char* pszFormat, ...) +{ + char buf[1024]; + va_list arglist; + va_start(arglist, pszFormat); + vsprintf(buf, pszFormat, arglist); + va_end(arglist); + OutputDebugString(buf); + return 0; +} +#define exit(v) return +#endif /* 16-bit Windows */ + + +#ifdef REGEX_DEBUG + +static void nfadump( REGEXCHAR *ap); + +/* + * symbolic - produce a symbolic dump of the nfa + */ +void +symbolic( char *s ) +{ + printf("pattern: %s\n", s); + printf("nfacode:\n"); + nfadump(nfa); +} + +static void +nfadump( REGEXCHAR *ap) +{ + register int n; + + while (*ap != END) + switch(*ap++) { + case CLO: + printf("CLOSURE"); + nfadump(ap); + switch(*ap) { + case CHR: + n = CHRSKIP; + break; + case ANY: + n = ANYSKIP; + break; + case CCL: + n = CCLSKIP; + break; + } + ap += n; + break; + case CHR: + printf("\tCHR %c\n",*ap++); + break; + case ANY: + printf("\tANY .\n"); + break; + case BOL: + printf("\tBOL -\n"); + break; + case EOL: + printf("\tEOL -\n"); + break; + case BOT: + printf("BOT: %d\n",*ap++); + break; + case EOT: + printf("EOT: %d\n",*ap++); + break; + case BOW: + printf("BOW\n"); + break; + case EOW: + printf("EOW\n"); + break; + case REF: + printf("REF: %d\n",*ap++); + break; + case CCL: + printf("\tCCL ["); + for (n = 0; n < MAXCHR; n++) + if (isinset(ap,(REGEXCHAR)n)) { + if (n < ' ') + printf("^%c", n ^ 0x040); + else + printf("%c", n); + } + printf("]\n"); + ap += BITBLK; + break; + default: + printf("bad nfa. opcode %o\n", ap[-1]); + exit(1); + break; + } +} +#endif /* REGEX_DEBUG */ +#endif /* DEBUG */ +#endif /* macintosh or DOS or _WINDOWS or NEED_BSDREGEX */ diff --git a/ldap/c-sdk/libldap/rename.c b/ldap/c-sdk/libldap/rename.c new file mode 100644 index 0000000000..ac3ec7c737 --- /dev/null +++ b/ldap/c-sdk/libldap/rename.c @@ -0,0 +1,265 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * rename.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * ldap_rename - initiate an ldap modifyDN operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to modify + * newrdn RDN that will form leftmost component of entry's new name + * newparent if present, this is the Distinguished Name of the entry + * which becomes the immediate parent of the existing entry + * deleteoldrdn nonzero means to delete old rdn values from the entry + * while zero means to retain them as attributes of the entry + * 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_rename() call succeeds + * + * Example: + * int rc; + * rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid ); + */ +int +LDAP_CALL +ldap_rename( + LDAP *ld, + const char *dn, + const char *newrdn, + const char *newparent, + int deleteoldrdn, + LDAPControl **serverctrls, + LDAPControl **clientctrls, /* not used for anything yet */ + int *msgidp +) +{ + BerElement *ber; + int rc, err; + + /* + * A modify dn request looks like this: + * ModifyDNRequest ::= SEQUENCE { + * entry LDAPDN, + * newrdn RelativeLDAPDN, + * newparent [0] LDAPDN OPTIONAL, + * deleteoldrdn BOOLEAN + * } + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + if ( NULL == newrdn) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + /* only ldapv3 or higher can do a proper rename + * (i.e. with non-NULL newparent and/or controls) + */ + + if (( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) + && ((newparent != NULL) || (serverctrls != NULL) + || (clientctrls != NULL))) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + if ( msgidp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* see if modRDN or modDN is handled by the cache */ + if ( ld->ld_cache_on ) { + if ( newparent == NULL && ld->ld_cache_modrdn != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_modrdn)( ld, *msgidp, + LDAP_REQ_MODRDN, dn, newrdn, deleteoldrdn )) + != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); +#if 0 + } else if ( ld->ld_cache_rename != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_rename)( ld, *msgidp, + LDAP_REQ_MODDN, dn, newrdn, newparent, + deleteoldrdn )) != 0 ) { + *msgidp = rc; + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); +#endif + } + } + + /* create a message to send */ + if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( err ); + } + + /* fill it in */ + if ( ber_printf( ber, "{it{ssb", *msgidp, LDAP_REQ_MODDN, dn, + newrdn, deleteoldrdn ) == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + if ( newparent == NULL ) { + if ( ber_printf( ber, "}" ) == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } else { + if ( ber_printf( ber, "ts}", LDAP_TAG_NEWSUPERIOR, newparent ) + == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + + if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( rc ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODDN, + (char *) dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +int +LDAP_CALL +ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn ) +{ + int msgid; + + if ( ldap_rename( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL, &msgid ) == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + +int +LDAP_CALL +ldap_modrdn( LDAP *ld, const char *dn, const char *newrdn ) +{ + return( ldap_modrdn2( ld, dn, newrdn, 1 ) ); +} + +int +LDAP_CALL +ldap_rename_s( + LDAP *ld, + const char *dn, + const char *newrdn, + const char *newparent, + int deleteoldrdn, + LDAPControl **serverctrls, + LDAPControl **clientctrls /* not used for anything yet */ +) +{ + int msgid; + LDAPMessage *res; + + if ( ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid ) != LDAP_SUCCESS ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( msgid == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + return( ldap_result2error( ld, res, 1 ) ); +} + +int +LDAP_CALL +ldap_modrdn2_s( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn ) +{ + int msgid; + LDAPMessage *res; + + if ( (msgid = ldap_modrdn2( ld, dn, newrdn, deleteoldrdn )) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + return( ldap_result2error( ld, res, 1 ) ); +} + +int +LDAP_CALL +ldap_modrdn_s( LDAP *ld, const char *dn, const char *newrdn ) +{ + return( ldap_modrdn2_s( ld, dn, newrdn, 1 ) ); +} diff --git a/ldap/c-sdk/libldap/request.c b/ldap/c-sdk/libldap/request.c new file mode 100644 index 0000000000..d379917b2b --- /dev/null +++ b/ldap/c-sdk/libldap/request.c @@ -0,0 +1,1659 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * request.c - sending of ldap requests; handling of referrals + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any ); +static void free_servers( LDAPServer *srvlist ); +static int chase_one_referral( LDAP *ld, LDAPRequest *lr, LDAPRequest *origreq, + char *refurl, char *desc, int *unknownp, int is_reference ); +static int re_encode_request( LDAP *ld, BerElement *origber, + int msgid, LDAPURLDesc *ludp, BerElement **berp, int is_reference ); + +#ifdef LDAP_DNS +static LDAPServer *dn2servers( LDAP *ld, char *dn ); +#endif /* LDAP_DNS */ + + +/* returns an LDAP error code and also sets error inside LDAP * */ +int +nsldapi_alloc_ber_with_options( LDAP *ld, BerElement **berp ) +{ + int err; + + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + if (( *berp = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + } else { + err = LDAP_SUCCESS; +#ifdef STR_TRANSLATION + nsldapi_set_ber_options( ld, *berp ); +#endif /* STR_TRANSLATION */ + } + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + + return( err ); +} + + +void +nsldapi_set_ber_options( LDAP *ld, BerElement *ber ) +{ + ber->ber_options = ld->ld_lberoptions; +#ifdef STR_TRANSLATION + if (( ld->ld_lberoptions & LBER_OPT_TRANSLATE_STRINGS ) != 0 ) { + ber_set_string_translators( ber, + ld->ld_lber_encode_translate_proc, + ld->ld_lber_decode_translate_proc ); + } +#endif /* STR_TRANSLATION */ +} + + +/* returns the message id of the request or -1 if an error occurs */ +int +nsldapi_send_initial_request( LDAP *ld, int msgid, unsigned long msgtype, + char *dn, BerElement *ber ) +{ + LDAPServer *servers; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_initial_request\n", 0,0,0 ); + +#ifdef LDAP_DNS + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + if (( ld->ld_options & LDAP_BITOPT_DNS ) != 0 && ldap_is_dns_dn( dn )) { + if (( servers = dn2servers( ld, dn )) == NULL ) { + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + return( -1 ); + } + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_TRACE ) { + LDAPServer *srv; + char msg[256]; + + for ( srv = servers; srv != NULL; + srv = srv->lsrv_next ) { + sprintf( msg, + "LDAP server %s: dn %s, port %d\n", + srv->lsrv_host, ( srv->lsrv_dn == NULL ) ? + "(default)" : srv->lsrv_dn, + srv->lsrv_port ); + ber_err_print( msg ); + } + } +#endif /* LDAP_DEBUG */ + } else { +#endif /* LDAP_DNS */ + /* + * use of DNS is turned off or this is an LDAP DN... + * use our default connection + */ + servers = NULL; +#ifdef LDAP_DNS + } + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); +#endif /* LDAP_DNS */ + + return( nsldapi_send_server_request( ld, ber, msgid, NULL, + servers, NULL, ( msgtype == LDAP_REQ_BIND ) ? dn : NULL, 0 )); +} + + +/* returns the message id of the request or -1 if an error occurs */ +int +nsldapi_send_server_request( + LDAP *ld, /* session handle */ + BerElement *ber, /* message to send */ + int msgid, /* ID of message to send */ + LDAPRequest *parentreq, /* non-NULL for referred requests */ + LDAPServer *srvlist, /* servers to connect to (NULL for default) */ + LDAPConn *lc, /* connection to use (NULL for default) */ + char *bindreqdn, /* non-NULL for bind requests */ + int bind /* perform a bind after opening new conn.? */ +) +{ + LDAPRequest *lr; + int err; + int incparent; /* did we bump parent's ref count? */ + /* EPIPE and Unsolicited Response handling variables */ + int res_rc = 0; + int epipe_err = 0; + int ext_res_rc = 0; + char *ext_oid = NULL; + struct berval *ext_data = NULL; + LDAPMessage *ext_res = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_server_request\n", 0, 0, 0 ); + + incparent = 0; + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + if ( lc == NULL ) { + if ( srvlist == NULL ) { + if ( ld->ld_defconn == NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + if ( bindreqdn == NULL && ( ld->ld_options + & LDAP_BITOPT_RECONNECT ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, + NULL, NULL ); + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + + if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + } + lc = ld->ld_defconn; + } else { + if (( lc = find_connection( ld, srvlist, 1 )) == + NULL ) { + if ( bind && (parentreq != NULL) ) { + /* Remember the bind in the parent */ + incparent = 1; + ++parentreq->lr_outrefcnt; + } + + lc = nsldapi_new_connection( ld, &srvlist, 0, + 1, bind ); + } + free_servers( srvlist ); + } + } + + + /* + * return a fatal error if: + * 1. no connections exists + * or + * 2. the connection is dead + * or + * 3. it is not in the connected state with normal (non async) I/O + */ + if ( lc == NULL + || ( lc->lconn_status == LDAP_CONNST_DEAD ) + || ( 0 == (ld->ld_options & LDAP_BITOPT_ASYNC) && + lc->lconn_status != LDAP_CONNST_CONNECTED) ) { + + ber_free( ber, 1 ); + if ( lc != NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); + } + if ( incparent ) { + /* Forget about the bind */ + --parentreq->lr_outrefcnt; + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + + if (( lr = nsldapi_new_request( lc, ber, msgid, + 1 /* expect a response */)) == NULL + || ( bindreqdn != NULL && ( bindreqdn = + nsldapi_strdup( bindreqdn )) == NULL )) { + if ( lr != NULL ) { + NSLDAPI_FREE( lr ); + } + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); + ber_free( ber, 1 ); + if ( incparent ) { + /* Forget about the bind */ + --parentreq->lr_outrefcnt; + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + lr->lr_binddn = bindreqdn; + + if ( parentreq != NULL ) { /* sub-request */ + if ( !incparent ) { + /* Increment if we didn't do it before the bind */ + ++parentreq->lr_outrefcnt; + } + lr->lr_origid = parentreq->lr_origid; + lr->lr_parentcnt = parentreq->lr_parentcnt + 1; + lr->lr_parent = parentreq; + if ( parentreq->lr_child != NULL ) { + lr->lr_sibling = parentreq->lr_child; + } + parentreq->lr_child = lr; + } else { /* original request */ + lr->lr_origid = lr->lr_msgid; + } + + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + /* add new request to the end of the list of outstanding requests */ + nsldapi_queue_request_nolock( ld, lr ); + + /* + * Issue a non-blocking poll() if we need to check this + * connection's status. + */ + if ( lc->lconn_status == LDAP_CONNST_CONNECTING || + lc->lconn_pending_requests > 0 ) { + struct timeval tv; + + tv.tv_sec = tv.tv_usec = 0; + (void)nsldapi_iostatus_poll( ld, &tv ); + } + + /* + * If the connect is pending, check to see if it has now completed. + */ + if ( lc->lconn_status == LDAP_CONNST_CONNECTING && + nsldapi_iostatus_is_write_ready( ld, lc->lconn_sb )) { + lc->lconn_status = LDAP_CONNST_CONNECTED; + + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: connection 0x%p -" + " LDAP_CONNST_CONNECTING -> LDAP_CONNST_CONNECTED\n", + lc, 0, 0 ); + } + + if ( lc->lconn_status == LDAP_CONNST_CONNECTING || + lc->lconn_pending_requests > 0 ) { + /* + * The connect is not yet complete, or there are existing + * requests that have not yet been sent to the server. + * Delay sending this request. + */ + lr->lr_status = LDAP_REQST_WRITING; + ++lc->lconn_pending_requests; + nsldapi_iostatus_interest_write( ld, lc->lconn_sb ); + + /* + * If the connection is now connected, and it is ready + * to accept some more outbound data, send as many + * pending requests as possible. + */ + if ( lc->lconn_status != LDAP_CONNST_CONNECTING + && nsldapi_iostatus_is_write_ready( ld, lc->lconn_sb )) { + if ( nsldapi_send_pending_requests_nolock( ld, lc ) + == -1 ) { /* error */ + /* + * Since nsldapi_send_pending_requests_nolock() + * sets LDAP errno, there is no need to do so + * here. + */ + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + } + + } else { + if (( err = nsldapi_send_ber_message( ld, lc->lconn_sb, + ber, 0 /* do not free ber */, + 1 /* will handle EPIPE */ )) != 0 ) { + + epipe_err = LDAP_GET_ERRNO( ld ); + if ( epipe_err == EPIPE ) { + res_rc = nsldapi_result_nolock(ld, LDAP_RES_UNSOLICITED, 1, + 1, (struct timeval *) NULL, &ext_res); + if ( ( res_rc == LDAP_RES_EXTENDED ) && ext_res ) { + ext_res_rc = ldap_parse_extended_result( ld, ext_res, + &ext_oid, &ext_data, 0 ); + if ( ext_res_rc != LDAP_SUCCESS ) { + if ( ext_res ) { + ldap_msgfree( ext_res ); + } + nsldapi_connection_lost_nolock( ld, lc->lconn_sb ); + } else { +#ifdef LDAP_DEBUG + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: Unsolicited response\n", 0, 0, 0 ); + if ( ext_oid ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: Unsolicited response oid: %s\n", + ext_oid, 0, 0 ); + } + if ( ext_data && ext_data->bv_len && ext_data->bv_val ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: Unsolicited response len: %d\n", + ext_data->bv_len, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: Unsolicited response val: %s\n", + ext_data->bv_val, 0, 0 ); + } + if ( !ext_oid && !ext_data ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_send_server_request: Unsolicited response is empty\n", + 0, 0, 0 ); + } +#endif /* LDAP_DEBUG */ + if ( ext_oid ) { + if ( strcmp ( ext_oid, + LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) { + if ( ext_data ) { + ber_bvfree( ext_data ); + } + if ( ext_oid ) { + ldap_memfree( ext_oid ); + } + if ( ext_res ) { + ldap_msgfree( ext_res ); + } + nsldapi_connection_lost_nolock( ld, + lc->lconn_sb ); + nsldapi_free_request( ld, lr, 0 ); + nsldapi_free_connection( ld, lc, + NULL, NULL, 0, 0 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + } + } + } else { + if ( ext_res ) { + ldap_msgfree( ext_res ); + } + nsldapi_connection_lost_nolock( ld, lc->lconn_sb ); + } + } + + /* need to continue write later */ + if (err == -2 ) { + lr->lr_status = LDAP_REQST_WRITING; + ++lc->lconn_pending_requests; + nsldapi_iostatus_interest_write( ld, lc->lconn_sb ); + } else { + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); + nsldapi_free_request( ld, lr, 0 ); + nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + return( -1 ); + } + + } else { + if ( parentreq == NULL ) { + ber->ber_end = ber->ber_ptr; + ber->ber_ptr = ber->ber_buf; + } + + /* sent -- waiting for a response */ + if (ld->ld_options & LDAP_BITOPT_ASYNC) { + lc->lconn_status = LDAP_CONNST_CONNECTED; + } + + nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); + return( msgid ); +} + + +/* + * nsldapi_send_ber_message(): Attempt to send a BER-encoded message. + * If freeit is non-zero, ber is freed when the send succeeds. + * If errno is EPIPE and epipe_handler is set we let the caller + * deal with EPIPE and dont call lost_nolock here but the caller + * should call lost_nolock itself when done with handling EPIPE. + * + * Return values: + * 0: message sent successfully. + * -1: a fatal error occurred while trying to send. + * -2: async. I/O is enabled and the send would block. + */ +int +nsldapi_send_ber_message( LDAP *ld, Sockbuf *sb, BerElement *ber, int freeit, + int epipe_handler ) +{ + int rc = 0; /* optimistic */ + int async = ( 0 != (ld->ld_options & LDAP_BITOPT_ASYNC)); + int more_to_send = 1; + + while ( more_to_send) { + /* + * ber_flush() doesn't set errno on EOF, so we pre-set it to + * zero to avoid getting tricked by leftover "EAGAIN" errors + */ + LDAP_SET_ERRNO( ld, 0 ); + + if ( ber_flush( sb, ber, freeit ) == 0 ) { + more_to_send = 0; /* success */ + } else { + int terrno = LDAP_GET_ERRNO( ld ); + if ( NSLDAPI_ERRNO_IO_INPROGRESS( terrno )) { + if ( async ) { + rc = -2; + break; + } + } else { + if ( !(epipe_handler && ( terrno == EPIPE )) ) { + nsldapi_connection_lost_nolock( ld, sb ); + } + rc = -1; /* fatal error */ + break; + } + } + } + + return( rc ); +} + + +/* + * nsldapi_send_pending_requests_nolock(): Send one or more pending requests + * that are associated with connection 'lc'. + * + * Return values: 0 -- success. + * -1 -- fatal error; connection closed. + * + * Must be called with these two mutexes locked, in this order: + * LDAP_CONN_LOCK + * LDAP_REQ_LOCK + */ +int +nsldapi_send_pending_requests_nolock( LDAP *ld, LDAPConn *lc ) +{ + int err; + int waiting_for_a_response = 0; + int rc = 0; + LDAPRequest *lr; + char *logname = "nsldapi_send_pending_requests_nolock"; + + LDAPDebug( LDAP_DEBUG_TRACE, "%s\n", logname, 0, 0 ); + + for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { + /* + * This code relies on the fact that the ld_requests list + * is in order from oldest to newest request (the oldest + * requests that have not yet been sent to the server are + * sent first). + */ + if ( lr->lr_status == LDAP_REQST_WRITING + && lr->lr_conn == lc ) { + err = nsldapi_send_ber_message( ld, lc->lconn_sb, + lr->lr_ber, 0 /* do not free ber */, + 0 /* will not handle EPIPE */ ); + if ( err == 0 ) { /* send succeeded */ + LDAPDebug( LDAP_DEBUG_TRACE, + "%s: 0x%p SENT\n", logname, lr, 0 ); + lr->lr_ber->ber_end = lr->lr_ber->ber_ptr; + lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf; + lr->lr_status = LDAP_REQST_INPROGRESS; + --lc->lconn_pending_requests; + } else if ( err == -2 ) { /* would block */ + rc = 0; /* not an error */ + LDAPDebug( LDAP_DEBUG_TRACE, + "%s: 0x%p WOULD BLOCK\n", logname, lr, 0 ); + break; + } else { /* fatal error */ + LDAPDebug( LDAP_DEBUG_TRACE, + "%s: 0x%p FATAL ERROR\n", logname, lr, 0 ); + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, + NULL, NULL ); + nsldapi_free_request( ld, lr, 0 ); + lr = NULL; + nsldapi_free_connection( ld, lc, NULL, NULL, + 0, 0 ); + lc = NULL; + rc = -1; + break; + } + } + + if (lr->lr_status == LDAP_REQST_INPROGRESS ) { + if (lr->lr_expect_resp) { + ++waiting_for_a_response; + } else { + LDAPDebug( LDAP_DEBUG_TRACE, + "%s: 0x%p NO RESPONSE EXPECTED;" + " freeing request \n", logname, lr, 0 ); + nsldapi_free_request( ld, lr, 0 ); + lr = NULL; + } + } + } + + if ( lc != NULL ) { + if ( lc->lconn_pending_requests < 1 ) { + /* no need to poll for "write ready" any longer */ + nsldapi_iostatus_interest_clear( ld, lc->lconn_sb ); + } + + if ( waiting_for_a_response ) { + /* need to poll for "read ready" */ + nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); + } + } + + LDAPDebug( LDAP_DEBUG_TRACE, "%s <- %d\n", logname, rc, 0 ); + return( rc ); +} + + +LDAPConn * +nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, + int connect, int bind ) +{ + int rc = -1; + LDAPConn *lc; + LDAPServer *prevsrv, *srv; + Sockbuf *sb = NULL; + + /* + * make a new LDAP server connection + */ + if (( lc = (LDAPConn *)NSLDAPI_CALLOC( 1, sizeof( LDAPConn ))) == NULL + || ( !use_ldsb && ( sb = ber_sockbuf_alloc()) == NULL )) { + if ( lc != NULL ) { + NSLDAPI_FREE( (char *)lc ); + } + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( NULL ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + if ( !use_ldsb ) { + /* + * we have allocated a new sockbuf + * set I/O routines to match those in default LDAP sockbuf + */ + IFP sb_fn; + struct lber_x_ext_io_fns extiofns; + + extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + + if ( ber_sockbuf_get_option( ld->ld_sbp, + LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ) == 0 ) { + ber_sockbuf_set_option( sb, + LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ); + } + if ( ber_sockbuf_get_option( ld->ld_sbp, + LBER_SOCKBUF_OPT_READ_FN, (void *)&sb_fn ) == 0 + && sb_fn != NULL ) { + ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_READ_FN, + (void *)sb_fn ); + } + if ( ber_sockbuf_get_option( ld->ld_sbp, + LBER_SOCKBUF_OPT_WRITE_FN, (void *)&sb_fn ) == 0 + && sb_fn != NULL ) { + ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_WRITE_FN, + (void *)sb_fn ); + } + } + + lc->lconn_sb = ( use_ldsb ) ? ld->ld_sbp : sb; + lc->lconn_version = ld->ld_version; /* inherited */ + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + + if ( connect ) { + prevsrv = NULL; + /* + * save the return code for later + */ + for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) { + rc = nsldapi_connect_to_host( ld, lc->lconn_sb, + srv->lsrv_host, srv->lsrv_port, + ( srv->lsrv_options & LDAP_SRV_OPT_SECURE ) != 0, + &lc->lconn_krbinstance ); + if (rc != -1) { + break; + } + prevsrv = srv; + } + + if ( srv == NULL ) { + if ( !use_ldsb ) { + NSLDAPI_FREE( (char *)lc->lconn_sb ); + } + NSLDAPI_FREE( (char *)lc ); + /* nsldapi_open_ldap_connection has already set ld_errno */ + return( NULL ); + } + + if ( prevsrv == NULL ) { + *srvlistp = srv->lsrv_next; + } else { + prevsrv->lsrv_next = srv->lsrv_next; + } + lc->lconn_server = srv; + } + + if ( 0 != (ld->ld_options & LDAP_BITOPT_ASYNC)) { + /* + * Technically, the socket may already be connected but we are + * not sure. By setting the state to LDAP_CONNST_CONNECTING, we + * ensure that we will check the socket status to make sure it + * is connected before we try to send any LDAP messages. + */ + lc->lconn_status = LDAP_CONNST_CONNECTING; + } else { + lc->lconn_status = LDAP_CONNST_CONNECTED; + } + + lc->lconn_next = ld->ld_conns; + ld->ld_conns = lc; + + /* + * XXX for now, we always do a synchronous bind. This will have + * to change in the long run... + */ + if ( bind ) { + int err, lderr, freepasswd, authmethod; + char *binddn, *passwd; + LDAPConn *savedefconn; + + freepasswd = err = 0; + + if ( ld->ld_rebind_fn == NULL ) { + binddn = passwd = ""; + authmethod = LDAP_AUTH_SIMPLE; + } else { + if (( lderr = (*ld->ld_rebind_fn)( ld, &binddn, &passwd, + &authmethod, 0, ld->ld_rebind_arg )) + == LDAP_SUCCESS ) { + freepasswd = 1; + } else { + LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); + err = -1; + } + } + + + if ( err == 0 ) { + savedefconn = ld->ld_defconn; + ld->ld_defconn = lc; + ++lc->lconn_refcnt; /* avoid premature free */ + + /* + * when binding, we will back down as low as LDAPv2 + * if we get back "protocol error" from bind attempts + */ + for ( ;; ) { + /* LDAP_MUTEX_UNLOCK(ld, LDAP_CONN_LOCK); */ + if (( lderr = ldap_bind_s( ld, binddn, passwd, + authmethod )) == LDAP_SUCCESS ) { + /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ + break; + } + /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ + if ( lc->lconn_version <= LDAP_VERSION2 + || lderr != LDAP_PROTOCOL_ERROR ) { + err = -1; + break; + } + --lc->lconn_version; /* try lower version */ + } + --lc->lconn_refcnt; + ld->ld_defconn = savedefconn; + } + + if ( freepasswd ) { + (*ld->ld_rebind_fn)( ld, &binddn, &passwd, + &authmethod, 1, ld->ld_rebind_arg ); + } + + if ( err != 0 ) { + nsldapi_free_connection( ld, lc, NULL, NULL, 1, 0 ); + lc = NULL; + } + } + + return( lc ); +} + + +#define LDAP_CONN_SAMEHOST( h1, h2 ) \ + (( (h1) == NULL && (h2) == NULL ) || \ + ( (h1) != NULL && (h2) != NULL && strcasecmp( (h1), (h2) ) == 0 )) + +static LDAPConn * +find_connection( LDAP *ld, LDAPServer *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; + + for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { + for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) { + if ( LDAP_CONN_SAMEHOST( ls->lsrv_host, + lc->lconn_server->lsrv_host ) + && ls->lsrv_port == lc->lconn_server->lsrv_port + && ls->lsrv_options == + lc->lconn_server->lsrv_options ) { + return( lc ); + } + if ( !any ) { + break; + } + } + } + + return( NULL ); +} + + +void +nsldapi_free_connection( LDAP *ld, LDAPConn *lc, LDAPControl **serverctrls, + LDAPControl **clientctrls, int force, int unbind ) +{ + LDAPConn *tmplc, *prevlc; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection\n", 0, 0, 0 ); + + if ( force || --lc->lconn_refcnt <= 0 ) { + nsldapi_iostatus_interest_clear( ld, lc->lconn_sb ); + if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { + if ( unbind ) { + nsldapi_send_unbind( ld, lc->lconn_sb, + serverctrls, clientctrls ); + } + } + nsldapi_close_connection( ld, lc->lconn_sb ); + prevlc = NULL; + for ( tmplc = ld->ld_conns; tmplc != NULL; + tmplc = tmplc->lconn_next ) { + if ( tmplc == lc ) { + if ( prevlc == NULL ) { + ld->ld_conns = tmplc->lconn_next; + } else { + prevlc->lconn_next = tmplc->lconn_next; + } + break; + } + prevlc = tmplc; + } + free_servers( lc->lconn_server ); + if ( lc->lconn_krbinstance != NULL ) { + NSLDAPI_FREE( lc->lconn_krbinstance ); + } + /* + * if this is the default connection (lc->lconn_sb==ld->ld_sbp) + * we do not free the Sockbuf here since it will be freed + * later inside ldap_unbind(). + */ + if ( lc->lconn_sb != ld->ld_sbp ) { + ber_sockbuf_free( lc->lconn_sb ); + lc->lconn_sb = NULL; + } + if ( lc->lconn_ber != NULLBER ) { + ber_free( lc->lconn_ber, 1 ); + } + if ( lc->lconn_binddn != NULL ) { + NSLDAPI_FREE( lc->lconn_binddn ); + } +#ifdef LDAP_SASLIO_HOOKS + if ( lc->lconn_sasl_ctx ) { /* the sasl connection context */ + sasl_dispose(&lc->lconn_sasl_ctx); + lc->lconn_sasl_ctx = NULL; + } +#endif /* LDAP_SASLIO_HOOKS */ + NSLDAPI_FREE( lc ); + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: actually freed\n", + 0, 0, 0 ); + } else { + lc->lconn_lastused = time( 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: refcnt %d\n", + lc->lconn_refcnt, 0, 0 ); + } +} + + +#ifdef LDAP_DEBUG +void +nsldapi_dump_connection( LDAP *ld, LDAPConn *lconns, int all ) +{ + LDAPConn *lc; + char msg[256]; +/* CTIME for this platform doesn't use this. */ +#if !defined(SUNOS4) && !defined(_WIN32) && !defined(LINUX) && !defined(macintosh) + char buf[26]; +#endif + + sprintf( msg, "** Connection%s:\n", all ? "s" : "" ); + ber_err_print( msg ); + for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) { + if ( lc->lconn_server != NULL ) { + sprintf( msg, "* 0x%p - host: %s port: %d secure: %s%s\n", + lc, ( lc->lconn_server->lsrv_host == NULL ) ? "(null)" + : lc->lconn_server->lsrv_host, + lc->lconn_server->lsrv_port, + ( lc->lconn_server->lsrv_options & + LDAP_SRV_OPT_SECURE ) ? "Yes" : + "No", ( lc->lconn_sb == ld->ld_sbp ) ? + " (default)" : "" ); + ber_err_print( msg ); + } + sprintf( msg, " refcnt: %d pending: %d status: %s\n", + lc->lconn_refcnt, lc->lconn_pending_requests, + ( lc->lconn_status == LDAP_CONNST_CONNECTING ) + ? "Connecting" : + ( lc->lconn_status == LDAP_CONNST_DEAD ) ? "Dead" : + "Connected" ); + ber_err_print( msg ); + sprintf( msg, " last used: %s", + NSLDAPI_CTIME( (time_t *) &lc->lconn_lastused, buf, + sizeof(buf) )); + ber_err_print( msg ); + if ( lc->lconn_ber != NULLBER ) { + ber_err_print( " partial response has been received:\n" ); + ber_dump( lc->lconn_ber, 1 ); + } + ber_err_print( "\n" ); + + if ( !all ) { + break; + } + } +} + + +void +nsldapi_dump_requests_and_responses( LDAP *ld ) +{ + LDAPRequest *lr; + LDAPMessage *lm, *l; + char msg[256]; + + ber_err_print( "** Outstanding Requests:\n" ); + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + if (( lr = ld->ld_requests ) == NULL ) { + ber_err_print( " Empty\n" ); + } + for ( ; lr != NULL; lr = lr->lr_next ) { + sprintf( msg, " * 0x%p - msgid %d, origid %d, status %s\n", + lr, 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_CONNDEAD ) ? "Dead" : + "Writing" ); + ber_err_print( msg ); + sprintf( msg, " outstanding referrals %d, parent count %d\n", + lr->lr_outrefcnt, lr->lr_parentcnt ); + ber_err_print( msg ); + if ( lr->lr_binddn != NULL ) { + sprintf( msg, " pending bind DN: <%s>\n", lr->lr_binddn ); + ber_err_print( msg ); + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + + ber_err_print( "** Response Queue:\n" ); + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + if (( lm = ld->ld_responses ) == NULLMSG ) { + ber_err_print( " Empty\n" ); + } + for ( ; lm != NULLMSG; lm = lm->lm_next ) { + sprintf( msg, " * 0x%p - msgid %d, type %d\n", + lm, lm->lm_msgid, lm->lm_msgtype ); + ber_err_print( msg ); + if (( l = lm->lm_chain ) != NULL ) { + ber_err_print( " chained responses:\n" ); + for ( ; l != NULLMSG; l = l->lm_chain ) { + sprintf( msg, + " * 0x%p - msgid %d, type %d\n", + l, l->lm_msgid, l->lm_msgtype ); + ber_err_print( msg ); + } + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); +} +#endif /* LDAP_DEBUG */ + + +LDAPRequest * +nsldapi_new_request( LDAPConn *lc, BerElement *ber, int msgid, int expect_resp ) +{ + LDAPRequest *lr; + + lr = (LDAPRequest *)NSLDAPI_CALLOC( 1, sizeof( LDAPRequest )); + + if ( lr != NULL ) { + lr->lr_conn = lc; + lr->lr_ber = ber; + lr->lr_msgid = lr->lr_origid = msgid; + lr->lr_expect_resp = expect_resp; + lr->lr_status = LDAP_REQST_INPROGRESS; + lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */ + + if ( lc != NULL ) { /* mark connection as in use */ + ++lc->lconn_refcnt; + lc->lconn_lastused = time( 0 ); + } + } + + return( lr ); +} + + +void +nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn ) +{ + LDAPRequest *tmplr, *nextlr; + + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_free_request 0x%p (origid %d, msgid %d)\n", + lr, lr->lr_origid, lr->lr_msgid ); + + if ( lr->lr_parent != NULL ) { + /* unlink child from parent */ + lr->lr_parent->lr_child = NULL; + --lr->lr_parent->lr_outrefcnt; + } + + if ( lr->lr_status == LDAP_REQST_WRITING ) { + --lr->lr_conn->lconn_pending_requests; + } + + /* free all of our spawned referrals (child requests) */ + for ( tmplr = lr->lr_child; tmplr != NULL; tmplr = nextlr ) { + nextlr = tmplr->lr_sibling; + nsldapi_free_request( ld, tmplr, free_conn ); + } + + if ( free_conn ) { + nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL, 0, 1 ); + } + + if ( lr->lr_prev == NULL ) { + ld->ld_requests = lr->lr_next; + } else { + lr->lr_prev->lr_next = lr->lr_next; + } + + if ( lr->lr_next != NULL ) { + lr->lr_next->lr_prev = lr->lr_prev; + } + + if ( lr->lr_ber != NULL ) { + ber_free( lr->lr_ber, 1 ); + } + + if ( lr->lr_res_error != NULL ) { + NSLDAPI_FREE( lr->lr_res_error ); + } + + if ( lr->lr_res_matched != NULL ) { + NSLDAPI_FREE( lr->lr_res_matched ); + } + + if ( lr->lr_binddn != NULL ) { + NSLDAPI_FREE( lr->lr_binddn ); + } + + if ( lr->lr_res_ctrls != NULL ) { + ldap_controls_free( lr->lr_res_ctrls ); + } + NSLDAPI_FREE( lr ); +} + + +/* + * Add a request to the end of the list of outstanding requests. + * This function must be called with these two locks in hand, acquired in + * this order: + * LDAP_CONN_LOCK + * LDAP_REQ_LOCK + */ +void +nsldapi_queue_request_nolock( LDAP *ld, LDAPRequest *lr ) +{ + if ( NULL == ld->ld_requests ) { + ld->ld_requests = lr; + } else { + LDAPRequest *tmplr; + + for ( tmplr = ld->ld_requests; tmplr->lr_next != NULL; + tmplr = tmplr->lr_next ) { + ; + } + tmplr->lr_next = lr; + lr->lr_prev = tmplr; + } +} + + +static void +free_servers( LDAPServer *srvlist ) +{ + LDAPServer *nextsrv; + + while ( srvlist != NULL ) { + nextsrv = srvlist->lsrv_next; + if ( srvlist->lsrv_dn != NULL ) { + NSLDAPI_FREE( srvlist->lsrv_dn ); + } + if ( srvlist->lsrv_host != NULL ) { + NSLDAPI_FREE( srvlist->lsrv_host ); + } + NSLDAPI_FREE( srvlist ); + srvlist = nextsrv; + } +} + + +/* + * Initiate chasing of LDAPv2+ (Umich extension) referrals. + * + * Returns an LDAP error code. + * + * Note that *hadrefp will be set to 1 if one or more referrals were found in + * "*errstrp" (even if we can't chase them) and zero if none were found. + * + * XXX merging of errors in this routine needs to be improved. + */ +int +nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, + int *totalcountp, int *chasingcountp ) +{ + char *p, *ref, *unfollowed; + LDAPRequest *origreq; + int rc, tmprc, len, unknown; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_chase_v2_referrals\n", 0, 0, 0 ); + + *totalcountp = *chasingcountp = 0; + + if ( *errstrp == NULL ) { + return( LDAP_SUCCESS ); + } + + len = strlen( *errstrp ); + for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { + if (( *p == 'R' || *p == 'r' ) && strncasecmp( p, + LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) { + *p = '\0'; + p += LDAP_REF_STR_LEN; + break; + } + } + + if ( len < LDAP_REF_STR_LEN ) { + return( LDAP_SUCCESS ); + } + + if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "more than %d referral hops (dropping)\n", + ld->ld_refhoplimit, 0, 0 ); + return( LDAP_REFERRAL_LIMIT_EXCEEDED ); + } + + /* find original request */ + for ( origreq = lr; origreq->lr_parent != NULL; + origreq = origreq->lr_parent ) { + ; + } + + unfollowed = NULL; + rc = LDAP_SUCCESS; + + /* parse out & follow referrals */ + for ( ref = p; rc == LDAP_SUCCESS && ref != NULL; ref = p ) { + if (( p = strchr( ref, '\n' )) != NULL ) { + *p++ = '\0'; + } else { + p = NULL; + } + + ++*totalcountp; + + rc = chase_one_referral( ld, lr, origreq, ref, "v2 referral", + &unknown, 0 /* not a reference */ ); + + if ( rc != LDAP_SUCCESS || unknown ) { + if (( tmprc = nsldapi_append_referral( ld, &unfollowed, + ref )) != LDAP_SUCCESS ) { + rc = tmprc; + } + } else { + ++*chasingcountp; + } + } + + NSLDAPI_FREE( *errstrp ); + *errstrp = unfollowed; + + return( rc ); +} + + +/* returns an LDAP error code */ +int +nsldapi_chase_v3_refs( LDAP *ld, LDAPRequest *lr, char **v3refs, + int is_reference, int *totalcountp, int *chasingcountp ) +{ + int rc = LDAP_SUCCESS; + int i, unknown; + LDAPRequest *origreq; + + *totalcountp = *chasingcountp = 0; + + if ( v3refs == NULL || v3refs[0] == NULL ) { + return( LDAP_SUCCESS ); + } + + *totalcountp = 1; + + if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "more than %d referral hops (dropping)\n", + ld->ld_refhoplimit, 0, 0 ); + return( LDAP_REFERRAL_LIMIT_EXCEEDED ); + } + + /* find original request */ + for ( origreq = lr; origreq->lr_parent != NULL; + origreq = origreq->lr_parent ) { + ; + } + + /* + * in LDAPv3, we just need to follow one referral in the set. + * we dp this by stopping as soon as we succeed in initiating a + * chase on any referral (basically this means we were able to connect + * to the server and bind). + */ + for ( i = 0; v3refs[i] != NULL; ++i ) { + rc = chase_one_referral( ld, lr, origreq, v3refs[i], + is_reference ? "v3 reference" : "v3 referral", &unknown, + is_reference ); + if ( rc == LDAP_SUCCESS && !unknown ) { + *chasingcountp = 1; + break; + } + } + + /* XXXmcs: should we save unfollowed referrals somewhere? */ + + return( rc ); /* last error is as good as any other I guess... */ +} + + +/* + * returns an LDAP error code + * + * XXXmcs: this function used to have #ifdef LDAP_DNS code in it but I + * removed it when I improved the parsing (we don't define LDAP_DNS + * here at Netscape). + */ +static int +chase_one_referral( LDAP *ld, LDAPRequest *lr, LDAPRequest *origreq, + char *refurl, char *desc, int *unknownp, int is_reference ) +{ + int rc, tmprc, secure, msgid; + LDAPServer *srv; + BerElement *ber; + LDAPURLDesc *ludp; + + *unknownp = 0; + ludp = NULLLDAPURLDESC; + + if ( nsldapi_url_parse( refurl, &ludp, 0 ) != 0 ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "ignoring unknown %s <%s>\n", desc, refurl, 0 ); + *unknownp = 1; + rc = LDAP_SUCCESS; + goto cleanup_and_return; + } + + secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ); + +/* XXXmcs: can't tell if secure is supported by connect callback */ + if ( secure && ld->ld_extconnect_fn == NULL ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "ignoring LDAPS %s <%s>\n", desc, refurl, 0 ); + *unknownp = 1; + rc = LDAP_SUCCESS; + goto cleanup_and_return; + } + + LDAPDebug( LDAP_DEBUG_TRACE, "chasing LDAP%s %s: <%s>\n", + secure ? "S" : "", desc, refurl ); + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + if (( tmprc = re_encode_request( ld, origreq->lr_ber, msgid, + ludp, &ber, is_reference )) != LDAP_SUCCESS ) { + rc = tmprc; + goto cleanup_and_return; + } + + if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) + == NULL ) { + ber_free( ber, 1 ); + rc = LDAP_NO_MEMORY; + goto cleanup_and_return; + } + + if ( ludp->lud_host == NULL && ld->ld_defhost == NULL ) { + srv->lsrv_host = NULL; + } else { + if ( ludp->lud_host == NULL ) { + srv->lsrv_host = + nsldapi_strdup( origreq->lr_conn->lconn_server->lsrv_host ); + LDAPDebug( LDAP_DEBUG_TRACE, + "chase_one_referral: using hostname '%s' from original " + "request on new request\n", + srv->lsrv_host, 0, 0); + } else { + srv->lsrv_host = nsldapi_strdup( ludp->lud_host ); + LDAPDebug( LDAP_DEBUG_TRACE, + "chase_one_referral: using hostname '%s' as specified " + "on new request\n", + srv->lsrv_host, 0, 0); + } + + if ( srv->lsrv_host == NULL ) { + NSLDAPI_FREE( (char *)srv ); + ber_free( ber, 1 ); + rc = LDAP_NO_MEMORY; + goto cleanup_and_return; + } + } + + if ( ludp->lud_port == 0 && ludp->lud_host == NULL ) { + srv->lsrv_port = origreq->lr_conn->lconn_server->lsrv_port; + LDAPDebug( LDAP_DEBUG_TRACE, + "chase_one_referral: using port (%d) from original " + "request on new request\n", + srv->lsrv_port, 0, 0); + } else if ( ludp->lud_port != 0 ) { + srv->lsrv_port = ludp->lud_port; + LDAPDebug( LDAP_DEBUG_TRACE, + "chase_one_referral: using port (%d) as specified on " + "new request\n", + srv->lsrv_port, 0, 0); + } else { + srv->lsrv_port = secure ? LDAPS_PORT : LDAP_PORT; + LDAPDebug( LDAP_DEBUG_TRACE, + "chase_one_referral: using default port (%d)\n", + srv->lsrv_port, 0, 0 ); + } + + if ( secure ) { + srv->lsrv_options |= LDAP_SRV_OPT_SECURE; + } + + if ( nsldapi_send_server_request( ld, ber, msgid, + lr, srv, NULL, NULL, 1 ) < 0 ) { + rc = LDAP_GET_LDERRNO( ld, NULL, NULL ); + LDAPDebug( LDAP_DEBUG_ANY, "Unable to chase %s %s (%s)\n", + desc, refurl, ldap_err2string( rc )); + } else { + rc = LDAP_SUCCESS; + } + +cleanup_and_return: + if ( ludp != NULLLDAPURLDESC ) { + ldap_free_urldesc( ludp ); + } + + return( rc ); +} + + +/* returns an LDAP error code */ +int +nsldapi_append_referral( LDAP *ld, char **referralsp, char *s ) +{ + int first; + + if ( *referralsp == NULL ) { + first = 1; + *referralsp = (char *)NSLDAPI_MALLOC( strlen( s ) + + LDAP_REF_STR_LEN + 1 ); + } else { + first = 0; + *referralsp = (char *)NSLDAPI_REALLOC( *referralsp, + strlen( *referralsp ) + strlen( s ) + 2 ); + } + + if ( *referralsp == NULL ) { + return( LDAP_NO_MEMORY ); + } + + if ( first ) { + strcpy( *referralsp, LDAP_REF_STR ); + } else { + strcat( *referralsp, "\n" ); + } + strcat( *referralsp, s ); + + return( LDAP_SUCCESS ); +} + + + +/* returns an LDAP error code */ +static int +re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *ludp, + BerElement **berp, int is_reference ) +{ +/* + * XXX this routine knows way too much about how the lber library works! + */ + ber_int_t origmsgid; + ber_tag_t tag; + ber_int_t ver; + int rc; + BerElement *ber; + struct berelement tmpber; + char *dn, *orig_dn; + /* extra stuff for search request */ + ber_int_t scope = -1; + + LDAPDebug( LDAP_DEBUG_TRACE, + "re_encode_request: new msgid %d, new dn <%s>\n", + msgid, ( ludp->lud_dn == NULL ) ? "NONE" : ludp->lud_dn, 0 ); + + tmpber = *origber; + + /* + * All LDAP requests are sequences that start with a message id. For + * everything except delete requests, this is followed by a sequence + * that is tagged with the operation code. For deletes, there is just + * a DN that is tagged with the operation code. + */ + + /* skip past msgid and get operation tag */ + if ( ber_scanf( &tmpber, "{it", &origmsgid, &tag ) == LBER_ERROR ) { + return( LDAP_DECODING_ERROR ); + } + + /* + * XXXmcs: we don't support filters in search referrals yet, + * so if present we return an error which is probably + * better than just ignoring the extra info. + * XXXrichm: we now support scopes. Supporting filters would require + * a lot more additional work to be able to read the filter from + * the ber original search request, convert to string, etc. It might + * be better and easier to change nsldapi_build_search_req to have + * some special mode by which you could tell it to skip filter and + * attrlist encoding if no filter was given - then we could just + * create a new ber search request with our new filter if present. + */ + if ( ( tag == LDAP_REQ_SEARCH ) && ( ludp->lud_filter != NULL )) { + return( LDAP_LOCAL_ERROR ); + } + + if ( tag == LDAP_REQ_BIND ) { + /* bind requests have a version number before the DN */ + rc = ber_scanf( &tmpber, "{ia", &ver, &orig_dn ); + } else if ( tag == LDAP_REQ_DELETE ) { + /* delete requests DNs are not within a sequence */ + rc = ber_scanf( &tmpber, "a", &orig_dn ); + } else if ( tag == LDAP_REQ_SEARCH ) { + /* need scope */ + rc = ber_scanf( &tmpber, "{ae", &orig_dn, &scope ); + } else { + rc = ber_scanf( &tmpber, "{a", &orig_dn ); + } + + if ( rc == LBER_ERROR ) { + return( LDAP_DECODING_ERROR ); + } + + if ( ludp->lud_dn == NULL ) { + dn = orig_dn; + } else { + dn = ludp->lud_dn; + NSLDAPI_FREE( orig_dn ); + orig_dn = NULL; + } + + if ( ludp->lud_scope != -1 ) { + scope = ludp->lud_scope; /* scope provided by ref - use it */ + } else if (is_reference) { + /* + * RFC 4511 says that the we should use scope BASE in the + * search reference if the client's original request was for scope + * ONELEVEL - since the server did not include the scope in the + * search reference returned, we must provide the correct behavior + * in the client (i.e. the correct behavior is implied) + * see RFC 4511 section 4.5.3 for more information + */ + if (scope == LDAP_SCOPE_ONELEVEL) { + scope = LDAP_SCOPE_BASE; + } + } + + /* allocate and build the new request */ + if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + if ( orig_dn != NULL ) { + NSLDAPI_FREE( orig_dn ); + } + return( rc ); + } + + if ( tag == LDAP_REQ_BIND ) { + rc = ber_printf( ber, "{it{is", msgid, tag, ver , dn ); + } else if ( tag == LDAP_REQ_DELETE ) { + rc = ber_printf( ber, "{its}", msgid, tag, dn ); + } else if ( tag == LDAP_REQ_SEARCH ) { + rc = ber_printf( ber, "{it{se", msgid, tag, dn, scope ); + } else { + rc = ber_printf( ber, "{it{s", msgid, tag, dn ); + } + + if ( orig_dn != NULL ) { + NSLDAPI_FREE( orig_dn ); + } +/* + * can't use "dn" or "orig_dn" from this point on (they've been freed) + */ + + if ( rc == -1 ) { + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + 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 )) { + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { + LDAPDebug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n", + 0, 0, 0 ); + ber_dump( ber, 0 ); + } +#endif /* LDAP_DEBUG */ + + *berp = ber; + return( LDAP_SUCCESS ); +} + + +LDAPRequest * +nsldapi_find_request_by_msgid( LDAP *ld, int msgid ) +{ + LDAPRequest *lr; + + for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { + if ( msgid == lr->lr_msgid ) { + break; + } + } + + return( lr ); +} + + +/* + * nsldapi_connection_lost_nolock() resets "ld" to a non-connected, known + * state. It should be called whenever a fatal error occurs on the + * Sockbuf "sb." sb == NULL means we don't know specifically where + * the problem was so we assume all connections are bad. + */ +void +nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb ) +{ + LDAPRequest *lr; + + /* + * change status of all pending requests that are associated with "sb + * to "connection dead." + * also change the connection status to "dead" and remove it from + * the list of sockets we are interested in. + */ + for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { + if ( sb == NULL || + ( lr->lr_conn != NULL && lr->lr_conn->lconn_sb == sb )) { + lr->lr_status = LDAP_REQST_CONNDEAD; + if ( lr->lr_conn != NULL ) { + lr->lr_conn->lconn_status = LDAP_CONNST_DEAD; + nsldapi_iostatus_interest_clear( ld, + lr->lr_conn->lconn_sb ); + } + } + } +} + + +#ifdef LDAP_DNS +static LDAPServer * +dn2servers( LDAP *ld, char *dn ) /* dn can also be a domain.... */ +{ + char *p, *domain, *host, *server_dn, **dxs; + int i, port; + LDAPServer *srvlist, *prevsrv, *srv; + + if (( domain = strrchr( dn, '@' )) != NULL ) { + ++domain; + } else { + domain = dn; + } + + if (( dxs = nsldapi_getdxbyname( domain )) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( NULL ); + } + + srvlist = NULL; + + for ( i = 0; dxs[ i ] != NULL; ++i ) { + port = LDAP_PORT; + 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 *)NSLDAPI_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 = nsldapi_strdup( host )) == NULL + || ( server_dn != NULL && ( srv->lsrv_dn = + nsldapi_strdup( server_dn )) == NULL )) { + free_servers( srvlist ); + srvlist = NULL; + break; /* exit loop & return */ + } + srv->lsrv_port = port; + } + } + + ldap_value_free( dxs ); + + if ( srvlist == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); + } + + return( srvlist ); +} +#endif /* LDAP_DNS */ diff --git a/ldap/c-sdk/libldap/reslist.c b/ldap/c-sdk/libldap/reslist.c new file mode 100644 index 0000000000..a382941eba --- /dev/null +++ b/ldap/c-sdk/libldap/reslist.c @@ -0,0 +1,86 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * reslist.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +LDAPMessage * +LDAP_CALL +ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e ) +{ + LDAPMessage *tmp, *prev = NULL; + + if ( list == NULL || e == NULL ) { + return( NULL ); + } + + for ( tmp = *list; tmp != NULL && tmp != e; tmp = tmp->lm_chain ) + prev = tmp; + + if ( tmp == NULL ) + return( NULL ); + + if ( prev == NULL ) + *list = tmp->lm_chain; + else + prev->lm_chain = tmp->lm_chain; + tmp->lm_chain = NULL; + + return( tmp ); +} + +void +LDAP_CALL +ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e ) +{ + if ( list != NULL && e != NULL ) { + e->lm_chain = *list; + *list = e; + } +} diff --git a/ldap/c-sdk/libldap/result.c b/ldap/c-sdk/libldap/result.c new file mode 100644 index 0000000000..59c15f8115 --- /dev/null +++ b/ldap/c-sdk/libldap/result.c @@ -0,0 +1,1473 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * result.c - wait for an ldap result + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +/* + * Special return values used by some functions (wait4msg() and read1msg()). + */ +#define NSLDAPI_RESULT_TIMEOUT 0 +#define NSLDAPI_RESULT_ERROR (-1) +#define NSLDAPI_RESULT_NOT_FOUND (-2) + +static int check_response_queue( LDAP *ld, int msgid, int all, + int do_abandon_check, LDAPMessage **result ); +static int ldap_abandoned( LDAP *ld, int msgid ); +static int ldap_mark_abandoned( LDAP *ld, int msgid ); +static int wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, + struct timeval *timeout, LDAPMessage **result ); +static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp, + LDAPMessage **result ); +static void check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, + int ldapversion, int *totalcountp, int *chasingcountp ); +static int build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ); +static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ); +#if defined( CLDAP ) +static int cldap_select1( LDAP *ld, struct timeval *timeout ); +#endif +static void link_pend( LDAP *ld, LDAPPend *lp ); + +/* + * ldap_result - wait for an ldap result response to a message from the + * ldap server. If msgid is -1, any message will be accepted, otherwise + * ldap_result will wait for a response with msgid. If all is 0 the + * first message with id msgid will be accepted, otherwise, ldap_result + * will wait for all responses with id msgid and then return a pointer to + * the entire list of messages. This is only useful for search responses, + * which can be of two message types (zero or more entries, followed by an + * ldap result). The type of the first message received is returned. + * When waiting, any messages that have been abandoned are discarded. + * + * Example: + * ldap_result( s, msgid, all, timeout, result ) + */ +int +LDAP_CALL +ldap_result( + LDAP *ld, + int msgid, + int all, + struct timeval *timeout, + LDAPMessage **result +) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); /* punt */ + } + + LDAP_MUTEX_LOCK( ld, LDAP_RESULT_LOCK ); + + rc = nsldapi_result_nolock(ld, msgid, all, 1, timeout, result); + + LDAP_MUTEX_UNLOCK( ld, LDAP_RESULT_LOCK ); + + return( rc ); +} + + +int +nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted, + struct timeval *timeout, LDAPMessage **result ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_result_nolock (msgid=%d, all=%d)\n", msgid, all, 0 ); + + /* + * First, look through the list of responses we have received on + * this association and see if the response we're interested in + * is there. If it is, return it. If not, call wait4msg() to + * wait until it arrives or timeout occurs. + */ + + if ( result == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( -1 ); + } + + if ( check_response_queue( ld, msgid, all, 1, result ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); + rc = (*result)->lm_msgtype; + } else { + rc = wait4msg( ld, msgid, all, unlock_permitted, timeout, + result ); + } + + /* + * XXXmcs should use cache function pointers to hook in memcache + */ + if ( ld->ld_memcache != NULL && NSLDAPI_SEARCH_RELATED_RESULT( rc ) && + !((*result)->lm_fromcache )) { + ldap_memcache_append( ld, (*result)->lm_msgid, + (all || NSLDAPI_IS_SEARCH_RESULT( rc )), *result ); + } + + return( rc ); +} + + +/* + * Look through the list of queued responses for a message that matches the + * criteria in the msgid and all parameters. msgid == LDAP_RES_ANY matches + * all ids. + * + * If an appropriate message is found, a non-zero value is returned and the + * message is dequeued and assigned to *result. + * + * If not, *result is set to NULL and this function returns 0. + */ +static int +check_response_queue( LDAP *ld, int msgid, int all, int do_abandon_check, + LDAPMessage **result ) +{ + LDAPMessage *lm, *lastlm, *nextlm; + LDAPRequest *lr; + + LDAPDebug( LDAP_DEBUG_TRACE, + "=> check_response_queue (msgid=%d, all=%d)\n", msgid, all, 0 ); + + *result = NULL; + lastlm = NULL; + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { + nextlm = lm->lm_next; + + if ( do_abandon_check && ldap_abandoned( ld, lm->lm_msgid ) ) { + ldap_mark_abandoned( ld, lm->lm_msgid ); + + if ( lastlm == NULL ) { + ld->ld_responses = lm->lm_next; + } else { + lastlm->lm_next = nextlm; + } + + ldap_msgfree( lm ); + + continue; + } + + if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { + LDAPMessage *tmp; + + if ( all == 0 + || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT + && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE + && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) + break; + + for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { + if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) + break; + } + + if ( tmp == NULL ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + LDAPDebug( LDAP_DEBUG_TRACE, + "<= check_response_queue NOT FOUND\n", + 0, 0, 0 ); + return( 0 ); /* no message to return */ + } + + break; + } + lastlm = lm; + } + + /* + * if we did not find a message OR if the one we found is a result for + * a request that is still pending, return failure. + */ + if ( lm == NULL + || (( lr = nsldapi_find_request_by_msgid( ld, lm->lm_msgid )) + != NULL && lr->lr_outrefcnt > 0 )) { + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + LDAPDebug( LDAP_DEBUG_TRACE, + "<= check_response_queue NOT FOUND\n", + 0, 0, 0 ); + return( 0 ); /* no message to return */ + } + + if ( all == 0 ) { + if ( lm->lm_chain == NULL ) { + if ( lastlm == NULL ) { + ld->ld_responses = lm->lm_next; + } else { + lastlm->lm_next = lm->lm_next; + } + } else { + if ( lastlm == NULL ) { + ld->ld_responses = lm->lm_chain; + ld->ld_responses->lm_next = lm->lm_next; + } else { + lastlm->lm_next = lm->lm_chain; + lastlm->lm_next->lm_next = lm->lm_next; + } + } + } else { + if ( lastlm == NULL ) { + ld->ld_responses = lm->lm_next; + } else { + lastlm->lm_next = lm->lm_next; + } + } + + if ( all == 0 ) { + lm->lm_chain = NULL; + } + lm->lm_next = NULL; + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + + *result = lm; + LDAPDebug( LDAP_DEBUG_TRACE, + "<= check_response_queue returning msgid %d type %d\n", + lm->lm_msgid, lm->lm_msgtype, 0 ); + return( 1 ); /* a message was found and returned in *result */ +} + + +/* + * wait4msg(): Poll for incoming LDAP messages, respecting the timeout. + * + * Return values: + * > 0: message received; value is the tag of the message. + * NSLDAPI_RESULT_TIMEOUT timeout exceeded. + * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed. + */ +static int +wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, + struct timeval *timeout, LDAPMessage **result ) +{ + int err, rc = NSLDAPI_RESULT_NOT_FOUND, msgfound; + struct timeval tv, *tvp; + long start_time = 0, tmp_time; + LDAPConn *lc, *nextlc; + /* lr points to the specific request we are waiting for, if any */ + LDAPRequest *lr = NULL; + +#ifdef LDAP_DEBUG + if ( timeout == NULL ) { + LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n", + 0, 0, 0 ); + } else { + LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n", + timeout->tv_sec, (long) timeout->tv_usec, 0 ); + } +#endif /* LDAP_DEBUG */ + + /* check the cache */ + if ( ld->ld_cache_on && ld->ld_cache_result != NULL ) { + /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */ + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + rc = (ld->ld_cache_result)( ld, msgid, all, timeout, result ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */ + if ( rc != NSLDAPI_RESULT_TIMEOUT ) { + return( rc ); + } + if ( ld->ld_cache_strategy == LDAP_CACHE_LOCALDB ) { + LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL ); + return( NSLDAPI_RESULT_TIMEOUT ); + } + } + + /* + * if we are looking for a specific msgid, check to see if it is + * associated with a dead connection and return an error if so. + */ + if ( msgid != LDAP_RES_ANY && msgid != LDAP_RES_UNSOLICITED ) { + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + if (( lr = nsldapi_find_request_by_msgid( ld, msgid )) + == NULL ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, + nsldapi_strdup( "unknown message id" )); + return( NSLDAPI_RESULT_ERROR ); /* could not find request for msgid */ + } + if ( lr->lr_conn != NULL && + lr->lr_conn->lconn_status == LDAP_CONNST_DEAD ) { + nsldapi_free_request( ld, lr, 1 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); + return( NSLDAPI_RESULT_ERROR ); /* connection dead */ + } + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + } + + if ( timeout == NULL ) { + tvp = NULL; + } else { + tv = *timeout; + tvp = &tv; + start_time = (long)time( NULL ); + } + + rc = NSLDAPI_RESULT_NOT_FOUND; + while ( rc == NSLDAPI_RESULT_NOT_FOUND ) { + msgfound = 0; +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_TRACE ) { + nsldapi_dump_connection( ld, ld->ld_conns, 1 ); + nsldapi_dump_requests_and_responses( ld ); + } +#endif /* LDAP_DEBUG */ + + /* + * Check if we have some data in a connection's BER buffer. + * If so, use it. + */ + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { + if ( lc->lconn_sb->sb_ber.ber_ptr < + lc->lconn_sb->sb_ber.ber_end ) { + /* read1msg() might free the connection. */ + rc = read1msg( ld, msgid, all, lc->lconn_sb, + &lc, result ); + /* Indicate to next segment that we've processed a message + (or several, via chased refs) this time around. */ + msgfound = 1; + break; + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + + if ( !msgfound ) { + /* + * There was no buffered data. Poll to check connection + * status (read/write readiness). + */ + err = nsldapi_iostatus_poll( ld, tvp ); + +#if defined( LDAP_DEBUG ) && !defined( macintosh ) && !defined( DOS ) + if ( err == -1 ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_iostatus_poll returned -1: errno %d\n", + LDAP_GET_ERRNO( ld ), 0, 0 ); + } +#endif + +#if !defined( macintosh ) && !defined( DOS ) + /* + * If the restart option is enabled and the error + * was EINTR, try again. + */ + if ( err == -1 + && 0 != ( ld->ld_options & LDAP_BITOPT_RESTART ) + && LDAP_GET_ERRNO( ld ) == EINTR ) { + continue; + } +#endif + + /* + * Handle timeouts (no activity) and fatal errors. + */ + if ( err == -1 || err == 0 ) { + LDAP_SET_LDERRNO( ld, (err == -1 ? + LDAP_SERVER_DOWN : LDAP_TIMEOUT), NULL, + NULL ); + if ( err == -1 ) { + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + nsldapi_connection_lost_nolock( ld, + NULL ); + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + rc = NSLDAPI_RESULT_ERROR; + } else { + rc = NSLDAPI_RESULT_TIMEOUT; + } + return( rc ); + } + + /* + * Check each connection for interesting activity. + */ + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + for ( lc = ld->ld_conns; + rc == NSLDAPI_RESULT_NOT_FOUND && lc != NULL; + lc = nextlc ) { + nextlc = lc->lconn_next; + + /* + * For connections that are in the CONNECTING + * state, check for write ready (which + * indicates that the connection completed) and + * transition to the CONNECTED state. + */ + if ( lc->lconn_status == LDAP_CONNST_CONNECTING + && nsldapi_iostatus_is_write_ready( ld, + lc->lconn_sb ) ) { + lc->lconn_status = LDAP_CONNST_CONNECTED; + LDAPDebug( LDAP_DEBUG_TRACE, + "wait4msg: connection 0x%p -" + " LDAP_CONNST_CONNECTING ->" + " LDAP_CONNST_CONNECTED\n", + lc, 0, 0 ); + } + + if ( lc->lconn_status + != LDAP_CONNST_CONNECTED ) { + continue; + } + + /* + * For connections that are CONNECTED, check + * for read ready (which indicates that data + * from server is available), and, for + * connections with associated requests that + * have not yet been sent, write ready (okay + * to send some data to the server). + */ + if ( nsldapi_iostatus_is_read_ready( ld, + lc->lconn_sb )) { + /* read1msg() might free the connection. */ + rc = read1msg( ld, msgid, all, + lc->lconn_sb, &lc, result ); + } + + /* + * Send pending requests if possible. If there is no lc then + * it was a child connection closed by read1msg(). + */ + if ( lc && lc->lconn_pending_requests > 0 + && nsldapi_iostatus_is_write_ready( ld, + lc->lconn_sb )) { + err = nsldapi_send_pending_requests_nolock( + ld, lc ); + if ( err == -1 && + rc == NSLDAPI_RESULT_NOT_FOUND ) { + rc = NSLDAPI_RESULT_ERROR; + } + } + + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + } + + /* + * It is possible that recursion occurred while chasing + * referrals and as a result the message we are looking + * for may have been placed on the response queue. Look + * for it there before continuing so we don't end up + * waiting on the network for a message that we already + * received! + */ + if ( rc == NSLDAPI_RESULT_NOT_FOUND && + check_response_queue( ld, msgid, all, 0, result ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); + rc = (*result)->lm_msgtype; + } + + /* + * honor the timeout if specified + */ + if ( rc == NSLDAPI_RESULT_NOT_FOUND && tvp != NULL ) { + tmp_time = (long)time( NULL ); + if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) { + rc = NSLDAPI_RESULT_TIMEOUT; + LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, + NULL ); + break; + } + + LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg: %ld secs to go\n", + tv.tv_sec, 0, 0 ); + start_time = tmp_time; + } + } + + return( rc ); +} + + +#define NSLDAPI_REQUEST_COMPLETE( lr ) \ + ( (lr)->lr_outrefcnt <= 0 && \ + (lr)->lr_res_msgtype != LDAP_RES_SEARCH_ENTRY && \ + (lr)->lr_res_msgtype != LDAP_RES_SEARCH_REFERENCE ) + +/* + * read1msg() should be called with LDAP_CONN_LOCK and LDAP_REQ_LOCK locked. + * + * Return values: + * > 0: message received; value is the tag of the message. + * NSLDAPI_RESULT_TIMEOUT timeout exceeded. + * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed. + * NSLDAPI_RESULT_NOT_FOUND message not yet complete; keep waiting. + * + * The LDAPConn passed in my be freed by read1msg() if the reference count + * shows that it's no longer needed. + */ +static int +read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp, + LDAPMessage **result ) +{ + BerElement *ber; + LDAPMessage *new, *l, *prev, *chainprev, *tmp; + ber_int_t id; + ber_tag_t tag; + ber_len_t len; + int terrno, lderr, foundit = 0; + LDAPRequest *lr; + int rc, has_parent, message_can_be_returned; + int manufactured_result = 0; + LDAPConn *lc = *lcp; + + LDAPDebug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 ); + + message_can_be_returned = 1; /* the usual case... */ + + /* + * if we are not already in the midst of reading a message, allocate + * a ber that is associated with this connection + */ + if ( lc->lconn_ber == NULLBER && nsldapi_alloc_ber_with_options( ld, + &lc->lconn_ber ) != LDAP_SUCCESS ) { + return( NSLDAPI_RESULT_ERROR ); + } + + /* + * ber_get_next() doesn't set errno on EOF, so we pre-set it to + * zero to avoid getting tricked by leftover "EAGAIN" errors + */ + LDAP_SET_ERRNO( ld, 0 ); + + /* get the next message */ + if ( (tag = ber_get_next( sb, &len, lc->lconn_ber )) + != LDAP_TAG_MESSAGE ) { + terrno = LDAP_GET_ERRNO( ld ); + if ( terrno == EWOULDBLOCK || terrno == EAGAIN ) { + return( NSLDAPI_RESULT_NOT_FOUND ); /* try again */ + } + LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : + LDAP_LOCAL_ERROR), NULL, NULL ); + if ( tag == LBER_DEFAULT ) { + nsldapi_connection_lost_nolock( ld, sb ); + } + return( NSLDAPI_RESULT_ERROR ); + } + + /* + * Since we have received a complete message now, we pull this ber + * out of the connection structure and never read into it again. + */ + ber = lc->lconn_ber; + lc->lconn_ber = NULLBER; + + /* message id */ + if ( ber_get_int( ber, &id ) == LBER_ERROR ) { + ber_free( ber, 1 ); + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( NSLDAPI_RESULT_ERROR ); + } + + /* if it's been abandoned, toss it */ + if ( ldap_abandoned( ld, (int)id ) ) { + ber_free( ber, 1 ); + return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ + } + + if ( id == LDAP_RES_UNSOLICITED ) { + lr = NULL; + } else if (( lr = nsldapi_find_request_by_msgid( ld, id )) == NULL ) { + LDAPDebug( LDAP_DEBUG_ANY, + "no request for response with msgid %d (tossing)\n", + id, 0, 0 ); + ber_free( ber, 1 ); + return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ + } + + /* the message type */ + if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { + ber_free( ber, 1 ); + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( NSLDAPI_RESULT_ERROR ); + } + LDAPDebug( LDAP_DEBUG_TRACE, "got %s msgid %d, original id %d\n", + ( tag == LDAP_RES_SEARCH_ENTRY ) ? "ENTRY" : + ( tag == LDAP_RES_SEARCH_REFERENCE ) ? "REFERENCE" : "RESULT", id, + ( lr == NULL ) ? id : lr->lr_origid ); + + if ( lr != NULL ) { + id = lr->lr_origid; + lr->lr_res_msgtype = tag; + } + rc = NSLDAPI_RESULT_NOT_FOUND; /* default is to keep looking (no response found) */ + + if ( id != LDAP_RES_UNSOLICITED && ( tag == LDAP_RES_SEARCH_REFERENCE || + tag != LDAP_RES_SEARCH_ENTRY )) { + int refchasing, reftotal, simple_request = 0; + LDAPControl **ctrls = NULL; + + check_for_refs( ld, lr, ber, lc->lconn_version, &reftotal, + &refchasing ); + + if ( refchasing > 0 || lr->lr_outrefcnt > 0 ) { + /* + * we're chasing one or more new refs... + */ + ber_free( ber, 1 ); + ber = NULLBER; + lr->lr_status = LDAP_REQST_CHASINGREFS; + message_can_be_returned = 0; + + } else if ( tag != LDAP_RES_SEARCH_REFERENCE ) { + /* + * this request is complete... + */ + has_parent = ( lr->lr_parent != NULL ); + + if ( lr->lr_outrefcnt <= 0 && !has_parent ) { + /* request without any refs */ + simple_request = ( reftotal == 0 ); + } + + /* + * If this is not a child request and it is a bind + * request, reset the connection's bind DN and + * status based on the result of the operation. + */ + if ( !has_parent && + LDAP_RES_BIND == lr->lr_res_msgtype && + lr->lr_conn != NULL ) { + if ( lr->lr_conn->lconn_binddn != NULL ) { + NSLDAPI_FREE( + lr->lr_conn->lconn_binddn ); + } + if ( LDAP_SUCCESS == nsldapi_parse_result( ld, + lr->lr_res_msgtype, ber, &lderr, NULL, + NULL, NULL, NULL ) + && LDAP_SUCCESS == lderr ) { + lr->lr_conn->lconn_bound = 1; + lr->lr_conn->lconn_binddn = + lr->lr_binddn; + lr->lr_binddn = NULL; + } else { + lr->lr_conn->lconn_bound = 0; + lr->lr_conn->lconn_binddn = NULL; + } + } + + /* + * if this response is to a child request, we toss + * the message contents and just merge error info. + * into the parent. + */ + if ( has_parent ) { + /* Extract any response controls from ber before ditching it */ + if( nsldapi_find_controls( ber, &ctrls ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + return( NSLDAPI_RESULT_ERROR ); + } + + ber_free( ber, 1 ); + ber = NULLBER; + } + while ( lr->lr_parent != NULL ) { + merge_error_info( ld, lr->lr_parent, lr ); + + lr = lr->lr_parent; + --lr->lr_outrefcnt; + if ( !NSLDAPI_REQUEST_COMPLETE(lr)) { + break; + } + } + /* Stash response controls in original request so they can be baked + into the manufactured result message later */ + if( ctrls != NULL ) { + if( lr->lr_res_ctrls != NULL ) { + /* There are controls saved in original request already, + replace them with the new ones because we only save + the final controls received. + May want to arrange for merging intermediate response + controls into the array in the future */ + ldap_controls_free( lr->lr_res_ctrls ); + } + lr->lr_res_ctrls = ctrls; + } + + /* + * we recognize a request as fully complete when: + * 1) it is not a child request (NULL parent) + * 2) it has no outstanding referrals + * 3) we have received a result for the request (i.e., + * something other than an entry or a reference). + */ + if ( lr->lr_parent == NULL + && NSLDAPI_REQUEST_COMPLETE(lr)) { + id = lr->lr_msgid; + tag = lr->lr_res_msgtype; + LDAPDebug( LDAP_DEBUG_TRACE, + "request %d done\n", id, 0, 0 ); +LDAPDebug( LDAP_DEBUG_TRACE, +"res_errno: %d, res_error: <%s>, res_matched: <%s>\n", +lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", +lr->lr_res_matched ? lr->lr_res_matched : "" ); + if ( !simple_request ) { + if ( ber != NULLBER ) { + ber_free( ber, 1 ); + ber = NULLBER; + } + if ( build_result_ber( ld, &ber, lr ) + != LDAP_SUCCESS ) { + rc = NSLDAPI_RESULT_ERROR; + } else { + manufactured_result = 1; + } + } + + nsldapi_free_request( ld, lr, 1 ); + /* Since we asked nsldapi_free_request() to free the + connection, lets make sure our callers know it's gone. */ + *lcp = NULL; + } else { + message_can_be_returned = 0; + } + } + } + + if ( ber == NULLBER ) { + return( rc ); + } + + /* make a new ldap message */ + if ( (new = (LDAPMessage*)NSLDAPI_CALLOC( 1, sizeof(struct ldapmsg) )) + == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( NSLDAPI_RESULT_ERROR ); + } + new->lm_msgid = (int)id; + new->lm_msgtype = tag; + new->lm_ber = ber; + + /* + * if this is a search entry or if this request is complete (i.e., + * there are no outstanding referrals) then add to cache and check + * to see if we should return this to the caller right away or not. + */ + if ( message_can_be_returned ) { + if ( ld->ld_cache_on ) { + nsldapi_add_result_to_cache( ld, new ); + } + + if ( msgid == LDAP_RES_ANY || id == msgid ) { + if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { + /* + * return the first response we have for this + * search request later (possibly an entire + * chain of messages). + */ + foundit = 1; + } else if ( all == 0 + || (new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE + && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) { + *result = new; + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, + NULL ); + return( tag ); + } + } + } + + /* + * if not, we must add it to the list of responses. if + * the msgid is already there, it must be part of an existing + * search response. + */ + + prev = NULL; + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) { + if ( l->lm_msgid == new->lm_msgid ) + break; + prev = l; + } + + /* not part of an existing search response */ + if ( l == NULL ) { + if ( foundit ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + *result = new; + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); + return( tag ); + } + + new->lm_next = ld->ld_responses; + ld->ld_responses = new; + LDAPDebug( LDAP_DEBUG_TRACE, + "adding new response id %d type %d (looking for id %d)\n", + new->lm_msgid, new->lm_msgtype, msgid ); + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + if( message_can_be_returned ) + POST( ld, new->lm_msgid, new ); + return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ + } + + LDAPDebug( LDAP_DEBUG_TRACE, + "adding response 0x%p - id %d type %d", + new, new->lm_msgid, new->lm_msgtype ); + LDAPDebug( LDAP_DEBUG_TRACE, " (looking for id %d)\n", msgid, 0, 0 ); + + /* + * part of a search response - add to end of list of entries + * + * the first step is to find the end of the list of entries and + * references. after the following loop is executed, tmp points to + * the last entry or reference in the chain. If there are none, + * tmp points to the search result. + */ + chainprev = NULL; + 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 ) { + chainprev = tmp; + } + + /* + * If this is a manufactured result message and a result is already + * queued we throw away the one that is queued and replace it with + * our new result. This is necessary so we don't end up returning + * more than one result. + */ + if ( manufactured_result && + tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { + /* + * the result is the only thing in the chain... replace it. + */ + new->lm_chain = tmp->lm_chain; + new->lm_next = tmp->lm_next; + if ( chainprev == NULL ) { + if ( prev == NULL ) { + ld->ld_responses = new; + } else { + prev->lm_next = new; + } + } else { + chainprev->lm_chain = new; + } + if ( l == tmp ) { + l = new; + } + ldap_msgfree( tmp ); + + } else if ( manufactured_result && tmp->lm_chain != NULL + && tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { + /* + * entries or references are also present, so the result + * is the next entry after tmp. replace it. + */ + new->lm_chain = tmp->lm_chain->lm_chain; + new->lm_next = tmp->lm_chain->lm_next; + ldap_msgfree( tmp->lm_chain ); + tmp->lm_chain = new; + + } else if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { + /* + * the result is the only thing in the chain... add before it. + */ + new->lm_chain = tmp; + if ( chainprev == NULL ) { + if ( prev == NULL ) { + ld->ld_responses = new; + } else { + prev->lm_next = new; + } + } else { + chainprev->lm_chain = new; + } + if ( l == tmp ) { + l = new; + } + + } else { + /* + * entries and/or references are present... add to the end + * of the entry/reference part of the chain. + */ + new->lm_chain = tmp->lm_chain; + tmp->lm_chain = new; + } + + /* + * return the first response or the whole chain if that's what + * we were looking for.... + */ + if ( foundit ) { + if ( all == 0 && l->lm_chain != NULL ) { + /* + * only return the first response in the chain + */ + if ( prev == NULL ) { + ld->ld_responses = l->lm_chain; + } else { + prev->lm_next = l->lm_chain; + } + l->lm_chain = NULL; + tag = l->lm_msgtype; + } else { + /* + * return all of the responses (may be a chain) + */ + if ( prev == NULL ) { + ld->ld_responses = l->lm_next; + } else { + prev->lm_next = l->lm_next; + } + } + *result = l; + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); + return( tag ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ +} + + +/* + * check for LDAPv2+ (UMich extension) or LDAPv3 referrals or references + * errors are merged in "lr". + */ +static void +check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, + int ldapversion, int *totalcountp, int *chasingcountp ) +{ + int err, origerr; + char *errstr, *matcheddn, **v3refs; + + LDAPDebug( LDAP_DEBUG_TRACE, "check_for_refs\n", 0, 0, 0 ); + + *chasingcountp = *totalcountp = 0; + + if ( ldapversion < LDAP_VERSION2 || ( lr->lr_parent == NULL + && ( ld->ld_options & LDAP_BITOPT_REFERRALS ) == 0 )) { + /* referrals are not supported or are disabled */ + return; + } + + if ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + err = nsldapi_parse_reference( ld, ber, &v3refs, NULL ); + origerr = LDAP_REFERRAL; /* a small lie... */ + matcheddn = errstr = NULL; + } else { + err = nsldapi_parse_result( ld, lr->lr_res_msgtype, ber, + &origerr, &matcheddn, &errstr, &v3refs, NULL ); + } + + if ( err != LDAP_SUCCESS ) { + /* parse failed */ + return; + } + + if ( origerr == LDAP_REFERRAL ) { /* ldapv3 */ + if ( v3refs != NULL ) { + err = nsldapi_chase_v3_refs( ld, lr, v3refs, + ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ), + totalcountp, chasingcountp ); + ldap_value_free( v3refs ); + } + } else if ( ldapversion == LDAP_VERSION2 + && origerr != LDAP_SUCCESS ) { + /* referrals may be present in the error string */ + err = nsldapi_chase_v2_referrals( ld, lr, &errstr, + totalcountp, chasingcountp ); + } + + /* set LDAP errno, message, and matched string appropriately */ + if ( lr->lr_res_error != NULL ) { + NSLDAPI_FREE( lr->lr_res_error ); + } + lr->lr_res_error = errstr; + + if ( lr->lr_res_matched != NULL ) { + NSLDAPI_FREE( lr->lr_res_matched ); + } + lr->lr_res_matched = matcheddn; + + if ( err == LDAP_SUCCESS && ( *chasingcountp == *totalcountp )) { + if ( *totalcountp > 0 && ( origerr == LDAP_PARTIAL_RESULTS + || origerr == LDAP_REFERRAL )) { + /* substitute success for referral error codes */ + lr->lr_res_errno = LDAP_SUCCESS; + } else { + /* preserve existing non-referral error code */ + lr->lr_res_errno = origerr; + } + } else if ( err != LDAP_SUCCESS ) { + /* error occurred while trying to chase referrals */ + lr->lr_res_errno = err; + } else { + /* some referrals were not recognized */ + lr->lr_res_errno = ( ldapversion == LDAP_VERSION2 ) + ? LDAP_PARTIAL_RESULTS : LDAP_REFERRAL; + } + + LDAPDebug( LDAP_DEBUG_TRACE, + "check_for_refs: new result: msgid %d, res_errno %d, ", + lr->lr_msgid, lr->lr_res_errno, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, " res_error <%s>, res_matched <%s>\n", + lr->lr_res_error ? lr->lr_res_error : "", + lr->lr_res_matched ? lr->lr_res_matched : "", 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, + "check_for_refs: %d new refs(s); chasing %d of them\n", + *totalcountp, *chasingcountp, 0 ); +} + + +/* returns an LDAP error code and also sets it in LDAP * */ +static int +build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ) +{ + ber_len_t len; + ber_int_t along; + BerElement *ber; + int err; + + if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( err ); + } + *berp = ber; + if ( ber_printf( ber, lr->lr_res_ctrls ? "{it{ess}" : "{it{ess}}", + lr->lr_msgid, (long)lr->lr_res_msgtype, lr->lr_res_errno, + lr->lr_res_matched ? lr->lr_res_matched : "", + lr->lr_res_error ? lr->lr_res_error : "" ) == -1 ) { + return( LDAP_ENCODING_ERROR ); + } + + if ( NULL != lr->lr_res_ctrls && nsldapi_put_controls( ld, + lr->lr_res_ctrls, 1 /* close seq */, ber ) != LDAP_SUCCESS ) { + return( LDAP_ENCODING_ERROR ); + } + + ber_reset( ber, 1 ); + if ( ber_skip_tag( ber, &len ) == LBER_ERROR || + ber_get_int( ber, &along ) == LBER_ERROR || + ber_peek_tag( ber, &len ) == LBER_ERROR ) { + return( LDAP_DECODING_ERROR ); + } + + return( LDAP_SUCCESS ); +} + + +static void +merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) +{ +/* + * Merge error information in "lr" with "parentr" error code and string. + */ + if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { + parentr->lr_res_errno = lr->lr_res_errno; + if ( lr->lr_res_error != NULL ) { + (void)nsldapi_append_referral( ld, &parentr->lr_res_error, + lr->lr_res_error ); + } + } else if ( lr->lr_res_errno != LDAP_SUCCESS && + parentr->lr_res_errno == LDAP_SUCCESS ) { + parentr->lr_res_errno = lr->lr_res_errno; + if ( parentr->lr_res_error != NULL ) { + NSLDAPI_FREE( parentr->lr_res_error ); + } + parentr->lr_res_error = lr->lr_res_error; + lr->lr_res_error = NULL; + if ( NAME_ERROR( lr->lr_res_errno )) { + if ( parentr->lr_res_matched != NULL ) { + NSLDAPI_FREE( parentr->lr_res_matched ); + } + parentr->lr_res_matched = lr->lr_res_matched; + lr->lr_res_matched = NULL; + } + } + + LDAPDebug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ", + parentr->lr_msgid, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "result lderrno %d, error <%s>, matched <%s>\n", + parentr->lr_res_errno, parentr->lr_res_error ? + parentr->lr_res_error : "", parentr->lr_res_matched ? + parentr->lr_res_matched : "" ); +} + +#if defined( CLDAP ) +#if !defined( macintosh ) && !defined( DOS ) && !defined( _WINDOWS ) && !defined(XP_OS2) +/* XXXmcs: was revised to support extended I/O callbacks but never compiled! */ +static int +cldap_select1( LDAP *ld, struct timeval *timeout ) +{ + int rc; + static int tblsize = 0; + NSLDAPIIOStatus *iosp = ld->ld_iostatus; + + if ( tblsize == 0 ) { +#ifdef USE_SYSCONF + tblsize = sysconf( _SC_OPEN_MAX ); +#else /* USE_SYSCONF */ + tblsize = getdtablesize(); +#endif /* USE_SYSCONF */ + } + + if ( tblsize >= FD_SETSIZE ) { + /* + * clamp value so we don't overrun the fd_set structure + */ + tblsize = FD_SETSIZE - 1; + } + + if ( NSLDAPI_IOSTATUS_TYPE_OSNATIVE == iosp->ios_type ) { + fd_set readfds; + + FD_ZERO( &readfds ); + FD_SET( ld->ld_sbp->sb_sd, &readfds ); + + /* XXXmcs: UNIX platforms should use poll() */ + rc = select( tblsize, &readfds, 0, 0, timeout ) ); + + } else if ( NSLDAPI_IOSTATUS_TYPE_CALLBACK == iosp->ios_type ) { + LDAP_X_PollFD pollfds[ 1 ]; + + pollfds[0].lpoll_fd = ld->ld_sbp->sb_sd; + pollfds[0].lpoll_arg = ld->ld_sbp->sb_arg; + pollfds[0].lpoll_events = LDAP_X_POLLIN; + pollfds[0].lpoll_revents = 0; + rc = ld->ld_extpoll_fn( pollfds, 1, nsldapi_tv2ms( timeout ), + ld->ld_ext_session_arg ); + } else { + LDAPDebug( LDAP_DEBUG_ANY, + "nsldapi_iostatus_poll: unknown I/O type %d\n", + rc = 0; /* simulate a timeout (what else to do?) */ + } + + return( rc ); +} +#endif /* !macintosh */ + + +#ifdef macintosh +static int +cldap_select1( LDAP *ld, struct timeval *timeout ) +{ + /* XXXmcs: needs to be revised to support I/O callbacks */ + return( tcpselect( ld->ld_sbp->sb_sd, timeout )); +} +#endif /* macintosh */ + + +#if (defined( DOS ) && defined( WINSOCK )) || defined( _WINDOWS ) || defined(XP_OS2) +/* XXXmcs: needs to be revised to support extended I/O callbacks */ +static int +cldap_select1( LDAP *ld, struct timeval *timeout ) +{ + fd_set readfds; + int rc; + + FD_ZERO( &readfds ); + FD_SET( ld->ld_sbp->sb_sd, &readfds ); + + if ( NSLDAPI_IO_TYPE_STANDARD == ld->ldiou_type && + NULL != ld->ld_select_fn ) { + rc = ld->ld_select_fn( 1, &readfds, 0, 0, timeout ); + } else if ( NSLDAPI_IO_TYPE_EXTENDED == ld->ldiou_type && + NULL != ld->ld_extselect_fn ) { + rc = ld->ld_extselect_fn( ld->ld_ext_session_arg, 1, &readfds, 0, + 0, timeout ) ); + } else { + /* XXXmcs: UNIX platforms should use poll() */ + rc = select( 1, &readfds, 0, 0, timeout ) ); + } + + return( rc == SOCKET_ERROR ? -1 : rc ); +} +#endif /* WINSOCK || _WINDOWS */ +#endif /* CLDAP */ + +int +LDAP_CALL +ldap_msgfree( LDAPMessage *lm ) +{ + LDAPMessage *next; + int type = 0; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); + + for ( ; lm != NULL; lm = next ) { + next = lm->lm_chain; + type = lm->lm_msgtype; + ber_free( lm->lm_ber, 1 ); + NSLDAPI_FREE( (char *) lm ); + } + + return( type ); +} + +/* + * ldap_msgdelete - delete a message. It returns: + * 0 if the entire message was deleted + * -1 if the message was not found, or only part of it was found + */ +int +ldap_msgdelete( LDAP *ld, int msgid ) +{ + LDAPMessage *lm, *prev; + int msgtype; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); /* punt */ + } + + prev = NULL; + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { + if ( lm->lm_msgid == msgid ) + break; + prev = lm; + } + + if ( lm == NULL ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + return( -1 ); + } + + if ( prev == NULL ) + ld->ld_responses = lm->lm_next; + else + prev->lm_next = lm->lm_next; + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + + msgtype = ldap_msgfree( lm ); + if ( msgtype == LDAP_RES_SEARCH_ENTRY + || msgtype == LDAP_RES_SEARCH_REFERENCE ) { + return( -1 ); + } + + return( 0 ); +} + + +/* + * return 1 if message msgid is waiting to be abandoned, 0 otherwise + */ +static int +ldap_abandoned( LDAP *ld, int msgid ) +{ + int i; + + LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); + if ( ld->ld_abandoned == NULL ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( 0 ); + } + + for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) + if ( ld->ld_abandoned[i] == msgid ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( 1 ); + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( 0 ); +} + + +static int +ldap_mark_abandoned( LDAP *ld, int msgid ) +{ + int i; + + LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); + if ( ld->ld_abandoned == NULL ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( -1 ); + } + + for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) + if ( ld->ld_abandoned[i] == msgid ) + break; + + if ( ld->ld_abandoned[i] == -1 ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( -1 ); + } + + for ( ; ld->ld_abandoned[i] != -1; i++ ) { + ld->ld_abandoned[i] = ld->ld_abandoned[i + 1]; + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); + return( 0 ); +} + + +#ifdef CLDAP +int +cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement **ber ) +{ + int rc; + ber_tag_t tag; + ber_len_t len; + + if ( ld->ld_sbp->sb_ber.ber_ptr >= ld->ld_sbp->sb_ber.ber_end ) { + rc = cldap_select1( ld, timeout ); + if ( rc == -1 || rc == 0 ) { + LDAP_SET_LDERRNO( ld, (rc == -1 ? LDAP_SERVER_DOWN : + LDAP_TIMEOUT), NULL, NULL ); + return( rc ); + } + } + + /* get the next message */ + if ( (tag = ber_get_next( ld->ld_sbp, &len, ber )) + != LDAP_TAG_MESSAGE ) { + LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : + LDAP_LOCAL_ERROR), NULL, NULL ); + return( -1 ); + } + + return( tag ); +} +#endif /* CLDAP */ + +int +nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result ) +{ + LDAPPend *lp; + + LDAPDebug( LDAP_DEBUG_TRACE, + "nsldapi_post_result(ld=0x%p, msgid=%d, result=0x%p)\n", + ld, msgid, result ); + LDAP_MUTEX_LOCK( ld, LDAP_PEND_LOCK ); + if( msgid == LDAP_RES_ANY ) { + /* + * Look for any pending request for which someone is waiting. + */ + for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) + { + if ( lp->lp_sema != NULL ) { + break; + } + } + /* + * If we did't find a pending request, lp is NULL at this + * point, and we will leave this function without doing + * anything more -- which is exactly what we want to do. + */ + } + else + { + /* + * Look for a pending request specific to this message id + */ + for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) + { + if( lp->lp_msgid == msgid ) + break; + } + + if( lp == NULL ) + { + /* + * No pending requests for this response... append to + * our pending result list. + */ + LDAPPend *newlp; + newlp = (LDAPPend *)NSLDAPI_CALLOC( 1, + sizeof( LDAPPend )); + if( newlp == NULL ) + { + LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, + NULL ); + return (-1); + } + newlp->lp_msgid = msgid; + newlp->lp_result = result; + link_pend( ld, newlp ); + } + } + + + if( lp != NULL ) + { + /* + * Wake up a thread that is waiting for this result. + */ + lp->lp_msgid = msgid; + lp->lp_result = result; + LDAP_SEMA_POST( ld, lp ); + } + + LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); + return (0); +} + +static void +link_pend( LDAP *ld, LDAPPend *lp ) +{ + if (( lp->lp_next = ld->ld_pend ) != NULL ) + { + lp->lp_next->lp_prev = lp; + } + ld->ld_pend = lp; + lp->lp_prev = NULL; +} diff --git a/ldap/c-sdk/libldap/saslbind.c b/ldap/c-sdk/libldap/saslbind.c new file mode 100644 index 0000000000..5cbe73bbff --- /dev/null +++ b/ldap/c-sdk/libldap/saslbind.c @@ -0,0 +1,877 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +#ifdef LDAP_SASLIO_HOOKS +/* + * Global SASL Init data + */ + +static int +nsldapi_sasl_fail() +{ + return( SASL_FAIL ); +} + +sasl_callback_t client_callbacks[] = { + { SASL_CB_GETOPT, nsldapi_sasl_fail, NULL }, + { SASL_CB_GETREALM, NULL, NULL }, + { SASL_CB_USER, NULL, NULL }, + { SASL_CB_CANON_USER, NULL, NULL }, + { SASL_CB_AUTHNAME, NULL, NULL }, + { SASL_CB_PASS, NULL, NULL }, + { SASL_CB_ECHOPROMPT, NULL, NULL }, + { SASL_CB_NOECHOPROMPT, NULL, NULL }, + { SASL_CB_LIST_END, NULL, NULL } +}; + +int +nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg ) +{ + int rc = LDAP_LOCAL_ERROR; + + switch (err) { + case SASL_OK: + rc = LDAP_SUCCESS; + break; + case SASL_NOMECH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_BADSERV: + rc = LDAP_CONNECT_ERROR; + break; + case SASL_DISABLED: + case SASL_ENCRYPT: + case SASL_EXPIRED: + case SASL_NOUSERPASS: + case SASL_NOVERIFY: + case SASL_PWLOCK: + case SASL_TOOWEAK: + case SASL_UNAVAIL: + case SASL_WEAKPASS: + rc = LDAP_INAPPROPRIATE_AUTH; + break; + case SASL_BADAUTH: + case SASL_NOAUTHZ: + rc = LDAP_INVALID_CREDENTIALS; + break; + case SASL_NOMEM: + rc = LDAP_NO_MEMORY; + break; + case SASL_NOUSER: + rc = LDAP_NO_SUCH_OBJECT; + break; + case SASL_CONTINUE: + case SASL_FAIL: + case SASL_INTERACT: + default: + rc = LDAP_LOCAL_ERROR; + break; + } + + LDAP_SET_LDERRNO( ld, rc, NULL, msg ); + return( rc ); +} + +#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER +/* + * Get available SASL Mechanisms supported by the server + */ + +static int +nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech ) +{ + char *attr[] = { "supportedSASLMechanisms", NULL }; + char **values, **v, *mech, *m; + LDAPMessage *res, *e; + struct timeval timeout; + int slen, rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + timeout.tv_sec = SEARCH_TIMEOUT_SECS; + timeout.tv_usec = 0; + + rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE, + "objectclass=*", attr, 0, &timeout, &res ); + + if ( rc != LDAP_SUCCESS ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + e = ldap_first_entry( ld, res ); + if ( e == NULL ) { + ldap_msgfree( res ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL ); + } + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); + if ( values == NULL ) { + ldap_msgfree( res ); + LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL ); + return( LDAP_NO_SUCH_ATTRIBUTE ); + } + + slen = 0; + for(v = values; *v != NULL; v++ ) { + slen += strlen(*v) + 1; + } + if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) { + ldap_value_free( values ); + ldap_msgfree( res ); + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + m = mech; + for(v = values; *v; v++) { + if (v != values) { + *m++ = ' '; + } + slen = strlen(*v); + strncpy(m, *v, slen); + m += slen; + } + *m = '\0'; + + ldap_value_free( values ); + ldap_msgfree( res ); + + *pmech = mech; + + return( LDAP_SUCCESS ); +} +#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ + +int +nsldapi_sasl_secprops( + const char *in, + sasl_security_properties_t *secprops ) +{ + int i; + char **props = NULL; + char *inp; + unsigned sflags = 0; + sasl_ssf_t max_ssf = 0; + sasl_ssf_t min_ssf = 0; + unsigned maxbufsize = 0; + int got_sflags = 0; + int got_max_ssf = 0; + int got_min_ssf = 0; + int got_maxbufsize = 0; + + if (in == NULL) { + return LDAP_PARAM_ERROR; + } + inp = nsldapi_strdup(in); + if (inp == NULL) { + return LDAP_PARAM_ERROR; + } + props = ldap_str2charray( inp, "," ); + NSLDAPI_FREE( inp ); + + if( props == NULL || secprops == NULL ) { + return LDAP_PARAM_ERROR; + } + + for( i=0; props[i]; i++ ) { + if( strcasecmp(props[i], "none") == 0 ) { + got_sflags++; + + } else if( strcasecmp(props[i], "noactive") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_NOACTIVE; + + } else if( strcasecmp(props[i], "noanonymous") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_NOANONYMOUS; + + } else if( strcasecmp(props[i], "nodict") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_NODICTIONARY; + + } else if( strcasecmp(props[i], "noplain") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_NOPLAINTEXT; + + } else if( strcasecmp(props[i], "forwardsec") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_FORWARD_SECRECY; + + } else if( strcasecmp(props[i], "passcred") == 0 ) { + got_sflags++; + sflags |= SASL_SEC_PASS_CREDENTIALS; + + } else if( strncasecmp(props[i], + "minssf=", sizeof("minssf")) == 0 ) { + if( isdigit( props[i][sizeof("minssf")] ) ) { + got_min_ssf++; + min_ssf = atoi( &props[i][sizeof("minssf")] ); + } else { + return LDAP_NOT_SUPPORTED; + } + + } else if( strncasecmp(props[i], + "maxssf=", sizeof("maxssf")) == 0 ) { + if( isdigit( props[i][sizeof("maxssf")] ) ) { + got_max_ssf++; + max_ssf = atoi( &props[i][sizeof("maxssf")] ); + } else { + return LDAP_NOT_SUPPORTED; + } + + } else if( strncasecmp(props[i], + "maxbufsize=", sizeof("maxbufsize")) == 0 ) { + if( isdigit( props[i][sizeof("maxbufsize")] ) ) { + got_maxbufsize++; + maxbufsize = atoi( &props[i][sizeof("maxbufsize")] ); + if( maxbufsize && + (( maxbufsize < SASL_MIN_BUFF_SIZE ) + || (maxbufsize > SASL_MAX_BUFF_SIZE ))) { + return( LDAP_PARAM_ERROR ); + } + } else { + return( LDAP_NOT_SUPPORTED ); + } + } else { + return( LDAP_NOT_SUPPORTED ); + } + } + + if(got_sflags) { + secprops->security_flags = sflags; + } + if(got_min_ssf) { + secprops->min_ssf = min_ssf; + } + if(got_max_ssf) { + secprops->max_ssf = max_ssf; + } + if(got_maxbufsize) { + secprops->maxbufsize = maxbufsize; + } + + ldap_charray_free( props ); + return( LDAP_SUCCESS ); +} +#endif /* LDAP_SASLIO_HOOKS */ + +static int +nsldapi_sasl_bind_s( + LDAP *ld, + const char *dn, + const char *mechanism, + const struct berval *cred, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct berval **servercredp, + LDAPControl ***responsectrls +) +{ + int err, msgid; + LDAPMessage *result; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_sasl_bind_s\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + if ( ( err = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls, + clientctrls, &msgid )) != LDAP_SUCCESS ) + return( err ); + + if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + /* Get the controls sent by the server if requested */ + if ( responsectrls ) { + if ( ( err = ldap_parse_result( ld, result, &err, NULL, NULL, + NULL, responsectrls, 0 )) != LDAP_SUCCESS ) + return( err ); + } + + err = ldap_parse_sasl_bind_result( ld, result, servercredp, 0 ); + if (err != LDAP_SUCCESS && err != LDAP_SASL_BIND_IN_PROGRESS) { + ldap_msgfree( result ); + return( err ); + } + + return( ldap_result2error( ld, result, 1 ) ); +} + +#ifdef LDAP_SASLIO_HOOKS +static int +nsldapi_sasl_do_bind( LDAP *ld, const char *dn, + const char *mechs, unsigned flags, + LDAP_SASL_INTERACT_PROC *callback, void *defaults, + LDAPControl **sctrl, LDAPControl **cctrl, LDAPControl ***rctrl ) +{ + sasl_interact_t *prompts = NULL; + sasl_conn_t *ctx = NULL; + sasl_ssf_t *ssf = NULL; + const char *mech = NULL; + int saslrc, rc; + struct berval ccred; + unsigned credlen; + int stepnum = 1; + char *sasl_username = NULL; + + if (rctrl) { + /* init to NULL so we can call ldap_controls_free below */ + *rctrl = NULL; + } + + if (NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + /* shouldn't happen */ + if (callback == NULL) { + return( LDAP_LOCAL_ERROR ); + } + + if ( (rc = nsldapi_sasl_open(ld, NULL, &ctx, 0)) != LDAP_SUCCESS ) { + return( rc ); + } + + ccred.bv_val = NULL; + ccred.bv_len = 0; + + LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n", + (mechs ? mechs : ""), 0, 0 ); + + do { + saslrc = sasl_client_start( ctx, + mechs, + &prompts, + (const char **)&ccred.bv_val, + &credlen, + &mech ); + + LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n", + stepnum, (mech ? mech : ""), 0 ); + stepnum++; + + if( saslrc == SASL_INTERACT && + (callback)(ld, flags, defaults, prompts) != LDAP_SUCCESS ) { + break; + } + } while ( saslrc == SASL_INTERACT ); + + ccred.bv_len = credlen; + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); + } + + stepnum = 1; + + do { + struct berval *scred; + int clientstepnum = 1; + + scred = NULL; + + if (rctrl) { + /* if we're looping again, we need to free any controls set + during the previous loop */ + /* NOTE that this assumes we only care about the controls + returned by the last call to nsldapi_sasl_bind_s - if + we care about _all_ controls, we will have to figure out + some way to append them each loop go round */ + ldap_controls_free(*rctrl); + *rctrl = NULL; + } + + LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n", + stepnum, (mech ? mech : ""), 0 ); + stepnum++; + + /* notify server of a sasl bind step */ + rc = nsldapi_sasl_bind_s(ld, dn, mech, &ccred, + sctrl, cctrl, &scred, rctrl); + + if ( ccred.bv_val != NULL ) { + ccred.bv_val = NULL; + } + + if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { + ber_bvfree( scred ); + return( rc ); + } + + if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) { + /* we're done, no need to step */ + if( scred ) { + if ( scred->bv_len == 0 ) { /* MS AD sends back empty screds */ + LDAPDebug(LDAP_DEBUG_ANY, + "SASL BIND complete - ignoring empty credential response\n", + 0, 0, 0); + ber_bvfree( scred ); + } else { + /* but server provided us with data! */ + LDAPDebug(LDAP_DEBUG_TRACE, + "SASL BIND complete but invalid because server responded with credentials - length [%u]\n", + scred->bv_len, 0, 0); + ber_bvfree( scred ); + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, + NULL, "Error during SASL handshake - invalid server credential response" ); + return( LDAP_LOCAL_ERROR ); + } + } + break; + } + + /* perform the next step of the sasl bind */ + do { + LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n", + clientstepnum, stepnum, (mech ? mech : "") ); + clientstepnum++; + saslrc = sasl_client_step( ctx, + (scred == NULL) ? NULL : scred->bv_val, + (scred == NULL) ? 0 : scred->bv_len, + &prompts, + (const char **)&ccred.bv_val, + &credlen ); + + if( saslrc == SASL_INTERACT && + (callback)(ld, flags, defaults, prompts) + != LDAP_SUCCESS ) { + break; + } + } while ( saslrc == SASL_INTERACT ); + + ccred.bv_len = credlen; + ber_bvfree( scred ); + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); + } + } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + if ( saslrc != SASL_OK ) { + return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); + } + + saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username ); + if ( (saslrc == SASL_OK) && sasl_username ) { + LDAPDebug(LDAP_DEBUG_TRACE, "SASL identity: %s\n", sasl_username, 0, 0); + } + + saslrc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); + if( saslrc == SASL_OK ) { + if( ssf && *ssf ) { + LDAPDebug(LDAP_DEBUG_TRACE, + "SASL install encryption, for SSF: %lu\n", + (unsigned long) *ssf, 0, 0 ); + nsldapi_sasl_install( ld, NULL ); + } + } + + return( rc ); +} +#endif /* LDAP_SASLIO_HOOKS */ + + +/* + * ldap_sasl_bind - authenticate to the ldap server. The dn, mechanism, + * and credentials of the entry to which to bind are supplied. An LDAP + * error code is returned and if LDAP_SUCCESS is returned *msgidp is set + * to the id of the request initiated. + * + * Example: + * struct berval creds; + * LDAPControl **ctrls; + * int err, msgid; + * ... fill in creds with credentials ... + * ... fill in ctrls with server controls ... + * err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", + * "mechanismname", &creds, ctrls, NULL, &msgid ); + */ +int +LDAP_CALL +ldap_sasl_bind( + LDAP *ld, + const char *dn, + const char *mechanism, + const struct berval *cred, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp +) +{ + BerElement *ber; + int rc, simple, msgid, ldapversion; + + /* + * The ldapv3 bind request looks like this: + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING, -- passwd + * sasl [3] SaslCredentials -- v3 only + * } + * } + * SaslCredentials ::= SEQUENCE { + * mechanism LDAPString, + * credentials OCTET STRING + * } + * all wrapped up in an LDAPMessage sequence. + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( msgidp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { + nsldapi_handle_reconnect( ld ); + } + + simple = ( mechanism == LDAP_SASL_SIMPLE ); + ldapversion = NSLDAPI_LDAP_VERSION( ld ); + + /* only ldapv3 or higher can do sasl binds */ + if ( !simple && ldapversion < LDAP_VERSION3 ) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + if ( dn == NULL ) + dn = ""; + + if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, + cred, LDAP_AUTH_SASL )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* create a message to send */ + if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( rc ); + } + + /* fill it in */ + if ( simple ) { /* simple bind; works in LDAPv2 or v3 */ + struct berval tmpcred; + + if ( cred == NULL ) { + tmpcred.bv_val = ""; + tmpcred.bv_len = 0; + cred = &tmpcred; + } + rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND, + ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val, + cred->bv_len ); + + } else { /* SASL bind; requires LDAPv3 or better */ + if ( cred == NULL || cred->bv_val == NULL || cred->bv_len == 0) { + rc = ber_printf( ber, "{it{ist{s}}", msgid, + LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, + mechanism ); + } else { + rc = ber_printf( ber, "{it{ist{so}}", msgid, + LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, + mechanism, cred->bv_val, + cred->bv_len ); + } + } + + if ( rc == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( rc ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, + (char *)dn, ber ); + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + +/* + * ldap_sasl_bind_s - bind to the ldap server using sasl authentication + * The dn, mechanism, and credentials of the entry to which to bind are + * supplied. LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. + * + * Example: + * struct berval creds; + * ... fill in creds with credentials ... + * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us", + * "mechanismname", &creds ) + */ +int +LDAP_CALL +ldap_sasl_bind_s( + LDAP *ld, + const char *dn, + const char *mechanism, + const struct berval *cred, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct berval **servercredp +) +{ + return ( nsldapi_sasl_bind_s( ld, dn, mechanism, cred, + serverctrls, clientctrls, servercredp, NULL ) ); +} + +#ifdef LDAP_SASLIO_HOOKS +/* + * SASL Authentication Interface: ldap_sasl_interactive_bind_s + * + * This routine takes a DN, SASL mech list, and a SASL callback + * and performs the necessary sequencing to complete a SASL bind + * to the LDAP connection ld. The user provided callback can + * use an optionally provided set of default values to complete + * any necessary interactions. + * + * Currently imposes the following restrictions: + * A mech list must be provided + * LDAP_SASL_INTERACTIVE mode requires a callback + */ +int +LDAP_CALL +ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, + const char *saslMechanism, + LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, + LDAP_SASL_INTERACT_PROC *callback, void *defaults ) +{ + return ldap_sasl_interactive_bind_ext_s( ld, dn, + saslMechanism, sctrl, cctrl, flags, callback, + defaults, NULL ); +} + +/* + * ldap_sasl_interactive_bind_ext_s + * + * This function extends ldap_sasl_interactive_bind_s by allowing + * controls received from the server to be returned as rctrl. The + * caller must pass in a valid LDAPControl** pointer and free the + * array of controls when finished with them e.g. + * LDAPControl **retctrls = NULL; + * ... + * ldap_sasl_interactive_bind_ext_s(ld, ...., &retctrls); + * ... + * ldap_controls_free(retctrls); + * Only the controls from the server during the last bind step are returned - + * intermediate controls (if any, usually not) are discarded. + */ +int +LDAP_CALL +ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, + const char *saslMechanism, + LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, + LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) +{ +#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER + char *smechs; +#endif + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind_s\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ((flags == LDAP_SASL_INTERACTIVE) && (callback == NULL)) { + return( LDAP_PARAM_ERROR ); + } + + LDAP_MUTEX_LOCK(ld, LDAP_SASL_LOCK ); + + if( saslMechanism == NULL || *saslMechanism == '\0' ) { +#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER + rc = nsldapi_get_sasl_mechs( ld, &smechs ); + if( rc != LDAP_SUCCESS ) { + LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); + return( rc ); + } + saslMechanism = smechs; +#else + LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); + return( LDAP_PARAM_ERROR ); +#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ + } + + rc = nsldapi_sasl_do_bind( ld, dn, saslMechanism, + flags, callback, defaults, sctrl, cctrl, rctrl); + + LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); + return( rc ); +} +#else /* LDAP_SASLIO_HOOKS */ +/* stubs for platforms that do not support SASL */ +int +LDAP_CALL +ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, + const char *saslMechanism, + LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, + LDAP_SASL_INTERACT_PROC *callback, void *defaults ) +{ + return LDAP_SUCCESS; +} + +int +LDAP_CALL +ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, + const char *saslMechanism, + LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, + LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) +{ + return LDAP_SUCCESS; +} +#endif /* LDAP_SASLIO_HOOKS */ + + +/* returns an LDAP error code that indicates if parse succeeded or not */ +int +LDAP_CALL +ldap_parse_sasl_bind_result( + LDAP *ld, + LDAPMessage *res, + struct berval **servercredp, + int freeit +) +{ + BerElement ber; + int rc, err; + ber_int_t along; + ber_len_t len; + char *m, *e; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); + + /* + * the ldapv3 SASL bind response looks like this: + * + * BindResponse ::= [APPLICATION 1] SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds [7] OCTET STRING OPTIONAL + * } + * + * all wrapped up in an LDAPMessage sequence. + */ + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || + !NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( res )) { + return( LDAP_PARAM_ERROR ); + } + + /* only ldapv3 or higher can do sasl binds */ + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + if ( servercredp != NULL ) { + *servercredp = NULL; + } + + ber = *(res->lm_ber); /* struct copy */ + + /* skip past message id, matched dn, error message ... */ + rc = ber_scanf( &ber, "{iaa}", &along, &m, &e ); + + if ( rc != LBER_ERROR && + ber_peek_tag( &ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { + rc = ber_get_stringal( &ber, servercredp ); + } + + if ( freeit ) { + ldap_msgfree( res ); + } + + if ( rc == LBER_ERROR ) { + err = LDAP_DECODING_ERROR; + } else { + err = (int) along; + } + + LDAP_SET_LDERRNO( ld, err, m, e ); + /* this is a little kludge for the 3.0 Barracuda/hammerhead relese */ + /* the docs state that the return is either LDAP_DECODING_ERROR */ + /* or LDAP_SUCCESS. Here we match the docs... it's cleaner in 3.1 */ + + if ( LDAP_DECODING_ERROR == err ) { + return (LDAP_DECODING_ERROR); + } else { + return( LDAP_SUCCESS ); + } +} + diff --git a/ldap/c-sdk/libldap/saslio.c b/ldap/c-sdk/libldap/saslio.c new file mode 100644 index 0000000000..6ab6303d0c --- /dev/null +++ b/ldap/c-sdk/libldap/saslio.c @@ -0,0 +1,635 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef LDAP_SASLIO_HOOKS +#include +#include "ldap-int.h" +#include "../liblber/lber-int.h" +#include +/* Should be pulled in from lber-int.h */ +#define READBUFSIZ 8192 + +#define SEARCH_TIMEOUT_SECS 120 +#define NSLDAPI_SM_BUF 128 + +/* + * Data structures: + */ + +/* data structure that populates the I/O callback socket-specific arg. */ +typedef struct lextiof_socket_private { + struct ldap_x_ext_io_fns sess_io_fns; /* the saved layered ld fns from the layer we are "pushing" */ + struct lber_x_ext_io_fns sock_io_fns; /* the saved layered ber fns from the layer we are "pushing" */ + sasl_conn_t *sasl_ctx; /* the sasl context - pointer to the one from the connection */ + char *sb_sasl_ibuf; /* sasl decrypted input buffer */ + char *sb_sasl_iptr; /* current location in buffer */ + int sb_sasl_bfsz; /* Alloc'd size of input buffer */ + int sb_sasl_ilen; /* remaining length to process */ + LDAP *ld; /* used to set errno */ + Sockbuf *sb; /* pointer to our associated sockbuf */ +} SASLIOSocketArg; + +static void +destroy_SASLIOSocketArg(SASLIOSocketArg** sockarg) +{ + if (sockarg && *sockarg) { + NSLDAPI_FREE((*sockarg)->sb_sasl_ibuf); + NSLDAPI_FREE((*sockarg)); + *sockarg = NULL; + } +} + +static SASLIOSocketArg* +new_SASLIOSocketArg(sasl_conn_t *ctx, int bufsiz, LDAP *ld, Sockbuf *sb) +{ + SASLIOSocketArg *sockarg = NULL; + + if (bufsiz <= 0) { + return sockarg; + } + + sockarg = (SASLIOSocketArg*)NSLDAPI_CALLOC(1, sizeof(SASLIOSocketArg)); + if (sockarg) { + sockarg->sasl_ctx = ctx; + sockarg->sb_sasl_ibuf = NSLDAPI_MALLOC(bufsiz); + if (!sockarg->sb_sasl_ibuf) { + destroy_SASLIOSocketArg(&sockarg); + return sockarg; + } + sockarg->sb_sasl_iptr = NULL; + sockarg->sb_sasl_bfsz = bufsiz; + sockarg->sb_sasl_ilen = 0; + sockarg->ld = ld; + sockarg->sb = sb; + } + + return sockarg; +} + +/* + * SASL Dependent routines + * + * SASL security and integrity options are supported through the + * use of the extended I/O functionality. Because the extended + * I/O functions may already be in use prior to enabling encryption, + * when SASL encryption si enabled, these routine interpose themselves + * over the exitng extended I/O routines and add an additional level + * of indirection. + * IE: Before SASL: client->libldap->lber->extio + * After SASL: client->libldap->lber->saslio->extio + * Any extio function are stilled used for the raw i/O [IE prldap] + * but SASL will decrypt before passing to lber. + * SASL cannot decrypt a stream so full packaets must be read + * before proceeding. + */ + +/* + * Get the 4 octet header [size] for a sasl encrypted buffer. + * See RFC222 [section 3]. + */ +static int +nsldapi_sasl_pktlen( char *buf, int maxbufsize ) +{ + int size; + +#if defined( _WINDOWS ) || defined( _WIN32 ) + size = ntohl(*(u_long *)buf); +#else + size = ntohl(*(uint32_t *)buf); +#endif + if ( size < 0 || size > maxbufsize ) { + return (-1 ); + } + + return( size + 4 ); /* include the first 4 bytes */ +} + +/* + * SASL encryption routines + */ + +static int +nsldapi_sasl_read( int s, void *buf, int len, + struct lextiof_socket_private *arg) +{ + LDAP *ld; + const char *dbuf; + char *cp; + int ret; + unsigned dlen, blen; + + ld = (LDAP *)arg->ld; + + /* Is there anything left in the existing buffer? */ + if ((ret = arg->sb_sasl_ilen) > 0) { + ret = (ret > len ? len : ret); + SAFEMEMCPY( buf, arg->sb_sasl_iptr, ret ); + if (ret == arg->sb_sasl_ilen) { + arg->sb_sasl_ilen = 0; + arg->sb_sasl_iptr = NULL; + } else { + arg->sb_sasl_ilen -= ret; + arg->sb_sasl_iptr += ret; + } + return( ret ); + } + + /* buffer is empty - fill it */ + cp = arg->sb_sasl_ibuf; + dlen = 0; + + /* Read the length of the packet */ + while ( dlen < 4 ) { + if (arg->sock_io_fns.lbextiofn_read != NULL) { + ret = arg->sock_io_fns.lbextiofn_read( + s, cp, 4 - dlen, + arg->sock_io_fns.lbextiofn_socket_arg); + } else { + ret = read( s, cp, 4 - dlen ); + } +#ifdef EINTR + if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return( ret ); + + cp += ret; + dlen += ret; + } + + blen = 4; + + ret = nsldapi_sasl_pktlen( arg->sb_sasl_ibuf, arg->sb_sasl_bfsz ); + if (ret < 0) { + LDAP_SET_ERRNO(ld, EIO); + return( -1 ); + } + dlen = ret - dlen; + + /* read the rest of the encrypted packet */ + while ( dlen > 0 ) { + if (arg->sock_io_fns.lbextiofn_read != NULL) { + ret = arg->sock_io_fns.lbextiofn_read( + s, cp, dlen, + arg->sock_io_fns.lbextiofn_socket_arg); + } else { + ret = read( s, cp, dlen ); + } + +#ifdef EINTR + if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return( ret ); + + cp += ret; + blen += ret; + dlen -= ret; + } + + /* Decode the packet */ + ret = sasl_decode( arg->sasl_ctx, + arg->sb_sasl_ibuf, blen, + &dbuf, &dlen); + if ( ret != SASL_OK ) { + /* sb_sasl_read: failed to decode packet, drop it, error */ + arg->sb_sasl_iptr = NULL; + arg->sb_sasl_ilen = 0; + LDAP_SET_ERRNO(ld, EIO); + return( -1 ); + } + + /* copy decrypted packet to the input buffer */ + SAFEMEMCPY( arg->sb_sasl_ibuf, dbuf, dlen ); + arg->sb_sasl_iptr = arg->sb_sasl_ibuf; + arg->sb_sasl_ilen = dlen; + + ret = (dlen > (unsigned) len ? len : dlen); + SAFEMEMCPY( buf, arg->sb_sasl_iptr, ret ); + if (ret == arg->sb_sasl_ilen) { + arg->sb_sasl_ilen = 0; + arg->sb_sasl_iptr = NULL; + } else { + arg->sb_sasl_ilen -= ret; + arg->sb_sasl_iptr += ret; + } + return( ret ); +} + +static int +nsldapi_sasl_write( int s, const void *buf, int len, + struct lextiof_socket_private *arg) +{ + int ret = 0; + const char *obuf, *optr, *cbuf = (const char *)buf; + unsigned olen, clen, tlen = 0; + unsigned *maxbuf; + + ret = sasl_getprop(arg->sasl_ctx, SASL_MAXOUTBUF, + (const void **)&maxbuf); + if ( ret != SASL_OK ) { + /* just a sanity check, should never happen */ + return( -1 ); + } + + while (len > 0) { + clen = (len > *maxbuf) ? *maxbuf : len; + /* encode the next packet. */ + ret = sasl_encode( arg->sasl_ctx, cbuf, clen, &obuf, &olen); + if ( ret != SASL_OK ) { + /* XXX Log error? "sb_sasl_write: failed to encode packet..." */ + return( -1 ); + } + /* Write everything now, buffer is only good until next sasl_encode */ + optr = obuf; + while (olen > 0) { + if (arg->sock_io_fns.lbextiofn_write != NULL) { + ret = arg->sock_io_fns.lbextiofn_write( + s, optr, olen, + arg->sock_io_fns.lbextiofn_socket_arg); + } else { + ret = write( s, optr, olen); + } + if ( ret < 0 ) + return( ret ); + optr += ret; + olen -= ret; + } + len -= clen; + cbuf += clen; + tlen += clen; + } + return( tlen ); +} + +/* + * What's all this then? + * First, take a look at os-ip.c:nsldapi_add_to_cb_pollfds(). When a new descriptor is + * added to the pollfds array, the lpoll_socketarg field is initialized to the value from + * the socketarg field - sb->sb_ext_io_fns.lbextiofn_socket_arg. In our case, since we + * override this with our sasl data (see below nsldapi_sasl_install), we need to restore + * the previous value so that the layer below us (i.e. prldap) can use the lpoll_socketarg + * which it sets. + * So how do which know which fds[i] is a "sasl" fd? + * We initialize the lextiof_session_private *arg (see nsldapi_sasl_install) to point to + * the socket_private data in sb->sb_ext_io_fns.lbextiofn_socket_arg for "sasl" sockets, + * which is then used to initialize lpoll_socketarg (see above). + * So, if the arg which gets passed into nsldapi_sasl_poll is the same as the + * fds[i].lpoll_socketarg, we know it is a "sasl" socket and we need to "pop" the sasl + * layer. We do this by replacing lpoll_socketarg with the one we saved when we "pushed" + * the sasl layer. + * So why the loop to restore the sasl lpoll_socketarg? + * The lower layer only uses lpoll_socketarg during poll(). See ldappr-io.c:prldap_poll() + * for more information about how that works. However, after the polling is done, there + * is some special magic in os-ip.c in the functions nsldapi_add_to_cb_pollfds(), + * nsldapi_clear_from_cb_pollfds(), and nsldapi_find_in_cb_pollfds() to find the correct + * Sockbuf to operate on. This is the macro NSLDAPI_CB_POLL_MATCH(). For the extended + * io function callbacks to work correctly, it is not sufficient to say that the file + * descriptor in the Sockbuf matches the one that poll says has activity - we also need + * to match the lpoll_socketarg with the sb->sb_ext_io_fns.lbextiofn_socket_arg to make + * sure this really is the Sockbuf we want to use. So we have to restore the + * lpoll_socketarg with the original one. + * Why have origarg and staticorigarg? + * To avoid malloc. The sizeof staticorigarg should be large enough to accomodate almost + * all clients without incurring too much additional overhead. However, if we need more + * room, origarg will grow to nfds. If this proves to be inadequate, the size of the + * staticorigarg is a good candidate for a #define set by configure. + */ +static int +nsldapi_sasl_poll( + LDAP_X_PollFD fds[], int nfds, int timeout, + struct lextiof_session_private *arg ) +{ + LDAP_X_EXTIOF_POLL_CALLBACK *origpoll; /* poll fn from the pushed layer */ + struct lextiof_session_private *origsess = NULL; /* session arg from the pushed layer */ + SASLIOSocketArg **origarg = NULL; /* list of saved original socket args */ + SASLIOSocketArg *staticorigarg[1024]; /* default list to avoid malloc */ + int origargsize = sizeof(staticorigarg)/sizeof(staticorigarg[0]); + int rc = -1; /* the return code - -1 means failure */ + + if (arg == NULL) { /* should not happen */ + return( rc ); + } + + origarg = staticorigarg; + /* if the static array is not large enough, alloc a dynamic one */ + if (origargsize < nfds) { + origarg = (SASLIOSocketArg **)NSLDAPI_MALLOC(nfds*sizeof(SASLIOSocketArg *)); + } + + if (fds && nfds > 0) { + int i; + for(i = 0; i < nfds; i++) { + /* save the original socket arg */ + origarg[i] = fds[i].lpoll_socketarg; + if (arg == (struct lextiof_session_private *)fds[i].lpoll_socketarg) { + /* lpoll_socketarg is a sasl socket arg - we need to replace it + with the one from the layer we pushed (i.e. prldap) */ + SASLIOSocketArg *sockarg = (SASLIOSocketArg *)fds[i].lpoll_socketarg; + /* reset to pushed layer's socket arg */ + fds[i].lpoll_socketarg = sockarg->sock_io_fns.lbextiofn_socket_arg; + /* grab the pushed layers' poll fn and its session arg */ + if (!origsess) { + origpoll = sockarg->sess_io_fns.lextiof_poll; + origsess = sockarg->sess_io_fns.lextiof_session_arg; + } + } + } + } + + if (origsess == NULL) { /* should not happen */ + goto done; + } + + /* call the "real" poll function */ + rc = origpoll( fds, nfds, timeout, origsess ); + + /* reset the lpoll_socketarg values to their original values because + they must match what's in sb->iofns->lbextiofn_socket_arg in order + for NSLDAPI_CB_POLL_MATCH to work - see os-ip.c */ + if (fds && nfds > 0) { + int i; + for(i = 0; i < nfds; i++) { + if ((SASLIOSocketArg *)arg == origarg[i]) { + fds[i].lpoll_socketarg = origarg[i]; + } + } + } + +done: + /* if we had to use a dynamic array, free it */ + if (origarg != staticorigarg) { + NSLDAPI_FREE(origarg); + } + + return rc; +} + +int +nsldapi_sasl_open( LDAP *ld, LDAPConn *lconn, sasl_conn_t **ctx, sasl_ssf_t ssf ) +{ + int saslrc; + char *host = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + if ( lconn == NULL ) { + if ( ld->ld_defconn == NULL || + ld->ld_defconn->lconn_status != LDAP_CONNST_CONNECTED) { + int rc = nsldapi_open_ldap_defconn( ld ); + if( rc < 0 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + } + lconn = ld->ld_defconn; + } + + /* need to clear out the old context for this connection, if any */ + /* client may have re-bind-ed this connection without closing first */ + if (lconn->lconn_sasl_ctx) { + sasl_dispose(&lconn->lconn_sasl_ctx); + lconn->lconn_sasl_ctx = NULL; + } + + if ( 0 != ldap_get_option( ld, LDAP_OPT_HOST_NAME, &host ) ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + saslrc = sasl_client_new( "ldap", host, + NULL, NULL, /* iplocalport, ipremoteport - use defaults */ + NULL, 0, ctx ); + ldap_memfree(host); + + if ( (saslrc != SASL_OK) || (!*ctx) ) { + return( nsldapi_sasl_cvterrno( ld, saslrc, NULL ) ); + } + + if( ssf ) { + sasl_ssf_t extprops; + memset(&extprops, 0L, sizeof(extprops)); + extprops = ssf; + + (void) sasl_setprop( *ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); + } + + /* (re)set security properties */ + sasl_setprop( *ctx, SASL_SEC_PROPS, &ld->ld_sasl_secprops ); + + /* set the connection context */ + lconn->lconn_sasl_ctx = *ctx; + + return( LDAP_SUCCESS ); +} + +static int +nsldapi_sasl_close( struct lextiof_socket_private *arg ) +{ + /* undo function pointer interposing */ + ldap_set_option( arg->ld, LDAP_X_OPT_EXTIO_FN_PTRS, &arg->sess_io_fns ); + /* have to do this separately to make sure the socketarg is set correctly */ + ber_sockbuf_set_option( arg->sb, + LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&arg->sock_io_fns ); + + destroy_SASLIOSocketArg(&arg); + return( LDAP_SUCCESS ); +} + +static int +nsldapi_sasl_close_socket(int s, struct lextiof_socket_private *arg ) +{ + LDAP_X_EXTIOF_CLOSE_CALLBACK *origclose; + struct lextiof_socket_private *origsock; + + if (arg == NULL) { + return( -1 ); + } + + origclose = arg->sess_io_fns.lextiof_close; + origsock = arg->sock_io_fns.lbextiofn_socket_arg; + + /* undo SASL */ + nsldapi_sasl_close( arg ); + arg = NULL; + /* arg is destroyed at this point - do not use it */ + + if (origclose ) + return ( origclose( s, origsock ) ); + else { + /* This is a copy of nsldapi_os_closesocket() + * from os-ip.c. It is declared static there, + * hence the copy of it. + */ + int rc; + +#ifdef NSLDAPI_AVOID_OS_SOCKETS + rc = -1; +#else /* NSLDAPI_AVOID_OS_SOCKETS */ +#ifdef _WINDOWS + rc = closesocket( s ); +#else /* _WINDOWS */ + rc = close( s ); +#endif /* _WINDOWS */ +#endif /* NSLDAPI_AVOID_OS_SOCKETS */ + return( rc ); + } + +} + +/* + * install encryption routines if security has been negotiated + */ +int +nsldapi_sasl_install( LDAP *ld, LDAPConn *lconn ) +{ + struct lber_x_ext_io_fns fns; + struct ldap_x_ext_io_fns iofns; + sasl_security_properties_t *secprops; + int rc, value; + int bufsiz; + Sockbuf *sb = NULL; + sasl_conn_t *ctx = NULL; + SASLIOSocketArg *sockarg = NULL; + + if ( lconn == NULL ) { + lconn = ld->ld_defconn; + if ( lconn == NULL ) { + return( LDAP_LOCAL_ERROR ); + } + } + if ( (sb = lconn->lconn_sb) == NULL ) { + return( LDAP_LOCAL_ERROR ); + } + rc = ber_sockbuf_get_option( sb, + LBER_SOCKBUF_OPT_TO_FILE_ONLY, + (void *) &value); + if (rc != 0 || value != 0) { + return( LDAP_LOCAL_ERROR ); + } + + /* the sasl context in the lconn must have been set prior to this */ + ctx = lconn->lconn_sasl_ctx; + rc = sasl_getprop( ctx, SASL_SEC_PROPS, + (const void **)&secprops ); + if (rc != SASL_OK) + return( LDAP_LOCAL_ERROR ); + bufsiz = secprops->maxbufsize; + if (bufsiz <= 0) { + return( LDAP_LOCAL_ERROR ); + } + + /* create our socket specific context */ + sockarg = new_SASLIOSocketArg(ctx, bufsiz, ld, sb); + if (!sockarg) { + return( LDAP_LOCAL_ERROR ); + } + + /* save a copy of the existing io fns and the session arg */ + memset( &sockarg->sess_io_fns, 0, LDAP_X_EXTIO_FNS_SIZE ); + sockarg->sess_io_fns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + rc = ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, + &sockarg->sess_io_fns ); + if (rc != 0) { + destroy_SASLIOSocketArg(&sockarg); + return( LDAP_LOCAL_ERROR ); + } + + /* save a copy of the existing ber io fns and the socket arg */ + memset( &sockarg->sock_io_fns, 0, LBER_X_EXTIO_FNS_SIZE ); + sockarg->sock_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + rc = ber_sockbuf_get_option( sb, + LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&sockarg->sock_io_fns); + if (rc != 0) { + destroy_SASLIOSocketArg(&sockarg); + return( LDAP_LOCAL_ERROR ); + } + + /* Always set the ext io close fn pointer to ensure we + * clean up our sockarg context */ + memset( &iofns, 0, sizeof(iofns)); + /* first, copy struct - sets defaults */ + iofns = sockarg->sess_io_fns; + iofns.lextiof_close = nsldapi_sasl_close_socket; + iofns.lextiof_session_arg = sockarg; /* needed for close and poll */ + + /* Set new values for the other ext io funcs if there are any - + when using the native io fns (as opposed to prldap) there + won't be any */ + if ( sockarg->sess_io_fns.lextiof_read != NULL || + sockarg->sess_io_fns.lextiof_write != NULL || + sockarg->sess_io_fns.lextiof_poll != NULL || + sockarg->sess_io_fns.lextiof_connect != NULL ) { + /* next, just reset those functions we want to override */ + iofns.lextiof_read = nsldapi_sasl_read; + iofns.lextiof_write = nsldapi_sasl_write; + iofns.lextiof_poll = nsldapi_sasl_poll; + } + + /* set the ext io funcs */ + rc = ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ); + if (rc != 0) { + /* frees everything and resets fns above */ + nsldapi_sasl_close(sockarg); + return( LDAP_LOCAL_ERROR ); + } + + /* set the new ber io funcs and socket arg */ + (void) memset( &fns, 0, LBER_X_EXTIO_FNS_SIZE); + fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + fns.lbextiofn_read = nsldapi_sasl_read; + fns.lbextiofn_write = nsldapi_sasl_write; + fns.lbextiofn_socket_arg = sockarg; + rc = ber_sockbuf_set_option( sb, + LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&fns); + if (rc != 0) { + /* frees everything and resets fns above */ + nsldapi_sasl_close(sockarg); + return( LDAP_LOCAL_ERROR ); + } + + return( LDAP_SUCCESS ); +} + +#endif diff --git a/ldap/c-sdk/libldap/sbind.c b/ldap/c-sdk/libldap/sbind.c new file mode 100644 index 0000000000..d9bfc71fd4 --- /dev/null +++ b/ldap/c-sdk/libldap/sbind.c @@ -0,0 +1,214 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * sbind.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +static int simple_bind_nolock( LDAP *ld, const char *dn, const char *passwd, + int unlock_permitted ); + +/* + * ldap_simple_bind - bind to the ldap server. The dn and + * password of the entry to which to bind are supplied. The message id + * of the request initiated is returned. + * + * Example: + * ldap_simple_bind( ld, "cn=manager, o=university of michigan, c=us", + * "secret" ) + */ + +int +LDAP_CALL +ldap_simple_bind( LDAP *ld, const char *dn, const char *passwd ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { + nsldapi_handle_reconnect( ld ); + } + + rc = simple_bind_nolock( ld, dn, passwd, 1 ); + + return( rc ); +} + + +static int +simple_bind_nolock( LDAP *ld, const char *dn, const char *passwd, + int unlock_permitted ) +{ + BerElement *ber; + int rc, msgid; + + /* + * The bind request looks like this: + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING -- passwd + * } + * } + * all wrapped up in an LDAPMessage sequence. + */ + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + if ( dn == NULL ) + dn = ""; + if ( passwd == NULL ) + passwd = ""; + + if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { + struct berval bv; + + bv.bv_val = (char *)passwd; + bv.bv_len = strlen( passwd ); + /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */ + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, &bv, + LDAP_AUTH_SIMPLE ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */ + if ( rc != 0 ) { + return( rc ); + } + } + + /* create a message to send */ + if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( -1 ); + } + + /* fill it in */ + if ( ber_printf( ber, "{it{ists}", msgid, LDAP_REQ_BIND, + NSLDAPI_LDAP_VERSION( ld ), dn, LDAP_AUTH_SIMPLE, passwd ) == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( -1 ); + } + + if ( nsldapi_put_controls( ld, NULL, 1, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( -1 ); + } + + /* send the message */ + return( nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, + (char *)dn, ber )); +} + + +/* + * ldap_simple_bind - bind to the ldap server 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_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us", + * "secret" ) + */ +int +LDAP_CALL +ldap_simple_bind_s( LDAP *ld, const char *dn, const char *passwd ) +{ + int msgid; + LDAPMessage *result; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + + return( ldap_result2error( ld, result, 1 ) ); +} + +void nsldapi_handle_reconnect( LDAP *ld ) +{ + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_handle_reconnect\n", 0, 0, 0 ); + + /* + * if the default connection has been lost and is now marked dead, + * dispose of the default connection so it will get re-established. + * + * if not, clear the bind DN and status to ensure that we don't + * report the wrong bind DN to a different thread while waiting + * for our bind result to return from the server. + */ + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + if ( NULL != ld->ld_defconn ) { + if ( LDAP_CONNST_DEAD == ld->ld_defconn->lconn_status ) { + nsldapi_free_connection( ld, ld->ld_defconn, NULL, NULL, 1, 0 ); + ld->ld_defconn = NULL; + } else if ( ld->ld_defconn->lconn_binddn != NULL ) { + NSLDAPI_FREE( ld->ld_defconn->lconn_binddn ); + ld->ld_defconn->lconn_binddn = NULL; + ld->ld_defconn->lconn_bound = 0; + } + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); +} diff --git a/ldap/c-sdk/libldap/search.c b/ldap/c-sdk/libldap/search.c new file mode 100644 index 0000000000..648d739e6a --- /dev/null +++ b/ldap/c-sdk/libldap/search.c @@ -0,0 +1,1022 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * search.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +static int nsldapi_timeval2ldaplimit( struct timeval *timeoutp, + int defaultvalue ); +static int nsldapi_search( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int timelimit, int sizelimit, int *msgidp ); +static char *find_right_paren( char *s ); +static char *put_complex_filter( BerElement *ber, char *str, + unsigned long tag, int not ); +static int put_filter( BerElement *ber, char *str ); +static int unescape_filterval( char *str ); +static int hexchar2int( char c ); +static int is_valid_attr( char *a ); +static int put_simple_filter( BerElement *ber, char *str ); +static int put_substring_filter( BerElement *ber, char *type, + char *str ); +static int put_filter_list( BerElement *ber, char *str ); +static int nsldapi_search_s( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct timeval *localtimeoutp, int timelimit, int sizelimit, + LDAPMessage **res ); + +/* + * ldap_search - initiate an ldap search operation. Parameters: + * + * ld LDAP descriptor + * base DN of the base object + * scope the search scope - one of LDAP_SCOPE_BASE, + * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE + * filter a string containing the search filter + * (e.g., "(|(cn=bob)(sn=bob))") + * attrs list of attribute types to return for matches + * attrsonly 1 => attributes only 0 => attributes and values + * + * Example: + * char *attrs[] = { "mail", "title", 0 }; + * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", + * attrs, attrsonly ); + */ +int +LDAP_CALL +ldap_search( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly +) +{ + int msgid; + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); + + if ( ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, NULL, + NULL, NULL, -1, &msgid ) == LDAP_SUCCESS ) { + return( msgid ); + } else { + return( -1 ); /* error is in ld handle */ + } +} + + +/* + * LDAPv3 extended search. + * Returns an LDAP error code. + */ +int +LDAP_CALL +ldap_search_ext( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct timeval *timeoutp, /* NULL means use ld->ld_timelimit */ + int sizelimit, + int *msgidp +) +{ + /* + * It is an error to pass in a zero'd timeval. + */ + if ( timeoutp != NULL && timeoutp->tv_sec == 0 && + timeoutp->tv_usec == 0 ) { + if ( ld != NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + } + return( LDAP_PARAM_ERROR ); + } + + return( nsldapi_search( ld, base, scope, filter, attrs, attrsonly, + serverctrls, clientctrls, + nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, msgidp )); +} + + +/* + * Like ldap_search_ext() except an integer timelimit is passed instead of + * using the overloaded struct timeval *timeoutp. + */ +static int +nsldapi_search( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int timelimit, /* -1 means use ld->ld_timelimit */ + int sizelimit, /* -1 means use ld->ld_sizelimit */ + int *msgidp +) +{ + BerElement *ber; + int rc, rc_key; + unsigned long key; /* XXXmcs: memcache */ + + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( base == NULL ) { + base = ""; + } + + if ( filter == NULL ) { + filter = "(objectclass=*)"; + } + + if ( msgidp == NULL || ( scope != LDAP_SCOPE_BASE + && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE ) + || ( sizelimit < -1 )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + *msgidp = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + /* + * XXXmcs: should use cache function pointers to hook in memcache + */ + if ( ld->ld_memcache == NULL ) { + rc_key = LDAP_NOT_SUPPORTED; + } else if (( rc_key = ldap_memcache_createkey( ld, base, scope, filter, + attrs, attrsonly, serverctrls, clientctrls, &key)) == LDAP_SUCCESS + && ldap_memcache_result( ld, *msgidp, key ) == LDAP_SUCCESS ) { + return LDAP_SUCCESS; + } + + /* check the cache */ + if ( ld->ld_cache_on && ld->ld_cache_search != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + if ( (rc = (ld->ld_cache_search)( ld, *msgidp, LDAP_REQ_SEARCH, + base, scope, filter, attrs, attrsonly )) != 0 ) { + *msgidp = rc; + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + return( LDAP_SUCCESS ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* caching off or did not find it in the cache - check the net */ + if (( rc = nsldapi_build_search_req( ld, base, scope, filter, attrs, + attrsonly, serverctrls, clientctrls, timelimit, sizelimit, + *msgidp, &ber )) != LDAP_SUCCESS ) { + return( rc ); + } + + /* send the message */ + rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_SEARCH, + (char *) base, ber ); + + /* + * XXXmcs: should use cache function pointers to hook in memcache + */ + if ( (rc_key == LDAP_SUCCESS) && (rc >= 0) ) { + ldap_memcache_new( ld, rc, key, base ); + } + + *msgidp = rc; + return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); +} + + +/* + * Convert a non-NULL timeoutp to a value in seconds that is appropriate to + * send in an LDAP search request. If timeoutp is NULL, return defaultvalue. + */ +static int +nsldapi_timeval2ldaplimit( struct timeval *timeoutp, int defaultvalue ) +{ + int timelimit; + + if ( NULL == timeoutp ) { + timelimit = defaultvalue; + } else if ( timeoutp->tv_sec > 0 ) { + timelimit = timeoutp->tv_sec; + } else if ( timeoutp->tv_usec > 0 ) { + timelimit = 1; /* minimum we can express in LDAP */ + } else { + /* + * both tv_sec and tv_usec are less than one (zero?) so + * to maintain compatiblity with our "zero means no limit" + * convention we pass no limit to the server. + */ + timelimit = 0; /* no limit */ + } + + return( timelimit ); +} + + +/* returns an LDAP error code and also sets it in ld */ +int +nsldapi_build_search_req( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, /* not used for anything yet */ + int timelimit, /* if -1, ld->ld_timelimit is used */ + int sizelimit, /* if -1, ld->ld_sizelimit is used */ + int msgid, + BerElement **berp +) +{ + BerElement *ber; + int err; + char *fdup; + + /* + * Create the search request. It looks like this: + * SearchRequest := [APPLICATION 3] SEQUENCE { + * baseObject DistinguishedName, + * scope ENUMERATED { + * baseObject (0), + * singleLevel (1), + * wholeSubtree (2) + * }, + * derefAliases ENUMERATED { + * neverDerefaliases (0), + * derefInSearching (1), + * derefFindingBaseObj (2), + * alwaysDerefAliases (3) + * }, + * sizelimit INTEGER (0 .. 65535), + * timelimit INTEGER (0 .. 65535), + * attrsOnly BOOLEAN, + * filter Filter, + * attributes SEQUENCE OF AttributeType + * } + * wrapped in an ldap message. + */ + + /* create a message to send */ + if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( err ); + } + + if ( base == NULL ) { + base = ""; + } + + if ( sizelimit == -1 ) { + sizelimit = ld->ld_sizelimit; + } + + if ( timelimit == -1 ) { + timelimit = ld->ld_timelimit; + } + +#ifdef CLDAP + if ( ld->ld_sbp->sb_naddr > 0 ) { + err = ber_printf( ber, "{ist{seeiib", msgid, + ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, + sizelimit, timelimit, attrsonly ); + } else { +#endif /* CLDAP */ + err = ber_printf( ber, "{it{seeiib", msgid, + LDAP_REQ_SEARCH, base, scope, ld->ld_deref, + sizelimit, timelimit, attrsonly ); +#ifdef CLDAP + } +#endif /* CLDAP */ + + if ( err == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + fdup = nsldapi_strdup( filter ); + err = put_filter( ber, fdup ); + NSLDAPI_FREE( fdup ); + + if ( err == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_FILTER_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_FILTER_ERROR ); + } + + if ( ber_printf( ber, "{v}}", attrs ) == -1 ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + if ( (err = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( err ); + } + + *berp = ber; + return( LDAP_SUCCESS ); +} + +static char * +find_right_paren( char *s ) +{ + int balance, escape; + + balance = 1; + escape = 0; + while ( *s && balance ) { + if ( escape == 0 ) { + if ( *s == '(' ) + balance++; + else if ( *s == ')' ) + balance--; + } + if ( *s == '\\' && ! escape ) + escape = 1; + else + escape = 0; + if ( balance ) + s++; + } + + return( *s ? s : NULL ); +} + +static char * +put_complex_filter( + BerElement *ber, + char *str, + unsigned long tag, + int not +) +{ + char *next; + + /* + * We have (x(filter)...) with str sitting on + * the x. We have to find the paren matching + * the one before the x and put the intervening + * filters by calling put_filter_list(). + */ + + /* put explicit tag */ + if ( ber_printf( ber, "t{", tag ) == -1 ) + return( NULL ); + + str++; + if ( (next = find_right_paren( str )) == NULL ) + return( NULL ); + + *next = '\0'; + if ( put_filter_list( ber, str ) == -1 ) + return( NULL ); + *next++ = ')'; + + /* flush explicit tagged thang */ + if ( ber_printf( ber, "}" ) == -1 ) + return( NULL ); + + return( next ); +} + +static int +put_filter( BerElement *ber, char *str ) +{ + char *next; + int parens, balance, escape; + + /* + * A Filter looks like this: + * 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] IA5String, + * any [1] IA5String, + * final [2] IA5String + * } + * } + * Note: tags in a choice are always explicit + */ + + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 ); + + parens = 0; + while ( *str ) { + switch ( *str ) { + case '(': + str++; + parens++; + switch ( *str ) { + case '&': + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: AND\n", + 0, 0, 0 ); + + if ( (str = put_complex_filter( ber, str, + LDAP_FILTER_AND, 0 )) == NULL ) + return( -1 ); + + parens--; + break; + + case '|': + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: OR\n", + 0, 0, 0 ); + + if ( (str = put_complex_filter( ber, str, + LDAP_FILTER_OR, 0 )) == NULL ) + return( -1 ); + + parens--; + break; + + case '!': + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: NOT\n", + 0, 0, 0 ); + + if ( (str = put_complex_filter( ber, str, + LDAP_FILTER_NOT, 1 )) == NULL ) + return( -1 ); + + parens--; + break; + + default: + LDAPDebug( LDAP_DEBUG_TRACE, + "put_filter: simple\n", 0, 0, 0 ); + + balance = 1; + escape = 0; + next = str; + while ( *next && balance ) { + if ( escape == 0 ) { + if ( *next == '(' ) + balance++; + else if ( *next == ')' ) + balance--; + } + if ( *next == '\\' && ! escape ) + escape = 1; + else + escape = 0; + if ( balance ) + next++; + } + if ( balance != 0 ) + return( -1 ); + + *next = '\0'; + if ( put_simple_filter( ber, str ) == -1 ) { + return( -1 ); + } + *next++ = ')'; + str = next; + parens--; + break; + } + break; + + case ')': + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0, + 0 ); + if ( ber_printf( ber, "]" ) == -1 ) + return( -1 ); + str++; + parens--; + break; + + case ' ': + str++; + break; + + default: /* assume it's a simple type=value filter */ + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, + 0 ); + next = strchr( str, '\0' ); + if ( put_simple_filter( ber, str ) == -1 ) { + return( -1 ); + } + str = next; + break; + } + } + + return( parens ? -1 : 0 ); +} + + +/* + * Put a list of filters like this "(filter1)(filter2)..." + */ + +static int +put_filter_list( BerElement *ber, char *str ) +{ + char *next; + char save; + + LDAPDebug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 ); + + while ( *str ) { + while ( *str && isspace( *str ) ) + str++; + if ( *str == '\0' ) + break; + + if ( (next = find_right_paren( str + 1 )) == NULL ) + return( -1 ); + save = *++next; + + /* now we have "(filter)" with str pointing to it */ + *next = '\0'; + if ( put_filter( ber, str ) == -1 ) + return( -1 ); + *next = save; + + str = next; + } + + return( 0 ); +} + + +/* + * is_valid_attr - returns 1 if a is a syntactically valid left-hand side + * of a filter expression, 0 otherwise. A valid string may contain only + * letters, numbers, hyphens, semi-colons, colons and periods. examples: + * cn + * cn;lang-fr + * 1.2.3.4;binary;dynamic + * mail;dynamic + * cn:dn:1.2.3.4 + * + * For compatibility with older servers, we also allow underscores in + * attribute types, even through they are not allowed by the LDAPv3 RFCs. + */ +static int +is_valid_attr( char *a ) +{ + for ( ; *a; a++ ) { + if ( !isascii( *a ) ) { + return( 0 ); + } else if ( !isalnum( *a ) ) { + switch ( *a ) { + case '-': + case '.': + case ';': + case ':': + case '_': + break; /* valid */ + default: + return( 0 ); + } + } + } + + return( 1 ); +} + +static char * +find_star( char *s ) +{ + for ( ; *s; ++s ) { + switch ( *s ) { + case '*': return s; + case '\\': + ++s; + if ( hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0 ) ++s; + default: break; + } + } + return NULL; +} + +static int +put_simple_filter( BerElement *ber, char *str ) +{ + char *s, *s2, *s3, filterop; + char *value; + unsigned long ftype; + int rc, len; + char *oid; /* for v3 extended filter */ + int dnattr; /* for v3 extended filter */ + + LDAPDebug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 ); + + rc = -1; /* pessimistic */ + + if (( str = nsldapi_strdup( str )) == NULL ) { + return( rc ); + } + + if ( (s = strchr( str, '=' )) == NULL ) { + goto free_and_return; + } + value = s + 1; + *s-- = '\0'; + filterop = *s; + if ( filterop == '<' || filterop == '>' || filterop == '~' || + filterop == ':' ) { + *s = '\0'; + } + + if ( ! is_valid_attr( str ) ) { + goto free_and_return; + } + + switch ( filterop ) { + case '<': + ftype = LDAP_FILTER_LE; + break; + case '>': + ftype = LDAP_FILTER_GE; + break; + case '~': + ftype = LDAP_FILTER_APPROX; + break; + case ':': /* extended filter - v3 only */ + /* + * extended filter looks like this: + * + * [type][':dn'][':'oid]':='value + * + * where one of type or :oid is required. + * + */ + ftype = LDAP_FILTER_EXTENDED; + s2 = s3 = NULL; + if ( (s2 = strrchr( str, ':' )) == NULL ) { + goto free_and_return; + } + if ( strcasecmp( s2, ":dn" ) == 0 ) { + oid = NULL; + dnattr = 1; + *s2 = '\0'; + } else { + oid = s2 + 1; + dnattr = 0; + *s2 = '\0'; + if ( (s3 = strrchr( str, ':' )) != NULL ) { + if ( strcasecmp( s3, ":dn" ) == 0 ) { + dnattr = 1; + } else { + goto free_and_return; + } + *s3 = '\0'; + } + } + if ( (rc = ber_printf( ber, "t{", ftype )) == -1 ) { + goto free_and_return; + } + if ( oid != NULL ) { + if ( (rc = ber_printf( ber, "ts", LDAP_TAG_MRA_OID, + oid )) == -1 ) { + goto free_and_return; + } + } + if ( *str != '\0' ) { + if ( (rc = ber_printf( ber, "ts", + LDAP_TAG_MRA_TYPE, str )) == -1 ) { + goto free_and_return; + } + } + if (( len = unescape_filterval( value )) < 0 || + ( rc = ber_printf( ber, "totb}", LDAP_TAG_MRA_VALUE, + value, len, LDAP_TAG_MRA_DNATTRS, dnattr )) == -1 ) { + goto free_and_return; + } + rc = 0; + goto free_and_return; + break; + default: + if ( find_star( value ) == NULL ) { + ftype = LDAP_FILTER_EQUALITY; + } else if ( strcmp( value, "*" ) == 0 ) { + ftype = LDAP_FILTER_PRESENT; + } else { + rc = put_substring_filter( ber, str, value ); + goto free_and_return; + } + break; + } + + if ( ftype == LDAP_FILTER_PRESENT ) { + rc = ber_printf( ber, "ts", ftype, str ); + } else if (( len = unescape_filterval( value )) >= 0 ) { + rc = ber_printf( ber, "t{so}", ftype, str, value, len ); + } + if ( rc != -1 ) { + rc = 0; + } + +free_and_return: + NSLDAPI_FREE( str ); + return( rc ); +} + + +/* + * Undo in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape + * sequences within the null-terminated string 'val'. The resulting value + * may contain null characters. + * + * If 'val' contains invalid escape sequences we return -1. + * Otherwise the length of the unescaped value is returned. + */ +static int +unescape_filterval( char *val ) +{ + int escape, firstdigit, ival; + char *s, *d; + + escape = firstdigit = 0; + for ( s = d = val; *s; s++ ) { + if ( escape ) { + /* + * first try LDAPv3 escape (hexadecimal) sequence + */ + if (( ival = hexchar2int( *s )) < 0 ) { + if ( firstdigit ) { + /* + * LDAPv2 (RFC1960) escape sequence + */ + *d++ = *s; + escape = 0; + } else { + return(-1); + } + } + if ( firstdigit ) { + *d = ( ival<<4 ); + firstdigit = 0; + } else { + *d++ |= ival; + escape = 0; + } + + } else if ( *s != '\\' ) { + *d++ = *s; + escape = 0; + + } else { + escape = 1; + firstdigit = 1; + } + } + + return( d - val ); +} + + +/* + * convert character 'c' that represents a hexadecimal digit to an integer. + * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned. + * otherwise the converted value is returned. + */ +static int +hexchar2int( char c ) +{ + if ( c >= '0' && c <= '9' ) { + return( c - '0' ); + } + if ( c >= 'A' && c <= 'F' ) { + return( c - 'A' + 10 ); + } + if ( c >= 'a' && c <= 'f' ) { + return( c - 'a' + 10 ); + } + return( -1 ); +} + +static int +put_substring_filter( BerElement *ber, char *type, char *val ) +{ + char *nextstar, gotstar = 0; + unsigned long ftype; + int len; + + LDAPDebug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type, + val, 0 ); + + if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 ) { + return( -1 ); + } + + for ( ; val != NULL; val = nextstar ) { + if ( (nextstar = find_star( val )) != NULL ) { + *nextstar++ = '\0'; + } + + if ( gotstar == 0 ) { + ftype = LDAP_SUBSTRING_INITIAL; + } else if ( nextstar == NULL ) { + ftype = LDAP_SUBSTRING_FINAL; + } else { + ftype = LDAP_SUBSTRING_ANY; + } + if ( *val != '\0' ) { + if (( len = unescape_filterval( val )) < 0 || + ber_printf( ber, "to", ftype, val, len ) == -1 ) { + return( -1 ); + } + } + + gotstar = 1; + } + + if ( ber_printf( ber, "}}" ) == -1 ) { + return( -1 ); + } + + return( 0 ); +} + +int +LDAP_CALL +ldap_search_st( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + struct timeval *timeout, + LDAPMessage **res +) +{ + return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, + NULL, NULL, timeout, -1, -1, res )); +} + +int +LDAP_CALL +ldap_search_s( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res +) +{ + return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, + NULL, NULL, NULL, -1, -1, res )); +} + +int LDAP_CALL +ldap_search_ext_s( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct timeval *timeoutp, + int sizelimit, + LDAPMessage **res +) +{ + return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, + serverctrls, clientctrls, timeoutp, + nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, res )); +} + + +static int +nsldapi_search_s( + LDAP *ld, + const char *base, + int scope, + const char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct timeval *localtimeoutp, + int timelimit, /* -1 means use ld->ld_timelimit */ + int sizelimit, /* -1 means use ld->ld_sizelimit */ + LDAPMessage **res +) +{ + int err, msgid; + + /* + * It is an error to pass in a zero'd timeval. + */ + if ( localtimeoutp != NULL && localtimeoutp->tv_sec == 0 && + localtimeoutp->tv_usec == 0 ) { + if ( ld != NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + } + if ( res != NULL ) { + *res = NULL; + } + return( LDAP_PARAM_ERROR ); + } + + if (( err = nsldapi_search( ld, base, scope, filter, attrs, attrsonly, + serverctrls, clientctrls, timelimit, sizelimit, &msgid )) + != LDAP_SUCCESS ) { + if ( res != NULL ) { + *res = NULL; + } + return( err ); + } + + if ( ldap_result( ld, msgid, 1, localtimeoutp, res ) == -1 ) { + /* + * Error. ldap_result() sets *res to NULL for us. + */ + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { + (void) ldap_abandon( ld, msgid ); + err = LDAP_TIMEOUT; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + if ( res != NULL ) { + *res = NULL; + } + return( err ); + } + + return( ldap_result2error( ld, *res, 0 ) ); +} diff --git a/ldap/c-sdk/libldap/setoption.c b/ldap/c-sdk/libldap/setoption.c new file mode 100644 index 0000000000..5c4d753f5a --- /dev/null +++ b/ldap/c-sdk/libldap/setoption.c @@ -0,0 +1,411 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * setoption.c - ldap_set_option implementation + */ + +#include "ldap-int.h" + +#define LDAP_SETCLR_BITOPT( ld, bit, optdata ) \ + if ( optdata != NULL ) { \ + (ld)->ld_options |= bit; \ + } else { \ + (ld)->ld_options &= ~bit; \ + } + + +int +LDAP_CALL +ldap_set_option( LDAP *ld, int option, const void *optdata ) +{ + int rc, i; + char *matched, *errstr; + + /* + * if ld is NULL, arrange to modify our default settings + */ + if ( ld == NULL ) { + if ( !nsldapi_initialized ) { + nsldapi_initialize_defaults(); + } + ld = &nsldapi_ld_defaults; + } + + /* + * process global options (not associated with an LDAP session handle) + */ + if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) { + struct lber_memalloc_fns memalloc_fns; + + /* set libldap ones via a struct copy */ + nsldapi_memalloc_fns = *((struct ldap_memalloc_fns *)optdata); + + /* also set liblber memory allocation callbacks */ + memalloc_fns.lbermem_malloc = + nsldapi_memalloc_fns.ldapmem_malloc; + memalloc_fns.lbermem_calloc = + nsldapi_memalloc_fns.ldapmem_calloc; + memalloc_fns.lbermem_realloc = + nsldapi_memalloc_fns.ldapmem_realloc; + memalloc_fns.lbermem_free = + nsldapi_memalloc_fns.ldapmem_free; + if ( ber_set_option( NULL, LBER_OPT_MEMALLOC_FN_PTRS, + &memalloc_fns ) != 0 ) { + return( -1 ); + } + + return( 0 ); + } + /* + * LDAP_OPT_DEBUG_LEVEL is global + */ + if (LDAP_OPT_DEBUG_LEVEL == option) + { +#ifdef LDAP_DEBUG + ldap_debug = *((int *) optdata); +#endif + return 0; + } + + /* + * process options that are associated with an LDAP session handle + */ + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); /* punt */ + } + + rc = 0; + if ( ld != &nsldapi_ld_defaults + && option != LDAP_OPT_EXTRA_THREAD_FN_PTRS + && option != LDAP_OPT_THREAD_FN_PTRS ) { + LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); + } + switch( option ) { + /* options that can be turned on and off */ +#ifdef LDAP_DNS + case LDAP_OPT_DNS: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_DNS, optdata ); + break; +#endif + + case LDAP_OPT_REFERRALS: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_REFERRALS, optdata ); + break; + + case LDAP_OPT_SSL: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_SSL, optdata ); + break; + + case LDAP_OPT_RESTART: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_RESTART, optdata ); + break; + + case LDAP_OPT_RECONNECT: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_RECONNECT, optdata ); + break; + + case LDAP_OPT_NOREBIND: + LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_NOREBIND, optdata ); + break; + +#ifdef LDAP_ASYNC_IO + case LDAP_OPT_ASYNC_CONNECT: + LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_ASYNC, optdata ); + break; +#endif /* LDAP_ASYNC_IO */ + + /* fields in the LDAP structure */ + case LDAP_OPT_DEREF: + ld->ld_deref = *((int *) optdata); + break; + case LDAP_OPT_SIZELIMIT: + ld->ld_sizelimit = *((int *) optdata); + break; + case LDAP_OPT_TIMELIMIT: + ld->ld_timelimit = *((int *) optdata); + break; + case LDAP_OPT_REFERRAL_HOP_LIMIT: + ld->ld_refhoplimit = *((int *) optdata); + break; + case LDAP_OPT_PROTOCOL_VERSION: + ld->ld_version = *((int *) optdata); + if ( ld->ld_defconn != NULL ) { /* also set in default conn. */ + ld->ld_defconn->lconn_version = ld->ld_version; + } + break; + case LDAP_OPT_SERVER_CONTROLS: + /* nsldapi_dup_controls returns -1 and sets lderrno on error */ + rc = nsldapi_dup_controls( ld, &ld->ld_servercontrols, + (LDAPControl **)optdata ); + break; + case LDAP_OPT_CLIENT_CONTROLS: + /* nsldapi_dup_controls returns -1 and sets lderrno on error */ + rc = nsldapi_dup_controls( ld, &ld->ld_clientcontrols, + (LDAPControl **)optdata ); + break; + + /* rebind proc */ + case LDAP_OPT_REBIND_FN: + ld->ld_rebind_fn = (LDAP_REBINDPROC_CALLBACK *) optdata; + break; + case LDAP_OPT_REBIND_ARG: + ld->ld_rebind_arg = (void *) optdata; + break; + + /* i/o function pointers */ + case LDAP_OPT_IO_FN_PTRS: + if (( rc = nsldapi_install_compat_io_fns( ld, + (struct ldap_io_fns *)optdata )) != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + rc = -1; + } + break; + + /* extended i/o function pointers */ + case LDAP_X_OPT_EXTIO_FN_PTRS: + /* denotes use of old iofns struct (no writev) */ + if (((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) { + ld->ld_extio_size = LDAP_X_EXTIO_FNS_SIZE; + ld->ld_extclose_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close; + ld->ld_extconnect_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect; + ld->ld_extread_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read; + ld->ld_extwrite_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write; + ld->ld_extpoll_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll; + ld->ld_extnewhandle_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle; + ld->ld_extdisposehandle_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle; + ld->ld_ext_session_arg = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg; + ld->ld_extwritev_fn = NULL; + if ( ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, + &(ld->ld_ext_io_fns) ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + rc = -1; + break; + } + } + else { + /* struct copy */ + ld->ld_ext_io_fns = *((struct ldap_x_ext_io_fns *) optdata); + } + if (( rc = nsldapi_install_lber_extiofns( ld, ld->ld_sbp )) + != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + rc = -1; + } + break; + + /* set Socket Arg in extended socket i/o functions*/ + case LDAP_X_OPT_SOCKETARG: + if ( ber_sockbuf_set_option( ld->ld_sbp, + LBER_SOCKBUF_OPT_SOCK_ARG, (void *)optdata ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + rc = -1; + } + + break; + + /* thread function pointers */ + case LDAP_OPT_THREAD_FN_PTRS: + /* + * It is only safe to set the thread function pointers + * when one thread is using the LDAP session handle. + */ + /* free existing mutexes (some are allocated by ldap_init()) */ + nsldapi_mutex_free_all( ld ); + + /* struct copy */ + ld->ld_thread = *((struct ldap_thread_fns *) optdata); + + /* allocate new mutexes */ + nsldapi_mutex_alloc_all( ld ); + + /* LDAP_OPTION_LOCK was never locked... so just return */ + return (rc); + + /* extra thread function pointers */ + case LDAP_OPT_EXTRA_THREAD_FN_PTRS: + /* The extra thread funcs will only pick up the threadid */ + ld->ld_thread2 = *((struct ldap_extra_thread_fns *) optdata); + + /* Reset the rest of the structure preserving the threadid fn */ + ld->ld_mutex_trylock_fn = (LDAP_TF_MUTEX_TRYLOCK_CALLBACK *)NULL; + ld->ld_sema_alloc_fn = (LDAP_TF_SEMA_ALLOC_CALLBACK *) NULL; + ld->ld_sema_free_fn = (LDAP_TF_SEMA_FREE_CALLBACK *) NULL; + ld->ld_sema_wait_fn = (LDAP_TF_SEMA_WAIT_CALLBACK *) NULL; + ld->ld_sema_post_fn = (LDAP_TF_SEMA_POST_CALLBACK *) NULL; + + /* We assume that only one thread is active when replacing */ + /* the threadid function. We will now proceed and reset all */ + /* of the threadid/refcounts */ + for( i=0; ild_mutex_threadid[i] = (void *) -1; + ld->ld_mutex_refcnt[i] = 0; + } + + /* LDAP_OPTION_LOCK was never locked... so just return */ + return (rc); + + /* DNS function pointers */ + case LDAP_OPT_DNS_FN_PTRS: + /* struct copy */ + ld->ld_dnsfn = *((struct ldap_dns_fns *) optdata); + break; + + /* cache function pointers */ + case LDAP_OPT_CACHE_FN_PTRS: + /* struct copy */ + ld->ld_cache = *((struct ldap_cache_fns *) optdata); + break; + case LDAP_OPT_CACHE_STRATEGY: + ld->ld_cache_strategy = *((int *) optdata); + break; + case LDAP_OPT_CACHE_ENABLE: + ld->ld_cache_on = *((int *) optdata); + break; + + case LDAP_OPT_ERROR_NUMBER: + LDAP_GET_LDERRNO( ld, &matched, &errstr ); + matched = nsldapi_strdup( matched ); + errstr = nsldapi_strdup( errstr ); + LDAP_SET_LDERRNO( ld, *((int *) optdata), matched, errstr ); + break; + + case LDAP_OPT_ERROR_STRING: + rc = LDAP_GET_LDERRNO( ld, &matched, NULL ); + matched = nsldapi_strdup( matched ); + LDAP_SET_LDERRNO( ld, rc, matched, + nsldapi_strdup((char *) optdata)); + rc = LDAP_SUCCESS; + break; + + case LDAP_OPT_MATCHED_DN: + rc = LDAP_GET_LDERRNO( ld, NULL, &errstr ); + errstr = nsldapi_strdup( errstr ); + LDAP_SET_LDERRNO( ld, rc, + nsldapi_strdup((char *) optdata), errstr ); + rc = LDAP_SUCCESS; + break; + + case LDAP_OPT_PREFERRED_LANGUAGE: + if ( NULL != ld->ld_preferred_language ) { + NSLDAPI_FREE(ld->ld_preferred_language); + } + ld->ld_preferred_language = nsldapi_strdup((char *) optdata); + break; + + case LDAP_OPT_HOST_NAME: + if ( NULL != ld->ld_defhost ) { + NSLDAPI_FREE(ld->ld_defhost); + } + ld->ld_defhost = nsldapi_strdup((char *) optdata); + break; + + case LDAP_X_OPT_CONNECT_TIMEOUT: + ld->ld_connect_timeout = *((int *) optdata); + break; + +#ifdef LDAP_SASLIO_HOOKS + /* SASL options */ + case LDAP_OPT_X_SASL_MECH: + NSLDAPI_FREE(ld->ld_def_sasl_mech); + ld->ld_def_sasl_mech = nsldapi_strdup((char *) optdata); + break; + case LDAP_OPT_X_SASL_REALM: + NSLDAPI_FREE(ld->ld_def_sasl_realm); + ld->ld_def_sasl_realm = nsldapi_strdup((char *) optdata); + break; + case LDAP_OPT_X_SASL_AUTHCID: + NSLDAPI_FREE(ld->ld_def_sasl_authcid); + ld->ld_def_sasl_authcid = nsldapi_strdup((char *) optdata); + break; + case LDAP_OPT_X_SASL_AUTHZID: + NSLDAPI_FREE(ld->ld_def_sasl_authzid); + ld->ld_def_sasl_authzid = nsldapi_strdup((char *) optdata); + break; + case LDAP_OPT_X_SASL_SSF_EXTERNAL: + { + int sc; + sasl_ssf_t extprops; + sasl_conn_t *ctx; + if( ld->ld_defconn == NULL ) { + return -1; + } + ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sasl_ctx); + if ( ctx == NULL ) { + return -1; + } + memset(&extprops, 0L, sizeof(extprops)); + extprops = * ((sasl_ssf_t *) optdata); + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); + if ( sc != SASL_OK ) { + return -1; + } + } + break; + case LDAP_OPT_X_SASL_SECPROPS: + { + int sc; + sc = nsldapi_sasl_secprops( (char *) optdata, + &ld->ld_sasl_secprops ); + return sc == LDAP_SUCCESS ? 0 : -1; + } + break; + case LDAP_OPT_X_SASL_SSF_MIN: + ld->ld_sasl_secprops.min_ssf = *((sasl_ssf_t *) optdata); + break; + case LDAP_OPT_X_SASL_SSF_MAX: + ld->ld_sasl_secprops.max_ssf = *((sasl_ssf_t *) optdata); + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + ld->ld_sasl_secprops.maxbufsize = *((sasl_ssf_t *) optdata); + break; + case LDAP_OPT_X_SASL_SSF: /* read only */ + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + rc = -1; + break; +#endif + + default: + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + rc = -1; + } + + if ( ld != &nsldapi_ld_defaults ) { + LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); + } + return( rc ); +} diff --git a/ldap/c-sdk/libldap/sort.c b/ldap/c-sdk/libldap/sort.c new file mode 100644 index 0000000000..8a716c818b --- /dev/null +++ b/ldap/c-sdk/libldap/sort.c @@ -0,0 +1,355 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1994 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. + */ +/* + * sort.c: LDAP library entry and value sort routines + */ + +#include "ldap-int.h" + +/* This xp_qsort fixes a memory problem (ABR) on Solaris for the client. + * Server is welcome to use it too, but I wasn't sure if it + * would be ok to use XP code here. -slamm + * + * We don't want to require use of libxp when linking with libldap, so + * I'll leave use of xp_qsort as a MOZILLA_CLIENT-only thing for now. --mcs + */ +#if defined(MOZILLA_CLIENT) && defined(SOLARIS) +#include "xp_qsort.h" +#else +#define XP_QSORT qsort +#endif + +typedef struct keycmp { + void *kc_arg; + LDAP_KEYCMP_CALLBACK *kc_cmp; +} keycmp_t; + +typedef struct keything { + keycmp_t *kt_cmp; + const struct berval *kt_key; + LDAPMessage *kt_msg; +} keything_t; + +static int LDAP_C LDAP_CALLBACK +ldapi_keycmp( const void *Lv, const void *Rv ) +{ + auto keything_t **L = (keything_t**)Lv; + auto keything_t **R = (keything_t**)Rv; + auto keycmp_t *cmp = (*L)->kt_cmp; + return cmp->kc_cmp( cmp->kc_arg, (*L)->kt_key, (*R)->kt_key ); +} + +int +LDAP_CALL +ldap_keysort_entries( + LDAP *ld, + LDAPMessage **chain, + void *arg, + LDAP_KEYGEN_CALLBACK *gen, + LDAP_KEYCMP_CALLBACK *cmp, + LDAP_KEYFREE_CALLBACK *fre) +{ + size_t count, i; + keycmp_t kc = {0}; + keything_t **kt; + LDAPMessage *e, *last; + LDAPMessage **ep; + int scount; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) + || chain == NULL || cmp == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + scount = ldap_count_entries( ld, *chain ); + + if (scount < 0) { /* error */ + return( LDAP_PARAM_ERROR ); + } + + count = scount; + + if (count < 2) { /* nothing to sort */ + return( 0 ); + } + + kt = (keything_t**)NSLDAPI_MALLOC( count * (sizeof(keything_t*) + sizeof(keything_t)) ); + if ( kt == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + for ( i = 0; i < count; i++ ) { + kt[i] = i + (keything_t*)(kt + count); + } + kc.kc_arg = arg; + kc.kc_cmp = cmp; + + for ( e = *chain, i = 0; i < count; i++, e = e->lm_chain ) { + kt[i]->kt_msg = e; + kt[i]->kt_cmp = &kc; + kt[i]->kt_key = gen( arg, ld, e ); + if ( kt[i]->kt_key == NULL ) { + if ( fre ) while ( i-- > 0 ) fre( arg, kt[i]->kt_key ); + NSLDAPI_FREE( (char*)kt ); + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + } + last = e; + + XP_QSORT( (void*)kt, count, (size_t)sizeof(keything_t*), ldapi_keycmp ); + + ep = chain; + for ( i = 0; i < count; i++ ) { + *ep = kt[i]->kt_msg; + ep = &(*ep)->lm_chain; + if ( fre ) fre( arg, kt[i]->kt_key ); + } + *ep = last; + NSLDAPI_FREE( (char*)kt ); + return( 0 ); +} + + +struct entrything { + char **et_vals; + LDAPMessage *et_msg; +}; + +typedef int (LDAP_C LDAP_CALLBACK LDAP_CHARCMP_CALLBACK)(char*, char*); +typedef int (LDAP_C LDAP_CALLBACK LDAP_VOIDCMP_CALLBACK)(const void*, + const void*); + +static LDAP_CHARCMP_CALLBACK *et_cmp_fn; +static LDAP_VOIDCMP_CALLBACK et_cmp; + +int +LDAP_C +LDAP_CALLBACK +ldap_sort_strcasecmp( + const char **a, + const char **b +) +{ + /* XXXceb + * I am not 100% sure this is the way this should be handled. + * For now we will return a 0 on invalid. + */ + if (NULL == a || NULL == b) + return (0); + return( strcasecmp( (char *)*a, (char *)*b ) ); +} + +static int +LDAP_C +LDAP_CALLBACK +et_cmp( + const void *aa, + const void *bb +) +{ + int i, rc; + struct entrything *a = (struct entrything *)aa; + struct entrything *b = (struct entrything *)bb; + + if ( a->et_vals == NULL && b->et_vals == NULL ) + return( 0 ); + if ( a->et_vals == NULL ) + return( -1 ); + if ( b->et_vals == NULL ) + return( 1 ); + + for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) { + if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] )) + != 0 ) { + return( rc ); + } + } + + if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL ) + return( 0 ); + if ( a->et_vals[i] == NULL ) + return( -1 ); + return( 1 ); +} + +int +LDAP_CALL +ldap_multisort_entries( + LDAP *ld, + LDAPMessage **chain, + char **attr, /* NULL => sort by DN */ + LDAP_CMP_CALLBACK *cmp +) +{ + int i, count; + struct entrything *et; + LDAPMessage *e, *last; + LDAPMessage **ep; + int scount; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) + || chain == NULL || cmp == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + scount = ldap_count_entries( ld, *chain ); + + if (scount < 0) { /* error, usually with bad ld or malloc */ + return( LDAP_PARAM_ERROR ); + } + + count = scount; + + if (count < 2) { /* nothing to sort */ + return( 0 ); + } + + if ( (et = (struct entrything *)NSLDAPI_MALLOC( count * + sizeof(struct entrything) )) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + + e = *chain; + for ( i = 0; i < count; i++ ) { + et[i].et_msg = e; + et[i].et_vals = NULL; + if ( attr == NULL ) { + char *dn; + + dn = ldap_get_dn( ld, e ); + et[i].et_vals = ldap_explode_dn( dn, 1 ); + NSLDAPI_FREE( dn ); + } else { + int attrcnt; + char **vals; + + for ( attrcnt = 0; attr[attrcnt] != NULL; attrcnt++ ) { + vals = ldap_get_values( ld, e, attr[attrcnt] ); + if ( ldap_charray_merge( &(et[i].et_vals), vals ) + != 0 ) { + int j; + + /* XXX risky: ldap_value_free( vals ); */ + for ( j = 0; j <= i; j++ ) + ldap_value_free( et[j].et_vals ); + NSLDAPI_FREE( (char *) et ); + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, + NULL ); + return( -1 ); + } + if ( vals != NULL ) { + NSLDAPI_FREE( (char *)vals ); + } + } + } + + e = e->lm_chain; + } + last = e; + + et_cmp_fn = (LDAP_CHARCMP_CALLBACK *)cmp; + XP_QSORT( (void *) et, (size_t) count, + (size_t) sizeof(struct entrything), et_cmp ); + + ep = chain; + for ( i = 0; i < count; i++ ) { + *ep = et[i].et_msg; + ep = &(*ep)->lm_chain; + + ldap_value_free( et[i].et_vals ); + } + *ep = last; + NSLDAPI_FREE( (char *) et ); + + return( 0 ); +} + +int +LDAP_CALL +ldap_sort_entries( + LDAP *ld, + LDAPMessage **chain, + char *attr, /* NULL => sort by DN */ + LDAP_CMP_CALLBACK *cmp +) +{ + char *attrs[2]; + + attrs[0] = attr; + attrs[1] = NULL; + return( ldap_multisort_entries( ld, chain, attr ? attrs : NULL, cmp ) ); +} + +int +LDAP_CALL +ldap_sort_values( + LDAP *ld, + char **vals, + LDAP_VALCMP_CALLBACK *cmp +) +{ + int nel; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || cmp == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + if ( NULL == vals) + { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + for ( nel = 0; vals[nel] != NULL; nel++ ) + ; /* NULL */ + + XP_QSORT( vals, nel, sizeof(char *), (LDAP_VOIDCMP_CALLBACK *)cmp ); + + return( LDAP_SUCCESS ); +} diff --git a/ldap/c-sdk/libldap/sortctrl.c b/ldap/c-sdk/libldap/sortctrl.c new file mode 100644 index 0000000000..585e2fd3fa --- /dev/null +++ b/ldap/c-sdk/libldap/sortctrl.c @@ -0,0 +1,438 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "ldap-int.h" + +/* ldap_create_sort_control: + + Parameters are + + ld LDAP pointer to the desired connection + + sortKeyList an array of sortkeys + + ctl_iscritical Indicates whether the control is critical of not. If + this field is non-zero, the operation will only be car- + ried out if the control is recognized by the server + and/or client + + ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_sort_control ( + LDAP *ld, + LDAPsortkey **sortKeyList, + const char ctl_iscritical, + LDAPControl **ctrlp +) +{ + BerElement *ber; + int i, rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( sortKeyList == NULL || ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + /* create a ber package to hold the controlValue */ + if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* encode the start of the sequence of sequences into the ber */ + if ( ber_printf( ber, "{" ) == -1 ) { + goto encoding_error_exit; + } + + /* the sort control value will be encoded as a sequence of sequences + which are each encoded as one of the following: {s} or {sts} or {stb} or {ststb} + since the orderingRule and reverseOrder flag are both optional */ + for ( i = 0; sortKeyList[i] != NULL; i++ ) { + + /* encode the attributeType into the ber */ + if ( ber_printf( ber, "{s", (sortKeyList[i])->sk_attrtype ) + == -1 ) { + goto encoding_error_exit; + } + + /* encode the optional orderingRule into the ber */ + if ( (sortKeyList[i])->sk_matchruleoid != NULL ) { + if ( ber_printf( ber, "ts", LDAP_TAG_SK_MATCHRULE, + (sortKeyList[i])->sk_matchruleoid ) + == -1 ) { + goto encoding_error_exit; + } + } + + /* Encode the optional reverseOrder flag into the ber. */ + /* If the flag is false, it should be absent. */ + if ( (sortKeyList[i])->sk_reverseorder ) { + if ( ber_printf( ber, "tb}", LDAP_TAG_SK_REVERSE, + (sortKeyList[i])->sk_reverseorder ) == -1 ) { + goto encoding_error_exit; + } + } else { + if ( ber_printf( ber, "}" ) == -1 ) { + goto encoding_error_exit; + } + } + } + + /* encode the end of the sequence of sequences into the ber */ + if ( ber_printf( ber, "}" ) == -1 ) { + goto encoding_error_exit; + } + + rc = nsldapi_build_control( LDAP_CONTROL_SORTREQUEST, ber, 1, + ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + +encoding_error_exit: + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); +} + +/* ldap_parse_sort_control: + + Parameters are + + ld LDAP pointer to the desired connection + + ctrlp An array of controls obtained from calling + ldap_parse_result on the set of results returned by + the server + + result the address of a place to put the result code + + attribute the address of a place to put the name of the + attribute which cause the operation to fail, optionally + returned by the server */ + +int +LDAP_CALL +ldap_parse_sort_control ( + LDAP *ld, + LDAPControl **ctrlp, + ber_int_t *result, + char **attribute +) +{ + BerElement *ber; + int i, foundSortControl; + LDAPControl *sortCtrlp; + ber_len_t len; + ber_tag_t tag; + char *attr; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || result == NULL || + attribute == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + + /* find the sortControl in the list of controls if it exists */ + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + foundSortControl = 0; + for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundSortControl )); i++ ) { + foundSortControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_SORTRESPONSE ); + } + if ( !foundSortControl ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } else { + /* let local var point to the sortControl */ + sortCtrlp = ctrlp[i-1]; + } + + /* allocate a Ber element with the contents of the sort_control's struct berval */ + if ( ( ber = ber_init( &sortCtrlp->ldctl_value ) ) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* decode the result from the Berelement */ + if ( ber_scanf( ber, "{i", result ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + + /* if the server returned one, decode the attribute from the Ber element */ + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SR_ATTRTYPE ) { + if ( ber_scanf( ber, "ta", &tag, &attr ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + *attribute = attr; + } else { + *attribute = NULL; + } + + if ( ber_scanf( ber, "}" ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + + /* the ber encoding is no longer needed */ + ber_free(ber,1); + + return( LDAP_SUCCESS ); +} + +/* Routines for the manipulation of string-representations of sort control keylists */ + +static int count_tokens(const char *s) +{ + int count = 0; + const char *p = s; + int whitespace = 1; + /* Loop along the string counting the number of times we see the + * beginning of non-whitespace. This tells us + * the number of tokens in the string + */ + while (*p != '\0') { + if (whitespace) { + if (!isspace(*p)) { + whitespace = 0; + count++; + } + } else { + if (isspace(*p)) { + whitespace = 1; + } + } + p++; + } + return count; +} + + +static int read_next_token(const char **s,LDAPsortkey **key) +{ + char c = 0; + const char *pos = *s; + int retval = 0; + LDAPsortkey *new_key = NULL; + + const char *matchrule_source = NULL; + int matchrule_size = 0; + const char *attrdesc_source = NULL; + int attrdesc_size = 0; + int reverse = 0; + + int state = 0; + + while ( ((c = *pos++) != '\0') && (state != 4) ) { + switch (state) { + case 0: + /* case where we've not seen the beginning of the attr yet */ + /* If we still see whitespace, nothing to do */ + if (!isspace(c)) { + /* Otherwise, something to look at */ + /* Is it a minus sign ? */ + if ('-' == c) { + reverse = 1; + } else { + attrdesc_source = pos - 1; + state = 1; + } + } + break; + case 1: + /* case where we've seen the beginning of the attr, but not the end */ + /* Is this char either whitespace or a ';' ? */ + if ( isspace(c) || (':' == c)) { + attrdesc_size = (pos - attrdesc_source) - 1; + if (':' == c) { + state = 2; + } else { + state = 4; + } + } + break; + case 2: + /* case where we've seen the end of the attr and want the beginning of match rule */ + if (!isspace(c)) { + matchrule_source = pos - 1; + state = 3; + } else { + state = 4; + } + break; + case 3: + /* case where we've seen the beginning of match rule and want to find the end */ + if (isspace(c)) { + matchrule_size = (pos - matchrule_source) - 1; + state = 4; + } + break; + default: + break; + } + } + + if (3 == state) { + /* means we fell off the end of the string looking for the end of the marching rule */ + matchrule_size = (pos - matchrule_source) - 1; + } + + if (1 == state) { + /* means we fell of the end of the string looking for the end of the attribute */ + attrdesc_size = (pos - attrdesc_source) - 1; + } + + if (NULL == attrdesc_source) { + /* Didn't find anything */ + return -1; + } + + new_key = (LDAPsortkey*)NSLDAPI_MALLOC(sizeof(LDAPsortkey)); + if (0 == new_key) { + return LDAP_NO_MEMORY; + } + + /* Allocate the strings */ + new_key->sk_attrtype = (char *)NSLDAPI_MALLOC(attrdesc_size + 1); + if (NULL != matchrule_source) { + new_key->sk_matchruleoid = (char *)NSLDAPI_MALLOC( + matchrule_size + 1); + } else { + new_key->sk_matchruleoid = NULL; + } + /* Copy over the strings */ + memcpy(new_key->sk_attrtype,attrdesc_source,attrdesc_size); + *(new_key->sk_attrtype + attrdesc_size) = '\0'; + if (NULL != matchrule_source) { + memcpy(new_key->sk_matchruleoid,matchrule_source,matchrule_size); + *(new_key->sk_matchruleoid + matchrule_size) = '\0'; + } + + new_key->sk_reverseorder = reverse; + + *s = pos - 1; + *key = new_key; + return retval; +} + +int +LDAP_CALL +ldap_create_sort_keylist ( + LDAPsortkey ***sortKeyList, + const char *string_rep +) +{ + int count = 0; + LDAPsortkey **pointer_array = NULL; + const char *current_position = NULL; + int retval = 0; + int i = 0; + + /* Figure out how many there are */ + if (NULL == string_rep) { + return LDAP_PARAM_ERROR; + } + if (NULL == sortKeyList) { + return LDAP_PARAM_ERROR; + } + count = count_tokens(string_rep); + if (0 == count) { + *sortKeyList = NULL; + return LDAP_PARAM_ERROR; + } + /* Allocate enough memory for the pointers */ + pointer_array = (LDAPsortkey**)NSLDAPI_MALLOC(sizeof(LDAPsortkey*) + * (count + 1) ); + if (NULL == pointer_array) { + return LDAP_NO_MEMORY; + } + /* Now walk along the string, allocating and filling in the LDAPsearchkey structure */ + current_position = string_rep; + + for (i = 0; i < count; i++) { + if (0 != (retval = read_next_token(¤t_position,&(pointer_array[i])))) { + pointer_array[count] = NULL; + ldap_free_sort_keylist(pointer_array); + *sortKeyList = NULL; + return retval; + } + } + pointer_array[count] = NULL; + *sortKeyList = pointer_array; + return LDAP_SUCCESS; +} + +void +LDAP_CALL +ldap_free_sort_keylist ( + LDAPsortkey **sortKeyList +) +{ + LDAPsortkey *this_one = NULL; + int i = 0; + + if ( NULL == sortKeyList ) { + return; + } + + /* Walk down the list freeing the LDAPsortkey structures */ + for (this_one = sortKeyList[0]; this_one ; this_one = sortKeyList[++i]) { + /* Free the strings, if present */ + if (NULL != this_one->sk_attrtype) { + NSLDAPI_FREE(this_one->sk_attrtype); + } + if (NULL != this_one->sk_matchruleoid) { + NSLDAPI_FREE(this_one->sk_matchruleoid); + } + NSLDAPI_FREE(this_one); + } + /* Free the pointer list */ + NSLDAPI_FREE(sortKeyList); +} diff --git a/ldap/c-sdk/libldap/srchpref.c b/ldap/c-sdk/libldap/srchpref.c new file mode 100644 index 0000000000..a3025afd39 --- /dev/null +++ b/ldap/c-sdk/libldap/srchpref.c @@ -0,0 +1,434 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1993, 1994 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. + * + */ +/* + * searchpref.c: search preferences library routines for LDAP clients + */ + +#include "ldap-int.h" +#include "srchpref.h" + +static void free_searchobj( struct ldap_searchobj *so ); +static int read_next_searchobj( char **bufp, long *blenp, + struct ldap_searchobj **sop, int soversion ); + + +static char *sobjoptions[] = { + "internal", + NULL +}; + + +static unsigned long sobjoptvals[] = { + LDAP_SEARCHOBJ_OPT_INTERNAL, +}; + + +int +LDAP_CALL +ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp ) +{ + FILE *fp; + char *buf; + long rlen, len; + int rc, eof; + + if (( fp = NSLDAPI_FOPEN( file, "r" )) == NULL ) { + return( LDAP_SEARCHPREF_ERR_FILE ); + } + + if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ + fclose( fp ); + return( LDAP_SEARCHPREF_ERR_FILE ); + } + + len = ftell( fp ); + + if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ + fclose( fp ); + return( LDAP_SEARCHPREF_ERR_FILE ); + } + + if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { + fclose( fp ); + return( LDAP_SEARCHPREF_ERR_MEM ); + } + + rlen = fread( buf, 1, (size_t)len, fp ); + eof = feof( fp ); + fclose( fp ); + + if ( rlen != len && !eof ) { /* error: didn't get the whole file */ + NSLDAPI_FREE( buf ); + return( LDAP_SEARCHPREF_ERR_FILE ); + } + + rc = ldap_init_searchprefs_buf( buf, rlen, solistp ); + NSLDAPI_FREE( buf ); + + return( rc ); +} + + +int +LDAP_CALL +ldap_init_searchprefs_buf( char *buf, long buflen, + struct ldap_searchobj **solistp ) +{ + int rc = 0, version; + char **toks; + struct ldap_searchobj *prevso, *so; + + *solistp = prevso = NULLSEARCHOBJ; + + if ( nsldapi_next_line_tokens( &buf, &buflen, &toks ) != 2 || + strcasecmp( toks[ 0 ], "version" ) != 0 ) { + nsldapi_free_strarray( toks ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + version = atoi( toks[ 1 ] ); + nsldapi_free_strarray( toks ); + if ( version != LDAP_SEARCHPREF_VERSION && + version != LDAP_SEARCHPREF_VERSION_ZERO ) { + return( LDAP_SEARCHPREF_ERR_VERSION ); + } + + while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so, + version )) == 0 && so != NULLSEARCHOBJ ) { + if ( prevso == NULLSEARCHOBJ ) { + *solistp = so; + } else { + prevso->so_next = so; + } + prevso = so; + } + + if ( rc != 0 ) { + ldap_free_searchprefs( *solistp ); + } + + return( rc ); +} + + + +void +LDAP_CALL +ldap_free_searchprefs( struct ldap_searchobj *solist ) +{ + struct ldap_searchobj *so, *nextso; + + if ( solist != NULL ) { + for ( so = solist; so != NULL; so = nextso ) { + nextso = so->so_next; + free_searchobj( so ); + } + } + /* XXX XXX need to do some work here */ +} + + +static void +free_searchobj( struct ldap_searchobj *so ) +{ + if ( so != NULL ) { + if ( so->so_objtypeprompt != NULL ) { + NSLDAPI_FREE( so->so_objtypeprompt ); + } + if ( so->so_prompt != NULL ) { + NSLDAPI_FREE( so->so_prompt ); + } + if ( so->so_filterprefix != NULL ) { + NSLDAPI_FREE( so->so_filterprefix ); + } + if ( so->so_filtertag != NULL ) { + NSLDAPI_FREE( so->so_filtertag ); + } + if ( so->so_defaultselectattr != NULL ) { + NSLDAPI_FREE( so->so_defaultselectattr ); + } + if ( so->so_defaultselecttext != NULL ) { + NSLDAPI_FREE( so->so_defaultselecttext ); + } + if ( so->so_salist != NULL ) { + struct ldap_searchattr *sa, *nextsa; + for ( sa = so->so_salist; sa != NULL; sa = nextsa ) { + nextsa = sa->sa_next; + if ( sa->sa_attrlabel != NULL ) { + NSLDAPI_FREE( sa->sa_attrlabel ); + } + if ( sa->sa_attr != NULL ) { + NSLDAPI_FREE( sa->sa_attr ); + } + if ( sa->sa_selectattr != NULL ) { + NSLDAPI_FREE( sa->sa_selectattr ); + } + if ( sa->sa_selecttext != NULL ) { + NSLDAPI_FREE( sa->sa_selecttext ); + } + NSLDAPI_FREE( sa ); + } + } + if ( so->so_smlist != NULL ) { + struct ldap_searchmatch *sm, *nextsm; + for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) { + nextsm = sm->sm_next; + if ( sm->sm_matchprompt != NULL ) { + NSLDAPI_FREE( sm->sm_matchprompt ); + } + if ( sm->sm_filter != NULL ) { + NSLDAPI_FREE( sm->sm_filter ); + } + NSLDAPI_FREE( sm ); + } + } + NSLDAPI_FREE( so ); + } +} + + + +struct ldap_searchobj * +LDAP_CALL +ldap_first_searchobj( struct ldap_searchobj *solist ) +{ + return( solist ); +} + + +struct ldap_searchobj * +LDAP_CALL +ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so ) +{ + return( so == NULLSEARCHOBJ ? so : so->so_next ); +} + + + +static int +read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop, + int soversion ) +{ + int i, j, tokcnt; + char **toks; + struct ldap_searchobj *so; + struct ldap_searchattr **sa; + struct ldap_searchmatch **sm; + + *sop = NULL; + + /* + * Object type prompt comes first + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX ); + } + + if (( so = (struct ldap_searchobj *)NSLDAPI_CALLOC( 1, + sizeof( struct ldap_searchobj ))) == NULL ) { + nsldapi_free_strarray( toks ); + return( LDAP_SEARCHPREF_ERR_MEM ); + } + so->so_objtypeprompt = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * if this is post-version zero, options come next + */ + if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) { + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) < 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + for ( i = 0; toks[ i ] != NULL; ++i ) { + for ( j = 0; sobjoptions[ j ] != NULL; ++j ) { + if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) { + so->so_options |= sobjoptvals[ j ]; + } + } + } + nsldapi_free_strarray( toks ); + } + + /* + * "Fewer choices" prompt is next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + so->so_prompt = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * Filter prefix for "More Choices" searching is next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + so->so_filterprefix = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * "Fewer Choices" filter tag comes next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + so->so_filtertag = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * Selection (disambiguation) attribute comes next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + so->so_defaultselectattr = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * Label for selection (disambiguation) attribute + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + so->so_defaultselecttext = toks[ 0 ]; + NSLDAPI_FREE( (char *)toks ); + + /* + * Search scope is next + */ + if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + if ( !strcasecmp(toks[ 0 ], "subtree" )) { + so->so_defaultscope = LDAP_SCOPE_SUBTREE; + } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) { + so->so_defaultscope = LDAP_SCOPE_ONELEVEL; + } else if ( !strcasecmp(toks[ 0 ], "base" )) { + so->so_defaultscope = LDAP_SCOPE_BASE; + } else { + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + nsldapi_free_strarray( toks ); + + + /* + * "More Choices" search option list comes next + */ + sa = &( so->so_salist ); + while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { + if ( tokcnt < 5 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + if (( *sa = ( struct ldap_searchattr * )NSLDAPI_CALLOC( 1, + sizeof( struct ldap_searchattr ))) == NULL ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_MEM ); + } + ( *sa )->sa_attrlabel = toks[ 0 ]; + ( *sa )->sa_attr = toks[ 1 ]; + ( *sa )->sa_selectattr = toks[ 3 ]; + ( *sa )->sa_selecttext = toks[ 4 ]; + /* Deal with bitmap */ + ( *sa )->sa_matchtypebitmap = 0; + for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) { + if ( toks[ 2 ][ i ] == '1' ) { + ( *sa )->sa_matchtypebitmap |= (1 << j); + } + } + NSLDAPI_FREE( toks[ 2 ] ); + NSLDAPI_FREE( ( char * ) toks ); + sa = &(( *sa )->sa_next); + } + *sa = NULL; + + /* + * Match types are last + */ + sm = &( so->so_smlist ); + while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { + if ( tokcnt < 2 ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_SYNTAX ); + } + if (( *sm = ( struct ldap_searchmatch * )NSLDAPI_CALLOC( 1, + sizeof( struct ldap_searchmatch ))) == NULL ) { + nsldapi_free_strarray( toks ); + ldap_free_searchprefs( so ); + return( LDAP_SEARCHPREF_ERR_MEM ); + } + ( *sm )->sm_matchprompt = toks[ 0 ]; + ( *sm )->sm_filter = toks[ 1 ]; + NSLDAPI_FREE( ( char * ) toks ); + sm = &(( *sm )->sm_next ); + } + *sm = NULL; + + *sop = so; + return( 0 ); +} diff --git a/ldap/c-sdk/libldap/test.c b/ldap/c-sdk/libldap/test.c new file mode 100644 index 0000000000..fa984f3430 --- /dev/null +++ b/ldap/c-sdk/libldap/test.c @@ -0,0 +1,1898 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* test.c - a simple test harness. */ +#include +#include +#include +#include +#ifdef MACOS +#ifdef THINK_C +#include +#include +#include +#endif /* THINK_C */ +#include "macos.h" +#else /* MACOS */ +#if defined( DOS ) +#include "msdos.h" +#if defined( WINSOCK ) +#include "console.h" +#endif /* WINSOCK */ +#else /* DOS */ +#ifdef _WINDOWS +#include +#include +#include +#include +//#include "console.h" +#else /* _WINDOWS */ +#include +#include +#include +#include +#include +#ifndef VMS +#include +#include +#endif /* VMS */ +#endif /* _WINDOWS */ +#endif /* DOS */ +#endif /* MACOS */ + +#include "ldap.h" +#include "disptmpl.h" +#include "ldaplog.h" +#include "portable.h" +#ifndef NO_LIBLCACHE +#include "lcache.h" +#endif /* !NO_LIBLCACHE */ + +#undef NET_SSL +#if defined(NET_SSL) +#include +#include +#endif + + +#if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS ) +#define MOD_USE_BVALS +#endif /* !PCNFS && !WINSOCK && !MACOS */ + +static void handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ); +static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ); +static void print_controls( LDAPControl **ctrls, int freeit ); +static void print_referrals( char **refs, int freeit ); +static void print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ); +static char *changetype_num2string( ber_int_t chgtype ); +static void print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ); +static void free_list( char **list ); +static int entry2textwrite( void *fp, char *buf, int len ); +static void bprint( char *data, int len ); +static char **string2words( char *str, char *delims ); +static const char * url_parse_err2string( int e ); + +char *dnsuffix; + +#ifndef WINSOCK +static char * +getline( char *line, int len, FILE *fp, char *prompt ) +{ + printf(prompt); + + if ( fgets( line, len, fp ) == NULL ) + return( NULL ); + + line[ strlen( line ) - 1 ] = '\0'; + + return( line ); +} +#endif /* WINSOCK */ + +static char ** +get_list( char *prompt ) +{ + static char buf[256]; + int num; + char **result; + + num = 0; + result = (char **) 0; + while ( 1 ) { + getline( buf, sizeof(buf), stdin, prompt ); + + if ( *buf == '\0' ) + break; + + if ( result == (char **) 0 ) + result = (char **) malloc( sizeof(char *) ); + else + result = (char **) realloc( result, + sizeof(char *) * (num + 1) ); + + result[num++] = (char *) strdup( buf ); + } + if ( result == (char **) 0 ) + return( NULL ); + result = (char **) realloc( result, sizeof(char *) * (num + 1) ); + result[num] = NULL; + + return( result ); +} + + +static void +free_list( char **list ) +{ + int i; + + if ( list != NULL ) { + for ( i = 0; list[ i ] != NULL; ++i ) { + free( list[ i ] ); + } + free( (char *)list ); + } +} + + +#ifdef MOD_USE_BVALS +static int +file_read( char *path, struct berval *bv ) +{ + FILE *fp; + long rlen; + int eof; + + if (( fp = NSLDAPI_FOPEN( path, "r" )) == NULL ) { + perror( path ); + return( -1 ); + } + + if ( fseek( fp, 0L, SEEK_END ) != 0 ) { + perror( path ); + fclose( fp ); + return( -1 ); + } + + bv->bv_len = ftell( fp ); + + if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) { + perror( "malloc" ); + fclose( fp ); + return( -1 ); + } + + if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { + perror( path ); + fclose( fp ); + return( -1 ); + } + + rlen = fread( bv->bv_val, 1, bv->bv_len, fp ); + eof = feof( fp ); + fclose( fp ); + + if ( (unsigned long)rlen != bv->bv_len ) { + perror( path ); + free( bv->bv_val ); + return( -1 ); + } + + return( bv->bv_len ); +} +#endif /* MOD_USE_BVALS */ + + +static LDAPMod ** +get_modlist( char *prompt1, char *prompt2, char *prompt3 ) +{ + static char buf[256]; + int num; + LDAPMod tmp; + LDAPMod **result; +#ifdef MOD_USE_BVALS + struct berval **bvals; +#endif /* MOD_USE_BVALS */ + + num = 0; + result = NULL; + while ( 1 ) { + if ( prompt1 ) { + getline( buf, sizeof(buf), stdin, prompt1 ); + tmp.mod_op = atoi( buf ); + + if ( tmp.mod_op == -1 || buf[0] == '\0' ) + break; + } else { + tmp.mod_op = 0; + } + + getline( buf, sizeof(buf), stdin, prompt2 ); + if ( buf[0] == '\0' ) + break; + tmp.mod_type = strdup( buf ); + + tmp.mod_values = get_list( prompt3 ); +#ifdef MOD_USE_BVALS + if ( tmp.mod_values != NULL ) { + int i; + + for ( i = 0; tmp.mod_values[i] != NULL; ++i ) + ; + bvals = (struct berval **)calloc( i + 1, + sizeof( struct berval *)); + for ( i = 0; tmp.mod_values[i] != NULL; ++i ) { + bvals[i] = (struct berval *)malloc( + sizeof( struct berval )); + if ( strncmp( tmp.mod_values[i], "{FILE}", + 6 ) == 0 ) { + if ( file_read( tmp.mod_values[i] + 6, + bvals[i] ) < 0 ) { + return( NULL ); + } + } else { + bvals[i]->bv_val = tmp.mod_values[i]; + bvals[i]->bv_len = + strlen( tmp.mod_values[i] ); + } + } + tmp.mod_bvalues = bvals; + tmp.mod_op |= LDAP_MOD_BVALUES; + } +#endif /* MOD_USE_BVALS */ + + if ( result == NULL ) + result = (LDAPMod **) malloc( sizeof(LDAPMod *) ); + else + result = (LDAPMod **) realloc( result, + sizeof(LDAPMod *) * (num + 1) ); + + result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) ); + *(result[num]) = tmp; /* struct copy */ + num++; + } + if ( result == NULL ) + return( NULL ); + result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); + result[num] = NULL; + + return( result ); +} + + +int LDAP_CALL LDAP_CALLBACK +bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp, + int freeit, void *dummy ) +{ + static char dn[256], passwd[256]; + + if ( !freeit ) { +#ifdef KERBEROS + 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; + } else { + *authmethodp |= 0x80; + } +#else /* KERBEROS */ + *authmethodp = LDAP_AUTH_SIMPLE; +#endif /* KERBEROS */ + + getline( dn, sizeof(dn), stdin, "re-bind dn? " ); + strcat( dn, dnsuffix ); + *dnp = dn; + + if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { + getline( passwd, sizeof(passwd), stdin, + "re-bind password? " ); + } else { + passwd[0] = '\0'; + } + *passwdp = passwd; + } + + return( LDAP_SUCCESS ); +} + + +#define HEX2BIN( h ) ( (h) >= '0' && (h) <='9' ? (h) - '0' : (h) - 'A' + 10 ) + +void +berval_from_hex( struct berval *bvp, char *hexstr ) +{ + char *src, *dst, c; + unsigned char abyte; + + dst = bvp->bv_val; + bvp->bv_len = 0; + src = hexstr; + while ( *src != '\0' ) { + c = *src; + if ( isupper( c )) { + c = tolower( c ); + } + abyte = HEX2BIN( c ) << 4; + + ++src; + c = *src; + if ( isupper( c )) { + c = tolower( c ); + } + abyte |= HEX2BIN( c ); + ++src; + + *dst++ = abyte; + ++bvp->bv_len; + } +} + + +static void +add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl ) +{ + int i; + + if ( *ctrlsp == NULL ) { + *ctrlsp = (LDAPControl **) calloc( 2, sizeof(LDAPControl *) ); + i = 0; + } else { + for ( i = 0; (*ctrlsp)[i] != NULL; i++ ) { + ; /* NULL */ + } + *ctrlsp = (LDAPControl **) realloc( *ctrlsp, + (i + 2) * sizeof(LDAPControl *) ); + } + (*ctrlsp)[i] = newctrl; + (*ctrlsp)[i+1] = NULL; +} + + +#ifdef TEST_CUSTOM_MALLOC + +typedef struct my_malloc_info { + long mmi_magic; + size_t mmi_actualsize; +} MyMallocInfo; +#define MY_MALLOC_MAGIC_NUMBER 0x19940618 + +#define MY_MALLOC_CHECK_MAGIC( p ) if ( ((MyMallocInfo *)( (p) - sizeof() + +void * +my_malloc( size_t size ) +{ + void *p; + MyMallocInfo *mmip; + + if (( p = malloc( size + sizeof( struct my_malloc_info ))) != NULL ) { + mmip = (MyMallocInfo *)p; + mmip->mmi_magic = MY_MALLOC_MAGIC_NUMBER; + mmip->mmi_actualsize = size; + } + + fprintf( stderr, "my_malloc: allocated ptr 0x%x, size %ld\n", + p, mmip->mmi_actualsize ); + + return( (char *)p + sizeof( MyMallocInfo )); +} + + +void * +my_calloc( size_t nelem, size_t elsize ) +{ + void *p; + + if (( p = my_malloc( nelem * elsize )) != NULL ) { + memset( p, 0, nelem * elsize ); + } + + return( p ); +} + + +void +my_free( void *ptr ) +{ + char *p; + MyMallocInfo *mmip; + + p = (char *)ptr; + p -= sizeof( MyMallocInfo ); + mmip = (MyMallocInfo *)p; + if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { + fprintf( stderr, + "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); + exit( 1 ); + } + + fprintf( stderr, "my_free: freeing ptr 0x%x, size %ld\n", + p, mmip->mmi_actualsize ); + + memset( p, 0, mmip->mmi_actualsize + sizeof( MyMallocInfo )); + free( p ); +} + + +void * +my_realloc( void *ptr, size_t size ) +{ + void *p; + MyMallocInfo *mmip; + + if ( ptr == NULL ) { + return( my_malloc( size )); + } + + mmip = (MyMallocInfo *)( (char *)ptr - sizeof( MyMallocInfo )); + if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { + fprintf( stderr, + "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); + exit( 1 ); + } + + if ( size <= mmip->mmi_actualsize ) { /* current block big enough? */ + return( ptr ); + } + + if (( p = my_malloc( size )) != NULL ) { + memcpy( p, ptr, mmip->mmi_actualsize ); + my_free( ptr ); + } + + return( p ); +} +#endif /* TEST_CUSTOM_MALLOC */ + +int +#ifdef WINSOCK +ldapmain( +#else /* WINSOCK */ +main( +#endif /* WINSOCK */ + int argc, char **argv ) +{ + LDAP *ld; + int rc, i, c, port, cldapflg, errflg, method, id, msgtype; + int version; + char line[256], command1, command2, command3; + char passwd[64], dn[256], rdn[64], attr[64], value[256]; + char filter[256], *host, **types; + char **exdn, *fnname; + int bound, all, scope, attrsonly, optval, ldapversion; + LDAPMessage *res; + LDAPMod **mods, **attrs; + struct timeval timeout, *tvp; + char *copyfname = NULL; + int copyoptions = 0; + LDAPURLDesc *ludp; + struct ldap_disptmpl *tmpllist = NULL; + int changetypes, changesonly, return_echg_ctls; + LDAPControl **tmpctrls, *newctrl, **controls = NULL; + char *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file] [-V protocolversion]\n"; + + extern char *optarg; + extern int optind; + +#ifdef MACOS + if (( argv = get_list( "cmd line arg?" )) == NULL ) { + exit( 1 ); + } + for ( argc = 0; argv[ argc ] != NULL; ++argc ) { + ; + } +#endif /* MACOS */ + +#ifdef TEST_CUSTOM_MALLOC + { + struct ldap_memalloc_fns memalloc_fns; + + memalloc_fns.ldapmem_malloc = my_malloc; + memalloc_fns.ldapmem_calloc = my_calloc; + memalloc_fns.ldapmem_realloc = my_realloc; + memalloc_fns.ldapmem_free = my_free; + + if ( ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, + &memalloc_fns ) != 0 ) { + fputs( "ldap_set_option failed\n", stderr ); + exit( 1 ); + } + } +#endif /* TEST_CUSTOM_MALLOC */ + + host = NULL; + port = LDAP_PORT; + dnsuffix = ""; + cldapflg = errflg = 0; + ldapversion = 0; /* use default */ +#ifndef _WIN32 +#ifdef LDAP_DEBUG + ldap_debug = LDAP_DEBUG_ANY; +#endif +#endif + + while (( c = getopt( argc, argv, "uh:d:s:p:t:T:V:" )) != -1 ) { + switch( c ) { + case 'u': +#ifdef CLDAP + cldapflg++; +#else /* CLDAP */ + printf( "Compile with -DCLDAP for UDP support\n" ); +#endif /* CLDAP */ + break; + + case 'd': +#ifndef _WIN32 +#ifdef LDAP_DEBUG + ldap_debug = atoi( optarg ) | LDAP_DEBUG_ANY; + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { + ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, + &ldap_debug ); + } +#else + printf( "Compile with -DLDAP_DEBUG for debugging\n" ); +#endif +#endif + break; + + case 'h': + host = optarg; + break; + + case 's': + dnsuffix = optarg; + break; + + case 'p': + port = atoi( optarg ); + break; + +#if !defined(MACOS) && !defined(DOS) + case 't': /* copy ber's to given file */ + copyfname = strdup( optarg ); + copyoptions = LBER_SOCKBUF_OPT_TO_FILE; + break; + + case 'T': /* only output ber's to given file */ + copyfname = strdup( optarg ); + copyoptions = (LBER_SOCKBUF_OPT_TO_FILE | + LBER_SOCKBUF_OPT_TO_FILE_ONLY); + break; +#endif + case 'V': /* LDAP protocol version */ + ldapversion = atoi( optarg ); + break; + + default: + ++errflg; + } + } + + if ( host == NULL && optind == argc - 1 ) { + host = argv[ optind ]; + ++optind; + } + + if ( errflg || optind < argc - 1 ) { + fprintf( stderr, usage, argv[ 0 ] ); + exit( 1 ); + } + + printf( "%sldap_init( %s, %d )\n", cldapflg ? "c" : "", + host == NULL ? "(null)" : host, port ); + + if ( cldapflg ) { +#ifdef CLDAP + ld = cldap_open( host, port ); +#endif /* CLDAP */ + } else { + ld = ldap_init( host, port ); + } + + if ( ld == NULL ) { + perror( "ldap_init" ); + exit(1); + } + + if ( ldapversion != 0 && ldap_set_option( ld, + LDAP_OPT_PROTOCOL_VERSION, (void *)&ldapversion ) != 0 ) { + ldap_perror( ld, "ldap_set_option (protocol version)" ); + exit(1); + } + +#ifdef notdef +#if !defined(MACOS) && !defined(DOS) + if ( copyfname != NULL ) { + int fd; + Sockbuf *sb; + + if ( (fd = open( copyfname, O_WRONLY | O_CREAT, 0600 )) + == -1 ) { + perror( copyfname ); + exit ( 1 ); + } + ldap_get_option( ld, LDAP_OPT_SOCKBUF, &sb ); + ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_COPYDESC, + (void *) &fd ); + ber_sockbuf_set_option( sb, copyoptions, LBER_OPT_ON ); + } +#endif +#endif + + bound = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + tvp = &timeout; + + (void) memset( line, '\0', sizeof(line) ); + while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) { + command1 = line[0]; + command2 = line[1]; + command3 = line[2]; + + switch ( command1 ) { + case 'a': /* add or abandon */ + switch ( command2 ) { + case 'd': /* add */ + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + if ( (attrs = get_modlist( NULL, "attr? ", + "value? " )) == NULL ) + break; + if ( (id = ldap_add( ld, dn, attrs )) == -1 ) + ldap_perror( ld, "ldap_add" ); + else + printf( "Add initiated with id %d\n", + id ); + break; + + case 'b': /* abandon */ + getline( line, sizeof(line), stdin, "msgid? " ); + id = atoi( line ); + if ( ldap_abandon( ld, id ) != 0 ) + ldap_perror( ld, "ldap_abandon" ); + else + printf( "Abandon successful\n" ); + break; + default: + printf( "Possibilities: [ad]d, [ab]ort\n" ); + } + break; + + case 'v': /* ldap protocol version */ + getline( line, sizeof(line), stdin, + "ldap version? " ); + version = atoi( line ); + if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, + (void *) &version ) != 0 ) { + ldap_perror( ld, "ldap_set_option" ); + } + break; + + case 'b': /* asynch bind */ + getline( line, sizeof(line), stdin, + "method 0->simple 3->sasl? " ); + method = atoi( line ); + if ( method == 0 ) { + method = LDAP_AUTH_SIMPLE; + } else if ( method == 3 ) { + method = LDAP_AUTH_SASL; + } + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + + if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { + } else { + passwd[0] = '\0'; + } + + if ( method == LDAP_AUTH_SIMPLE ) { + if ( dn[0] != '\0' ) { + getline( passwd, sizeof(passwd), stdin, + "password? " ); + } else { + passwd[0] = '\0'; + } + rc = ldap_simple_bind( ld, dn, passwd ); + } else { + struct berval cred; + char mechanism[BUFSIZ]; + + getline( mechanism, sizeof(mechanism), stdin, + "mechanism? " ); + getline( passwd, sizeof(passwd), stdin, + "credentials? " ); + cred.bv_val = passwd; + cred.bv_len = strlen( passwd ); + if ( ldap_sasl_bind( ld, dn, mechanism, &cred, + NULL, NULL, &rc ) != LDAP_SUCCESS ) { + rc = -1; + } + } + if ( rc == -1 ) { + fprintf( stderr, "ldap_bind failed\n" ); + ldap_perror( ld, "ldap_bind" ); + } else { + printf( "Bind initiated\n" ); + bound = 1; + } + break; + + case 'B': /* synch bind */ + getline( line, sizeof(line), stdin, + "method 0->simple 3->sasl? " ); + method = atoi( line ); + if ( method == 0 ) { + method = LDAP_AUTH_SIMPLE; + } else if ( method == 3 ) { + method = LDAP_AUTH_SASL; + } + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + + if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { + } else { + passwd[0] = '\0'; + } + + if ( method == LDAP_AUTH_SIMPLE ) { + if ( dn[0] != '\0' ) { + getline( passwd, sizeof(passwd), stdin, + "password? " ); + } else { + passwd[0] = '\0'; + } + rc = ldap_simple_bind_s( ld, dn, passwd ); + fnname = "ldap_simple_bind_s"; + } else { + struct berval cred; + char mechanism[BUFSIZ]; + + getline( mechanism, sizeof(mechanism), stdin, + "mechanism? " ); + getline( passwd, sizeof(passwd), stdin, + "credentials? " ); + cred.bv_val = passwd; + cred.bv_len = strlen( passwd ); + rc = ldap_sasl_bind_s( ld, dn, mechanism, + &cred, NULL, NULL, NULL ); + fnname = "ldap_sasl_bind_s"; + } + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s failed\n", fnname ); + ldap_perror( ld, fnname ); + } else { + printf( "Bind successful\n" ); + bound = 1; + } + break; + + case 'c': /* compare */ + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + getline( attr, sizeof(attr), stdin, "attr? " ); + getline( value, sizeof(value), stdin, "value? " ); + + if ( (id = ldap_compare( ld, dn, attr, value )) == -1 ) + ldap_perror( ld, "ldap_compare" ); + else + printf( "Compare initiated with id %d\n", id ); + break; + + case 'x': /* extended operation */ + { + char oid[100]; + struct berval val; + + getline( oid, sizeof(oid), stdin, "oid? " ); + getline( value, sizeof(value), stdin, "value? " ); + if ( strncmp( value, "0x", 2 ) == 0 ) { + val.bv_val = (char *)malloc( strlen( value ) / 2 ); + berval_from_hex( &val, value + 2 ); + } else { + val.bv_val = strdup( value ); + val.bv_len = strlen( value ); + } + if ( ldap_extended_operation( ld, oid, &val, NULL, + NULL, &id ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_extended_operation" ); + } else { + printf( "Extended op initiated with id %d\n", + id ); + } + free( val.bv_val ); + } + break; + + case 'C': /* set cache parameters */ +#ifdef NO_LIBLCACHE + getline( line, sizeof(line), stdin, + "cache init (memcache 0)? " ); +#else + getline( line, sizeof(line), stdin, + "cache init (memcache 0, lcache 1)? " ); +#endif + i = atoi( line ); + if ( i == 0 ) { /* memcache */ + unsigned long ttl, size; + char **basedns, *dnarray[2]; + LDAPMemCache *mc; + + getline( line, sizeof(line), stdin, + "memcache ttl? " ); + ttl = atoi( line ); + getline( line, sizeof(line), stdin, + "memcache size? " ); + size = atoi( line ); + getline( line, sizeof(line), stdin, + "memcache baseDN? " ); + if ( *line == '\0' ) { + basedns = NULL; + } else { + dnarray[0] = line; + dnarray[1] = NULL; + basedns = dnarray; + } + if (( rc = ldap_memcache_init( ttl, size, + basedns, NULL, &mc )) != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_memcache_init: %s\n", + ldap_err2string( rc )); + } else if (( rc = ldap_memcache_set( ld, mc )) + != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_memcache_set: %s\n", + ldap_err2string( rc )); + } + +#ifndef NO_LIBLCACHE + } else if ( i == 1 ) { + getline( line, sizeof(line), stdin, + "cache config file? " ); + if ( line[0] != '\0' ) { + if ( lcache_init( ld, line ) != 0 ) { + perror( "ldap_cache_init" ); + break; + } + } + getline( line, sizeof(line), stdin, + "cache on/off (on 1, off 0)? " ); + if ( line[0] != '\0' ) { + i = atoi( line ); + if ( ldap_set_option( ld, + LDAP_OPT_CACHE_ENABLE, &i ) != 0 ) { + ldap_perror( ld, "ldap_cache_enable" ); + break; + } + } + getline( line, sizeof(line), stdin, + "cache strategy (check 0, populate 1, localdb 2)? " ); + if ( line[0] != '\0' ) { + i = atoi( line ); + if ( ldap_set_option( ld, + LDAP_OPT_CACHE_STRATEGY, &i ) + != 0 ) { + ldap_perror(ld, "ldap_cache_strategy"); + break; + } + } +#endif /* !NO_LIBLCACHE */ + + } else { + fprintf( stderr, "unknown cachetype %d\n", i ); + } + break; + + case 'd': /* turn on debugging */ +#ifndef _WIN32 +#ifdef LDAP_DEBUG + getline( line, sizeof(line), stdin, "debug level? " ); + ldap_debug = atoi( line ) | LDAP_DEBUG_ANY; + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { + ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, + &ldap_debug ); + } +#else + printf( "Compile with -DLDAP_DEBUG for debugging\n" ); +#endif +#endif + break; + + case 'E': /* explode a dn */ + getline( line, sizeof(line), stdin, "dn? " ); + exdn = ldap_explode_dn( line, 0 ); + for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { + printf( "\t\"%s\"\n", exdn[i] ); + } + break; + + case 'R': /* explode an rdn */ + getline( line, sizeof(line), stdin, "rdn? " ); + exdn = ldap_explode_rdn( line, 0 ); + for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { + printf( "\t\"%s\"\n", exdn[i] ); + } + break; + + case 'm': /* modify or modifyrdn */ + if ( strncmp( line, "modify", 4 ) == 0 ) { + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + if ( (mods = get_modlist( + "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ", + "attribute type? ", "attribute value? " )) + == NULL ) + break; + if ( (id = ldap_modify( ld, dn, mods )) == -1 ) + ldap_perror( ld, "ldap_modify" ); + else + printf( "Modify initiated with id %d\n", + id ); + } else if ( strncmp( line, "modrdn", 4 ) == 0 ) { + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + getline( rdn, sizeof(rdn), stdin, "newrdn? " ); + getline( line, sizeof(line), stdin, + "deleteoldrdn? " ); + if ( (id = ldap_modrdn2( ld, dn, rdn, + atoi(line) )) == -1 ) + ldap_perror( ld, "ldap_modrdn" ); + else + printf( "Modrdn initiated with id %d\n", + id ); + } else { + printf( "Possibilities: [modi]fy, [modr]dn\n" ); + } + break; + + case 'q': /* quit */ +#ifdef CLDAP + if ( cldapflg ) + cldap_close( ld ); +#endif /* CLDAP */ + if ( !cldapflg ) + ldap_unbind( ld ); + exit( 0 ); + break; + + case 'r': /* result or remove */ + switch ( command3 ) { + case 's': /* result */ + getline( line, sizeof(line), stdin, + "msgid (-1=>any)? " ); + if ( line[0] == '\0' ) + id = -1; + else + id = atoi( line ); + getline( line, sizeof(line), stdin, + "all (0=>any, 1=>all)? " ); + if ( line[0] == '\0' ) + all = 1; + else + all = atoi( line ); + if (( msgtype = ldap_result( ld, id, all, + tvp, &res )) < 1 ) { + ldap_perror( ld, "ldap_result" ); + break; + } + printf( "\nresult: msgtype %d msgid %d\n", + msgtype, ldap_msgid( res ) ); + handle_result( ld, res, 0 ); + res = NULL; + break; + + case 'm': /* remove */ + getline( dn, sizeof(dn), stdin, "dn? " ); + strcat( dn, dnsuffix ); + if ( (id = ldap_delete( ld, dn )) == -1 ) + ldap_perror( ld, "ldap_delete" ); + else + printf( "Remove initiated with id %d\n", + id ); + break; + + default: + printf( "Possibilities: [rem]ove, [res]ult\n" ); + break; + } + break; + + case 's': /* search */ + getline( dn, sizeof(dn), stdin, "searchbase? " ); + strcat( dn, dnsuffix ); + getline( line, sizeof(line), stdin, + "scope (0=Base, 1=One Level, 2=Subtree)? " ); + scope = atoi( line ); + getline( filter, sizeof(filter), stdin, + "search filter (e.g. sn=jones)? " ); + types = get_list( "attrs to return? " ); + getline( line, sizeof(line), stdin, + "attrsonly (0=attrs&values, 1=attrs only)? " ); + attrsonly = atoi( line ); + + if ( cldapflg ) { +#ifdef CLDAP + getline( line, sizeof(line), stdin, + "Requestor DN (for logging)? " ); + if ( cldap_search_s( ld, dn, scope, filter, types, + attrsonly, &res, line ) != 0 ) { + ldap_perror( ld, "cldap_search_s" ); + } else { + printf( "\nresult: msgid %d\n", + res->lm_msgid ); + handle_result( ld, res, 0 ); + res = NULL; + } +#endif /* CLDAP */ + } else { + if (( id = ldap_search( ld, dn, scope, filter, + types, attrsonly )) == -1 ) { + ldap_perror( ld, "ldap_search" ); + } else { + printf( "Search initiated with id %d\n", id ); + } + } + free_list( types ); + break; + + case 't': /* set timeout value */ + getline( line, sizeof(line), stdin, "timeout (-1=infinite)? " ); + timeout.tv_sec = atoi( line ); + if ( timeout.tv_sec < 0 ) { + tvp = NULL; + } else { + tvp = &timeout; + } + break; + + case 'U': /* set ufn search prefix */ + getline( line, sizeof(line), stdin, "ufn prefix? " ); + ldap_ufn_setprefix( ld, line ); + break; + + case 'u': /* user friendly search w/optional timeout */ + getline( dn, sizeof(dn), stdin, "ufn? " ); + strcat( dn, dnsuffix ); + types = get_list( "attrs to return? " ); + getline( line, sizeof(line), stdin, + "attrsonly (0=attrs&values, 1=attrs only)? " ); + attrsonly = atoi( line ); + + if ( command2 == 't' ) { + id = ldap_ufn_search_c( ld, dn, types, + attrsonly, &res, ldap_ufn_timeout, + &timeout ); + } else { + id = ldap_ufn_search_s( ld, dn, types, + attrsonly, &res ); + } + if ( res == NULL ) + ldap_perror( ld, "ldap_ufn_search" ); + else { + printf( "\nresult: err %d\n", id ); + handle_result( ld, res, 0 ); + res = NULL; + } + free_list( types ); + break; + + case 'l': /* URL search */ + getline( line, sizeof(line), stdin, + "attrsonly (0=attrs&values, 1=attrs only)? " ); + attrsonly = atoi( line ); + getline( line, sizeof(line), stdin, "LDAP URL? " ); + if (( id = ldap_url_search( ld, line, attrsonly )) + == -1 ) { + ldap_perror( ld, "ldap_url_search" ); + } else { + printf( "URL search initiated with id %d\n", id ); + } + break; + + case 'p': /* parse LDAP URL */ + getline( line, sizeof(line), stdin, "LDAP URL? " ); + if (( i = ldap_url_parse( line, &ludp )) != 0 ) { + fprintf( stderr, "ldap_url_parse: error %d (%s)\n", i, + url_parse_err2string( i )); + } else { + printf( "\t host: " ); + if ( ludp->lud_host == NULL ) { + printf( "DEFAULT\n" ); + } else { + printf( "<%s>\n", ludp->lud_host ); + } + printf( "\t port: " ); + if ( ludp->lud_port == 0 ) { + printf( "DEFAULT\n" ); + } else { + printf( "%d\n", ludp->lud_port ); + } + printf( "\tsecure: %s\n", ( ludp->lud_options & + LDAP_URL_OPT_SECURE ) != 0 ? "Yes" : "No" ); + printf( "\t dn: " ); + if ( ludp->lud_dn == NULL ) { + printf( "ROOT\n" ); + } else { + printf( "%s\n", ludp->lud_dn ); + } + printf( "\t attrs:" ); + if ( ludp->lud_attrs == NULL ) { + printf( " ALL" ); + } else { + for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) { + printf( " <%s>", ludp->lud_attrs[ i ] ); + } + } + printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? + "ONE" : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" : + ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" : "**invalid**" ); + printf( "\tfilter: <%s>\n", ludp->lud_filter ); + ldap_free_urldesc( ludp ); + } + break; + + case 'n': /* set dn suffix, for convenience */ + getline( line, sizeof(line), stdin, "DN suffix? " ); + strcpy( dnsuffix, line ); + break; + + case 'N': /* add an LDAPv3 control */ + getline( line, sizeof(line), stdin, + "Control oid (. to clear list)? " ); + if ( *line == '.' && *(line+1) == '\0' ) { + controls = NULL; + } else { + newctrl = (LDAPControl *) malloc( + sizeof(LDAPControl) ); + newctrl->ldctl_oid = strdup( line ); + getline( line, sizeof(line), stdin, + "Control value? " ); + if ( strncmp( line, "0x", 2 ) == 0 ) { + newctrl->ldctl_value.bv_val = + (char *)malloc( strlen( line ) / 2 ); + berval_from_hex( &(newctrl->ldctl_value), + line + 2 ); + } else { + newctrl->ldctl_value.bv_val + = strdup( line ); + } + newctrl->ldctl_value.bv_len = strlen( line ); + getline( line, sizeof(line), stdin, + "Critical (0=no, 1=yes)? " ); + newctrl->ldctl_iscritical = atoi( line ); + add_control( &controls, newctrl ); + } + ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, + controls ); + ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, + &tmpctrls ); + print_controls( tmpctrls, 0 ); + break; + + case 'P': /* add a persistent search control */ + getline( line, sizeof(line), stdin, "Changetypes to " + " return (additive - add (1), delete (2), " + "modify (4), modDN (8))? " ); + changetypes = atoi(line); + getline( line, sizeof(line), stdin, + "Return changes only (0=no, 1=yes)? " ); + changesonly = atoi(line); + getline( line, sizeof(line), stdin, "Return entry " + "change controls (0=no, 1=yes)? " ); + return_echg_ctls = atoi(line); + getline( line, sizeof(line), stdin, + "Critical (0=no, 1=yes)? " ); + if ( ldap_create_persistentsearch_control( ld, + changetypes, changesonly, return_echg_ctls, + (char)atoi(line), &newctrl ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_create_persistent" + "search_control" ); + } else { + add_control( &controls, newctrl ); + ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, + controls ); + ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, + &tmpctrls ); + print_controls( tmpctrls, 0 ); + } + break; + + case 'o': /* set ldap options */ + getline( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" ); + i = atoi( line ); + ldap_set_option( ld, LDAP_OPT_DEREF, &i ); + getline( line, sizeof(line), stdin, "timelimit?" ); + i = atoi( line ); + ldap_set_option( ld, LDAP_OPT_TIMELIMIT, &i ); + getline( line, sizeof(line), stdin, "sizelimit?" ); + i = atoi( line ); + ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &i ); + +#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_OPT_TRANSLATE_STRINGS; + } else { + ld->ld_lberoptions |= LBER_OPT_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_DNS + getline( line, sizeof(line), stdin, + "Use DN & DNS to determine where to send requests (0=no, 1=yes)?" ); + optval = ( atoi( line ) != 0 ); + ldap_set_option( ld, LDAP_OPT_DNS, (void *) optval ); +#endif /* LDAP_DNS */ + + getline( line, sizeof(line), stdin, + "Recognize and chase referrals (0=no, 1=yes)?" ); + optval = ( atoi( line ) != 0 ); + ldap_set_option( ld, LDAP_OPT_REFERRALS, + (void *) optval ); + if ( optval ) { + getline( line, sizeof(line), stdin, + "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" ); + if ( atoi( line ) != 0 ) { + ldap_set_rebind_proc( ld, bind_prompt, + NULL ); + } + } +#ifdef NET_SSL + getline( line, sizeof(line), stdin, + "Use Secure Sockets Layer - SSL (0=no, 1=yes)?" ); + optval = ( atoi( line ) != 0 ); + if ( optval ) { + getline( line, sizeof(line), stdin, + "security DB path?" ); + if ( ldapssl_client_init( (*line == '\0') ? + NULL : line, NULL ) < 0 ) { + perror( "ldapssl_client_init" ); + optval = 0; /* SSL not avail. */ + } else if ( ldapssl_install_routines( ld ) + < 0 ) { + ldap_perror( ld, + "ldapssl_install_routines" ); + optval = 0; /* SSL not avail. */ + } + } + + ldap_set_option( ld, LDAP_OPT_SSL, + optval ? LDAP_OPT_ON : LDAP_OPT_OFF ); + + getline( line, sizeof(line), stdin, + "Set SSL options (0=no, 1=yes)?" ); + optval = ( atoi( line ) != 0 ); + while ( 1 ) { + PRInt32 sslopt; + PRBool on; + + getline( line, sizeof(line), stdin, + "Option to set (0 if done)?" ); + sslopt = atoi(line); + if ( sslopt == 0 ) { + break; + } + getline( line, sizeof(line), stdin, + "On=1, Off=0?" ); + on = ( atoi( line ) != 0 ); + if ( ldapssl_set_option( ld, sslopt, on ) != 0 ) { + ldap_perror( ld, "ldapssl_set_option" ); + } + } +#endif + + getline( line, sizeof(line), stdin, "Reconnect?" ); + ldap_set_option( ld, LDAP_OPT_RECONNECT, + ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : + LDAP_OPT_ON ); + + getline( line, sizeof(line), stdin, "Async I/O?" ); + ldap_set_option( ld, LDAP_OPT_ASYNC_CONNECT, + ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : + LDAP_OPT_ON ); + break; + + case 'I': /* initialize display templates */ + getline( line, sizeof(line), stdin, + "Template file [ldaptemplates.conf]?" ); + if (( i = ldap_init_templates( *line == '\0' ? + "ldaptemplates.conf" : line, &tmpllist )) + != 0 ) { + fprintf( stderr, "ldap_init_templates: %s\n", + ldap_tmplerr2string( i )); + } + break; + + case 'T': /* read & display using template */ + getline( dn, sizeof(dn), stdin, "entry DN? " ); + strcat( dn, dnsuffix ); + if (( i = ldap_entry2text_search( ld, dn, NULL, NULL, + tmpllist, NULL, NULL, entry2textwrite, stdout, + "\n", 0, 0 )) != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_entry2text_search: %s\n", + ldap_err2string( i )); + } + break; + + case 'L': /* set preferred language */ + getline( line, sizeof(line), stdin, + "Preferred language? " ); + if ( *line == '\0' ) { + ldap_set_option( ld, + LDAP_OPT_PREFERRED_LANGUAGE, NULL ); + } else { + ldap_set_option( ld, + LDAP_OPT_PREFERRED_LANGUAGE, line ); + } + break; + + case 'F': /* create filter */ + { + char filtbuf[ 512 ], pattern[ 512 ]; + char prefix[ 512 ], suffix[ 512 ]; + char attr[ 512 ], value[ 512 ]; + char *dupvalue, **words; + + getline( pattern, sizeof(pattern), stdin, + "pattern? " ); + getline( prefix, sizeof(prefix), stdin, + "prefix? " ); + getline( suffix, sizeof(suffix), stdin, + "suffix? " ); + getline( attr, sizeof(attr), stdin, + "attribute? " ); + getline( value, sizeof(value), stdin, + "value? " ); + + if (( dupvalue = strdup( value )) != NULL ) { + words = string2words( value, " " ); + } else { + words = NULL; + } + if ( ldap_create_filter( filtbuf, + sizeof(filtbuf), pattern, prefix, suffix, + attr, value, words) != 0 ) { + fprintf( stderr, + "ldap_create_filter failed\n" ); + } else { + printf( "filter is \"%s\"\n", filtbuf ); + } + if ( dupvalue != NULL ) free( dupvalue ); + if ( words != NULL ) free( words ); + } + break; + + case '?': /* help */ + case '\0': /* help */ + printf( "Commands: [ad]d [ab]andon [b]ind\n" ); + printf( " synch [B]ind [c]ompare [l]URL search\n" ); + printf( " [modi]fy [modr]dn [rem]ove\n" ); + printf( " [res]ult [s]earch [q]uit/unbind\n\n" ); + printf( " [u]fn search [ut]fn search with timeout\n" ); + printf( " [d]ebug [C]set cache parms[g]set msgid\n" ); + printf( " d[n]suffix [t]imeout [v]ersion\n" ); + printf( " [U]fn prefix [?]help [o]ptions\n" ); + printf( " [E]xplode dn [p]arse LDAP URL [R]explode RDN\n" ); + printf( " e[x]tended op [F]ilter create\n" ); + printf( " set co[N]trols set preferred [L]anguage\n" ); + printf( " add a [P]ersistent search control\n" ); + printf( " [I]nitialize display templates\n" ); + printf( " [T]read entry and display using template\n" ); + break; + + default: + printf( "Invalid command. Type ? for help.\n" ); + break; + } + + (void) memset( line, '\0', sizeof(line) ); + } + + return( 0 ); +} + +static void +handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ) +{ + int msgtype; + + switch ( (msgtype = ldap_msgtype( lm )) ) { + case LDAP_RES_COMPARE: + printf( "Compare result\n" ); + print_ldap_result( ld, lm, "compare" ); + break; + + case LDAP_RES_SEARCH_RESULT: + printf( "Search result\n" ); + print_ldap_result( ld, lm, "search" ); + break; + + case LDAP_RES_SEARCH_ENTRY: + printf( "Search entry\n" ); + print_search_entry( ld, lm, onlyone ); + break; + + case LDAP_RES_SEARCH_REFERENCE: + printf( "Search reference\n" ); + print_search_reference( ld, lm, onlyone ); + break; + + case LDAP_RES_ADD: + printf( "Add result\n" ); + print_ldap_result( ld, lm, "add" ); + break; + + case LDAP_RES_DELETE: + printf( "Delete result\n" ); + print_ldap_result( ld, lm, "delete" ); + break; + + case LDAP_RES_MODIFY: + printf( "Modify result\n" ); + print_ldap_result( ld, lm, "modify" ); + break; + + case LDAP_RES_MODRDN: + printf( "ModRDN result\n" ); + print_ldap_result( ld, lm, "modrdn" ); + break; + + case LDAP_RES_BIND: + printf( "Bind result\n" ); + print_ldap_result( ld, lm, "bind" ); + break; + case LDAP_RES_EXTENDED: + if ( ldap_msgid( lm ) == LDAP_RES_UNSOLICITED ) { + printf( "Unsolicited result\n" ); + print_ldap_result( ld, lm, "unsolicited" ); + } else { + printf( "ExtendedOp result\n" ); + print_ldap_result( ld, lm, "extendedop" ); + } + break; + + default: + printf( "Unknown result type 0x%x\n", msgtype ); + print_ldap_result( ld, lm, "unknown" ); + } + + if ( !onlyone ) { + ldap_msgfree( lm ); + } +} + +static void +print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ) +{ + int lderr; + char *matcheddn, *errmsg, *oid, **refs; + LDAPControl **ctrls; + struct berval *servercred, *data; + + if ( ldap_parse_result( ld, lm, &lderr, &matcheddn, &errmsg, &refs, + &ctrls, 0 ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_parse_result" ); + } else { + fprintf( stderr, "%s: %s", s, ldap_err2string( lderr )); + if ( lderr == LDAP_CONNECT_ERROR ) { + perror( " - " ); + } else { + fputc( '\n', stderr ); + } + if ( errmsg != NULL ) { + if ( *errmsg != '\0' ) { + fprintf( stderr, "Additional info: %s\n", + errmsg ); + } + ldap_memfree( errmsg ); + } + if ( matcheddn != NULL ) { + if ( NAME_ERROR( lderr )) { + fprintf( stderr, "Matched DN: %s\n", + matcheddn ); + } + ldap_memfree( matcheddn ); + } + print_referrals( refs, 1 ); + print_controls( ctrls, 1 ); + } + + /* if SASL bind response, get and show server credentials */ + if ( ldap_msgtype( lm ) == LDAP_RES_BIND && + ldap_parse_sasl_bind_result( ld, lm, &servercred, 0 ) == + LDAP_SUCCESS && servercred != NULL ) { + fputs( "\tSASL server credentials:\n", stderr ); + bprint( servercred->bv_val, servercred->bv_len ); + ber_bvfree( servercred ); + } + + /* if ExtendedOp response, get and show oid plus data */ + if ( ldap_msgtype( lm ) == LDAP_RES_EXTENDED && + ldap_parse_extended_result( ld, lm, &oid, &data, 0 ) == + LDAP_SUCCESS ) { + if ( oid != NULL ) { + if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) + == 0 ) { + printf( + "\t%s Notice of Disconnection (OID: %s)\n", + s, oid ); + } else { + printf( "\t%s OID: %s\n", s, oid ); + } + ldap_memfree( oid ); + } + if ( data != NULL ) { + printf( "\t%s data:\n", s ); + bprint( data->bv_val, data->bv_len ); + ber_bvfree( data ); + } + } +} + +static void +print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ) +{ + BerElement *ber; + char *a, *dn, *ufn; + struct berval **vals; + int i, count; + LDAPMessage *e, *msg; + LDAPControl **ectrls; + + count = 0; + for ( msg = ldap_first_message( ld, res ); + msg != NULL && ( !onlyone || count == 0 ); + msg = ldap_next_message( ld, msg ), ++count ) { + if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) { + handle_result( ld, msg, 1 ); /* something else */ + continue; + } + e = msg; + + dn = ldap_get_dn( ld, e ); + printf( "\tDN: %s\n", dn ); + + ufn = ldap_dn2ufn( dn ); + printf( "\tUFN: %s\n", ufn ); +#ifdef WINSOCK + ldap_memfree( dn ); + ldap_memfree( ufn ); +#else /* WINSOCK */ + free( dn ); + free( ufn ); +#endif /* WINSOCK */ + + for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; + a = ldap_next_attribute( ld, e, ber ) ) { + printf( "\t\tATTR: %s\n", a ); + if ( (vals = ldap_get_values_len( ld, e, a )) + == NULL ) { + printf( "\t\t\t(no values)\n" ); + } else { + for ( i = 0; vals[i] != NULL; i++ ) { + int nonascii = 0; + unsigned long j; + + for ( j = 0; j < vals[i]->bv_len; j++ ) + if ( !isascii( vals[i]->bv_val[j] ) ) { + nonascii = 1; + break; + } + + if ( nonascii ) { + printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len ); +#ifdef BPRINT_NONASCII + bprint( vals[i]->bv_val, + vals[i]->bv_len ); +#endif /* BPRINT_NONASCII */ + continue; + } + printf( "\t\t\tlength (%ld) %s\n", + vals[i]->bv_len, vals[i]->bv_val ); + } + ber_bvecfree( vals ); + } + ldap_memfree( a ); + } + if ( ldap_get_lderrno( ld, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, + "ldap_first_attribute/ldap_next_attribute" ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + + if ( ldap_get_entry_controls( ld, e, &ectrls ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_get_entry_controls" ); + } else { + int changenumpresent; + ber_int_t changetype; + char *prevdn; + ber_int_t changenum; + + if ( ldap_parse_entrychange_control( ld, ectrls, + &changetype, &prevdn, &changenumpresent, + &changenum ) == LDAP_SUCCESS ) { + fprintf( stderr, "EntryChangeNotification\n" + "\tchangeType: %s\n", + changetype_num2string( changetype )); + if ( prevdn != NULL ) { + fprintf( stderr, + "\tpreviousDN: \"%s\"\n", + prevdn ); + } + if ( changenumpresent ) { + fprintf( stderr, "\tchangeNumber: %d\n", + changenum ); + } + if ( prevdn != NULL ) { + free( prevdn ); + } + } + print_controls( ectrls, 1 ); + } + } +} + + +static char * +changetype_num2string( ber_int_t chgtype ) +{ + static char buf[ 25 ]; + char *s; + + switch( chgtype ) { + case LDAP_CHANGETYPE_ADD: + s = "add"; + break; + case LDAP_CHANGETYPE_DELETE: + s = "delete"; + break; + case LDAP_CHANGETYPE_MODIFY: + s = "modify"; + break; + case LDAP_CHANGETYPE_MODDN: + s = "moddn"; + break; + default: + s = buf; + sprintf( s, "unknown (%d)", chgtype ); + } + + return( s ); +} + + +static void +print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ) +{ + LDAPMessage *msg; + LDAPControl **ctrls; + char **refs; + int count; + + count = 0; + for ( msg = ldap_first_message( ld, res ); + msg != NULL && ( !onlyone || count == 0 ); + msg = ldap_next_message( ld, msg ), ++count ) { + if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_REFERENCE ) { + handle_result( ld, msg, 1 ); /* something else */ + continue; + } + + if ( ldap_parse_reference( ld, msg, &refs, &ctrls, 0 ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_parse_reference" ); + } else { + print_referrals( refs, 1 ); + print_controls( ctrls, 1 ); + } + } +} + + +static void +print_referrals( char **refs, int freeit ) +{ + int i; + + if ( refs == NULL ) { + return; + } + + fprintf( stderr, "Referrals:\n" ); + for ( i = 0; refs[ i ] != NULL; ++i ) { + fprintf( stderr, "\t%s\n", refs[ i ] ); + } + + if ( freeit ) { + ldap_value_free( refs ); + } +} + + +static void +print_controls( LDAPControl **ctrls, int freeit ) +{ + int i; + + if ( ctrls == NULL ) { + return; + } + + fprintf( stderr, "Controls:\n" ); + for ( i = 0; ctrls[ i ] != NULL; ++i ) { + if ( i > 0 ) { + fputs( "\t-----------\n", stderr ); + } + fprintf( stderr, "\toid: %s\n", ctrls[ i ]->ldctl_oid ); + fprintf( stderr, "\tcritical: %s\n", + ctrls[ i ]->ldctl_iscritical ? "YES" : "NO" ); + fputs( "\tvalue:\n", stderr ); + bprint( ctrls[ i ]->ldctl_value.bv_val, + ctrls[ i ]->ldctl_value.bv_len ); + } + + if ( freeit ) { + ldap_controls_free( ctrls ); + } +} + + +static int +entry2textwrite( void *fp, char *buf, int len ) +{ + return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len ); +} + + +/* similar to getfilter.c:break_into_words() */ +static char ** +string2words( char *str, char *delims ) +{ + char *word, **words; + int count; + char *lasts; + + if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) { + return( NULL ); + } + count = 0; + words[ count ] = NULL; + + word = ldap_utf8strtok_r( str, delims, &lasts ); + while ( word != NULL ) { + if (( words = (char **)realloc( words, + ( count + 2 ) * sizeof( char * ))) == NULL ) { + free( words ); + return( NULL ); + } + + words[ count ] = word; + words[ ++count ] = NULL; + word = ldap_utf8strtok_r( NULL, delims, &lasts ); + } + + return( words ); +} + + +static const char * +url_parse_err2string( int e ) +{ + const char *s = "unknown"; + + switch( e ) { + case LDAP_URL_ERR_NOTLDAP: + s = "URL doesn't begin with \"ldap://\""; + break; + case LDAP_URL_ERR_NODN: + s = "URL has no DN (required)"; + break; + case LDAP_URL_ERR_BADSCOPE: + s = "URL scope string is invalid"; + break; + case LDAP_URL_ERR_MEM: + s = "can't allocate memory space"; + break; + case LDAP_URL_ERR_PARAM: + s = "bad parameter to an URL function"; + break; + case LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION: + s = "unrecognized critical URL extension"; + break; + } + + return( s ); +} + + +/* + * Print arbitrary stuff, for debugging. + */ + +#define BPLEN 48 +static void +bprint( char *data, int len ) +{ + static char hexdig[] = "0123456789abcdef"; + char out[ BPLEN ]; + int i = 0; + + memset( out, 0, BPLEN ); + for ( ;; ) { + if ( len < 1 ) { + fprintf( stderr, "\t%s\n", ( i == 0 ) ? "(end)" : out ); + break; + } + +#ifndef HEX + if ( isgraph( (unsigned char)*data )) { + out[ i ] = ' '; + out[ i+1 ] = *data; + } else { +#endif + out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; + out[ i+1 ] = hexdig[ *data & 0x0f ]; +#ifndef HEX + } +#endif + i += 2; + len--; + data++; + + if ( i > BPLEN - 2 ) { + fprintf( stderr, "\t%s\n", out ); + memset( out, 0, BPLEN ); + i = 0; + continue; + } + out[ i++ ] = ' '; + } + + fflush( stderr ); +} diff --git a/ldap/c-sdk/libldap/tmplout.c b/ldap/c-sdk/libldap/tmplout.c new file mode 100644 index 0000000000..0dded6b4c5 --- /dev/null +++ b/ldap/c-sdk/libldap/tmplout.c @@ -0,0 +1,1144 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * tmplout.c: display template library output routines for LDAP clients + * + */ + +#include "ldap-int.h" +#include "disptmpl.h" + +#if defined(_WINDOWS) || defined(aix) || defined(SCOOS) || defined(OSF1) || defined(SOLARIS) +#include /* for struct tm and ctime */ +#endif + + +/* This is totally lame, since it should be coming from time.h, but isn't. */ +#if defined(SOLARIS) +char *ctime_r(const time_t *, char *, int); +#endif + +static int do_entry2text( LDAP *ld, char *buf, char *base, LDAPMessage *entry, + struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, + writeptype writeproc, void *writeparm, char *eol, int rdncount, + unsigned long opts, char *urlprefix ); +static int do_entry2text_search( LDAP *ld, char *dn, char *base, + LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, + char ***defvals, writeptype writeproc, void *writeparm, char *eol, + int rdncount, unsigned long opts, char *urlprefix ); +static int do_vals2text( LDAP *ld, char *buf, char **vals, char *label, + int labelwidth, unsigned long syntaxid, writeptype writeproc, + void *writeparm, char *eol, int rdncount, char *urlprefix ); +static int max_label_len( struct ldap_disptmpl *tmpl ); +static int output_label( char *buf, char *label, int width, + writeptype writeproc, void *writeparm, char *eol, int html ); +static int output_dn( char *buf, char *dn, int width, int rdncount, + writeptype writeproc, void *writeparm, char *eol, char *urlprefix ); +static void strcat_escaped( char *s1, char *s2 ); +static char *time2text( char *ldtimestr, int dateonly ); +static long gtime( struct tm *tm ); +static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, + char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount, + writeptype writeproc, void *writeparm, char *eol, char *urlprefix ); + +#define DEF_LABEL_WIDTH 15 +#define SEARCH_TIMEOUT_SECS 120 +#define OCATTRNAME "objectClass" + + +#define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \ + err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED ) + +#define DEF_LDAP_URL_PREFIX "ldap:///" + + +int +LDAP_CALL +ldap_entry2text( + LDAP *ld, + char *buf, /* NULL for "use internal" */ + LDAPMessage *entry, + struct ldap_disptmpl *tmpl, + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, + unsigned long opts +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2text\n", 0, 0, 0 ); + + return( do_entry2text( ld, buf, NULL, entry, tmpl, defattrs, defvals, + writeproc, writeparm, eol, rdncount, opts, NULL )); + +} + + + +int +LDAP_CALL +ldap_entry2html( + LDAP *ld, + char *buf, /* NULL for "use internal" */ + LDAPMessage *entry, + struct ldap_disptmpl *tmpl, + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, + unsigned long opts, + char *base, + char *urlprefix +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2html\n", 0, 0, 0 ); + + if ( urlprefix == NULL ) { + urlprefix = DEF_LDAP_URL_PREFIX; + } + + return( do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, + writeproc, writeparm, eol, rdncount, opts, urlprefix )); +} + + +static int +do_entry2text( + LDAP *ld, + char *buf, /* NULL for use-internal */ + char *base, /* used for search actions */ + LDAPMessage *entry, + struct ldap_disptmpl *tmpl, + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, + unsigned long opts, + char *urlprefix /* if non-NULL, do HTML */ +) +{ + int i, err, html, show, labelwidth; + int freebuf, freevals; + char *dn, **vals; + struct ldap_tmplitem *rowp, *colp; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( writeproc == NULL || + !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { + err = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + if (( dn = ldap_get_dn( ld, entry )) == NULL ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( buf == NULL ) { + if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + NSLDAPI_FREE( dn ); + return( err ); + } + freebuf = 1; + } else { + freebuf = 0; + } + + html = ( urlprefix != NULL ); + + if ( html ) { + /* + * add HTML intro. and title + */ + if (!(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { + sprintf( buf, "%s%s%s%s - ", eol, eol, eol, + ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); + (*writeproc)( writeparm, buf, strlen( buf )); + output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); + sprintf( buf, "%s%s%s%s

%s - ", eol, eol, + eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); + (*writeproc)( writeparm, buf, strlen( buf )); + output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); + sprintf( buf, "

%s", eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + } + + if (( opts & LDAP_DISP_OPT_NONLEAF ) != 0 && + ( vals = ldap_explode_dn( dn, 0 )) != NULL ) { + char *untagged; + + /* + * add "Move Up" link + */ + sprintf( buf, "
1 ) { + strcat_escaped( buf, ", " ); + } + strcat_escaped( buf, vals[ i ] ); + } + if ( vals[ 1 ] != NULL ) { + untagged = strchr( vals[ 1 ], '=' ); + } else { + untagged = "=The World"; + } + sprintf( buf + strlen( buf ), + "%s\">Move Up To %s%s
", + ( vals[ 1 ] == NULL ) ? "??one" : "", + ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + + /* + * add "Browse" link + */ + untagged = strchr( vals[ 0 ], '=' ); + sprintf( buf, "Browse Below %s%s%s", + ( untagged != NULL ) ? untagged + 1 : vals[ 0 ], eol, eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + + ldap_value_free( vals ); + } + + (*writeproc)( writeparm, "
", 4 ); /* horizontal rule */ + } else { + (*writeproc)( writeparm, "\"", 1 ); + output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); + sprintf( buf, "\"%s", eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + } + + if ( tmpl != NULL && ( opts & LDAP_DISP_OPT_AUTOLABELWIDTH ) != 0 ) { + labelwidth = max_label_len( tmpl ) + 3; + } else { + labelwidth = DEF_LABEL_WIDTH;; + } + + err = LDAP_SUCCESS; + + if ( tmpl == NULL ) { + BerElement *ber; + char *attr; + + ber = NULL; + for ( attr = ldap_first_attribute( ld, entry, &ber ); + NONFATAL_LDAP_ERR( err ) && attr != NULL; + attr = ldap_next_attribute( ld, entry, ber )) { + if (( vals = ldap_get_values( ld, entry, attr )) == NULL ) { + freevals = 0; + if ( defattrs != NULL ) { + for ( i = 0; defattrs[ i ] != NULL; ++i ) { + if ( strcasecmp( attr, defattrs[ i ] ) == 0 ) { + break; + } + } + if ( defattrs[ i ] != NULL ) { + vals = defvals[ i ]; + } + } + } else { + freevals = 1; + } + + if ( islower( *attr )) { /* cosmetic -- upcase attr. name */ + *attr = toupper( *attr ); + } + + err = do_vals2text( ld, buf, vals, attr, labelwidth, + LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol, + rdncount, urlprefix ); + if ( freevals ) { + ldap_value_free( vals ); + } + } + if ( ber == NULL ) { + ber_free( ber, 0 ); + } + /* + * XXX check for errors in ldap_first_attribute/ldap_next_attribute + * here (but what should we do if there was one?) + */ + + } else { + for ( rowp = ldap_first_tmplrow( tmpl ); + NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM; + rowp = ldap_next_tmplrow( tmpl, rowp )) { + for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; + colp = ldap_next_tmplcol( tmpl, rowp, colp )) { + vals = NULL; + if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld, + entry, colp->ti_attrname )) == NULL ) { + freevals = 0; + if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp, + LDAP_DITEM_OPT_HIDEIFEMPTY ) && defattrs != NULL + && colp->ti_attrname != NULL ) { + for ( i = 0; defattrs[ i ] != NULL; ++i ) { + if ( strcasecmp( colp->ti_attrname, defattrs[ i ] ) + == 0 ) { + break; + } + } + if ( defattrs[ i ] != NULL ) { + vals = defvals[ i ]; + } + } + } else { + freevals = 1; + if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, + LDAP_DITEM_OPT_SORTVALUES ) && vals[ 0 ] != NULL + && vals[ 1 ] != NULL ) { + ldap_sort_values(ld, vals, ldap_sort_strcasecmp); + } + } + + /* + * don't bother even calling do_vals2text() if no values + * or boolean with value false and "hide if false" option set + */ + show = ( vals != NULL && vals[ 0 ] != NULL ); + if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) + == LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET( + colp, LDAP_DITEM_OPT_HIDEIFFALSE ) && + toupper( vals[ 0 ][ 0 ] ) != 'T' ) { + show = 0; + } + + if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) { + if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) { + if ( colp->ti_attrname == NULL || ( show && + toupper( vals[ 0 ][ 0 ] ) == 'T' )) { + err = searchaction( ld, buf, base, entry, dn, colp, + labelwidth, rdncount, writeproc, + writeparm, eol, urlprefix ); + } + } + show = 0; + } + + if ( show ) { + err = do_vals2text( ld, buf, vals, colp->ti_label, + labelwidth, colp->ti_syntaxid, writeproc, writeparm, + eol, rdncount, urlprefix ); + } + + if ( freevals ) { + ldap_value_free( vals ); + } + } + } + } + + if ( html && !(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { + sprintf( buf, "%s%s", eol, eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + } + + NSLDAPI_FREE( dn ); + if ( freebuf ) { + NSLDAPI_FREE( buf ); + } + + return( err ); +} + + +int +LDAP_CALL +ldap_entry2text_search( + LDAP *ld, + char *dn, /* if NULL, use entry */ + char *base, /* if NULL, no search actions */ + LDAPMessage *entry, /* if NULL, use dn */ + struct ldap_disptmpl* tmpllist, /* if NULL, load default file */ + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, /* if 0, display full DN */ + unsigned long opts +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2text_search\n", 0, 0, 0 ); + + return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs, + defvals, writeproc, writeparm, eol, rdncount, opts, NULL )); +} + + + +int +LDAP_CALL +ldap_entry2html_search( + LDAP *ld, + char *dn, /* if NULL, use entry */ + char *base, /* if NULL, no search actions */ + LDAPMessage *entry, /* if NULL, use dn */ + struct ldap_disptmpl* tmpllist, /* if NULL, load default file */ + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, /* if 0, display full DN */ + unsigned long opts, + char *urlprefix +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2html_search\n", 0, 0, 0 ); + + return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs, + defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix )); +} + + +static int +do_entry2text_search( + LDAP *ld, + char *dn, /* if NULL, use entry */ + char *base, /* if NULL, no search actions */ + LDAPMessage *entry, /* if NULL, use dn */ + struct ldap_disptmpl* tmpllist, /* if NULL, no template used */ + char **defattrs, + char ***defvals, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, /* if 0, display full DN */ + unsigned long opts, + char *urlprefix +) +{ + int err, freedn, html; + char *buf, **fetchattrs, **vals; + LDAPMessage *ldmp; + struct ldap_disptmpl *tmpl; + struct timeval timeout; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( dn == NULL && entry == NULLMSG ) { + err = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + html = ( urlprefix != NULL ); + + timeout.tv_sec = SEARCH_TIMEOUT_SECS; + timeout.tv_usec = 0; + + if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + freedn = 0; + tmpl = NULL; + + if ( dn == NULL ) { + if (( dn = ldap_get_dn( ld, entry )) == NULL ) { + NSLDAPI_FREE( buf ); + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + freedn = 1; + } + + + if ( tmpllist != NULL ) { + ldmp = NULLMSG; + + if ( entry == NULL ) { + char *ocattrs[2]; + + ocattrs[0] = OCATTRNAME; + ocattrs[1] = NULL; +#ifdef CLDAP + if ( LDAP_IS_CLDAP( ld )) + err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, + "objectClass=*", ocattrs, 0, &ldmp, NULL ); + else +#endif /* CLDAP */ + err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, + "objectClass=*", ocattrs, 0, &timeout, &ldmp ); + + if ( err == LDAP_SUCCESS ) { + entry = ldap_first_entry( ld, ldmp ); + } + } + + if ( entry != NULL ) { + vals = ldap_get_values( ld, entry, OCATTRNAME ); + tmpl = ldap_oc2template( vals, tmpllist ); + if ( vals != NULL ) { + ldap_value_free( vals ); + } + } + if ( ldmp != NULL ) { + ldap_msgfree( ldmp ); + } + } + + entry = NULL; + + if ( tmpl == NULL ) { + fetchattrs = NULL; + } else { + fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER ); + } + +#ifdef CLDAP + if ( LDAP_IS_CLDAP( ld )) + err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + fetchattrs, 0, &ldmp, NULL ); + else +#endif /* CLDAP */ + err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", + fetchattrs, 0, &timeout, &ldmp ); + + if ( freedn ) { + NSLDAPI_FREE( dn ); + } + if ( fetchattrs != NULL ) { + ldap_value_free( fetchattrs ); + } + + if ( err != LDAP_SUCCESS || + ( entry = ldap_first_entry( ld, ldmp )) == NULL ) { + NSLDAPI_FREE( buf ); + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, + writeproc, writeparm, eol, rdncount, opts, urlprefix ); + + NSLDAPI_FREE( buf ); + ldap_msgfree( ldmp ); + return( err ); +} + + +int +LDAP_CALL +ldap_vals2text( + LDAP *ld, + char *buf, /* NULL for "use internal" */ + char **vals, + char *label, + int labelwidth, /* 0 means use default */ + unsigned long syntaxid, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_vals2text\n", 0, 0, 0 ); + + return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid, + writeproc, writeparm, eol, rdncount, NULL )); +} + + +int +LDAP_CALL +ldap_vals2html( + LDAP *ld, + char *buf, /* NULL for "use internal" */ + char **vals, + char *label, + int labelwidth, /* 0 means use default */ + unsigned long syntaxid, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, + char *urlprefix +) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_vals2html\n", 0, 0, 0 ); + + if ( urlprefix == NULL ) { + urlprefix = DEF_LDAP_URL_PREFIX; + } + + return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid, + writeproc, writeparm, eol, rdncount, urlprefix )); +} + + +static int +do_vals2text( + LDAP *ld, + char *buf, /* NULL for "use internal" */ + char **vals, + char *label, + int labelwidth, /* 0 means use default */ + unsigned long syntaxid, + writeptype writeproc, + void *writeparm, + char *eol, + int rdncount, + char *urlprefix +) +{ + int err, i, html, writeoutval, freebuf, notascii; + char *p, *s, *outval; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || writeproc == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + if ( vals == NULL ) { + return( LDAP_SUCCESS ); + } + + html = ( urlprefix != NULL ); + + switch( LDAP_GET_SYN_TYPE( syntaxid )) { + case LDAP_SYN_TYPE_TEXT: + case LDAP_SYN_TYPE_BOOLEAN: + break; /* we only bother with these two types... */ + default: + return( LDAP_SUCCESS ); + } + + if ( labelwidth == 0 || labelwidth < 0 ) { + labelwidth = DEF_LABEL_WIDTH; + } + + if ( buf == NULL ) { + if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + freebuf = 1; + } else { + freebuf = 0; + } + + output_label( buf, label, labelwidth, writeproc, writeparm, eol, html ); + + for ( i = 0; vals[ i ] != NULL; ++i ) { + for ( p = vals[ i ]; *p != '\0'; ++p ) { + if ( !isascii( *p )) { + break; + } + } + notascii = ( *p != '\0' ); + outval = notascii ? "(unable to display non-ASCII text value)" + : vals[ i ]; + + writeoutval = 0; /* if non-zero, write outval after switch */ + + switch( syntaxid ) { + case LDAP_SYN_CASEIGNORESTR: + ++writeoutval; + break; + + case LDAP_SYN_RFC822ADDR: + if ( html ) { + strcpy( buf, "
%s
%s", outval, eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + } else { + ++writeoutval; + } + break; + + case LDAP_SYN_DN: /* for now */ + output_dn( buf, outval, labelwidth, rdncount, writeproc, + writeparm, eol, urlprefix ); + break; + + case LDAP_SYN_MULTILINESTR: + if ( i > 0 && !html ) { + output_label( buf, label, labelwidth, writeproc, + writeparm, eol, html ); + } + + p = s = outval; + while (( s = strchr( s, '$' )) != NULL ) { + *s++ = '\0'; + while ( ldap_utf8isspace( s )) { + ++s; + } + if ( html ) { + sprintf( buf, "
%s
%s", p, eol ); + } else { + sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol ); + } + (*writeproc)( writeparm, buf, strlen( buf )); + p = s; + } + outval = p; + ++writeoutval; + break; + + case LDAP_SYN_BOOLEAN: + outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE"; + ++writeoutval; + break; + + case LDAP_SYN_TIME: + case LDAP_SYN_DATE: + outval = time2text( outval, syntaxid == LDAP_SYN_DATE ); + ++writeoutval; + break; + + case LDAP_SYN_LABELEDURL: + if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) { + *p++ = '\0'; + while ( ldap_utf8isspace( p )) { + ++p; + } + s = outval; + } else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) { + *s++ = '\0'; + while ( ldap_utf8isspace( s )) { + ++s; + } + p = outval; + } else { + s = "URL"; + p = outval; + } + + /* + * at this point `s' points to the label & `p' to the URL + */ + if ( html ) { + sprintf( buf, "
%s
%s", p, s, eol ); + } else { + sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ", + s, eol, labelwidth + 2, " ",p , eol ); + } + (*writeproc)( writeparm, buf, strlen( buf )); + break; + + default: + sprintf( buf, " Can't display item type %ld%s", + syntaxid, eol ); + (*writeproc)( writeparm, buf, strlen( buf )); + } + + if ( writeoutval ) { + if ( html ) { + sprintf( buf, "
%s
%s", outval, eol ); + } else { + sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol ); + } + (*writeproc)( writeparm, buf, strlen( buf )); + } + } + + if ( freebuf ) { + NSLDAPI_FREE( buf ); + } + + return( LDAP_SUCCESS ); +} + + +static int +max_label_len( struct ldap_disptmpl *tmpl ) +{ + struct ldap_tmplitem *rowp, *colp; + int len, maxlen; + + maxlen = 0; + + for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM; + rowp = ldap_next_tmplrow( tmpl, rowp )) { + for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; + colp = ldap_next_tmplcol( tmpl, rowp, colp )) { + if (( len = strlen( colp->ti_label )) > maxlen ) { + maxlen = len; + } + } + } + + return( maxlen ); +} + + +static int +output_label( char *buf, char *label, int width, writeptype writeproc, + void *writeparm, char *eol, int html ) +{ + char *p; + + if ( html ) { + sprintf( buf, "
%s", label ); + } else { + auto size_t w; + sprintf( buf, " %s:", label ); + p = buf + strlen( buf ); + + for (w = ldap_utf8characters(buf); w < (size_t)width; ++w) { + *p++ = ' '; + } + + *p = '\0'; + strcat( buf, eol ); + } + + return ((*writeproc)( writeparm, buf, strlen( buf ))); +} + + +static int +output_dn( char *buf, char *dn, int width, int rdncount, + writeptype writeproc, void *writeparm, char *eol, char *urlprefix ) +{ + char **dnrdns; + int i; + + if (( dnrdns = ldap_explode_dn( dn, 1 )) == NULL ) { + return( -1 ); + } + + if ( urlprefix != NULL ) { + sprintf( buf, "
" ); + } else if ( width > 0 ) { + sprintf( buf, "%-*s", width, " " ); + } else { + *buf = '\0'; + } + + for ( i = 0; dnrdns[ i ] != NULL && ( rdncount == 0 || i < rdncount ); + ++i ) { + if ( i > 0 ) { + strcat( buf, ", " ); + } + strcat( buf, dnrdns[ i ] ); + } + + if ( urlprefix != NULL ) { + strcat( buf, "
" ); + } + + ldap_value_free( dnrdns ); + + strcat( buf, eol ); + + return ((*writeproc)( writeparm, buf, strlen( buf ))); +} + + + +#define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \ + ( c >= '@' && c <= 'Z' ) || \ + ( c == '_' ) || \ + ( c >= 'a' && c <= 'z' )) + +static void +strcat_escaped( char *s1, char *s2 ) +{ + char *p, *q; + char *hexdig = "0123456789ABCDEF"; + + p = s1 + strlen( s1 ); + for ( q = s2; *q != '\0'; ++q ) { + if ( HREF_CHAR_ACCEPTABLE( *q )) { + *p++ = *q; + } else { + *p++ = '%'; + *p++ = hexdig[ 0x0F & ((*(unsigned char*)q) >> 4) ]; + *p++ = hexdig[ 0x0F & *q ]; + } + } + + *p = '\0'; +} + + +#define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' )) + +static char * +time2text( char *ldtimestr, int dateonly ) +{ + int len; + struct tm t; + char *p, *timestr, zone, *fmterr = "badly formatted time"; + time_t gmttime; +/* CTIME for this platform doesn't use this. */ +#if !defined(SUNOS4) && !defined(BSDI) && !defined(LINUX1_2) && \ + !defined(SNI) && !defined(_WIN32) && !defined(macintosh) && !defined(LINUX) + char buf[26]; +#endif + + memset( (char *)&t, 0, sizeof( struct tm )); + if (( len = (int)strlen( ldtimestr )) < 13 ) { + return( fmterr ); + } + if ( len > 15 ) { /* throw away excess from 4-digit year time string */ + len = 15; + } else if ( len == 14 ) { + len = 13; /* assume we have a time w/2-digit year (len=13) */ + } + + for ( p = ldtimestr; p - ldtimestr + 1 < len; ++p ) { + if ( !isdigit( *p )) { + return( fmterr ); + } + } + + p = ldtimestr; + t.tm_year = GET2BYTENUM( p ); p += 2; + if ( len == 15 ) { + t.tm_year = 100 * (t.tm_year - 19); + t.tm_year += GET2BYTENUM( p ); p += 2; + } + else { + /* 2 digit years...assumed to be in the range (19)70 through + (20)69 ...less than 70 (for now, 38) means 20xx */ + if(t.tm_year < 70) { + t.tm_year += 100; + } + } + t.tm_mon = GET2BYTENUM( p ) - 1; p += 2; + t.tm_mday = GET2BYTENUM( p ); p += 2; + t.tm_hour = GET2BYTENUM( p ); p += 2; + t.tm_min = GET2BYTENUM( p ); p += 2; + t.tm_sec = GET2BYTENUM( p ); p += 2; + + if (( zone = *p ) == 'Z' ) { /* GMT */ + zone = '\0'; /* no need to indicate on screen, so we make it null */ + } + + gmttime = gtime( &t ); + timestr = NSLDAPI_CTIME( &gmttime, buf, sizeof(buf) ); + + timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */ + if ( dateonly ) { + strcpy( timestr + 11, timestr + 20 ); + } + + return( timestr ); +} + + + +/* gtime.c - inverse gmtime */ + +#if !defined( macintosh ) && !defined( _WINDOWS ) && !defined( DOS ) && !defined(XP_OS2) +#include +#endif /* !macintosh */ + +/* gtime(): the inverse of localtime(). + This routine was supplied by Mike Accetta at CMU many years ago. + */ + +static int dmsize[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +#define dysize(y) \ + (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366))) + +/* +#define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900) +*/ +#define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y)) + +/* */ + +static long gtime ( struct tm *tm ) +{ + register int i, + sec, + mins, + hour, + mday, + mon, + year; + register long result; + + if ((sec = tm -> tm_sec) < 0 || sec > 59 + || (mins = tm -> tm_min) < 0 || mins > 59 + || (hour = tm -> tm_hour) < 0 || hour > 24 + || (mday = tm -> tm_mday) < 1 || mday > 31 + || (mon = tm -> tm_mon + 1) < 1 || mon > 12) + return ((long) -1); + if (hour == 24) { + hour = 0; + mday++; + } + year = YEAR (tm -> tm_year); + + result = 0L; + for (i = 1970; i < year; i++) + result += dysize (i); + if (dysize (year) == 366 && mon >= 3) + result++; + while (--mon) + result += dmsize[mon - 1]; + result += mday - 1; + result = 24 * result + hour; + result = 60 * result + mins; + result = 60 * result + sec; + + return result; +} + +static int +searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, char *dn, + struct ldap_tmplitem *tip, int labelwidth, int rdncount, + writeptype writeproc, void *writeparm, char *eol, char *urlprefix ) +{ + int err = LDAP_SUCCESS, lderr, i, count, html; + char **vals, **members; + char *value, *filtpattern, *attr, *selectname; + char *retattrs[2], filter[ 256 ]; + LDAPMessage *ldmp; + struct timeval timeout; + + html = ( urlprefix != NULL ); + + for ( i = 0; tip->ti_args != NULL && tip->ti_args[ i ] != NULL; ++i ) { + ; + } + if ( i < 3 ) { + return( LDAP_PARAM_ERROR ); + } + attr = tip->ti_args[ 0 ]; + filtpattern = tip->ti_args[ 1 ]; + retattrs[ 0 ] = tip->ti_args[ 2 ]; + retattrs[ 1 ] = NULL; + selectname = tip->ti_args[ 3 ]; + + vals = NULL; + if ( attr == NULL ) { + value = NULL; + } else if ( strcasecmp( attr, "-dnb" ) == 0 ) { + return( LDAP_PARAM_ERROR ); + } else if ( strcasecmp( attr, "-dnt" ) == 0 ) { + value = dn; + } else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) { + value = vals[ 0 ]; + } else { + value = NULL; + } + + ldap_build_filter( filter, sizeof( filter ), filtpattern, NULL, NULL, NULL, + value, NULL ); + + if ( html ) { + /* + * if we are generating HTML, we add an HREF link that embodies this + * search action as an LDAP URL, instead of actually doing the search + * now. + */ + sprintf( buf, "
%s

%s", + tip->ti_label, eol ); + if ((*writeproc)( writeparm, buf, strlen( buf )) < 0 ) { + return( LDAP_LOCAL_ERROR ); + } + return( LDAP_SUCCESS ); + } + + timeout.tv_sec = SEARCH_TIMEOUT_SECS; + timeout.tv_usec = 0; + +#ifdef CLDAP + if ( LDAP_IS_CLDAP( ld )) + lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs, + 0, &ldmp, NULL ); + else +#endif /* CLDAP */ + lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, + retattrs, 0, &timeout, &ldmp ); + + if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) { + if (( count = ldap_count_entries( ld, ldmp )) > 0 ) { + if (( members = (char **)NSLDAPI_MALLOC( (count + 1) + * sizeof(char *))) == NULL ) { + err = LDAP_NO_MEMORY; + } else { + for ( i = 0, entry = ldap_first_entry( ld, ldmp ); + entry != NULL; + entry = ldap_next_entry( ld, entry ), ++i ) { + members[ i ] = ldap_get_dn( ld, entry ); + } + members[ i ] = NULL; + + ldap_sort_values(ld,members, ldap_sort_strcasecmp); + + err = do_vals2text( ld, NULL, members, tip->ti_label, + html ? -1 : 0, LDAP_SYN_DN, writeproc, writeparm, + eol, rdncount, urlprefix ); + + ldap_value_free( members ); + } + } + ldap_msgfree( ldmp ); + } + + + if ( vals != NULL ) { + ldap_value_free( vals ); + } + + return(( err == LDAP_SUCCESS ) ? lderr : err ); +} diff --git a/ldap/c-sdk/libldap/tmpltest.c b/ldap/c-sdk/libldap/tmpltest.c new file mode 100644 index 0000000000..35ee54e06d --- /dev/null +++ b/ldap/c-sdk/libldap/tmpltest.c @@ -0,0 +1,319 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* tmpltest.c - implements a test/config templates. */ +#include +#include + +#ifdef _WINDOWS +#include +#endif + +#include "ldap-int.h" +#include "disptmpl.h" +#include "srchpref.h" + +#ifdef MACOS +#include +#include +#endif /* MACOS */ + +#ifdef NEEDPROTOS +void dump_tmpl( struct ldap_disptmpl *tmpl ); +void dump_srchpref( struct ldap_searchobj *sp ); +#else /* NEEDPROTOS */ +void dump_tmpl(); +void dump_srchpref(); +#endif /* NEEDPROTOS */ + + +#define NULLSTRINGIFNULL( s ) ( s == NULL ? "(null)" : s ) + + +int +main( int argc, char **argv ) +{ + struct ldap_disptmpl *templates, *dtp; + struct ldap_searchobj *so, *sop; + int err; + +#ifdef MACOS + ccommand( &argv ); + for ( argc = 0; argv[ argc ] != NULL; ++argc ) { + ; + } + cshow( stdout ); +#endif /* MACOS */ + + if (( err = ldap_init_templates( "ldaptemplates.conf", &templates )) + != 0 ) { + fprintf( stderr, "ldap_init_templates failed (%d)\n", err ); + exit( 1 ); + } + + if (( err = ldap_init_searchprefs( "ldapsearchprefs.conf", &so )) + != 0 ) { + fprintf( stderr, "ldap_init_searchprefs failed (%d)\n", err ); + exit( 1 ); + } + + if ( argc == 1 ) { + printf( "*** Display Templates:\n" ); + for ( dtp = ldap_first_disptmpl( templates ); dtp != NULLDISPTMPL; + dtp = ldap_next_disptmpl( templates, dtp )) { + dump_tmpl( dtp ); + printf( "\n\n" ); + } + + printf( "\n\n*** Search Objects:\n" ); + for ( sop = ldap_first_searchobj( so ); sop != NULLSEARCHOBJ; + sop = ldap_next_searchobj( so, sop )) { + dump_srchpref( sop ); + printf( "\n\n" ); + } + + } else { + if (( dtp = ldap_oc2template( ++argv, templates )) == NULL ) { + fprintf( stderr, "no matching template found\n" ); + } else { + dump_tmpl( dtp ); + } + } + + + ldap_free_templates( templates ); + ldap_free_searchprefs( so ); + + exit( 0 ); +} + + +static char *syn_name[] = { + "?", "CIS", "MLS", "DN", "BOOL", "JPEG", "JPEGBTN", "FAX", "FAXBTN", + "AUDIOBTN", "TIME", "DATE", "URL", "SEARCHACT", "LINKACT", "ADDDNACT", + "VERIFYACT", +}; + +static char *syn_type[] = { + "?", "txt", "img", "?", "bool", "?", "?", "?", "btn", + "?", "?", "?", "?", "?", "?", "?", + "action", "?" +}; + +static char *includeattrs[] = { "objectClass", "sn", NULL }; + +static char *item_opts[] = { + "ro", "sort", "1val", "hide", "required", "hideiffalse", NULL +}; + +static unsigned long item_opt_vals[] = { + LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, + LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, + LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, +}; + + +void +dump_tmpl( struct ldap_disptmpl *tmpl ) +{ + struct ldap_tmplitem *rowp, *colp; + int i, rowcnt, colcnt; + char **fetchattrs; + struct ldap_oclist *ocp; + struct ldap_adddeflist *adp; + + printf( "** Template \"%s\" (plural \"%s\", icon \"%s\")\n", + NULLSTRINGIFNULL( tmpl->dt_name ), + NULLSTRINGIFNULL( tmpl->dt_pluralname ), + NULLSTRINGIFNULL( tmpl->dt_iconname )); + + printf( "object class list:\n" ); + for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = ocp->oc_next ) { + for ( i = 0; ocp->oc_objclasses[ i ] != NULL; ++i ) { + printf( "%s%s", i == 0 ? " " : " & ", + NULLSTRINGIFNULL( ocp->oc_objclasses[ i ] )); + } + putchar( '\n' ); + } + putchar( '\n' ); + + printf( "template options: " ); + if ( tmpl->dt_options == 0L ) { + printf( "NONE\n" ); + } else { + printf( "%s %s %s\n", LDAP_IS_DISPTMPL_OPTION_SET( tmpl, + LDAP_DTMPL_OPT_ADDABLE ) ? "addable" : "", + LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALLOWMODRDN ) + ? "modrdn" : "", + LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALTVIEW ) + ? "altview" : "" ); + } + + printf( "authenticate as attribute: %s\n", tmpl->dt_authattrname != NULL ? + tmpl->dt_authattrname : "" ); + + printf( "default RDN attribute: %s\n", tmpl->dt_defrdnattrname != NULL ? + tmpl->dt_defrdnattrname : "NONE" ); + + printf( "default add location: %s\n", tmpl->dt_defaddlocation != NULL ? + tmpl->dt_defaddlocation : "NONE" ); + + printf( "\nnew entry value default rules:\n" ); + for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = adp->ad_next ) { + if ( adp->ad_source == LDAP_ADSRC_CONSTANTVALUE ) { + printf( " attribute %s <-- constant value \"%s\"\n", + NULLSTRINGIFNULL( adp->ad_attrname), + NULLSTRINGIFNULL( adp->ad_value )); + } else { + printf( " attribute %s <-- adder's DN\n", + NULLSTRINGIFNULL( adp->ad_attrname )); + } + } + putchar( '\n' ); + + printf( "\nfetch attributes & values:\n" ); + if (( fetchattrs = ldap_tmplattrs( tmpl, includeattrs, 1, + LDAP_SYN_OPT_DEFER )) == NULL ) { + printf( " \n" ); + } else { + for ( i = 0; fetchattrs[ i ] != NULL; ++i ) { + printf( " %s\n", fetchattrs[ i ] ); + free( fetchattrs[ i ] ); + } + free( (char *)fetchattrs ); + } + + printf( "\nfetch attributes only:\n" ); + if (( fetchattrs = ldap_tmplattrs( tmpl, NULL, 0, + LDAP_SYN_OPT_DEFER )) == NULL ) { + printf( " \n" ); + } else { + for ( i = 0; fetchattrs[ i ] != NULL; ++i ) { + printf( " %s\n", fetchattrs[ i ] ); + free( fetchattrs[ i ] ); + } + free( (char *)fetchattrs ); + } + + printf( "\ntemplate items:\n" ); + rowcnt = 0; + for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM; + rowp = ldap_next_tmplrow( tmpl, rowp )) { + ++rowcnt; + colcnt = 0; + for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; + colp = ldap_next_tmplcol( tmpl, rowp, colp )) { + ++colcnt; + printf( " %2d-%d: %s (%s%s", rowcnt, colcnt, + syn_name[ colp->ti_syntaxid & 0x0000FFFF ], + syn_type[ LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) >> 24 ], + (( LDAP_GET_SYN_OPTIONS( colp->ti_syntaxid ) & + LDAP_SYN_OPT_DEFER ) != 0 ) ? ",defer" : "" ); + + for ( i = 0; item_opts[ i ] != NULL; ++i ) { + if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, item_opt_vals[ i ] )) { + printf( ",%s", NULLSTRINGIFNULL( item_opts[ i ] )); + } + } + + printf( "), %s, %s", NULLSTRINGIFNULL( colp->ti_attrname ), + NULLSTRINGIFNULL( colp->ti_label )); + if ( colp->ti_args != NULL ) { + printf( ",args=" ); + for ( i = 0; colp->ti_args[ i ] != NULL; ++i ) { + printf( "<%s>", NULLSTRINGIFNULL( colp->ti_args[ i ] )); + } + } + + putchar( '\n' ); + } + } +} + + +void +dump_srchpref( struct ldap_searchobj *so ) +{ + int i; + struct ldap_searchattr *sa; + struct ldap_searchmatch *sm; + + printf( "Object type prompt: %s\n", + NULLSTRINGIFNULL( so->so_objtypeprompt )); + printf( "Options: %s\n", + LDAP_IS_SEARCHOBJ_OPTION_SET( so, LDAP_SEARCHOBJ_OPT_INTERNAL ) ? + "internal" : "NONE" ); + printf( "Prompt: %s\n", NULLSTRINGIFNULL( so->so_prompt )); + printf( "Scope: " ); + switch ( so->so_defaultscope ) { + case LDAP_SCOPE_BASE: + printf( "LDAP_SCOPE_BASE" ); + break; + case LDAP_SCOPE_ONELEVEL: + printf( "LDAP_SCOPE_ONELEVEL" ); + break; + case LDAP_SCOPE_SUBTREE: + printf( "LDAP_SCOPE_SUBTREE" ); + break; + default: + printf("*** unknown!" ); + } + puts( "\n" ); + printf( "Filter prefix: %s\n", + NULLSTRINGIFNULL( so->so_filterprefix )); + printf( "Filter tag: %s\n", + NULLSTRINGIFNULL( so->so_filtertag )); + printf( "Default select attr: %s\n", + NULLSTRINGIFNULL( so->so_defaultselectattr )); + printf( "Default select text: %s\n", + NULLSTRINGIFNULL( so->so_defaultselecttext )); + printf( "Searchable attributes ---- \n" ); + for ( sa = so->so_salist; sa != NULL; sa = sa->sa_next ) { + printf( " Label: %s\n", NULLSTRINGIFNULL( sa->sa_attrlabel )); + printf( " Attribute: %s\n", NULLSTRINGIFNULL( sa->sa_attr )); + printf( " Select attr: %s\n", NULLSTRINGIFNULL( sa->sa_selectattr )); + printf( " Select text: %s\n", NULLSTRINGIFNULL( sa->sa_selecttext )); + printf( " Match types ---- \n" ); + for ( i = 0, sm = so->so_smlist; sm != NULL; i++, sm = sm->sm_next ) { + if (( sa->sa_matchtypebitmap >> i ) & 1 ) { + printf( " %s (%s)\n", + NULLSTRINGIFNULL( sm->sm_matchprompt ), + NULLSTRINGIFNULL( sm->sm_filter )); + } + } + } +} diff --git a/ldap/c-sdk/libldap/ufn.c b/ldap/c-sdk/libldap/ufn.c new file mode 100644 index 0000000000..54e737e158 --- /dev/null +++ b/ldap/c-sdk/libldap/ufn.c @@ -0,0 +1,563 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* + * ufn.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +typedef int (LDAP_CALL *cancelptype)( void *cancelparm ); + +static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, + char *prefix, char **attrs, int attrsonly, + LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, + char *tag1, char *tag2, char *tag3 ); +static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ); +static LDAPMessage *ldap_ufn_expand( LDAP *ld, + LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char **dns, + char *filter, int scope, char **attrs, int aonly, int *err ); + +/* + * ldap_ufn_search_ctx - do user friendly searching; provide cancel feature; + * specify ldapfilter.conf tags for each phase of search + * + * ld LDAP descriptor + * ufncomp the exploded user friendly name to look for + * ncomp number of elements in ufncomp + * prefix where to start searching + * attrs list of attribute types to return for matches + * attrsonly 1 => attributes only 0 => attributes and values + * res will contain the result of the search + * cancelproc routine that returns non-zero if operation should be + * cancelled. This can be NULL. If it is non-NULL, the + * routine will be called periodically. + * cancelparm void * that is passed to cancelproc + * tag[123] the ldapfilter.conf tag that will be used in phases + * 1, 2, and 3 of the search, respectively + * + * Example: + * char *attrs[] = { "mail", "title", 0 }; + * char *ufncomp[] = { "howes", "umich", "us", 0 } + * LDAPMessage *res; + * error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly, + * &res, acancelproc, along, "ufn first", + * "ufn intermediate", "ufn last" ); + */ + +static int +ldap_ufn_search_ctx( + LDAP *ld, + char **ufncomp, + int ncomp, + char *prefix, + char **attrs, + int attrsonly, + LDAPMessage **res, + LDAP_CANCELPROC_CALLBACK *cancelproc, + void *cancelparm, + char *tag1, + char *tag2, + char *tag3 +) +{ + char *dn, *ftag = NULL; + char **dns = NULL; + int max, i, err, scope = 0, phase, tries; + LDAPFiltInfo *fi; + LDAPMessage *tmpcand; + LDAPMessage *candidates; + static char *objattrs[] = { "objectClass", NULL }; + + /* + * look up ufn components from most to least significant. + * there are 3 phases. + * phase 1 search the root for orgs or countries + * phase 2 search for orgs + * phase 3 search for a person + * in phases 1 and 2, we are building a list of candidate DNs, + * below which we will search for the final component of the ufn. + * for each component we try the filters listed in the + * filterconfig file, first one-level (except the last compoment), + * then subtree. if any of them produce any results, we go on to + * the next component. + */ + + *res = NULL; + candidates = NULL; + phase = 1; + for ( ncomp--; ncomp != -1; ncomp-- ) { + if ( *ufncomp[ncomp] == '"' ) { + char *quote; + + if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL ) + *quote = '\0'; + strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 ); + } + if ( ncomp == 0 ) + phase = 3; + + switch ( phase ) { + case 1: + ftag = tag1; + scope = LDAP_SCOPE_ONELEVEL; + break; + case 2: + ftag = tag2; + scope = LDAP_SCOPE_ONELEVEL; + break; + case 3: + ftag = tag3; + scope = LDAP_SCOPE_SUBTREE; + break; + } + + /* + * construct an array of DN's to search below from the + * list of candidates. + */ + + if ( candidates == NULL ) { + if ( prefix != NULL ) { + if ( (dns = (char **)NSLDAPI_MALLOC( + sizeof(char *) * 2 )) == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + dns[0] = nsldapi_strdup( prefix ); + dns[1] = NULL; + } else { + dns = NULL; + } + } else { + i = 0, max = 0; + for ( tmpcand = candidates; tmpcand != NULL && + tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT; + tmpcand = tmpcand->lm_chain ) + { + if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL ) + continue; + + if ( dns == NULL ) { + if ( (dns = (char **)NSLDAPI_MALLOC( + sizeof(char *) * 8 )) == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, + NULL, NULL ); + return( err ); + } + max = 8; + } else if ( i >= max ) { + if ( (dns = (char **)NSLDAPI_REALLOC( + dns, sizeof(char *) * 2 * max )) + == NULL ) { + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, + NULL, NULL ); + return( err ); + } + max *= 2; + } + dns[i++] = dn; + dns[i] = NULL; + } + ldap_msgfree( candidates ); + candidates = NULL; + } + tries = 0; + tryagain: + tries++; + for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag, + ufncomp[ncomp] ); fi != NULL; + fi = ldap_getnextfilter( ld->ld_filtd ) ) + { + if ( (candidates = ldap_ufn_expand( ld, cancelproc, + cancelparm, dns, fi->lfi_filter, scope, + phase == 3 ? attrs : objattrs, + phase == 3 ? attrsonly : 1, &err )) != NULL ) + { + break; + } + + if ( err == -1 || err == LDAP_USER_CANCELLED ) { + if ( dns != NULL ) { + ldap_value_free( dns ); + dns = NULL; + } + return( err ); + } + } + + if ( candidates == NULL ) { + if ( tries < 2 && phase != 3 ) { + scope = LDAP_SCOPE_SUBTREE; + goto tryagain; + } else { + if ( dns != NULL ) { + ldap_value_free( dns ); + dns = NULL; + } + return( err ); + } + } + + /* go on to the next component */ + if ( phase == 1 ) + phase++; + if ( dns != NULL ) { + ldap_value_free( dns ); + dns = NULL; + } + } + *res = candidates; + + return( err ); +} + +int +LDAP_CALL +ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly, + LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, + char *tag1, char *tag2, char *tag3 ) +{ + char **ufncomp, **prefixcomp; + char *pbuf; + int ncomp, pcomp, i, err = 0; + + /* getfilter stuff must be inited before we are called */ + if ( ld->ld_filtd == NULL ) { + err = LDAP_PARAM_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + /* call ldap_explode_dn() to break the ufn into its components */ + if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) { + err = LDAP_LOCAL_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ ) + ; /* NULL */ + + /* more than two components => try it fully qualified first */ + if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) { + err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs, + attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); + + if ( ldap_count_entries( ld, *res ) > 0 ) { + ldap_value_free( ufncomp ); + return( err ); + } else { + ldap_msgfree( *res ); + *res = NULL; + } + } + + if ( ld->ld_ufnprefix == NULL ) { + ldap_value_free( 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 ); + err = LDAP_LOCAL_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ ) + ; /* NULL */ + if ( (pbuf = (char *)NSLDAPI_MALLOC( strlen( ld->ld_ufnprefix ) + 1 )) + == NULL ) { + ldap_value_free( ufncomp ); + ldap_value_free( prefixcomp ); + err = LDAP_NO_MEMORY; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + for ( i = 0; i < pcomp; i++ ) { + int j; + + *pbuf = '\0'; + for ( j = i; j < pcomp; j++ ) { + strcat( pbuf, prefixcomp[j] ); + if ( j + 1 < pcomp ) + strcat( pbuf, "," ); + } + err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs, + attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); + + if ( ldap_count_entries( ld, *res ) > 0 ) { + break; + } else { + ldap_msgfree( *res ); + *res = NULL; + } + } + + ldap_value_free( ufncomp ); + ldap_value_free( prefixcomp ); + NSLDAPI_FREE( pbuf ); + + return( err ); +} + +/* + * same as ldap_ufn_search_ct, except without the ability to specify + * ldapfilter.conf tags. + */ +int +LDAP_CALL +ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly, + LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm ) +{ + return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc, + cancelparm, "ufn first", "ufn intermediate", "ufn last" ) ); +} + +/* + * same as ldap_ufn_search_c without the cancel function + */ +int +LDAP_CALL +ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly, + LDAPMessage **res ) +{ + struct timeval tv; + + tv.tv_sec = ld->ld_timelimit; + + return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, + ld->ld_timelimit ? ldap_ufn_timeout : NULL, + ld->ld_timelimit ? (void *) &tv : NULL, + "ufn first", "ufn intermediate", "ufn last" ) ); +} + + +/* + * ldap_msg_merge - merge two ldap search result chains. the more + * serious of the two error result codes is kept. + */ + +static LDAPMessage * +ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ) +{ + LDAPMessage *end, *aprev, *aend, *bprev, *bend; + + if ( a == NULL ) + return( b ); + + if ( b == NULL ) + return( a ); + + /* find the ends of the a and b chains */ + aprev = NULL; + for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain ) + aprev = aend; + bprev = NULL; + for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain ) + bprev = bend; + + /* keep result a */ + if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) { + /* remove result b */ + ldap_msgfree( bend ); + if ( bprev != NULL ) + bprev->lm_chain = NULL; + else + b = NULL; + end = aend; + if ( aprev != NULL ) + aprev->lm_chain = NULL; + else + a = NULL; + /* keep result b */ + } else { + /* remove result a */ + ldap_msgfree( aend ); + if ( aprev != NULL ) + aprev->lm_chain = NULL; + else + a = NULL; + end = bend; + if ( bprev != NULL ) + bprev->lm_chain = NULL; + else + b = NULL; + } + + if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) || + (b == NULL && aprev == NULL) ) + return( end ); + + if ( a == NULL ) { + bprev->lm_chain = end; + return( b ); + } else if ( b == NULL ) { + aprev->lm_chain = end; + return( a ); + } else { + bprev->lm_chain = end; + aprev->lm_chain = b; + return( a ); + } +} + +static LDAPMessage * +ldap_ufn_expand( LDAP *ld, LDAP_CANCELPROC_CALLBACK *cancelproc, + void *cancelparm, char **dns, char *filter, int scope, + char **attrs, int aonly, int *err ) +{ + LDAPMessage *tmpcand, *tmpres; + char *dn; + int i, msgid; + struct timeval tv; + + /* search for this component below the current candidates */ + tmpcand = NULL; + i = 0; + do { + if ( dns != NULL ) + dn = dns[i]; + else + dn = ""; + + if (( msgid = ldap_search( ld, dn, scope, filter, attrs, + aonly )) == -1 ) { + ldap_msgfree( tmpcand ); + tmpcand = NULL; + *err = LDAP_GET_LDERRNO( ld, NULL, NULL ); + /* + * Compiling with gcc-4.2 on Mac: + * gcc-4.2 -arch ppc -c -o ufn.o -gdwarf-2 -01 ufn.c + * having a return NULL statement here causes gcc to + * hang. Therefore set tmpcand to null (above) and break + * out of this loop to make gcc happy. + */ + break; + } + + tv.tv_sec = 0; + tv.tv_usec = 100000; /* 1/10 of a second */ + + do { + *err = ldap_result( ld, msgid, 1, &tv, &tmpres ); + if ( *err == 0 && cancelproc != NULL && + (*cancelproc)( cancelparm ) != 0 ) { + ldap_abandon( ld, msgid ); + *err = LDAP_USER_CANCELLED; + LDAP_SET_LDERRNO( ld, *err, NULL, NULL ); + } + } while ( *err == 0 ); + + if ( *err == LDAP_USER_CANCELLED || *err < 0 || + ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) { + ldap_msgfree( tmpcand ); + return( NULL ); + } + + tmpcand = ldap_msg_merge( ld, tmpcand, tmpres ); + + i++; + } while ( dns != NULL && dns[i] != NULL ); + + /* Catch the tmpcand = NULL case as required by breaking out the loop + * to prevent gcc-4.2 hanging on Mac. + */ + if (!tmpcand) + return NULL; + + if ( ldap_count_entries( ld, tmpcand ) > 0 ) { + return( tmpcand ); + } else { + ldap_msgfree( tmpcand ); + return( NULL ); + } +} + +/* + * ldap_ufn_setfilter - set the filter config file used in ufn searching + */ + +LDAPFiltDesc * +LDAP_CALL +ldap_ufn_setfilter( LDAP *ld, char *fname ) +{ + if ( ld->ld_filtd != NULL ) + ldap_getfilter_free( ld->ld_filtd ); + + return( ld->ld_filtd = ldap_init_getfilter( fname ) ); +} + +void +LDAP_CALL +ldap_ufn_setprefix( LDAP *ld, char *prefix ) +{ + if ( ld->ld_ufnprefix != NULL ) + NSLDAPI_FREE( ld->ld_ufnprefix ); + + ld->ld_ufnprefix = nsldapi_strdup( prefix ); +} + +int +LDAP_C +ldap_ufn_timeout( void *tvparam ) +{ + struct timeval *tv; + + tv = (struct timeval *)tvparam; + + if ( tv->tv_sec != 0 ) { + tv->tv_usec = tv->tv_sec * 1000000; /* sec => micro sec */ + tv->tv_sec = 0; + } + tv->tv_usec -= 100000; /* 1/10 of a second */ + + return( tv->tv_usec <= 0 ? 1 : 0 ); +} diff --git a/ldap/c-sdk/libldap/unbind.c b/ldap/c-sdk/libldap/unbind.c new file mode 100644 index 0000000000..95ca49411f --- /dev/null +++ b/ldap/c-sdk/libldap/unbind.c @@ -0,0 +1,248 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +/* + * unbind.c + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + +int +LDAP_CALL +ldap_unbind( LDAP *ld ) +{ + LDAPDebug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 ); + + return( ldap_ld_free( ld, NULL, NULL, 1 ) ); +} + + +int +LDAP_CALL +ldap_unbind_s( LDAP *ld ) +{ + return( ldap_ld_free( ld, NULL, NULL, 1 )); +} + + +int +LDAP_CALL +ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + return( ldap_ld_free( ld, serverctrls, clientctrls, 1 )); +} + + +/* + * Dispose of the LDAP session ld, including all associated connections + * and resources. If close is non-zero, an unbind() request is sent as well. + */ +int +ldap_ld_free( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls, int close ) +{ + LDAPMessage *lm, *next; + int err = LDAP_SUCCESS; + LDAPRequest *lr, *nextlr; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ld->ld_sbp->sb_naddr == 0 ) { + LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); + /* free LDAP structure and outstanding requests/responses */ + for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) { + nextlr = lr->lr_next; + nsldapi_free_request( ld, lr, 0 ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); + + /* free and unbind from all open connections */ + LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); + while ( ld->ld_conns != NULL ) { + nsldapi_free_connection( ld, ld->ld_conns, serverctrls, + clientctrls, 1, close ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); + + } else { + int i; + + for ( i = 0; i < ld->ld_sbp->sb_naddr; ++i ) { + NSLDAPI_FREE( ld->ld_sbp->sb_addrs[ i ] ); + } + NSLDAPI_FREE( ld->ld_sbp->sb_addrs ); + NSLDAPI_FREE( ld->ld_sbp->sb_fromaddr ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); + for ( lm = ld->ld_responses; lm != NULL; lm = next ) { + next = lm->lm_next; + ldap_msgfree( lm ); + } + LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); + + /* call cache unbind function to allow it to clean up after itself */ + if ( ld->ld_cache_unbind != NULL ) { + LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); + (void)ld->ld_cache_unbind( ld, 0, 0 ); + LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); + } + + /* call the dispose handle I/O callback if one is defined */ + if ( ld->ld_extdisposehandle_fn != NULL ) { + /* + * We always pass the session extended I/O argument to + * the dispose handle callback. + */ + ld->ld_extdisposehandle_fn( ld, ld->ld_ext_session_arg ); + } + + if ( ld->ld_error != NULL ) + NSLDAPI_FREE( ld->ld_error ); + if ( ld->ld_matched != NULL ) + NSLDAPI_FREE( ld->ld_matched ); + if ( ld->ld_host != NULL ) + NSLDAPI_FREE( ld->ld_host ); + if ( ld->ld_ufnprefix != NULL ) + NSLDAPI_FREE( ld->ld_ufnprefix ); + if ( ld->ld_filtd != NULL ) + ldap_getfilter_free( ld->ld_filtd ); + if ( ld->ld_abandoned != NULL ) + NSLDAPI_FREE( ld->ld_abandoned ); + if ( ld->ld_sbp != NULL ) + ber_sockbuf_free( ld->ld_sbp ); + if ( ld->ld_defhost != NULL ) + NSLDAPI_FREE( ld->ld_defhost ); + if ( ld->ld_servercontrols != NULL ) + ldap_controls_free( ld->ld_servercontrols ); + if ( ld->ld_clientcontrols != NULL ) + ldap_controls_free( ld->ld_clientcontrols ); + if ( ld->ld_preferred_language != NULL ) + NSLDAPI_FREE( ld->ld_preferred_language ); + nsldapi_iostatus_free( ld ); +#ifdef LDAP_SASLIO_HOOKS + NSLDAPI_FREE( ld->ld_def_sasl_mech ); + NSLDAPI_FREE( ld->ld_def_sasl_realm ); + NSLDAPI_FREE( ld->ld_def_sasl_authcid ); + NSLDAPI_FREE( ld->ld_def_sasl_authzid ); +#endif + + /* + * XXXmcs: should use cache function pointers to hook in memcache + */ + if ( ld->ld_memcache != NULL ) { + ldap_memcache_set( ld, NULL ); + } + + /* free all mutexes we have allocated */ + nsldapi_mutex_free_all( ld ); + NSLDAPI_FREE( ld->ld_mutex ); + + NSLDAPI_FREE( (char *) ld ); + + return( err ); +} + + + +int +nsldapi_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ + BerElement *ber; + int err, msgid; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_unbind\n", 0, 0, 0 ); + + /* create a message to send */ + if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) + != LDAP_SUCCESS ) { + return( err ); + } + + /* fill it in */ + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + if ( ber_printf( ber, "{itn", msgid, LDAP_REQ_UNBIND ) == -1 ) { + ber_free( ber, 1 ); + err = LDAP_ENCODING_ERROR; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + + if (( err = nsldapi_put_controls( ld, serverctrls, 1, ber )) + != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( err ); + } + + /* send the message */ + err = nsldapi_send_ber_message( ld, sb, ber, 1 /* free ber */, + 0 /* will not handle EPIPE */ ); + if ( err != 0 ) { + ber_free( ber, 1 ); + if (err != -2 ) { + /* + * Message could not be sent, and the reason is + * something other than a "would block" error. + * Note that we ignore "would block" errors because + * it is not critical that an UnBind request + * actually reach the LDAP server. + */ + err = LDAP_SERVER_DOWN; + LDAP_SET_LDERRNO( ld, err, NULL, NULL ); + return( err ); + } + } + + return( LDAP_SUCCESS ); +} diff --git a/ldap/c-sdk/libldap/unescape.c b/ldap/c-sdk/libldap/unescape.c new file mode 100644 index 0000000000..66d5bd27ff --- /dev/null +++ b/ldap/c-sdk/libldap/unescape.c @@ -0,0 +1,84 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * LIBLDAP unescape.c -- LDAP URL un-escape routines + * We also tolerate URLs that look like: and + */ + +#include "ldap-int.h" + + +static int unhex( char c ); + + +void +nsldapi_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. + */ + char *p; + + for ( p = s; *s != '\0'; ++s ) { + if ( *s == '%' ) { + if ( *++s == '\0' ) { + break; + } + *p = unhex( *s ) << 4; + if ( *++s == '\0' ) { + break; + } + *p++ += unhex( *s ); + + } else { + *p++ = *s; + } + } + + *p = '\0'; +} + + +static int +unhex( char c ) +{ + return( c >= '0' && c <= '9' ? c - '0' + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : c - 'a' + 10 ); +} diff --git a/ldap/c-sdk/libldap/url.c b/ldap/c-sdk/libldap/url.c new file mode 100644 index 0000000000..789ee3ac2a --- /dev/null +++ b/ldap/c-sdk/libldap/url.c @@ -0,0 +1,527 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* + * Copyright (c) 1996 Regents of the University of Michigan. + * All rights reserved. + * + */ +/* LIBLDAP url.c -- LDAP URL related routines + * + * LDAP URLs look like this: + * l d a p : / / [ hostport ] [ / dn [ ? [ attributes ] [ ? [ scope ] + * [ ? [ filter ] [ ? extensions ] ] ] ] ] + * + * where: + * hostport is a host or a host:port list that can be space-separated. + * attributes is a comma separated list + * scope is one of these three strings: base one sub (default=base) + * filter is a string-represented filter as in RFC 2254 + * extensions is a comma-separated list of name=value pairs. + * + * e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich + * + * To accomodate IPv6 addresses, the host portion of a host that appears + * in hostport can be enclosed in square brackets, e.g + * + * e.g., ldap://[fe80::a00:20ff:fee5:c0b4]:3389/dc=siroe,dc=com + * + * We also tolerate URLs that look like: and + */ + +#if 0 +#ifndef lint +static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University of Michigan.\nAll rights reserved.\n"; +#endif +#endif + +#include "ldap-int.h" + + +static int skip_url_prefix( const char **urlp, int *enclosedp, int *securep ); + + +int +LDAP_CALL +ldap_is_ldap_url( const char *url ) +{ + int enclosed, secure; + + return( url != NULL + && skip_url_prefix( &url, &enclosed, &secure )); +} + + +static int +skip_url_prefix( const char **urlp, int *enclosedp, int *securep ) +{ +/* + * return non-zero if this looks like a LDAP URL; zero if not + * if non-zero returned, *urlp will be moved past "ldap://" part of URL + * The data that *urlp points to is not changed by this function. + */ + if ( *urlp == NULL ) { + return( 0 ); + } + + /* skip leading '<' (if any) */ + if ( **urlp == '<' ) { + *enclosedp = 1; + ++*urlp; + } else { + *enclosedp = 0; + } + + /* skip leading "URL:" (if any) */ + if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp( + *urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { + *urlp += LDAP_URL_URLCOLON_LEN; + } + + /* check for an "ldap://" prefix */ + if ( strlen( *urlp ) >= LDAP_URL_PREFIX_LEN && strncasecmp( *urlp, + LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { + /* skip over URL prefix and return success */ + *urlp += LDAP_URL_PREFIX_LEN; + *securep = 0; + return( 1 ); + } + + /* check for an "ldaps://" prefix */ + if ( strlen( *urlp ) >= LDAPS_URL_PREFIX_LEN && strncasecmp( *urlp, + LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { + /* skip over URL prefix and return success */ + *urlp += LDAPS_URL_PREFIX_LEN; + *securep = 1; + return( 1 ); + } + + return( 0 ); /* not an LDAP URL */ +} + + +int +LDAP_CALL +ldap_url_parse_no_defaults( const char *url, LDAPURLDesc **ludpp, int dn_required) +{ + return( nsldapi_url_parse( url, ludpp, dn_required ) ); +} + + +int +LDAP_CALL +ldap_url_parse( const char *url, LDAPURLDesc **ludpp ) +{ +/* + * Pick apart the pieces of an LDAP URL. + */ + int rc; + + if (( rc = nsldapi_url_parse( url, ludpp, 1 )) == 0 ) { + if ( (*ludpp)->lud_scope == -1 ) { + (*ludpp)->lud_scope = LDAP_SCOPE_BASE; + } + if ( (*ludpp)->lud_filter == NULL ) { + (*ludpp)->lud_filter = "(objectclass=*)"; + } + if ( *((*ludpp)->lud_dn) == '\0' ) { + (*ludpp)->lud_dn = NULL; + } + } else if ( rc == LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION ) { + rc = LDAP_URL_ERR_PARAM; /* mapped for backwards compatibility */ + } + + return( rc ); +} + + +/* + * like ldap_url_parse() with a few exceptions: + * 1) if dn_required is zero, a missing DN does not generate an error + * (we just leave the lud_dn field NULL) + * 2) no defaults are set for lud_scope and lud_filter (they are set to -1 + * and NULL respectively if no SCOPE or FILTER are present in the URL). + * 3) when there is a zero-length DN in a URL we do not set lud_dn to NULL. + * + * note that LDAPv3 URL extensions are ignored unless they are marked + * critical, in which case an LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION error + * is returned. + */ +int +nsldapi_url_parse( const char *url, LDAPURLDesc **ludpp, int dn_required ) +{ + + LDAPURLDesc *ludp; + char *urlcopy, *attrs, *scope, *extensions = NULL, *p, *q; + int enclosed, secure, i, nattrs, at_start; + + LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_url_parse(%s)\n", url, 0, 0 ); + + if ( url == NULL || ludpp == NULL ) { + return( LDAP_URL_ERR_PARAM ); + } + + *ludpp = NULL; /* pessimistic */ + + if ( !skip_url_prefix( &url, &enclosed, &secure )) { + return( LDAP_URL_ERR_NOTLDAP ); + } + + /* allocate return struct */ + if (( ludp = (LDAPURLDesc *)NSLDAPI_CALLOC( 1, sizeof( LDAPURLDesc ))) + == NULLLDAPURLDESC ) { + return( LDAP_URL_ERR_MEM ); + } + + if ( secure ) { + ludp->lud_options |= LDAP_URL_OPT_SECURE; + } + + /* make working copy of the remainder of the URL */ + if (( urlcopy = nsldapi_strdup( url )) == NULL ) { + ldap_free_urldesc( ludp ); + return( LDAP_URL_ERR_MEM ); + } + + if ( enclosed && *((p = urlcopy + strlen( urlcopy ) - 1)) == '>' ) { + *p = '\0'; + } + + /* initialize scope and filter */ + ludp->lud_scope = -1; + ludp->lud_filter = NULL; + + /* lud_string is the only malloc'd string space we use */ + ludp->lud_string = urlcopy; + + /* scan forward for '/' that marks end of hostport and begin. of dn */ + if (( ludp->lud_dn = strchr( urlcopy, '/' )) == NULL ) { + if ( dn_required ) { + ldap_free_urldesc( ludp ); + return( LDAP_URL_ERR_NODN ); + } + } else { + /* terminate hostport; point to start of dn */ + *ludp->lud_dn++ = '\0'; + } + + + if ( *urlcopy == '\0' ) { + ludp->lud_host = NULL; + } else { + ludp->lud_host = urlcopy; + nsldapi_hex_unescape( ludp->lud_host ); + + /* + * Locate and strip off optional port number (:#) in host + * portion of URL. + * + * If more than one space-separated host is listed, we only + * look for a port number within the right-most one since + * ldap_init() will handle host parameters that look like + * host:port anyway. + */ + if (( p = strrchr( ludp->lud_host, ' ' )) == NULL ) { + p = ludp->lud_host; + } else { + ++p; + } + if ( *p == '[' && ( q = strchr( p, ']' )) != NULL ) { + /* square brackets present -- skip past them */ + p = q++; + } + if (( p = strchr( p, ':' )) != NULL ) { + *p++ = '\0'; + ludp->lud_port = atoi( p ); + if ( *ludp->lud_host == '\0' ) { + ludp->lud_host = NULL; /* no hostname */ + } + } + } + + /* scan for '?' that marks end of dn and beginning of attributes */ + attrs = NULL; + if ( ludp->lud_dn != NULL && + ( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) { + /* terminate dn; point to start of attrs. */ + *attrs++ = '\0'; + + /* scan for '?' that marks end of attrs and begin. of scope */ + if (( p = strchr( attrs, '?' )) != NULL ) { + /* + * terminate attrs; point to start of scope and scan for + * '?' that marks end of scope and begin. of filter + */ + *p++ = '\0'; + scope = p; + + if (( p = strchr( scope, '?' )) != NULL ) { + /* terminate scope; point to start of filter */ + *p++ = '\0'; + if ( *p != '\0' ) { + ludp->lud_filter = p; + /* + * scan for the '?' that marks the end + * of the filter and the start of any + * extensions + */ + if (( p = strchr( ludp->lud_filter, '?' )) + != NULL ) { + *p++ = '\0'; /* term. filter */ + extensions = p; + } + if ( *ludp->lud_filter == '\0' ) { + ludp->lud_filter = NULL; + } else { + nsldapi_hex_unescape( ludp->lud_filter ); + } + } + } + + if ( strcasecmp( scope, "one" ) == 0 ) { + ludp->lud_scope = LDAP_SCOPE_ONELEVEL; + } else if ( strcasecmp( scope, "base" ) == 0 ) { + ludp->lud_scope = LDAP_SCOPE_BASE; + } else if ( strcasecmp( scope, "sub" ) == 0 ) { + ludp->lud_scope = LDAP_SCOPE_SUBTREE; + } else if ( *scope != '\0' ) { + ldap_free_urldesc( ludp ); + return( LDAP_URL_ERR_BADSCOPE ); + } + } + } + + if ( ludp->lud_dn != NULL ) { + nsldapi_hex_unescape( ludp->lud_dn ); + } + + /* + * if attrs list was included, turn it into a null-terminated array + */ + if ( attrs != NULL && *attrs != '\0' ) { + nsldapi_hex_unescape( attrs ); + for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) { + if ( *p == ',' ) { + ++nattrs; + } + } + + if (( ludp->lud_attrs = (char **)NSLDAPI_CALLOC( nattrs + 1, + sizeof( char * ))) == NULL ) { + ldap_free_urldesc( ludp ); + return( LDAP_URL_ERR_MEM ); + } + + for ( i = 0, p = attrs; i < nattrs; ++i ) { + ludp->lud_attrs[ i ] = p; + if (( p = strchr( p, ',' )) != NULL ) { + *p++ ='\0'; + } + nsldapi_hex_unescape( ludp->lud_attrs[ i ] ); + } + } + + /* if extensions list was included, check for critical ones */ + if ( extensions != NULL && *extensions != '\0' ) { + /* Note: at present, we do not recognize ANY extensions */ + at_start = 1; + for ( p = extensions; *p != '\0'; ++p ) { + if ( at_start ) { + if ( *p == '!' ) { /* critical extension */ + ldap_free_urldesc( ludp ); + return( LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION ); + } + at_start = 0; + } else if ( *p == ',' ) { + at_start = 1; + } + } + } + + *ludpp = ludp; + + return( 0 ); +} + + +void +LDAP_CALL +ldap_free_urldesc( LDAPURLDesc *ludp ) +{ + if ( ludp != NULLLDAPURLDESC ) { + if ( ludp->lud_string != NULL ) { + NSLDAPI_FREE( ludp->lud_string ); + } + if ( ludp->lud_attrs != NULL ) { + NSLDAPI_FREE( ludp->lud_attrs ); + } + NSLDAPI_FREE( ludp ); + } +} + + +int +LDAP_CALL +ldap_url_search( LDAP *ld, const char *url, int attrsonly ) +{ + int err, msgid; + LDAPURLDesc *ludp; + BerElement *ber; + LDAPServer *srv; + char *host; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( -1 ); /* punt */ + } + + if ( ldap_url_parse( url, &ludp ) != 0 ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( -1 ); + } + + LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); + msgid = ++ld->ld_msgid; + LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); + + if ( nsldapi_build_search_req( ld, ludp->lud_dn, ludp->lud_scope, + ludp->lud_filter, ludp->lud_attrs, attrsonly, NULL, NULL, + -1, -1, msgid, &ber ) != LDAP_SUCCESS ) { + return( -1 ); + } + + err = 0; + + if ( ludp->lud_host == NULL ) { + host = ld->ld_defhost; + } else { + host = ludp->lud_host; + } + + if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) + == NULL || ( host != NULL && + ( srv->lsrv_host = nsldapi_strdup( host )) == NULL )) { + if ( srv != NULL ) { + NSLDAPI_FREE( srv ); + } + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + err = -1; + } else { + if ( ludp->lud_port != 0 ) { + /* URL includes a port - use it */ + srv->lsrv_port = ludp->lud_port; + } else if ( ludp->lud_host == NULL ) { + /* URL has no port or host - use port from ld */ + srv->lsrv_port = ld->ld_defport; + } else if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) == 0 ) { + /* ldap URL has a host but no port - use std. port */ + srv->lsrv_port = LDAP_PORT; + } else { + /* ldaps URL has a host but no port - use std. port */ + srv->lsrv_port = LDAPS_PORT; + } + } + + if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ) { + srv->lsrv_options |= LDAP_SRV_OPT_SECURE; + } + + if ( err != 0 ) { + ber_free( ber, 1 ); + } else { + err = nsldapi_send_server_request( ld, ber, msgid, NULL, srv, + NULL, NULL, 1 ); + } + + ldap_free_urldesc( ludp ); + return( err ); +} + + +int +LDAP_CALL +ldap_url_search_st( LDAP *ld, const char *url, int attrsonly, + struct timeval *timeout, LDAPMessage **res ) +{ + int msgid; + + /* + * It is an error to pass in a zero'd timeval. + */ + if ( timeout != NULL && timeout->tv_sec == 0 && + timeout->tv_usec == 0 ) { + if ( ld != NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + } + if ( res != NULL ) { + *res = NULL; + } + return( LDAP_PARAM_ERROR ); + } + + if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { + (void) ldap_abandon( ld, msgid ); + LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL ); + return( LDAP_TIMEOUT ); + } + + return( ldap_result2error( ld, *res, 0 )); +} + + +int +LDAP_CALL +ldap_url_search_s( LDAP *ld, const char *url, int attrsonly, LDAPMessage **res ) +{ + int msgid; + + if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + return( ldap_result2error( ld, *res, 0 )); +} diff --git a/ldap/c-sdk/libldap/userstatusctrl.c b/ldap/c-sdk/libldap/userstatusctrl.c new file mode 100644 index 0000000000..1127d67bb7 --- /dev/null +++ b/ldap/c-sdk/libldap/userstatusctrl.c @@ -0,0 +1,228 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): abobrov@sun.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_create_userstatus_control: + + Parameters are + + ld LDAP pointer to the desired connection + + ctl_iscritical Indicates whether the control is critical of not. If + this field is non-zero, the operation will only be car- + ried out if the control is recognized by the server + and/or client + + ctrlp the address of a place to put the constructed control +*/ + +int +LDAP_CALL +ldap_create_userstatus_control ( + LDAP *ld, + const char ctl_iscritical, + LDAPControl **ctrlp + ) +{ + int rc; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + rc = nsldapi_build_control( LDAP_CONTROL_ACCOUNT_USABLE, + NULL, 0, ctl_iscritical, ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); +} + +/* ldap_parse_userstatus_control: + + Parameters are + + ld LDAP pointer to the desired connection + + ctrlp An array of controls obtained from calling + ldap_parse_result on the set of results + returned by the server + + us the address of struct LDAPuserstatus + to parse control results to +*/ + +int +LDAP_CALL +ldap_parse_userstatus_control ( + LDAP *ld, + LDAPControl **ctrlp, + LDAPuserstatus *us + ) +{ + BerElement *ber = NULL; + int i, foundUSControl; + LDAPControl *USCtrlp = NULL; + ber_tag_t tag; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || us == NULL ) { + return( LDAP_PARAM_ERROR ); + } + + /* find the control in the list of controls if it exists */ + if ( ctrlp == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + foundUSControl = 0; + for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundUSControl )); i++ ) { + foundUSControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_ACCOUNT_USABLE ); + } + if ( !foundUSControl ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } else { + /* let local var point to the control */ + USCtrlp = ctrlp[i-1]; + } + + /* allocate a Ber element with the contents of the control's struct berval */ + if ( ( ber = ber_init( &USCtrlp->ldctl_value ) ) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + memset( us, 0, sizeof(struct LDAPuserstatus) ); + + /* + * The control value should look like this: + * + * ACCOUNT_USABLE_RESPONSE::= CHOICE { + * is_available [0] INTEGER, ** seconds before expiration ** + * is_not_available [1] More_info + * } + * More_info::= SEQUENCE { + * inactive [0] BOOLEAN DEFAULT FALSE, + * reset [1] BOOLEAN DEFAULT FALSE, + * expired [2] BOOLEAN DEFAULT FALSE, + * remaining_grace [3] INTEGER OPTIONAL, + * seconds_before_unlock [4] INTEGER OPTIONAL + * } + */ + + if ( ( ber_scanf( ber, "t", &tag ) ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + + tag = (( tag & LBER_CONSTRUCTED ) == LBER_CONSTRUCTED ) ? 1 : 0; + + if ( !tag ) { + us->us_available = 1; + if ( ber_scanf( ber, "i", &us->us_expire ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + } else { + us->us_available = 0; + tag = 0; + if ( ( ber_scanf( ber, "{t", &tag ) ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + while ( tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET ) { + tag = tag & (~LBER_CLASS_CONTEXT); + switch (tag) + { + case 0: + if ( ber_scanf( ber, "b", &us->us_inactive ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + us->us_inactive = ( us->us_inactive != 0 ) ? 1 : 0; + break; + case 1: + if ( ber_scanf( ber, "b", &us->us_reset ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + us->us_reset = ( us->us_reset != 0 ) ? 1 : 0; + break; + case 2: + if ( ber_scanf( ber, "b", &us->us_expired ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + us->us_expired = ( us->us_expired != 0 ) ? 1 : 0; + break; + case 3: + if ( ber_scanf( ber, "i", &us->us_remaining ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + break; + case 4: + if ( ber_scanf( ber, "i", &us->us_seconds ) == LBER_ERROR ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + break; + default: + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + ber_scanf( ber, "t", &tag ); + } + } + + /* the ber encoding is no longer needed */ + ber_free( ber, 1 ); + return( LDAP_SUCCESS ); +} diff --git a/ldap/c-sdk/libldap/utf8.c b/ldap/c-sdk/libldap/utf8.c new file mode 100644 index 0000000000..98957cc5b4 --- /dev/null +++ b/ldap/c-sdk/libldap/utf8.c @@ -0,0 +1,282 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* uft8.c - misc. utf8 "string" functions. */ +#include "ldap-int.h" + +static char UTF8len[64] += {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6}; + +int +LDAP_CALL +ldap_utf8len (const char* s) + /* Return the number of char's in the character at *s. */ +{ + return ldap_utf8next((char*)s) - s; +} + +char* +LDAP_CALL +ldap_utf8next (char* s) + /* Return a pointer to the character immediately following *s. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register unsigned char* next = (unsigned char*)s; + switch (UTF8len [(*next >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + case 6: if ((*++next & 0xC0) != 0x80) break; + case 5: if ((*++next & 0xC0) != 0x80) break; + case 4: if ((*++next & 0xC0) != 0x80) break; + case 3: if ((*++next & 0xC0) != 0x80) break; + case 2: if ((*++next & 0xC0) != 0x80) break; + case 1: ++next; + } + return (char*) next; +} + +char* +LDAP_CALL +ldap_utf8prev (char* s) + /* Return a pointer to the character immediately preceding *s. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register unsigned char* prev = (unsigned char*)s; + unsigned char* limit = prev - 6; + while (((*--prev & 0xC0) == 0x80) && (prev != limit)) { + ; + } + return (char*) prev; +} + +int +LDAP_CALL +ldap_utf8copy (char* dst, const char* src) + /* Copy a character from src to dst; return the number of char's copied. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register const unsigned char* s = (const unsigned char*)src; + switch (UTF8len [(*s >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + case 6: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 5: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 4: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 3: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 2: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 1: *dst = *s++; + } + return s - (const unsigned char*)src; +} + +size_t +LDAP_CALL +ldap_utf8characters (const char* src) + /* Return the number of UTF-8 characters in the 0-terminated array s. */ +{ + register char* s = (char*)src; + size_t n; + for (n = 0; *s; LDAP_UTF8INC(s)) ++n; + return n; +} + +unsigned long LDAP_CALL +ldap_utf8getcc( const char** src ) +{ + register unsigned long c = 0; + register const unsigned char* s = (const unsigned char*)*src; + switch (UTF8len [(*s >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + c = (*s++) & 0x3F; goto more5; + case 1: c = (*s++); break; + case 2: c = (*s++) & 0x1F; goto more1; + case 3: c = (*s++) & 0x0F; goto more2; + case 4: c = (*s++) & 0x07; goto more3; + case 5: c = (*s++) & 0x03; goto more4; + case 6: c = (*s++) & 0x01; goto more5; + more5: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more4: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more3: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more2: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more1: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + break; + } + *src = (const char*)s; + return c; +} + +char* +LDAP_CALL +ldap_utf8strtok_r( char* sp, const char* brk, char** next) +{ + const char *bp; + unsigned long sc, bc; + char *tok; + + if (sp == NULL && (sp = *next) == NULL) + return NULL; + + /* Skip leading delimiters; roughly, sp += strspn(sp, brk) */ + cont: + sc = LDAP_UTF8GETC(sp); + for (bp = brk; (bc = LDAP_UTF8GETCC(bp)) != 0;) { + if (sc == bc) + goto cont; + } + + if (sc == 0) { /* no non-delimiter characters */ + *next = NULL; + return NULL; + } + tok = LDAP_UTF8PREV(sp); + + /* Scan token; roughly, sp += strcspn(sp, brk) + * Note that brk must be 0-terminated; we stop if we see that, too. + */ + while (1) { + sc = LDAP_UTF8GETC(sp); + bp = brk; + do { + if ((bc = LDAP_UTF8GETCC(bp)) == sc) { + if (sc == 0) { + *next = NULL; + } else { + *next = sp; + *(LDAP_UTF8PREV(sp)) = 0; + } + return tok; + } + } while (bc != 0); + } + /* NOTREACHED */ +} + +int +LDAP_CALL +ldap_utf8isalnum( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= 'A' && c <= 'Z') return 1; + if (c >= 'a' && c <= 'z') return 1; + if (c >= '0' && c <= '9') return 1; + return 0; +} + +int +LDAP_CALL +ldap_utf8isalpha( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= 'A' && c <= 'Z') return 1; + if (c >= 'a' && c <= 'z') return 1; + return 0; +} + +int +LDAP_CALL +ldap_utf8isdigit( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= '0' && c <= '9') return 1; + return 0; +} + +int +LDAP_CALL +ldap_utf8isxdigit( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= '0' && c <= '9') return 1; + if (c >= 'A' && c <= 'F') return 1; + if (c >= 'a' && c <= 'f') return 1; + return 0; +} + +int +LDAP_CALL +ldap_utf8isspace( char* s ) +{ + register unsigned char *c = (unsigned char*)s; + int len = ldap_utf8len(s); + + if (len == 0) { + return 0; + } else if (len == 1) { + switch (*c) { + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x20: + return 1; + default: + return 0; + } + } else if (len == 2) { + if (*c == 0xc2) { + return *(c+1) == 0x80; + } + } else if (len == 3) { + if (*c == 0xE2) { + c++; + if (*c == 0x80) { + c++; + return (*c>=0x80 && *c<=0x8a); + } + } else if (*c == 0xE3) { + return (*(c+1)==0x80) && (*(c+2)==0x80); + } else if (*c==0xEF) { + return (*(c+1)==0xBB) && (*(c+2)==0xBF); + } + return 0; + } + + /* should never reach here */ + return 0; +} diff --git a/ldap/c-sdk/libldap/vlistctrl.c b/ldap/c-sdk/libldap/vlistctrl.c new file mode 100644 index 0000000000..e42d746412 --- /dev/null +++ b/ldap/c-sdk/libldap/vlistctrl.c @@ -0,0 +1,259 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* vlistctrl.c - virtual list control implementation. */ +#include "ldap-int.h" + + + +/* + * function to create a VirtualListViewRequest control that can be passed + * to ldap_search_ext() or ldap_search_ext_s(). *ctrlp will be set to a + * freshly allocated LDAPControl structure. Returns an LDAP error code + * (LDAP_SUCCESS if all goes well). + * + * Parameters + * ld LDAP pointer to the desired connection + * + * ldvlistp the control structure. + * + * ctrlp the address of a place to put the constructed control + + 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 { + byIndex [0] SEQUENCE { + index INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt) } + byValue [1] greaterThanOrEqual assertionValue } + + 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. + index and contentCount identify the target entry + 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 the supplied value is the target entry. + + */ + +int +LDAP_CALL +ldap_create_virtuallist_control( + LDAP *ld, + LDAPVirtualList *ldvlistp, + LDAPControl **ctrlp +) +{ + BerElement *ber; + int rc; + + if (!NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + + if ( NULL == ctrlp || NULL == ldvlistp ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return ( LDAP_PARAM_ERROR ); + } + + /* create a ber package to hold the controlValue */ + if ( LDAP_SUCCESS != nsldapi_alloc_ber_with_options( ld, &ber ) ) + { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + if ( LBER_ERROR == ber_printf( ber, + "{ii", + ldvlistp->ldvlist_before_count, + ldvlistp->ldvlist_after_count )) + /* XXX lossy casts */ + { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + + if (NULL == ldvlistp->ldvlist_attrvalue) + { + if ( LBER_ERROR == ber_printf( ber, + "t{ii}}", + LDAP_TAG_VLV_BY_INDEX, + ldvlistp->ldvlist_index, + ldvlistp->ldvlist_size ) ) + /* XXX lossy casts */ + { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + else + { + if ( LBER_ERROR == ber_printf( ber, + "to}", + LDAP_TAG_VLV_BY_VALUE, + ldvlistp->ldvlist_attrvalue, + (int)strlen( ldvlistp->ldvlist_attrvalue )) ) { + LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_ENCODING_ERROR ); + } + } + + + rc = nsldapi_build_control( LDAP_CONTROL_VLVREQUEST , + ber, + 1, + 1, + ctrlp ); + + LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); + return( rc ); + +} + + +/* + * function to find and parse a VirtualListViewResponse control contained in + * "ctrls" *target_posp, *list_sizep, and *errcodep are set based on its + * contents. Returns an LDAP error code that indicates whether the parsing + * itself was successful (LDAP_SUCCESS if all goes well). + + 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), + operatonsError (1), + unwillingToPerform (53), + insufficientAccessRights (50), + busy (51), + timeLimitExceeded (3), + adminLimitExceeded (11), + sortControlMissing (60), + indexRangeError (61), + other (80) } } + + */ +int +LDAP_CALL +ldap_parse_virtuallist_control +( + LDAP *ld, + LDAPControl **ctrls, + ber_int_t *target_posp, + ber_int_t *list_sizep, + int *errcodep +) +{ + BerElement *ber; + int i, foundListControl; + ber_int_t errcode; + LDAPControl *listCtrlp; + ber_int_t target_pos, list_size; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + return( LDAP_PARAM_ERROR ); + } + + /* only ldapv3 or higher can do virtual lists. */ + if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { + LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); + return( LDAP_NOT_SUPPORTED ); + } + + /* find the listControl in the list of controls if it exists */ + if ( ctrls == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } + + foundListControl = 0; + for ( i = 0; (( ctrls[i] != NULL ) && ( !foundListControl )); i++ ) { + foundListControl = !strcmp( ctrls[i]->ldctl_oid, + LDAP_CONTROL_VLVRESPONSE ); + } + if ( !foundListControl ) { + LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); + return ( LDAP_CONTROL_NOT_FOUND ); + } else { + /* let local var point to the listControl */ + listCtrlp = ctrls[i-1]; + } + + /* allocate a Ber element with the contents of the list_control's struct berval */ + if ( ( ber = ber_init( &listCtrlp->ldctl_value ) ) == NULL ) { + LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* decode the result from the Berelement */ + if ( LBER_ERROR == ber_scanf( ber, "{iie}", &target_pos, &list_size, + &errcode ) ) { + LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); + ber_free( ber, 1 ); + return( LDAP_DECODING_ERROR ); + } + + if ( target_posp != NULL ) { + *target_posp = target_pos; + } + if ( list_sizep != NULL ) { + *list_sizep = list_size; + } + if ( errcodep != NULL ) { + *errcodep = (int)errcode; + } + + /* the ber encoding is no longer needed */ + ber_free(ber,1); + + return(LDAP_SUCCESS); + +} diff --git a/ldap/c-sdk/libldap/whoami.c b/ldap/c-sdk/libldap/whoami.c new file mode 100644 index 0000000000..35e10e71c7 --- /dev/null +++ b/ldap/c-sdk/libldap/whoami.c @@ -0,0 +1,130 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Sun LDAP C SDK. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * + * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): abobrov@sun.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ldap-int.h" + +/* ldap_whoami */ +int +LDAP_CALL +ldap_whoami ( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp + ) +{ + int rc; + struct berval *requestdata = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + rc = ldap_extended_operation( ld, LDAP_EXOP_WHO_AM_I, requestdata, + serverctrls, clientctrls, msgidp ); + + return( rc ); +} + +/* ldap_parse_whoami */ +int +LDAP_CALL +ldap_parse_whoami ( + LDAP *ld, + LDAPMessage *result, + struct berval **authzid + ) +{ + int rc; + char *retoidp = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + if ( !result ) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + *authzid = NULL; + + rc = ldap_parse_extended_result( ld, result, &retoidp, authzid, 0 ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + ldap_memfree( retoidp ); + return( LDAP_SUCCESS ); +} + +/* ldap_whoami_s */ +int +LDAP_CALL +ldap_whoami_s ( + LDAP *ld, + struct berval **authzid, + LDAPControl **serverctrls, + LDAPControl **clientctrls + ) +{ + int rc; + int msgid; + LDAPMessage *result = NULL; + + if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { + LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + rc = ldap_whoami( ld, serverctrls, clientctrls, &msgid ); + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( rc == -1 ) { + return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); + } + + rc = ldap_parse_whoami( ld, result, authzid ); + + ldap_msgfree( result ); + + return( rc ); +} diff --git a/ldap/c-sdk/libldif/libldif.def b/ldap/c-sdk/libldif/libldif.def new file mode 100644 index 0000000000..1c5ad53820 --- /dev/null +++ b/ldap/c-sdk/libldif/libldif.def @@ -0,0 +1,58 @@ +; +; ***** BEGIN LICENSE BLOCK ***** +; Version: MPL 1.1/GPL 2.0/LGPL 2.1 +; +; The contents of this file are subject to the Mozilla Public License Version +; 1.1 (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" basis, +; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +; for the specific language governing rights and limitations under the +; License. +; +; The Original Code is Mozilla Communicator client code. +; +; The Initial Developer of the Original Code is +; Netscape Communications Corporation. +; Portions created by the Initial Developer are Copyright (C) 1996-1999 +; the Initial Developer. All Rights Reserved. +; +; Contributor(s): +; +; Alternatively, the contents of this file may be used under the terms of +; either of the GNU General Public License Version 2 or later (the "GPL"), +; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +; in which case the provisions of the GPL or the LGPL are applicable instead +; of those above. If you wish to allow use of your version of this file only +; under the terms of either the GPL or the LGPL, and not to allow others to +; use your version of this file under the terms of the MPL, indicate your +; decision by deleting the provisions above and replace them with the notice +; and other provisions required by the GPL or the LGPL. If you do not delete +; the provisions above, a recipient may use your version of this file under +; the terms of any one of the MPL, the GPL or the LGPL. +; +; ***** END LICENSE BLOCK ***** + +LIBRARY LDIF60 +VERSION 6.0 +HEAPSIZE 4096 + +EXPORTS +; exports list (generated by genexports.pl) +; + ldif_parse_line + ldif_getline + ldif_put_type_and_value + ldif_put_type_and_value_nowrap + ldif_put_type_and_value_with_options + ldif_type_and_value + ldif_type_and_value_nowrap + ldif_type_and_value_with_options + ldif_base64_decode + ldif_base64_encode + ldif_base64_encode_nowrap + ldif_get_entry +; +; end of generated exports list. diff --git a/ldap/c-sdk/libldif/line64.c b/ldap/c-sdk/libldif/line64.c new file mode 100644 index 0000000000..a819825cce --- /dev/null +++ b/ldap/c-sdk/libldif/line64.c @@ -0,0 +1,612 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* line64.c - routines for dealing with the slapd line format */ + +#include +#include +#include +#include +#ifndef macintosh +#include +#endif +#ifdef _WIN32 +#include +#elif !defined( macintosh ) +#include +#endif +#include "ldaplog.h" +#include "ldif.h" + +#ifndef isascii +#define isascii( c ) (!((c) & ~0177)) +#endif + +#define RIGHT2 0x03 +#define RIGHT4 0x0f +#define CONTINUED_LINE_MARKER '\001' + +#define ISBLANK(c) (c == ' ' || c == '\t' || c == '\n') /* not "\r\v\f" */ + +#define LDIF_OPT_ISSET( value, opt ) (((value) & (opt)) != 0 ) + +static char nib2b64[0x40f] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static unsigned char b642nib[0x80] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static int ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, + int lenused, int wraplen ); + +/* + * ldif_parse_line - takes a line of the form "type:[:] value" and splits it + * into components "type" and "value". if a double colon separates type from + * value, then value is encoded in base 64, and parse_line un-decodes it + * (in place) before returning. + */ + +int +ldif_parse_line( + char *line, + char **type, + char **value, + int *vlen +) +{ + char *p, *s, *d; + int b64; + + /* skip any leading space */ + while ( ISBLANK( *line ) ) { + line++; + } + *type = line; + + for ( s = line; *s && *s != ':'; s++ ) + ; /* NULL */ + if ( *s == '\0' ) { + + /* Comment-out while we address calling libldif from ns-back-ldbm + on NT. 1 of 3 */ +#if defined( _WIN32 ) + /* +#endif + LDAPDebug( LDAP_DEBUG_PARSE, "ldif_parse_line: missing ':' " + "on line \"%s\"\n", line, 0, 0 ); +#if defined( _WIN32 ) + */ +#endif + return( -1 ); + } + + /* trim any space between type and : */ + for ( p = s - 1; p > line && ISBLANK( *p ); p-- ) { + *p = '\0'; + } + *s++ = '\0'; + + /* check for double : - indicates base 64 encoded value */ + if ( *s == ':' ) { + s++; + b64 = 1; + + /* single : - normally encoded value */ + } else { + b64 = 0; + } + + /* skip space between : and value */ + while ( ISBLANK( *s ) ) { + s++; + } + + /* + * If no value is present, return a zero-length string for + * *value, with *vlen set to zero. + */ + if ( *s == '\0' ) { + *value = s; + *vlen = 0; + return( 0 ); + } + + /* 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'; + + *value = s; + if ( b64 ) { + if (( *vlen = ldif_base64_decode( s, (unsigned char *)s )) + < 0 ) { + /* Comment-out while we address calling libldif from ns-back-ldbm + on NT. 3 of 3 */ +#if defined( _WIN32 ) + /* +#endif + LDAPDebug( LDAP_DEBUG_ANY, + "ldif_parse_line: invalid base 64 char on line \"%s\"\n", + line, 0, 0 ); +#if defined( _WIN32 ) + */ +#endif + return( -1 ); + } + s[ *vlen ] = '\0'; + } else { + *vlen = (int) (d - s); + } + + return( 0 ); +} + + +/* + * ldif_base64_decode - take the BASE64-encoded characters in "src" + * (a zero-terminated string) and decode them into the the buffer "dst". + * "src" and "dst" can be the same if in-place decoding is desired. + * "dst" must be large enough to hold the decoded octets. No more than + * 3 * strlen( src ) / 4 bytes will be produced. + * "dst" may contain zero octets anywhere within it, but it is not + * zero-terminated by this function. + * + * The number of bytes copied to "dst" is returned if all goes well. + * -1 is returned if the BASE64 encoding in "src" is invalid. + */ + +int +ldif_base64_decode( char *src, unsigned char *dst ) +{ + char *p, *stop; + unsigned char nib, *byte; + int i, len; + + stop = strchr( src, '\0' ); + byte = dst; + for ( p = src, len = 0; p < stop; p += 4, len += 3 ) { + for ( i = 0; i < 4; i++ ) { + if ( p[i] != '=' && (p[i] & 0x80 || + b642nib[ p[i] & 0x7f ] > 0x3f) ) { + return( -1 ); + } + } + + /* first digit */ + nib = b642nib[ p[0] & 0x7f ]; + byte[0] = nib << 2; + + /* second digit */ + nib = b642nib[ p[1] & 0x7f ]; + byte[0] |= nib >> 4; + + /* third digit */ + if ( p[2] == '=' ) { + len += 1; + break; + } + byte[1] = (nib & RIGHT4) << 4; + nib = b642nib[ p[2] & 0x7f ]; + byte[1] |= nib >> 2; + + /* fourth digit */ + if ( p[3] == '=' ) { + len += 2; + break; + } + byte[2] = (nib & RIGHT2) << 6; + nib = b642nib[ p[3] & 0x7f ]; + byte[2] |= nib; + + byte += 3; + } + + return( len ); +} + +/* + * ldif_getline - return the next "line" (minus newline) of input from a + * string buffer of lines separated by newlines, terminated by \n\n + * or \0. this routine handles continued lines, bundling them into + * a single big line before returning. if a line begins with a white + * space character, it is a continuation of the previous line. the white + * space character (nb: only one char), and preceeding newline are changed + * into CONTINUED_LINE_MARKER chars, to be deleted later by the + * ldif_parse_line() routine above. + * + * it takes a pointer to a pointer to the buffer on the first call, + * which it updates and must be supplied on subsequent calls. + * + * XXX need to update this function to also support as EOL. + * XXX supports as of 07/29/1998 (richm) + */ + +char * +ldif_getline( char **next ) +{ + char *l; + char c; + char *p; + + if ( *next == NULL || **next == '\n' || **next == '\0' ) { + return( NULL ); + } + + while ( **next == '#' ) { /* skip comment lines */ + if (( *next = strchr( *next, '\n' )) == NULL ) { + return( NULL ); + } + (*next)++; + } + + l = *next; + while ( (*next = strchr( *next, '\n' )) != NULL ) { + p = *next - 1; /* pointer to character previous to the newline */ + c = *(*next + 1); /* character after the newline */ + if ( ISBLANK( c ) && c != '\n' ) { + /* DOS EOL is \r\n, so if the character before */ + /* the \n is \r, continue it too */ + if (*p == '\r') + *p = CONTINUED_LINE_MARKER; + **next = CONTINUED_LINE_MARKER; + *(*next+1) = CONTINUED_LINE_MARKER; + } else { + /* DOS EOL is \r\n, so if the character before */ + /* the \n is \r, null it too */ + if (*p == '\r') + *p = '\0'; + *(*next)++ = '\0'; + break; + } + (*next)++; + } + + return( l ); +} + + +#define LDIF_SAFE_CHAR( c ) ( (c) != '\r' && (c) != '\n' ) +#define LDIF_CONSERVATIVE_CHAR( c ) ( LDIF_SAFE_CHAR(c) && isascii((c)) \ + && ( isprint((c)) || (c) == '\t' )) +#define LDIF_SAFE_INITCHAR( c ) ( LDIF_SAFE_CHAR(c) && (c) != ':' \ + && (c) != ' ' && (c) != '<' ) +#define LDIF_CONSERVATIVE_INITCHAR( c ) ( LDIF_SAFE_INITCHAR( c ) && \ + ! ( isascii((c)) && isspace((c)))) +#define LDIF_CONSERVATIVE_FINALCHAR( c ) ( (c) != ' ' ) + + +void +ldif_put_type_and_value_with_options( char **out, char *t, char *val, + int vlen, unsigned long options ) +{ + unsigned char *p, *byte, *stop; + char *save; + int b64, len, savelen, wraplen; + len = 0; + + if ( LDIF_OPT_ISSET( options, LDIF_OPT_NOWRAP )) { + wraplen = -1; + } else { + wraplen = LDIF_MAX_LINE_WIDTH; + } + + /* put the type + ": " */ + for ( p = (unsigned char *) t; *p; p++, len++ ) { + *(*out)++ = *p; + } + *(*out)++ = ':'; + len++; + if ( LDIF_OPT_ISSET( options, LDIF_OPT_VALUE_IS_URL )) { + *(*out)++ = '<'; /* add '<' for URLs */ + len++; + } + save = *out; + savelen = len; + b64 = 0; + + stop = (unsigned char *)val; + if ( val && vlen > 0 ) { + *(*out)++ = ' '; + stop = (unsigned char *) (val + vlen); + if ( LDIF_OPT_ISSET( options, LDIF_OPT_MINIMAL_ENCODING )) { + if ( !LDIF_SAFE_INITCHAR( val[0] )) { + b64 = 1; + } + } else { + if ( !LDIF_CONSERVATIVE_INITCHAR( val[0] ) || + !LDIF_CONSERVATIVE_FINALCHAR( val[vlen-1] )) { + b64 = 1; + } + } + } + + if ( !b64 ) { + for ( byte = (unsigned char *) val; byte < stop; + byte++, len++ ) { + if ( LDIF_OPT_ISSET( options, + LDIF_OPT_MINIMAL_ENCODING )) { + if ( !LDIF_SAFE_CHAR( *byte )) { + b64 = 1; + break; + } + } else if ( !LDIF_CONSERVATIVE_CHAR( *byte )) { + b64 = 1; + break; + } + + if ( wraplen != -1 && len > wraplen ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + *(*out)++ = *byte; + } + } + + if ( b64 ) { + *out = save; + *(*out)++ = ':'; + *(*out)++ = ' '; + len = ldif_base64_encode_internal( (unsigned char *)val, *out, vlen, + savelen + 2, wraplen ); + *out += len; + } + + *(*out)++ = '\n'; +} + +void +ldif_put_type_and_value( char **out, char *t, char *val, int vlen ) +{ + ldif_put_type_and_value_with_options( out, t, val, vlen, 0 ); +} + +void +ldif_put_type_and_value_nowrap( char **out, char *t, char *val, int vlen ) +{ + ldif_put_type_and_value_with_options( out, t, val, vlen, LDIF_OPT_NOWRAP ); +} + +/* + * ldif_base64_encode_internal - encode "srclen" bytes in "src", place BASE64 + * encoded bytes in "dst" and return the length of the BASE64 + * encoded string. "dst" is also zero-terminated by this function. + * + * If "lenused" >= 0, newlines will be included in "dst" and "lenused" if + * appropriate. "lenused" should be a count of characters already used + * on the current line. The LDIF lines we create will contain at most + * "wraplen" characters on each line, unless "wraplen" is -1, in which + * case output line length is unlimited. + * + * If "lenused" < 0, no newlines will be included, and the LDIF_BASE64_LEN() + * macro can be used to determine how many bytes will be placed in "dst." + */ + +static int +ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, int lenused, int wraplen ) +{ + unsigned char *byte, *stop; + unsigned char buf[3]; + char *out; + unsigned long bits; + int i, pad, len; + + len = 0; + out = dst; + stop = src + srclen; + + /* convert to base 64 (3 bytes => 4 base 64 digits) */ + for ( byte = src; byte < stop - 2; byte += 3 ) { + bits = (byte[0] & 0xff) << 16; + bits |= (byte[1] & 0xff) << 8; + bits |= (byte[2] & 0xff); + + for ( i = 0; i < 4; i++, bits <<= 6 ) { + if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) { + *out++ = '\n'; + *out++ = ' '; + lenused = 2; + } + + /* get b64 digit from high order 6 bits */ + *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; + } + } + + /* add padding if necessary */ + if ( byte < stop ) { + for ( i = 0; byte + i < stop; i++ ) { + buf[i] = byte[i]; + } + for ( pad = 0; i < 3; i++, pad++ ) { + buf[i] = '\0'; + } + byte = buf; + bits = (byte[0] & 0xff) << 16; + bits |= (byte[1] & 0xff) << 8; + bits |= (byte[2] & 0xff); + + for ( i = 0; i < 4; i++, bits <<= 6 ) { + if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) { + *out++ = '\n'; + *out++ = ' '; + lenused = 2; + } + + if (( i == 3 && pad > 0 ) || ( i == 2 && pad == 2 )) { + /* Pad as appropriate */ + *out++ = '='; + } else { + /* get b64 digit from low order 6 bits */ + *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; + } + } + } + + *out = '\0'; + + return( out - dst ); +} + +int +ldif_base64_encode( unsigned char *src, char *dst, int srclen, int lenused ) +{ + return ldif_base64_encode_internal( src, dst, srclen, lenused, LDIF_MAX_LINE_WIDTH ); +} + +int +ldif_base64_encode_nowrap( unsigned char *src, char *dst, int srclen, int lenused ) +{ + return ldif_base64_encode_internal( src, dst, srclen, lenused, -1 ); +} + + +/* + * return malloc'd, zero-terminated LDIF line + */ +char * +ldif_type_and_value_with_options( char *type, char *val, int vlen, + unsigned long options ) +{ + char *buf, *p; + int tlen; + + tlen = strlen( type ); + if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) != + NULL ) { + p = buf; + ldif_put_type_and_value_with_options( &p, type, val, vlen, options ); + *p = '\0'; + } + + return( buf ); +} + +char * +ldif_type_and_value( char *type, char *val, int vlen ) +{ + return ldif_type_and_value_with_options( type, val, vlen, 0 ); +} + +char * +ldif_type_and_value_nowrap( char *type, char *val, int vlen ) +{ + return ldif_type_and_value_with_options( type, val, vlen, LDIF_OPT_NOWRAP ); +} + +/* + * ldif_get_entry - read the next ldif entry from the FILE referenced + * by fp. return a pointer to a malloc'd, null-terminated buffer. also + * returned is the last line number read, in *lineno. + */ +char * +ldif_get_entry( FILE *fp, int *lineno ) +{ + char line[BUFSIZ]; + char *buf; + int max, cur, len, gotsome; + + buf = NULL; + max = cur = gotsome = 0; + while ( fgets( line, sizeof(line), fp ) != NULL ) { + if ( lineno != NULL ) { + (*lineno)++; + } + /* ldif entries are terminated by a \n on a line by itself */ + if ( line[0] == '\0' || line[0] == '\n' +#if !defined( XP_WIN32 ) + || ( line[0] == '\r' && line[1] == '\n' ) /* DOS format */ +#endif + ) { + if ( gotsome ) { + break; + } else { + continue; + } + } else if ( line[0] == '#' ) { + continue; + } + gotsome = 1; + len = strlen( line ); +#if !defined( XP_WIN32 ) + /* DOS format */ + if ( len > 0 && line[len-1] == '\r' ) { + --len; + line[len] = '\0'; + } else if ( len > 1 && line[len-2] == '\r' && line[len-1] == '\n' ) { + --len; + line[len-1] = line[len]; + line[len] = '\0'; + } +#endif + while ( cur + (len + 1) > max ) { + if ( buf == NULL ) { + max += BUFSIZ; + buf = (char *) malloc( max ); + } else { + max *= 2; + buf = (char *) realloc( buf, max ); + } + if ( buf == NULL ) { + return( NULL ); + } + } + + memcpy( buf + cur, line, len + 1 ); + cur += len; + } + + return( buf ); +} diff --git a/ldap/c-sdk/libldif/moz.build b/ldap/c-sdk/libldif/moz.build new file mode 100644 index 0000000000..9281f20c4e --- /dev/null +++ b/ldap/c-sdk/libldif/moz.build @@ -0,0 +1,23 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include('../common.mozbuild') + +SharedLibrary('ldif60') + +SOURCES += [ + 'line64.c' +] + +LOCAL_INCLUDES += [ + '../include' +] + +if CONFIG['OS_ARCH'] == 'WINNT': + DEFFILE = SRCDIR + '/libldif.def' + +DEFINES['USE_WAITPID'] = True +DEFINES['NEEDPROTOS'] = True + diff --git a/ldap/c-sdk/libprldap/ldappr-dns.c b/ldap/c-sdk/libprldap/ldappr-dns.c new file mode 100644 index 0000000000..a88bfe31c7 --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-dns.c @@ -0,0 +1,166 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * DNS callback functions for libldap that use the NSPR (Netscape + * Portable Runtime) thread API. + * + */ + +#include "ldappr-int.h" + +static LDAPHostEnt *prldap_gethostbyname( const char *name, + LDAPHostEnt *result, char *buffer, int buflen, int *statusp, + void *extradata ); +static LDAPHostEnt *prldap_gethostbyaddr( const char *addr, int length, + int type, LDAPHostEnt *result, char *buffer, int buflen, + int *statusp, void *extradata ); +static int prldap_getpeername( LDAP *ld, struct sockaddr *addr, + char *buffer, int buflen ); +static LDAPHostEnt *prldap_convert_hostent( LDAPHostEnt *ldhp, + PRHostEnt *prhp ); + + +/* + * Install NSPR DNS functions into ld (if ld is NULL, they are installed + * as the default functions for new LDAP * handles). + * + * Returns 0 if all goes well and -1 if not. + */ +int +prldap_install_dns_functions( LDAP *ld ) +{ + struct ldap_dns_fns dnsfns; + + memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) ); + dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; + dnsfns.lddnsfn_gethostbyname = prldap_gethostbyname; + dnsfns.lddnsfn_gethostbyaddr = prldap_gethostbyaddr; + dnsfns.lddnsfn_getpeername = prldap_getpeername; + if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) != 0 ) { + return( -1 ); + } + + return( 0 ); +} + + +static LDAPHostEnt * +prldap_gethostbyname( const char *name, LDAPHostEnt *result, + char *buffer, int buflen, int *statusp, void *extradata ) +{ + PRHostEnt prhent; + + if( !statusp || ( *statusp = (int)PR_GetIPNodeByName( name, + PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT, + buffer, buflen, &prhent )) == PR_FAILURE ) { + return( NULL ); + } + + return( prldap_convert_hostent( result, &prhent )); +} + + +static LDAPHostEnt * +prldap_gethostbyaddr( const char *addr, int length, int type, + LDAPHostEnt *result, char *buffer, int buflen, int *statusp, + void *extradata ) +{ + PRHostEnt prhent; + PRNetAddr iaddr; + + if ( NULL == statusp ) { + return( NULL ); + } + + memset( &iaddr, 0, sizeof( iaddr )); + if ( PR_StringToNetAddr( addr, &iaddr ) == PR_FAILURE ) { + return( NULL ); + } + PRLDAP_SET_PORT( &iaddr, 0 ); + + if( PR_FAILURE == (*statusp = + PR_GetHostByAddr(&iaddr, buffer, buflen, &prhent ))) { + return( NULL ); + } + + return( prldap_convert_hostent( result, &prhent )); +} + + +static int +prldap_getpeername( LDAP *ld, struct sockaddr *addr, char *buffer, int buflen) +{ + PRLDAPIOSocketArg *sa; + PRNetAddr iaddr; + int ret; + + if (NULL != ld) { + ret = prldap_socket_arg_from_ld( ld, &sa ); + if (ret != LDAP_SUCCESS) { + return (-1); + } + ret = PR_GetPeerName(sa->prsock_prfd, &iaddr); + if( ret == PR_FAILURE ) { + return( -1 ); + } + *addr = *((struct sockaddr *)&iaddr.raw); + ret = PR_NetAddrToString(&iaddr, buffer, buflen); + if( ret == PR_FAILURE ) { + return( -1 ); + } + return (0); + } + return (-1); +} + + +/* + * Function: prldap_convert_hostent() + * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt + * Returns: the LDAPHostEnt pointer passed in. + */ +static LDAPHostEnt * +prldap_convert_hostent( LDAPHostEnt *ldhp, PRHostEnt *prhp ) +{ + ldhp->ldaphe_name = prhp->h_name; + ldhp->ldaphe_aliases = prhp->h_aliases; + ldhp->ldaphe_addrtype = prhp->h_addrtype; + ldhp->ldaphe_length = prhp->h_length; + ldhp->ldaphe_addr_list = prhp->h_addr_list; + return( ldhp ); +} diff --git a/ldap/c-sdk/libprldap/ldappr-error.c b/ldap/c-sdk/libprldap/ldappr-error.c new file mode 100644 index 0000000000..b0cb6ed967 --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-error.c @@ -0,0 +1,335 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Utilities for manageing the relationship between NSPR errors and + * OS (errno-style) errors. + * + * The overall strategy used is to map NSPR errors into OS errors. + */ + +#include "ldappr-int.h" + +void +prldap_set_system_errno( int oserrno ) +{ + PR_SetError( PR_GetError(), oserrno ); +} + + +int +prldap_get_system_errno( void ) +{ + return( PR_GetOSError()); +} + +/* + * Retrieve the NSPR error number, convert to a system error code, and return + * the result. + */ +struct prldap_errormap_entry { + PRInt32 erm_nspr; /* NSPR error code */ + int erm_system; /* corresponding system error code */ +}; + +/* XXX: not sure if this extra mapping for Windows is good or correct */ +#ifdef _WINDOWS +#ifndef ENOTSUP +#define ENOTSUP -1 +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT WSAETIMEDOUT +#endif +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif +#ifndef EISCONN +#define EISCONN WSAEISCONN +#endif +#ifndef EADDRINUSE +#define EADDRINUSE WSAEADDRINUSE +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED WSAECONNREFUSED +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH WSAEHOSTUNREACH +#endif +#ifndef ENOTCONN +#define ENOTCONN WSAENOTCONN +#endif +#ifndef ENOTSOCK +#define ENOTSOCK WSAENOTSOCK +#endif +#ifndef EPROTOTYPE +#define EPROTOTYPE WSAEPROTOTYPE +#endif +#ifndef EOPNOTSUPP +#define EOPNOTSUPP WSAEOPNOTSUPP +#endif +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#endif +#ifndef EOVERFLOW +#define EOVERFLOW -1 +#endif +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET +#endif +#ifndef ELOOP +#define ELOOP WSAELOOP +#endif +#ifndef ENOTBLK +#define ENOTBLK -1 +#endif +#ifndef ETXTBSY +#define ETXTBSY -1 +#endif +#ifndef ENETDOWN +#define ENETDOWN WSAENETDOWN +#endif +#ifndef ESHUTDOWN +#define ESHUTDOWN WSAESHUTDOWN +#endif +#ifndef ECONNABORTED +#define ECONNABORTED WSAECONNABORTED +#endif +#endif /* _WINDOWS */ + +#if defined(macintosh) +/* + * Some Unix error defs. Under CW 7, we can't define OTUNIXERRORS because + * it generates many conflicts with errno.h. Define what we need here. + * These need to be in sync with OpenTransport.h + */ +#define EWOULDBLOCK 35 +#define ENOTSOCK 38 +#define EPROTOTYPE 41 +#define EPROTONOSUPPORT 43 +#define EOPNOTSUPP 45 +#define EADDRINUSE 48 +#define EADDRNOTAVAIL 49 +#define ENETDOWN 50 +#define ECONNABORTED 53 +#define ECONNRESET 54 +#define EISCONN 56 +#define ENOTCONN 57 +#define ESHUTDOWN 58 +#define ETIMEDOUT 60 +#define ECONNREFUSED 61 +#define EHOSTUNREACH 65 +#define EAFNOSUPPORT -1 +#define ELOOP -1 +#define ENOTBLK -1 +#define ENOTSUP -1 +#define EOVERFLOW -1 +#define ETXTBSY -1 +#endif /* macintosh */ + +#ifdef XP_OS2 +#define SOCBASEERR 0 +#endif +#ifndef ENOTSUP +#define ENOTSUP -1 +#endif +#ifndef EOVERFLOW +#define EOVERFLOW -1 +#endif +#ifndef EDEADLOCK +#define EDEADLOCK -1 +#endif +#ifndef EFAULT +#define EFAULT SOCEFAULT +#endif +#ifndef EPIPE +#define EPIPE SOCEPIPE +#endif +#ifndef EIO +#define EIO (SOCBASEERR+5) +#endif +#ifndef EDEADLK +#define EDEADLK (SOCBASEERR+11) +#endif +#ifndef ENOTBLK +#define ENOTBLK (SOCBASEERR+15) +#endif +#ifndef EBUSY +#define EBUSY (SOCBASEERR+16) +#endif +#ifndef ENOTDIR +#define ENOTDIR (SOCBASEERR+20) +#endif +#ifndef EISDIR +#define EISDIR (SOCBASEERR+21) +#endif +#ifndef ENFILE +#define ENFILE (SOCBASEERR+23) +#endif +#ifndef ETXTBSY +#define ETXTBSY (SOCBASEERR+26) +#endif +#ifndef EFBIG +#define EFBIG (SOCBASEERR+27) +#endif +#ifndef ESPIPE +#define ESPIPE (SOCBASEERR+29) +#endif +#ifndef EROFS +#define EROFS (SOCBASEERR+30) +#endif + +#ifdef BEOS +#define ENOTSUP -1 +#define ENOTBLK -1 +#define ETXTBSY -1 +#endif + +#if defined(BSDI) || defined(OPENBSD) || defined (NETBSD) +#define ENOTSUP -1 +#endif + +#if defined(OSF1) || defined(BSDI) || defined(VMS) || defined(OPENBSD) +#define EOVERFLOW -1 +#endif + +#if defined(__hpux) || defined(_AIX) || defined(OSF1) || defined(DARWIN) || \ + defined(BEOS) || defined(FREEBSD) || defined(BSDI) || defined(VMS) || \ + defined(OPENBSD) || defined(NETBSD) +#define EDEADLOCK -1 +#endif + +/* XXX: need to verify that the -1 entries are correct (no mapping) */ +static struct prldap_errormap_entry prldap_errormap[] = { + { PR_OUT_OF_MEMORY_ERROR, ENOMEM }, + { PR_BAD_DESCRIPTOR_ERROR, EBADF }, + { PR_WOULD_BLOCK_ERROR, EAGAIN }, + { PR_ACCESS_FAULT_ERROR, EFAULT }, + { PR_INVALID_METHOD_ERROR, EINVAL }, /* XXX: correct mapping ? */ + { PR_ILLEGAL_ACCESS_ERROR, EACCES }, /* XXX: correct mapping ? */ + { PR_UNKNOWN_ERROR, -1 }, + { PR_PENDING_INTERRUPT_ERROR, -1 }, + { PR_NOT_IMPLEMENTED_ERROR, ENOTSUP }, + { PR_IO_ERROR, EIO }, + { PR_IO_TIMEOUT_ERROR, ETIMEDOUT }, /* XXX: correct mapping ? */ + { PR_IO_PENDING_ERROR, -1 }, + { PR_DIRECTORY_OPEN_ERROR, ENOTDIR }, + { PR_INVALID_ARGUMENT_ERROR, EINVAL }, + { PR_ADDRESS_NOT_AVAILABLE_ERROR, EADDRNOTAVAIL }, + { PR_ADDRESS_NOT_SUPPORTED_ERROR, EAFNOSUPPORT }, + { PR_IS_CONNECTED_ERROR, EISCONN }, + { PR_BAD_ADDRESS_ERROR, EFAULT }, /* XXX: correct mapping ? */ + { PR_ADDRESS_IN_USE_ERROR, EADDRINUSE }, + { PR_CONNECT_REFUSED_ERROR, ECONNREFUSED }, + { PR_NETWORK_UNREACHABLE_ERROR, EHOSTUNREACH }, + { PR_CONNECT_TIMEOUT_ERROR, ETIMEDOUT }, + { PR_NOT_CONNECTED_ERROR, ENOTCONN }, + { PR_LOAD_LIBRARY_ERROR, -1 }, + { PR_UNLOAD_LIBRARY_ERROR, -1 }, + { PR_FIND_SYMBOL_ERROR, -1 }, + { PR_INSUFFICIENT_RESOURCES_ERROR, -1 }, + { PR_DIRECTORY_LOOKUP_ERROR, EHOSTUNREACH },/* an approximation */ + { PR_TPD_RANGE_ERROR, -1 }, + { PR_PROC_DESC_TABLE_FULL_ERROR, -1 }, + { PR_SYS_DESC_TABLE_FULL_ERROR, -1 }, + { PR_NOT_SOCKET_ERROR, ENOTSOCK }, + { PR_NOT_TCP_SOCKET_ERROR, EPROTOTYPE }, + { PR_SOCKET_ADDRESS_IS_BOUND_ERROR, -1 }, + { PR_NO_ACCESS_RIGHTS_ERROR, EACCES }, /* XXX: correct mapping ? */ + { PR_OPERATION_NOT_SUPPORTED_ERROR, EOPNOTSUPP }, + { PR_PROTOCOL_NOT_SUPPORTED_ERROR, EPROTONOSUPPORT }, + { PR_REMOTE_FILE_ERROR, -1 }, + { PR_BUFFER_OVERFLOW_ERROR, EOVERFLOW }, + { PR_CONNECT_RESET_ERROR, ECONNRESET }, + { PR_RANGE_ERROR, ERANGE }, + { PR_DEADLOCK_ERROR, EDEADLK }, + { PR_FILE_IS_LOCKED_ERROR, EDEADLOCK }, /* XXX: correct mapping ? */ + { PR_FILE_TOO_BIG_ERROR, EFBIG }, + { PR_NO_DEVICE_SPACE_ERROR, ENOSPC }, + { PR_PIPE_ERROR, EPIPE }, + { PR_NO_SEEK_DEVICE_ERROR, ESPIPE }, + { PR_IS_DIRECTORY_ERROR, EISDIR }, + { PR_LOOP_ERROR, ELOOP }, + { PR_NAME_TOO_LONG_ERROR, ENAMETOOLONG }, + { PR_FILE_NOT_FOUND_ERROR, ENOENT }, + { PR_NOT_DIRECTORY_ERROR, ENOTDIR }, + { PR_READ_ONLY_FILESYSTEM_ERROR, EROFS }, + { PR_DIRECTORY_NOT_EMPTY_ERROR, ENOTEMPTY }, + { PR_FILESYSTEM_MOUNTED_ERROR, EBUSY }, + { PR_NOT_SAME_DEVICE_ERROR, EXDEV }, + { PR_DIRECTORY_CORRUPTED_ERROR, -1 }, + { PR_FILE_EXISTS_ERROR, EEXIST }, + { PR_MAX_DIRECTORY_ENTRIES_ERROR, -1 }, + { PR_INVALID_DEVICE_STATE_ERROR, ENOTBLK }, /* XXX: correct mapping ? */ + { PR_DEVICE_IS_LOCKED_ERROR, -2 }, + { PR_NO_MORE_FILES_ERROR, ENFILE }, + { PR_END_OF_FILE_ERROR, -1 }, + { PR_FILE_SEEK_ERROR, ESPIPE }, /* XXX: correct mapping ? */ + { PR_FILE_IS_BUSY_ERROR, ETXTBSY }, + { PR_OPERATION_ABORTED_ERROR, -1 }, + { PR_IN_PROGRESS_ERROR, -1 }, + { PR_ALREADY_INITIATED_ERROR, -1 }, + { PR_GROUP_EMPTY_ERROR, -1 }, + { PR_INVALID_STATE_ERROR, -1 }, + { PR_NETWORK_DOWN_ERROR, ENETDOWN }, + { PR_SOCKET_SHUTDOWN_ERROR, ESHUTDOWN }, + { PR_CONNECT_ABORTED_ERROR, ECONNABORTED }, + { PR_HOST_UNREACHABLE_ERROR, EHOSTUNREACH }, + { PR_MAX_ERROR, -1 }, +}; + + +int +prldap_prerr2errno( void ) +{ + int oserr, i; + PRInt32 nsprerr; + + nsprerr = PR_GetError(); + + oserr = -1; /* unknown */ + for ( i = 0; prldap_errormap[i].erm_nspr != PR_MAX_ERROR; ++i ) { + if ( prldap_errormap[i].erm_nspr == nsprerr ) { + oserr = prldap_errormap[i].erm_system; + break; + } + } + + return( oserr ); +} diff --git a/ldap/c-sdk/libprldap/ldappr-int.h b/ldap/c-sdk/libprldap/ldappr-int.h new file mode 100644 index 0000000000..ed4bfbce61 --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-int.h @@ -0,0 +1,139 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Internal header for libprldap -- glue NSPR (Netscape Portable Runtime) + * to libldap. + * + */ + +#include "ldap.h" +#include "nspr.h" +#include "ldappr.h" + +#include +#include +#include + +/* + * Macros: + */ + +/* #define PRLDAP_DEBUG 1 */ /* uncomment to enable debugging printfs */ + +/* + * All of the sockets we use are IPv6 capable. + * Change the following #define to PR_AF_INET to support IPv4 only. + */ +#define PRLDAP_DEFAULT_ADDRESS_FAMILY PR_AF_INET6 + +/* + * Max length for sending message with one PR_Send. + * If a single message is larger than this size, the message is divided + * into multiple pieces up to this length and sent out. This is necessary + * on Microsoft Windows at least where attempts to send really large + * messages in one PR_Send() call result in an error. + */ +#define PRLDAP_MAX_SEND_SIZE (8*1024*1024) /* 8MB */ + +/* + * Macro to set port to the 'port' field of a NSPR PRNetAddr union. + ** INPUTS: + ** PRNetAddr *myaddr A network address. + ** PRUint16 myport port to set to the 'port' field of 'addr'. + ** RETURN: none + */ +#define PRLDAP_SET_PORT(myaddr,myport) \ + ((myaddr)->raw.family == PR_AF_INET6 ? ((myaddr)->ipv6.port = PR_htons(myport)) : ((myaddr)->inet.port = PR_htons(myport))) + +/* + * Data structures: + */ + +/* data structure that populates the I/O callback session arg. */ +typedef struct lextiof_session_private { + PRPollDesc *prsess_pollds; /* for poll callback */ + int prsess_pollds_count; /* # of elements in pollds */ + int prsess_io_max_timeout; /* in milliseconds */ + void *prsess_appdata; /* application specific data */ +} PRLDAPIOSessionArg; + +/* data structure that populates the I/O callback socket-specific arg. */ +typedef struct lextiof_socket_private { + PRFileDesc *prsock_prfd; /* associated NSPR file desc. */ + int prsock_io_max_timeout; /* in milliseconds */ + void *prsock_appdata; /* application specific data */ +} PRLDAPIOSocketArg; + + +/* + * Function prototypes: + */ + +/* + * From ldapprio.c: + */ +int prldap_install_io_functions( LDAP *ld, int shared ); +int prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ); +int prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, + int io_max_timeout ); +int prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, + int *io_max_timeoutp ); +int prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ); +PRLDAPIOSocketArg *prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ); + + +/* + * From ldapprthreads.c: + */ +int prldap_install_thread_functions( LDAP *ld, int shared ); +int prldap_thread_new_handle( LDAP *ld, void *sessionarg ); +void prldap_thread_dispose_handle( LDAP *ld, void *sessionarg ); + + +/* + * From ldapprdns.c: + */ +int prldap_install_dns_functions( LDAP *ld ); + + +/* + * From ldapprerror.c: + */ +void prldap_set_system_errno( int e ); +int prldap_get_system_errno( void ); +int prldap_prerr2errno( void ); diff --git a/ldap/c-sdk/libprldap/ldappr-io.c b/ldap/c-sdk/libprldap/ldappr-io.c new file mode 100644 index 0000000000..863545146a --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-io.c @@ -0,0 +1,744 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Extended I/O callback functions for libldap that use + * NSPR (Netscape Portable Runtime) I/O. + * + * High level strategy: we use the socket-specific arg to hold our own data + * structure that includes the NSPR file handle (PRFileDesc *), among other + * useful information. We use the default argument to hold an LDAP session + * handle specific data structure. + */ + +#include "ldappr-int.h" + +#define PRLDAP_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ + +/* + * Local function prototypes: + */ +static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout ); +static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds, + int timeout, struct lextiof_session_private *sessionarg ); +static int LDAP_CALLBACK prldap_connect( const char *hostlist, int defport, + int timeout, unsigned long options, + struct lextiof_session_private *sessionarg, + struct lextiof_socket_private **socketargp ); +static int LDAP_CALLBACK prldap_close( int s, + struct lextiof_socket_private *socketarg ); +static int LDAP_CALLBACK prldap_newhandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ); +static PRLDAPIOSessionArg *prldap_session_arg_alloc( void ); +static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ); +static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ); +static void *prldap_safe_realloc( void *ptr, PRUint32 size ); + + + +/* + * Local macros: + */ +/* given a socket-specific arg, return the corresponding PRFileDesc * */ +#define PRLDAP_GET_PRFD( socketarg ) \ + (((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd) + +/* + * Static variables. + */ +static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; + + +/* + * Install NSPR I/O functions into ld (if ld is NULL, they are installed + * as the default functions for new LDAP * handles). + * + * Returns 0 if all goes well and -1 if not. + */ +int +prldap_install_io_functions( LDAP *ld, int shared ) +{ + struct ldap_x_ext_io_fns iofns; + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + iofns.lextiof_read = prldap_read; + iofns.lextiof_write = prldap_write; + iofns.lextiof_poll = prldap_poll; + iofns.lextiof_connect = prldap_connect; + iofns.lextiof_close = prldap_close; + if ( shared ) { + iofns.lextiof_newhandle = prldap_shared_newhandle; + iofns.lextiof_disposehandle = prldap_shared_disposehandle; + } else { + iofns.lextiof_newhandle = prldap_newhandle; + iofns.lextiof_disposehandle = prldap_disposehandle; + } + if ( NULL != ld ) { + /* + * If we are dealing with a real ld, we allocate the session specific + * data structure now. If not allocated here, it will be allocated + * inside prldap_newhandle() or prldap_shared_newhandle(). + */ + if ( NULL == + ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { + ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( -1 ); + } + } else { + iofns.lextiof_session_arg = NULL; + } + + if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) { + prldap_session_arg_free( + (PRLDAPIOSessionArg **) &iofns.lextiof_session_arg ); + return( -1 ); + } + + return( 0 ); +} + + +static PRIntervalTime +prldap_timeout2it( int ms_timeout, int ms_maxtimeout ) +{ + PRIntervalTime prit; + + if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) { + prit = PR_INTERVAL_NO_WAIT; + } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) { + prit = PR_INTERVAL_NO_TIMEOUT; + } else { + prit = PR_MillisecondsToInterval( ms_timeout ); + } + + /* cap at maximum I/O timeout */ + if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) { + prit = LDAP_X_IO_TIMEOUT_NO_WAIT; + } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) { + if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout || + ms_timeout > ms_maxtimeout ) { + prit = PR_MillisecondsToInterval( ms_maxtimeout ); + } + } + +#ifdef PRLDAP_DEBUG + if ( PR_INTERVAL_NO_WAIT == prit ) { + fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" ); + } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) { + fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" ); + } else { + fprintf( stderr, "prldap_timeout2it: %dms\n", + PR_IntervalToMilliseconds(prit)); + } +#endif /* PRLDAP_DEBUG */ + + return( prit ); +} + + +static int LDAP_CALLBACK +prldap_read( int s, void *buf, int bufsize, + struct lextiof_socket_private *socketarg ) +{ + PRIntervalTime prit; + + prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, + socketarg->prsock_io_max_timeout ); + return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit )); +} + + +static int LDAP_CALLBACK +prldap_write( int s, const void *buf, int len, + struct lextiof_socket_private *socketarg ) +{ + PRIntervalTime prit; + char *ptr = (char *)buf; + int rest = len; + + prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, + socketarg->prsock_io_max_timeout ); + + while ( rest > 0 ) { + int rval; + if ( rest > PRLDAP_MAX_SEND_SIZE ) { + len = PRLDAP_MAX_SEND_SIZE; + } else { + len = rest; + } + /* + * Note the 4th parameter (flags) to PR_Send() has been obsoleted and + * must always be 0 + */ + rval = PR_Send( PRLDAP_GET_PRFD(socketarg), ptr, len, 0, prit ); + if ( 0 > rval ) { + return rval; + } + + if ( 0 == rval ) { + break; + } + + ptr += rval; + rest -= rval; + } + + return (int)( ptr - (char *)buf ); +} + + +struct prldap_eventmap_entry { + PRInt16 evm_nspr; /* corresponding NSPR PR_Poll() event */ + int evm_ldap; /* LDAP poll event */ +}; + +static struct prldap_eventmap_entry prldap_eventmap[] = { + { PR_POLL_READ, LDAP_X_POLLIN }, + { PR_POLL_EXCEPT, LDAP_X_POLLPRI }, + { PR_POLL_WRITE, LDAP_X_POLLOUT }, + { PR_POLL_ERR, LDAP_X_POLLERR }, + { PR_POLL_HUP, LDAP_X_POLLHUP }, + { PR_POLL_NVAL, LDAP_X_POLLNVAL }, +}; + +#define PRLDAP_EVENTMAP_ENTRIES \ + sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry ) + +static int LDAP_CALLBACK +prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout, + struct lextiof_session_private *sessionarg ) +{ + PRLDAPIOSessionArg *prsessp = sessionarg; + PRPollDesc *pds; + int i, j, rc; + + if ( NULL == prsessp ) { + prldap_set_system_errno( EINVAL ); + return( -1 ); + } + + /* allocate or resize NSPR poll descriptor array */ + if ( prsessp->prsess_pollds_count < nfds ) { + pds = prldap_safe_realloc( prsessp->prsess_pollds, + ( nfds + PRLDAP_POLL_ARRAY_GROWTH ) + * sizeof( PRPollDesc )); + if ( NULL == pds ) { + prldap_set_system_errno( prldap_prerr2errno()); + return( -1 ); + } + prsessp->prsess_pollds = pds; + prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH; + } else { + pds = prsessp->prsess_pollds; + } + + /* populate NSPR poll info. based on LDAP info. */ + for ( i = 0; i < nfds; ++i ) { + if ( NULL == fds[i].lpoll_socketarg ) { + pds[i].fd = NULL; + } else { + pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg ); + } + pds[i].in_flags = pds[i].out_flags = 0; + if ( fds[i].lpoll_fd >= 0 ) { + for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { + if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap ) + != 0 ) { + pds[i].in_flags |= prldap_eventmap[j].evm_nspr; + } + } + } + fds[i].lpoll_revents = 0; /* clear revents */ + } + + /* call PR_Poll() to do the real work */ + rc = PR_Poll( pds, nfds, + prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout )); + + /* populate LDAP info. based on NSPR results */ + for ( i = 0; i < nfds; ++i ) { + if ( pds[i].fd != NULL ) { + for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { + if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr ) + != 0 ) { + fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap; + } + } + } + } + + return( rc ); +} + + +/* + * Utility function to try one TCP connect() + * Returns 1 if successful and -1 if not. Sets the NSPR fd inside prsockp. + */ +static int +prldap_try_one_address( struct lextiof_socket_private *prsockp, + PRNetAddr *addrp, int timeout, unsigned long options ) +{ + /* + * Open a TCP socket: + */ + if (( prsockp->prsock_prfd = PR_OpenTCPSocket( + PR_NetAddrFamily(addrp) )) == NULL ) { + return( -1 ); + } + + /* + * Set nonblocking option if requested: + */ + if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) { + PRSocketOptionData optdata; + + optdata.option = PR_SockOpt_Nonblocking; + optdata.value.non_blocking = PR_TRUE; + if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata ) + != PR_SUCCESS ) { + prldap_set_system_errno( prldap_prerr2errno()); + PR_Close( prsockp->prsock_prfd ); + return( -1 ); + } + } + +#ifdef PRLDAP_DEBUG + { + char buf[ 256 ], *p, *fmtstr; + + if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) { + strcpy( buf, "conversion failed!" ); + } + if ( strncmp( buf, "::ffff:", 7 ) == 0 ) { + /* IPv4 address mapped into IPv6 address space */ + p = buf + 7; + fmtstr = "prldap_try_one_address(): Trying %s:%d...\n"; + } else { + p = buf; + fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n"; + } + fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port )); + } +#endif /* PRLDAP_DEBUG */ + + /* + * Try to open the TCP connection itself: + */ + if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp, + prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout )) + && PR_IN_PROGRESS_ERROR != PR_GetError() ) { + PR_Close( prsockp->prsock_prfd ); + prsockp->prsock_prfd = NULL; + return( -1 ); + } + +#ifdef PRLDAP_DEBUG + fputs( "prldap_try_one_address(): Connected.\n", stderr ); +#endif /* PRLDAP_DEBUG */ + + /* + * Success. Return a valid file descriptor (1 is always valid) + */ + return( 1 ); +} + + +/* + * XXXmcs: At present, this code ignores the timeout when doing DNS lookups. + */ +static int LDAP_CALLBACK +prldap_connect( const char *hostlist, int defport, int timeout, + unsigned long options, struct lextiof_session_private *sessionarg, + struct lextiof_socket_private **socketargp ) +{ + int rc, parse_err, port; + char *host; + struct ldap_x_hostlist_status *status; + struct lextiof_socket_private *prsockp; + PRNetAddr addr; + PRAddrInfo *infop = NULL; + + if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { + prldap_set_system_errno( EINVAL ); + return( -1 ); + } + + if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) { + prldap_set_system_errno( prldap_prerr2errno()); + return( -1 ); + } + + rc = -1; /* pessimistic */ + for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, + &status ); + rc < 0 && LDAP_SUCCESS == parse_err && NULL != host; + parse_err = ldap_x_hostlist_next( &host, &port, status )) { + /* + * First, call PR_GetAddrInfoByName; PR_GetAddrInfoByName could + * support both IPv4 and IPv6 addresses depending upon the system's + * configuration. All available addresses are returned and each of + * them is examined in prldap_try_one_address till it succeeds. + * Then, try converting the string address, in case the string + * address was not successfully handled in PR_GetAddrInfoByName. + */ + if ( NULL != ( infop = + PR_GetAddrInfoByName( host, PR_AF_UNSPEC, + (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME) ))) { + void *enump = NULL; + do { + memset( &addr, 0, sizeof( addr )); + enump = PR_EnumerateAddrInfo( enump, infop, port, &addr ); + if ( NULL == enump ) { + break; + } + rc = prldap_try_one_address( prsockp, &addr, timeout, options ); + } while ( rc < 0 ); + PR_FreeAddrInfo( infop ); + } else if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) { + PRLDAP_SET_PORT( &addr, port ); + rc = prldap_try_one_address( prsockp, &addr, timeout, options ); + } + ldap_memfree( host ); + } + + if ( host ) { + ldap_memfree( host ); + } + ldap_x_hostlist_statusfree( status ); + + if ( rc < 0 ) { + prldap_set_system_errno( prldap_prerr2errno()); + prldap_socket_arg_free( &prsockp ); + } else { + *socketargp = prsockp; + } + + return( rc ); +} + + +static int LDAP_CALLBACK +prldap_close( int s, struct lextiof_socket_private *socketarg ) +{ + int rc; + + rc = 0; + if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) { + rc = -1; + prldap_set_system_errno( prldap_prerr2errno()); + } + prldap_socket_arg_free( &socketarg ); + + return( rc ); +} + + +/* + * LDAP session handle creation callback. + * + * Allocate a session argument if not already done, and then call the + * thread's new handle function. + */ +static int LDAP_CALLBACK +prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + + if ( NULL == sessionarg ) { + struct ldap_x_ext_io_fns iofns; + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, + (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + if ( NULL == + ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { + return( LDAP_NO_MEMORY ); + } + if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, + (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + } + + return( LDAP_SUCCESS ); +} + + +/* only called/installed if shared is non-zero. */ +static int LDAP_CALLBACK +prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + int rc; + + if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) { + rc = prldap_thread_new_handle( ld, sessionarg ); + } + + return( rc ); +} + + +static void LDAP_CALLBACK +prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg ) +{ + prldap_session_arg_free( &sessionarg ); +} + + +/* only called/installed if shared is non-zero */ +static void LDAP_CALLBACK +prldap_shared_disposehandle( LDAP *ld, + struct lextiof_session_private *sessionarg ) +{ + prldap_thread_dispose_handle( ld, sessionarg ); + prldap_disposehandle( ld, sessionarg ); +} + + +/* + * Allocate a session argument. + */ +static PRLDAPIOSessionArg * +prldap_session_arg_alloc( void ) +{ + PRLDAPIOSessionArg *prsessp; + + prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg )); + + if ( NULL != prsessp ) { + /* copy global defaults to the new session handle */ + prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout; + } + + return( prsessp ); +} + + +static void +prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ) +{ + if ( NULL != prsesspp && NULL != *prsesspp ) { + if ( NULL != (*prsesspp)->prsess_pollds ) { + PR_Free( (*prsesspp)->prsess_pollds ); + (*prsesspp)->prsess_pollds = NULL; + } + PR_Free( *prsesspp ); + *prsesspp = NULL; + } +} + + +/* + * Given an LDAP session handle, retrieve a session argument. + * Returns an LDAP error code. + */ +int +prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ) +{ + struct ldap_x_ext_io_fns iofns; + + if ( NULL == ld || NULL == sessargpp ) { + /* XXXmcs: NULL ld's are not supported */ + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + if ( NULL == iofns.lextiof_session_arg ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + *sessargpp = iofns.lextiof_session_arg; + return( LDAP_SUCCESS ); +} + + +/* + * Given an LDAP session handle, retrieve a socket argument. + * Returns an LDAP error code. + */ +int +prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ) +{ + Sockbuf *sbp; + struct lber_x_ext_io_fns extiofns; + + if ( NULL == ld || NULL == sockargpp ) { + /* XXXmcs: NULL ld's are not supported */ + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + memset( &extiofns, 0, sizeof(extiofns)); + extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; + if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, + (void *)&extiofns ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + if ( NULL == extiofns.lbextiofn_socket_arg ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + *sockargpp = extiofns.lbextiofn_socket_arg; + return( LDAP_SUCCESS ); +} + + +/* + * Allocate a socket argument. + */ +PRLDAPIOSocketArg * +prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ) +{ + PRLDAPIOSocketArg *prsockp; + + prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg )); + + if ( NULL != prsockp && NULL != sessionarg ) { + /* copy socket defaults from the session */ + prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout; + } + + return( prsockp ); +} + + +static void +prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ) +{ + if ( NULL != prsockpp && NULL != *prsockpp ) { + PR_Free( *prsockpp ); + *prsockpp = NULL; + } +} + + +static void * +prldap_safe_realloc( void *ptr, PRUint32 size ) +{ + void *p; + + if ( NULL == ptr ) { + p = PR_Malloc( size ); + } else { + p = PR_Realloc( ptr, size ); + } + + return( p ); +} + + + +/* returns an LDAP result code */ +int +prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + + if ( NULL == prsessp ) { + prldap_default_io_max_timeout = io_max_timeout; + } else { + prsessp->prsess_io_max_timeout = io_max_timeout; + } + + return( rc ); +} + + +/* returns an LDAP result code */ +int +prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + + if ( NULL == io_max_timeoutp ) { + rc = LDAP_PARAM_ERROR; + } else if ( NULL == prsessp ) { + *io_max_timeoutp = prldap_default_io_max_timeout; + } else { + *io_max_timeoutp = prsessp->prsess_io_max_timeout; + } + + return( rc ); +} + +/* Check if NSPR layer has been installed for a LDAP session. + * Simply check whether prldap_connect() I/O function is installed + */ +PRBool +prldap_is_installed( LDAP *ld ) +{ + struct ldap_x_ext_io_fns iofns; + + /* Retrieve current I/O functions */ + memset( &iofns, 0, sizeof(iofns)); + iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; + if ( ld == NULL || ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) + != 0 || iofns.lextiof_connect != prldap_connect ) + { + return( PR_FALSE ); + } + + return( PR_TRUE ); +} + diff --git a/ldap/c-sdk/libprldap/ldappr-public.c b/ldap/c-sdk/libprldap/ldappr-public.c new file mode 100644 index 0000000000..6e9e597e6a --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-public.c @@ -0,0 +1,454 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Public interface for libprldap -- use NSPR (Netscape Portable Runtime) + * I/O, threads, etc. with libldap. + * + */ + +#include "ldappr-int.h" +#include + +/* + * Function: prldap_init(). + * + * Create a new LDAP session handle, but with NSPR I/O, threading, and DNS + * functions installed. + * + * Pass a non-zero value for the 'shared' parameter if you plan to use + * this LDAP * handle from more than one thread. + * + * prldap_init() returns an LDAP session handle (or NULL if an error occurs). + */ +LDAP * LDAP_CALL +prldap_init( const char *defhost, int defport, int shared ) +{ + LDAP *ld; + + if (( ld = ldap_init( defhost, defport )) != NULL ) { + if ( prldap_install_routines( ld, shared ) != LDAP_SUCCESS ) { + prldap_set_system_errno( EINVAL ); /* XXXmcs: just a guess! */ + ldap_unbind( ld ); + ld = NULL; + } + } + + return( ld ); +} + + +/* + * Function: prldap_install_routines(). + * + * Install NSPR I/O, threading, and DNS functions so they will be used by + * 'ld'. + * + * If 'ld' is NULL, the functions are installed as the default functions + * for all new LDAP * handles). + * + * Pass a non-zero value for the 'shared' parameter if you plan to use + * this LDAP * handle from more than one thread. + * + * prldap_install_routines() returns an LDAP API error code (LDAP_SUCCESS + * if all goes well). + */ +int LDAP_CALL +prldap_install_routines( LDAP *ld, int shared ) +{ + + if ( prldap_install_io_functions( ld, shared ) != 0 + || prldap_install_thread_functions( ld, shared ) != 0 + || prldap_install_dns_functions( ld ) != 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_set_session_option(). + * + * Given an LDAP session handle or a session argument such is passed to + * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, set + * an option that affects the prldap layer. + * + * If 'ld' and 'session" are both NULL, the option is set as the default + * for all new prldap sessions. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). + */ +int LDAP_CALL +prldap_set_session_option( LDAP *ld, void *sessionarg, int option, ... ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + PRLDAPIOSessionArg *prsessp = NULL; + va_list ap; + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { + return( rc ); + } + } else if ( NULL != sessionarg ) { + prsessp = (PRLDAPIOSessionArg *)sessionarg; + } + + va_start( ap, option ); + switch ( option ) { + case PRLDAP_OPT_IO_MAX_TIMEOUT: + rc = prldap_set_io_max_timeout( prsessp, va_arg( ap, int )); + break; + default: + rc = LDAP_PARAM_ERROR; + } + va_end( ap ); + + return( rc ); +} + + +/* + * Function: prldap_get_session_option(). + * + * Given an LDAP session handle or a session argument such is passed to + * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, retrieve + * the setting for an option that affects the prldap layer. + * + * If 'ld' and 'session" are both NULL, the default option value for all new + * new prldap sessions is retrieved. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). + */ +int LDAP_CALL prldap_get_session_option( LDAP *ld, void *sessionarg, + int option, ... ) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + PRLDAPIOSessionArg *prsessp = NULL; + va_list ap; + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { + return( rc ); + } + } else if ( NULL != sessionarg ) { + prsessp = (PRLDAPIOSessionArg *)sessionarg; + } + + va_start( ap, option ); + switch ( option ) { + case PRLDAP_OPT_IO_MAX_TIMEOUT: + rc = prldap_get_io_max_timeout( prsessp, va_arg( ap, int * )); + break; + default: + rc = LDAP_PARAM_ERROR; + } + va_end( ap ); + + return( rc ); +} + + +/* + * Function: prldap_set_session_info(). + * + * Given an LDAP session handle, set some application-specific data. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). + */ +int LDAP_CALL +prldap_set_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip ) +{ + int rc; + PRLDAPIOSessionArg *prsessp; + + if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { + return( rc ); + } + } else if ( NULL != sessionarg ) { + prsessp = (PRLDAPIOSessionArg *)sessionarg; + } else { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + prsessp->prsess_appdata = seip->seinfo_appdata; + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_get_session_info(). + * + * Given an LDAP session handle, retrieve some application-specific data. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in + * which case the fields in the structure that seip points to are filled in). + */ +int LDAP_CALL +prldap_get_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip ) +{ + int rc; + PRLDAPIOSessionArg *prsessp; + + if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { + return( rc ); + } + } else if ( NULL != sessionarg ) { + prsessp = (PRLDAPIOSessionArg *)sessionarg; + } else { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + seip->seinfo_appdata = prsessp->prsess_appdata; + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_set_socket_info(). + * + * Given an integer fd and a void * argument such as those passed to the + * extended I/O callback functions, set socket specific information. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). + * + * Note: it is only safe to change soinfo_prfd from within the SOCKET + * extended I/O callback function. + */ +int LDAP_CALL +prldap_set_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip ) +{ + PRLDAPIOSocketArg *prsockp; + + if ( NULL == socketarg || NULL == soip || + PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { + return( LDAP_PARAM_ERROR ); + } + + prsockp = (PRLDAPIOSocketArg *)socketarg; + prsockp->prsock_prfd = soip->soinfo_prfd; + prsockp->prsock_appdata = soip->soinfo_appdata; + + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_get_socket_info(). + * + * Given an integer fd and a void * argument such as those passed to the + * extended I/O callback functions, retrieve socket specific information. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in + * which case the fields in the structure that soip points to are filled in). + */ +int LDAP_CALL +prldap_get_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip ) +{ + PRLDAPIOSocketArg *prsockp; + + if ( NULL == socketarg || NULL == soip || + PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { + return( LDAP_PARAM_ERROR ); + } + + prsockp = (PRLDAPIOSocketArg *)socketarg; + soip->soinfo_prfd = prsockp->prsock_prfd; + soip->soinfo_appdata = prsockp->prsock_appdata; + + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_get_default_socket_info(). + * + * Given an LDAP session handle, retrieve socket specific information. + * If ld is NULL, LDAP_PARAM_ERROR is returned. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in + * which case the fields in the structure that soip points to are filled in). + */ +int LDAP_CALL +prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ) +{ + int rc; + PRLDAPIOSocketArg *prsockp; + + + if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) { + return( rc ); + } + } else { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + soip->soinfo_prfd = prsockp->prsock_prfd; + soip->soinfo_appdata = prsockp->prsock_appdata; + + return( LDAP_SUCCESS ); +} + + +/* + * Function: prldap_set_default_socket_info(). + * + * Given an LDAP session handle, set socket specific information. + * If ld is NULL, LDAP_PARAM_ERROR is returned. + * + * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in + * which case the fields in the structure that soip points to are filled in). + */ +int LDAP_CALL +prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ) +{ + int rc; + PRLDAPIOSocketArg *prsockp; + + + if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + if ( NULL != ld ) { + if ( LDAP_SUCCESS != + ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) { + return( rc ); + } + } else { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + prsockp->prsock_prfd = soip->soinfo_prfd; + prsockp->prsock_appdata = soip->soinfo_appdata; + + return( LDAP_SUCCESS ); +} + + +/* +* Function: prldap_import_connection(). +* +* Given the LDAP handle the connection parameters for the +* file descriptor are imported into NSPR layer. +* +* Returns an LDAP API code (LDAP_SUCCESS) if all goes well. +*/ +int LDAP_CALL +prldap_import_connection (LDAP *ld) +{ + int rc = LDAP_SUCCESS; /* optimistic */ + int shared = 1; /* Assume shared init */ + LBER_SOCKET orig_socket = -1; + PRLDAPIOSessionArg *prsessp = NULL; + PRLDAPIOSocketArg *prsockp = NULL; + PRFileDesc *pr_socket = NULL; + + /* Check for invalid ld handle */ + if ( ld == NULL) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); + return( LDAP_PARAM_ERROR ); + } + + /* Retrieve TCP socket's integer file descriptor */ + if ( ldap_get_option( ld, LDAP_OPT_DESC, &orig_socket ) < 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + /* Check for NSPR functions on ld */ + if ( prldap_is_installed(ld)) { /* Error : NSPR already Installed */ + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + if (LDAP_SUCCESS != (rc = prldap_install_routines(ld, shared))) { + return( rc ); + } + + if (LDAP_SUCCESS != (rc = prldap_session_arg_from_ld( ld, &prsessp ))) { + return( rc ); + } + + /* Get NSPR Socket Arg */ + if ( NULL == ( prsockp = prldap_socket_arg_alloc( prsessp ))) { + ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + + /* Import file descriptor of connection made via ldap_init() */ + if (NULL == (pr_socket = PR_ImportTCPSocket(orig_socket)) ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( LDAP_LOCAL_ERROR ); + } + + prsockp->prsock_prfd = pr_socket; + + /* Set Socket Arg in Extended I/O Layer */ + if ( ldap_set_option( ld, LDAP_X_OPT_SOCKETARG, prsockp) != 0 ) { + return( ldap_get_lderrno( ld, NULL, NULL )); + } + + return( rc ); +} diff --git a/ldap/c-sdk/libprldap/ldappr-threads.c b/ldap/c-sdk/libprldap/ldappr-threads.c new file mode 100644 index 0000000000..1cfdc92635 --- /dev/null +++ b/ldap/c-sdk/libprldap/ldappr-threads.c @@ -0,0 +1,643 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Thread callback functions for libldap that use the NSPR (Netscape + * Portable Runtime) thread API. + * + */ + +#include "ldappr-int.h" + +/* + * Macros: + */ +/* + * Grow thread private data arrays 10 elements at a time. + */ +#define PRLDAP_TPD_ARRAY_INCREMENT 10 + +/* + * Structures and types: + */ +/* + * Structure used by libldap thread callbacks to maintain error information. + */ +typedef struct prldap_errorinfo { + int plei_magic; /* must be first in the structure */ + int plei_lderrno; + char *plei_matched; + char *plei_errmsg; +} PRLDAP_ErrorInfo; + +#define PRLDAP_ERRORINFO_MAGIC 0x4D4F5A45 /* 'MOZE' */ + + +/* + * Structure used to maintain thread-private data. At the present time, + * only error info. is thread-private. One of these structures is allocated + * for each thread. + */ +typedef struct prldap_tpd_header { + int ptpdh_tpd_count; /* # of data items allocated */ + void **ptpdh_dataitems; /* array of data items */ +} PRLDAP_TPDHeader; + +/* + * Structure used by associate a PRLDAP thread-private data index with an + * LDAP session handle. One of these exists for each active LDAP session + * handle. + */ +typedef struct prldap_tpd_map { + LDAP *prtm_ld; /* non-NULL if in use */ + PRUintn prtm_index; /* index into TPD array */ + struct prldap_tpd_map *prtm_next; +} PRLDAP_TPDMap; + + + +/* + * Static Variables: + */ +/* + * prldap_map_list points to all of the PRLDAP_TPDMap structures + * we have ever allocated. We recycle them as we open and close LDAP + * sessions. + */ +static PRLDAP_TPDMap *prldap_map_list = NULL; + + +/* + * The prldap_map_mutex is used to protect access to the prldap_map_list. + */ +static PRLock *prldap_map_mutex = NULL; + +/* + * The prldap_tpd_maxindex value is used to track the largest TPD array + * index we have used. + */ +static PRInt32 prldap_tpd_maxindex = -1; + +/* + * prldap_tpdindex is an NSPR thread private data index we use to + * maintain our own thread-private data. It is initialized inside + * prldap_init_tpd(). + */ +static PRUintn prldap_tpdindex = 0; + +/* + * The prldap_callonce_init_tpd structure is used by NSPR to ensure + * that prldap_init_tpd() is called at most once. + */ +static PRCallOnceType prldap_callonce_init_tpd = { 0, 0, 0 }; + + +/* + * Private function prototypes: + */ +static void prldap_set_ld_error( int err, char *matched, char *errmsg, + void *errorarg ); +static int prldap_get_ld_error( char **matchedp, char **errmsgp, + void *errorarg ); +static void *prldap_mutex_alloc( void ); +static void prldap_mutex_free( void *mutex ); +static int prldap_mutex_lock( void *mutex ); +static int prldap_mutex_unlock( void *mutex ); +static void *prldap_get_thread_id( void ); +static PRStatus prldap_init_tpd( void ); +static PRLDAP_TPDMap *prldap_allocate_map( LDAP *ld ); +static void prldap_return_map( PRLDAP_TPDMap *map ); +static PRUintn prldap_new_tpdindex( void ); +static int prldap_set_thread_private( PRInt32 tpdindex, void *priv ); +static void *prldap_get_thread_private( PRInt32 tpdindex ); +static PRLDAP_TPDHeader *prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, + int maxindex ); +static void prldap_tsd_destroy( void *priv ); + + +/* + * Install NSPR thread functions into ld (if ld is NULL, they are installed + * as the default functions for new LDAP * handles). + * + * Returns 0 if all goes well and -1 if not. + */ +int +prldap_install_thread_functions( LDAP *ld, int shared ) +{ + struct ldap_thread_fns tfns; + struct ldap_extra_thread_fns xtfns; + + if ( PR_CallOnce( &prldap_callonce_init_tpd, prldap_init_tpd ) + != PR_SUCCESS ) { + ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); + return( -1 ); + } + + /* set thread function pointers */ + memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); + tfns.ltf_get_errno = prldap_get_system_errno; + tfns.ltf_set_errno = prldap_set_system_errno; + if ( shared ) { + tfns.ltf_mutex_alloc = prldap_mutex_alloc; + tfns.ltf_mutex_free = prldap_mutex_free; + tfns.ltf_mutex_lock = prldap_mutex_lock; + tfns.ltf_mutex_unlock = prldap_mutex_unlock; + tfns.ltf_get_lderrno = prldap_get_ld_error; + tfns.ltf_set_lderrno = prldap_set_ld_error; + if ( ld != NULL ) { + /* + * If this is a real ld (i.e., we are not setting the global + * defaults) allocate thread private data for error information. + * If ld is NULL we do not do this here but it is done in + * prldap_thread_new_handle(). + */ + if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) + == NULL ) { + return( -1 ); + } + } + } + + if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, + (void *)&tfns ) != 0 ) { + prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); + return( -1 ); + } + + /* set extended thread function pointers */ + memset( &xtfns, '\0', sizeof(struct ldap_extra_thread_fns) ); + xtfns.ltf_threadid_fn = prldap_get_thread_id; + if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, + (void *)&xtfns ) != 0 ) { + return( -1 ); + } + + return( 0 ); +} + + +static void * +prldap_mutex_alloc( void ) +{ + return( (void *)PR_NewLock()); +} + + +static void +prldap_mutex_free( void *mutex ) +{ + PR_DestroyLock( (PRLock *)mutex ); +} + + +static int +prldap_mutex_lock( void *mutex ) +{ + PR_Lock( (PRLock *)mutex ); + return( 0 ); +} + + +static int +prldap_mutex_unlock( void *mutex ) +{ + if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) { + return( -1 ); + } + + return( 0 ); +} + + +static void * +prldap_get_thread_id( void ) +{ + return( (void *)PR_GetCurrentThread()); +} + + +static int +prldap_get_ld_error( char **matchedp, char **errmsgp, void *errorarg ) +{ + PRLDAP_TPDMap *map; + PRLDAP_ErrorInfo *eip; + + if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL && ( eip = + (PRLDAP_ErrorInfo *)prldap_get_thread_private( + map->prtm_index )) != NULL ) { + if ( matchedp != NULL ) { + *matchedp = eip->plei_matched; + } + if ( errmsgp != NULL ) { + *errmsgp = eip->plei_errmsg; + } + return( eip->plei_lderrno ); + } else { + if ( matchedp != NULL ) { + *matchedp = NULL; + } + if ( errmsgp != NULL ) { + *errmsgp = NULL; + } + return( LDAP_LOCAL_ERROR ); /* punt */ + } +} + + +static void +prldap_set_ld_error( int err, char *matched, char *errmsg, void *errorarg ) +{ + PRLDAP_TPDMap *map; + PRLDAP_ErrorInfo *eip; + + if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL ) { + if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( + map->prtm_index )) == NULL ) { + /* + * Error info. has not yet been allocated for this thread. + * Do so now. Note that we free this memory only for the + * thread that calls prldap_thread_dispose_handle(), which + * should be the one that called ldap_unbind() -- see + * prldap_return_map(). Not freeing the memory used by + * other threads is deemed acceptable since it will be + * recycled and used by other LDAP sessions. All of the + * thread-private memory is freed when a thread exits + * (inside the prldap_tsd_destroy() function). + */ + eip = (PRLDAP_ErrorInfo *)PR_Calloc( 1, + sizeof( PRLDAP_ErrorInfo )); + if ( eip == NULL ) { + return; /* punt */ + } + eip->plei_magic = PRLDAP_ERRORINFO_MAGIC; + (void)prldap_set_thread_private( map->prtm_index, eip ); + } + + eip->plei_lderrno = err; + + if ( eip->plei_matched != NULL ) { + ldap_memfree( eip->plei_matched ); + } + eip->plei_matched = matched; + + if ( eip->plei_errmsg != NULL ) { + ldap_memfree( eip->plei_errmsg ); + } + eip->plei_errmsg = errmsg; + } +} + + +/* + * Utility function to free a PRLDAP_ErrorInfo structure and everything + * it contains. + */ +static void +prldap_free_errorinfo( PRLDAP_ErrorInfo *eip ) +{ + if ( NULL != eip && PRLDAP_ERRORINFO_MAGIC == eip->plei_magic ) { + if ( eip->plei_matched != NULL ) { + ldap_memfree( eip->plei_matched ); + } + if ( eip->plei_errmsg != NULL ) { + ldap_memfree( eip->plei_errmsg ); + } + + PR_Free( eip ); + } +} + + +/* + * Called when a new LDAP * session handle is allocated. + * Allocate thread-private data for error information, but only if + * it has not already been allocated and the get_ld_error callback has + * been installed. If ld is not NULL when prldap_install_thread_functions() + * is called, we will have already allocated the thread-private data there. + */ +int +prldap_thread_new_handle( LDAP *ld, void *sessionarg ) +{ + struct ldap_thread_fns tfns; + + if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *)&tfns ) != 0 ) { + return( LDAP_LOCAL_ERROR ); + } + + if ( tfns.ltf_lderrno_arg == NULL && tfns.ltf_get_lderrno != NULL ) { + if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) == NULL + || ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, + (void *)&tfns ) != 0 ) { + return( LDAP_LOCAL_ERROR ); + } + } + + return( LDAP_SUCCESS ); +} + + +/* + * Called when an LDAP * session handle is being destroyed. + * Clean up our thread private data map. + */ +void +prldap_thread_dispose_handle( LDAP *ld, void *sessionarg ) +{ + struct ldap_thread_fns tfns; + + if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, + (void *)&tfns ) == 0 && + tfns.ltf_lderrno_arg != NULL ) { + prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); + } +} + + +static PRStatus +prldap_init_tpd( void ) +{ + if (( prldap_map_mutex = PR_NewLock()) == NULL || PR_NewThreadPrivateIndex( + &prldap_tpdindex, prldap_tsd_destroy ) != PR_SUCCESS ) { + return( PR_FAILURE ); + } + + prldap_map_list = NULL; + + return( PR_SUCCESS ); +} + + +/* + * Function: prldap_allocate_map() + * Description: allocate a thread-private data map to use for a new + * LDAP session handle. + * Returns: a pointer to the TPD map or NULL if none available. + */ +static PRLDAP_TPDMap * +prldap_allocate_map( LDAP *ld ) +{ + PRLDAP_TPDMap *map, *prevmap; + + PR_Lock( prldap_map_mutex ); + + /* + * first look for a map that is already allocated but free to be re-used + */ + prevmap = NULL; + for ( map = prldap_map_list; map != NULL; map = map->prtm_next ) { + if ( map->prtm_ld == NULL ) { + break; + } + prevmap = map; + } + + /* + * if none was found (map == NULL), try to allocate a new one and add it + * to the end of our global list. + */ + if ( map == NULL ) { + PRUintn tpdindex; + + tpdindex = prldap_new_tpdindex(); + map = (PRLDAP_TPDMap *)PR_Malloc( sizeof( PRLDAP_TPDMap )); + if ( map != NULL ) { + map->prtm_index = tpdindex; + map->prtm_next = NULL; + if ( prevmap == NULL ) { + prldap_map_list = map; + } else { + prevmap->prtm_next = map; + } + } + } + + if ( map != NULL ) { + map->prtm_ld = ld; /* now marked as "in use" */ + + /* + * If old thread-private error information exists, reset it. It may + * have been left behind by an old LDAP session that was used by + * this thread but disposed of by a different thread. + */ + if ( NULL != prldap_get_thread_private( map->prtm_index )) { + prldap_set_ld_error( LDAP_SUCCESS, NULL, NULL, map ); + } + } + + PR_Unlock( prldap_map_mutex ); + + return( map ); +} + + +/* + * Function: prldap_return_map() + * Description: return a thread-private data map to the pool of ones + * available for re-use. + */ +static void +prldap_return_map( PRLDAP_TPDMap *map ) +{ + PRLDAP_ErrorInfo *eip; + + PR_Lock( prldap_map_mutex ); + + /* + * Dispose of thread-private LDAP error information. Note that this + * only disposes of the memory consumed on THIS thread, but that is + * okay. See the comment in prldap_set_ld_error() for the reason why. + */ + if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( + map->prtm_index )) != NULL && + prldap_set_thread_private( map->prtm_index, NULL ) == 0 ) { + prldap_free_errorinfo( eip ); + } + + /* mark map as available for re-use */ + map->prtm_ld = NULL; + + PR_Unlock( prldap_map_mutex ); +} + + +/* + * Function: prldap_new_tpdindex() + * Description: allocate a thread-private data index. + * Returns: the new index. + */ +static PRUintn +prldap_new_tpdindex( void ) +{ + PRUintn tpdindex; + + tpdindex = (PRUintn)PR_AtomicIncrement( &prldap_tpd_maxindex ); + return( tpdindex ); +} + + +/* + * Function: prldap_set_thread_private() + * Description: store a piece of thread-private data. + * Returns: 0 if successful and -1 if not. + */ +static int +prldap_set_thread_private( PRInt32 tpdindex, void *priv ) +{ + PRLDAP_TPDHeader *tsdhdr; + + if ( tpdindex > prldap_tpd_maxindex ) { + return( -1 ); /* bad index */ + } + + tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); + if ( tsdhdr == NULL || tpdindex >= tsdhdr->ptpdh_tpd_count ) { + tsdhdr = prldap_tsd_realloc( tsdhdr, tpdindex ); + if ( tsdhdr == NULL ) { + return( -1 ); /* realloc failed */ + } + } + + tsdhdr->ptpdh_dataitems[ tpdindex ] = priv; + return( 0 ); +} + + +/* + * Function: prldap_get_thread_private() + * Description: retrieve a piece of thread-private data. If not set, + * NULL is returned. + * Returns: 0 if successful and -1 if not. + */ +static void * +prldap_get_thread_private( PRInt32 tpdindex ) +{ + PRLDAP_TPDHeader *tsdhdr; + + tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); + if ( tsdhdr == NULL ) { + return( NULL ); /* no thread private data */ + } + + if ( tpdindex >= tsdhdr->ptpdh_tpd_count + || tsdhdr->ptpdh_dataitems == NULL ) { + return( NULL ); /* fewer data items than requested index */ + } + + return( tsdhdr->ptpdh_dataitems[ tpdindex ] ); +} + + +/* + * Function: prldap_tsd_realloc() + * Description: enlarge the thread-private data array. + * Returns: the new PRLDAP_TPDHeader value (non-NULL if successful). + * Note: tsdhdr can be NULL (allocates a new PRLDAP_TPDHeader). + */ +static PRLDAP_TPDHeader * +prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, int maxindex ) +{ + void *newdataitems = NULL; + int count; + + if ( tsdhdr == NULL ) { + /* allocate a new thread private data header */ + if (( tsdhdr = PR_Calloc( 1, sizeof( PRLDAP_TPDHeader ))) == NULL ) { + return( NULL ); + } + (void)PR_SetThreadPrivate( prldap_tpdindex, tsdhdr ); + } + + /* + * Make the size of the new array the next highest multiple of + * the array increment value that is greater than maxindex. + */ + count = PRLDAP_TPD_ARRAY_INCREMENT * + ( 1 + ( maxindex / PRLDAP_TPD_ARRAY_INCREMENT )); + + /* increase the size of the data item array if necessary */ + if ( count > tsdhdr->ptpdh_tpd_count ) { + newdataitems = (PRLDAP_ErrorInfo *)PR_Calloc( count, sizeof( void * )); + if ( newdataitems == NULL ) { + return( NULL ); + } + if ( tsdhdr->ptpdh_dataitems != NULL ) { /* preserve old data */ + memcpy( newdataitems, tsdhdr->ptpdh_dataitems, + tsdhdr->ptpdh_tpd_count * sizeof( void * )); + PR_Free( tsdhdr->ptpdh_dataitems ); + } + + tsdhdr->ptpdh_tpd_count = count; + tsdhdr->ptpdh_dataitems = newdataitems; + } + + return( tsdhdr ); +} + + +/* + * Function: prldap_tsd_destroy() + * Description: Free a thread-private data array. Installed as an NSPR TPD + * destructor function + * Returns: nothing. + */ +static void +prldap_tsd_destroy( void *priv ) +{ + PRLDAP_TPDHeader *tsdhdr; + PRLDAP_ErrorInfo *eip; + int i; + + tsdhdr = (PRLDAP_TPDHeader *)priv; + if ( tsdhdr != NULL ) { + if ( tsdhdr->ptpdh_dataitems != NULL ) { + for ( i = 0; i < tsdhdr->ptpdh_tpd_count; ++i ) { + if ( tsdhdr->ptpdh_dataitems[ i ] != NULL ) { + eip = (PRLDAP_ErrorInfo *)tsdhdr->ptpdh_dataitems[ i ]; + if ( PRLDAP_ERRORINFO_MAGIC == eip->plei_magic ) { + prldap_free_errorinfo( eip ); + } else { + PR_Free( tsdhdr->ptpdh_dataitems[ i ] ); + } + tsdhdr->ptpdh_dataitems[ i ] = NULL; + } + } + PR_Free( tsdhdr->ptpdh_dataitems ); + tsdhdr->ptpdh_dataitems = NULL; + } + PR_Free( tsdhdr ); + } +} diff --git a/ldap/c-sdk/libprldap/libprldap.def b/ldap/c-sdk/libprldap/libprldap.def new file mode 100644 index 0000000000..a18e7ee824 --- /dev/null +++ b/ldap/c-sdk/libprldap/libprldap.def @@ -0,0 +1,59 @@ +; +; ***** BEGIN LICENSE BLOCK ***** +; Version: MPL 1.1/GPL 2.0/LGPL 2.1 +; +; The contents of this file are subject to the Mozilla Public License Version +; 1.1 (the "License"); you may not use this file except in compliance with +; the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" basis, +; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +; for the specific language governing rights and limitations under the +; License. +; +; The Original Code is Mozilla Communicator client code. +; +; The Initial Developer of the Original Code is +; Netscape Communications Corporation. +; Portions created by the Initial Developer are Copyright (C) 1996-1999 +; the Initial Developer. All Rights Reserved. +; +; Contributor(s): +; +; Alternatively, the contents of this file may be used under the terms of +; either of the GNU General Public License Version 2 or later (the "GPL"), +; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +; in which case the provisions of the GPL or the LGPL are applicable instead +; of those above. If you wish to allow use of your version of this file only +; under the terms of either the GPL or the LGPL, and not to allow others to +; use your version of this file under the terms of the MPL, indicate your +; decision by deleting the provisions above and replace them with the notice +; and other provisions required by the GPL or the LGPL. If you do not delete +; the provisions above, a recipient may use your version of this file under +; the terms of any one of the MPL, the GPL or the LGPL. +; +; ***** END LICENSE BLOCK ***** + +LIBRARY PRLDAP60 +VERSION 6.0 +HEAPSIZE 4096 + +EXPORTS +; exports list (generated by genexports.pl) +; + + prldap_init + prldap_install_routines + prldap_set_session_info + prldap_get_session_info + prldap_set_socket_info + prldap_get_socket_info + prldap_set_session_option + prldap_get_session_option + prldap_is_installed + prldap_import_connection + prldap_set_default_socket_info + prldap_get_default_socket_info +; +; end of generated exports list. diff --git a/ldap/c-sdk/libprldap/moz.build b/ldap/c-sdk/libprldap/moz.build new file mode 100644 index 0000000000..4b096a73fe --- /dev/null +++ b/ldap/c-sdk/libprldap/moz.build @@ -0,0 +1,31 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include('../common.mozbuild') + +SharedLibrary('prldap60') + +SOURCES += [ + 'ldappr-dns.c', + 'ldappr-error.c', + 'ldappr-io.c', + 'ldappr-public.c', + 'ldappr-threads.c', +] + +if CONFIG['OS_ARCH'] == 'WINNT': + DEFFILE = SRCDIR + '/libprldap.def' + +DEFINES['USE_WAITPID'] = True +DEFINES['NEEDPROTOS'] = True + +LOCAL_INCLUDES += [ + '../include' +] + +USE_LIBS += [ + 'ldap60', + 'nspr' +] diff --git a/ldap/c-sdk/libraries/liblber/bprint.c b/ldap/c-sdk/libraries/liblber/bprint.c deleted file mode 100644 index 7a7ccc01f2..0000000000 --- a/ldap/c-sdk/libraries/liblber/bprint.c +++ /dev/null @@ -1,102 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* bprint.c - a printing utility for debuging output */ -#include -#include "lber-int.h" - -#ifdef LDAP_DEBUG -/* - * Print arbitrary stuff, for debugging. - */ - -#define BPLEN 48 - -void -lber_bprint( char *data, int len ) -{ - static char hexdig[] = "0123456789abcdef"; - char out[ BPLEN ]; - int i = 0; - - memset( out, 0, BPLEN ); - for ( ;; ) { - if ( len < 1 ) { - char msg[BPLEN + 80]; - sprintf( msg, "\t%s\n", ( i == 0 ) ? "(end)" : out ); - ber_err_print( msg ); - break; - } - -#ifndef HEX - if ( isgraph( (unsigned char)*data )) { - out[ i ] = ' '; - out[ i+1 ] = *data; - } else { -#endif - out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; - out[ i+1 ] = hexdig[ *data & 0x0f ]; -#ifndef HEX - } -#endif - i += 2; - len--; - data++; - - if ( i > BPLEN - 2 ) { - char msg[BPLEN + 80]; - sprintf( msg, "\t%s\n", out ); - ber_err_print( msg ); - memset( out, 0, BPLEN ); - i = 0; - continue; - } - out[ i++ ] = ' '; - } -} - -#endif - -void ber_err_print( char *data ) -{ -#ifdef USE_DEBUG_WIN - OutputDebugString( data ); -#else - fputs( data, stderr ); - fflush( stderr ); -#endif -} diff --git a/ldap/c-sdk/libraries/liblber/decode.c b/ldap/c-sdk/libraries/liblber/decode.c deleted file mode 100644 index 732dd6e646..0000000000 --- a/ldap/c-sdk/libraries/liblber/decode.c +++ /dev/null @@ -1,833 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ - -/* decode.c - ber input decoding routines */ - -#include "lber-int.h" - -/* - * Note: ber_get_tag() only uses the ber_end and ber_ptr elements of ber. - * If that changes, the ber_peek_tag() and/or ber_skip_tag() implementations - * will need to be changed. - */ -/* return the tag - LBER_DEFAULT returned means trouble */ -ber_tag_t -LDAP_CALL -ber_get_tag( BerElement *ber ) -{ - unsigned char xbyte; - ber_tag_t tag; - char *tagp; - int i; - - if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) - return( LBER_DEFAULT ); - - if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) - return( (ber_uint_t) xbyte ); - - tagp = (char *) &tag; - tagp[0] = xbyte; - for ( i = 1; i < sizeof(ber_int_t); i++ ) { - if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) - return( LBER_DEFAULT ); - - tagp[i] = xbyte; - - if ( ! (xbyte & LBER_MORE_TAG_MASK) ) - break; - } - - /* tag too big! */ - if ( i == sizeof(ber_int_t) ) - return( LBER_DEFAULT ); - - /* want leading, not trailing 0's */ - return( tag >> (sizeof(ber_int_t) - i - 1) ); -} - -/* - * Note: ber_skip_tag() only uses the ber_end and ber_ptr elements of ber. - * If that changes, the implementation of ber_peek_tag() will need to - * be changed. - */ -ber_tag_t -LDAP_CALL -ber_skip_tag( BerElement *ber, ber_len_t *len ) -{ - ber_tag_t tag; - unsigned char lc; - int noctets, diff; - ber_len_t netlen; - - /* - * Any ber element looks like this: tag length contents. - * Assuming everything's ok, we return the tag byte (we - * can assume a single byte), and return the length in len. - * - * Assumptions: - * 1) definite lengths - * 2) primitive encodings used whenever possible - */ - - /* - * First, we read the tag. - */ - - if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - - /* - * Next, read the length. The first byte contains the length of - * the length. If bit 8 is set, the length is the long form, - * otherwise it's the short form. We don't allow a length that's - * greater than what we can hold in an unsigned long. - */ - - *len = netlen = 0; - if ( ber_read( ber, (char *) &lc, 1 ) != 1 ) - return( LBER_DEFAULT ); - if ( lc & 0x80 ) { - noctets = (lc & 0x7f); - if ( noctets > sizeof(ber_uint_t) ) - return( LBER_DEFAULT ); - diff = sizeof(ber_int_t) - noctets; - if ( ber_read( ber, (char *) &netlen + diff, noctets ) - != noctets ) - return( LBER_DEFAULT ); - *len = LBER_NTOHL( netlen ); - } else { - *len = lc; - } - - return( tag ); -} - - -/* - * Note: Previously, we passed the "ber" parameter directly to ber_skip_tag(), - * saving and restoring the ber_ptr element only. We now take advantage - * of the fact that the only ber structure elements touched by ber_skip_tag() - * are ber_end and ber_ptr. If that changes, this code must change too. - */ -ber_tag_t -LDAP_CALL -ber_peek_tag( BerElement *ber, ber_len_t *len ) -{ - BerElement bercopy; - - bercopy.ber_end = ber->ber_end; - bercopy.ber_ptr = ber->ber_ptr; - return( ber_skip_tag( &bercopy, len )); -} - -static int -ber_getnint( BerElement *ber, ber_int_t *num, ber_slen_t len ) -{ - int i; - ber_int_t value; - unsigned char buffer[sizeof(ber_int_t)]; - /* - * The tag and length have already been stripped off. We should - * be sitting right before len bytes of 2's complement integer, - * ready to be read straight into an int. We may have to sign - * extend after we read it in. - */ - - if ( len > sizeof(ber_slen_t) ) - return( -1 ); - - /* read into the low-order bytes of netnum */ - if ( ber_read( ber, (char *) buffer, len ) != len ) - return( -1 ); - - /* This sets the required sign extension */ - if ( len != 0) { - value = 0x80 & buffer[0] ? (-1) : 0; - } else { - value = 0; - } - - for ( i = 0; i < len; i++ ) - value = (value << 8) | buffer[i]; - - *num = value; - - return( len ); -} - -ber_tag_t -LDAP_CALL -ber_get_int( BerElement *ber, ber_int_t *num ) -{ - ber_tag_t tag; - ber_len_t len; - - if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - - /* - * len is being demoted to a long here -- possible conversion error - */ - - if ( ber_getnint( ber, num, (int)len ) != (ber_slen_t)len ) - return( LBER_DEFAULT ); - else - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_stringb( BerElement *ber, char *buf, ber_len_t *len ) -{ - ber_len_t datalen; - ber_tag_t tag; -#ifdef STR_TRANSLATION - char *transbuf; -#endif /* STR_TRANSLATION */ - - if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - if ( datalen > (*len - 1) ) - return( LBER_DEFAULT ); - - /* - * datalen is being demoted to a long here -- possible conversion error - */ - - if ( ber_read( ber, buf, datalen ) != (ber_slen_t) datalen ) - return( LBER_DEFAULT ); - - buf[datalen] = '\0'; - -#ifdef STR_TRANSLATION - if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) - != 0 && ber->ber_decode_translate_proc != NULL ) { - transbuf = buf; - ++datalen; - if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen, - 0 ) != 0 ) { - return( LBER_DEFAULT ); - } - if ( datalen > *len ) { - NSLBERI_FREE( transbuf ); - return( LBER_DEFAULT ); - } - SAFEMEMCPY( buf, transbuf, datalen ); - NSLBERI_FREE( transbuf ); - --datalen; - } -#endif /* STR_TRANSLATION */ - - *len = datalen; - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_stringa( BerElement *ber, char **buf ) -{ - ber_len_t datalen, ndatalen; - ber_tag_t tag; - - if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - - if ( ((ndatalen = (size_t)datalen + 1) < (size_t) datalen) || - ( datalen > (ber->ber_end - ber->ber_ptr) ) || - ( (*buf = (char *)NSLBERI_MALLOC( (size_t)ndatalen )) == NULL )) - return( LBER_DEFAULT ); - - /* - * datalen is being demoted to a long here -- possible conversion error - */ - if ( ber_read( ber, *buf, datalen ) != (ber_slen_t) datalen ) { - NSLBERI_FREE( *buf ); - *buf = NULL; - return( LBER_DEFAULT ); - } - - (*buf)[datalen] = '\0'; - -#ifdef STR_TRANSLATION - if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) - != 0 && ber->ber_decode_translate_proc != NULL ) { - ++datalen; - if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 ) - != 0 ) { - NSLBERI_FREE( *buf ); - *buf = NULL; - return( LBER_DEFAULT ); - } - } -#endif /* STR_TRANSLATION */ - - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_stringal( BerElement *ber, struct berval **bv ) -{ - ber_len_t len, nlen; - ber_tag_t tag; - - if ( (*bv = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) - == NULL ) { - return( LBER_DEFAULT ); - } - - (*bv)->bv_val = NULL; - (*bv)->bv_len = 0; - - if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) { - NSLBERI_FREE( *bv ); - *bv = NULL; - return( LBER_DEFAULT ); - } - - if ( ((nlen = (size_t) len + 1) < (size_t)len) || - ( len > (ber->ber_end - ber->ber_ptr) ) || - (((*bv)->bv_val = (char *)NSLBERI_MALLOC( (size_t)nlen )) - == NULL )) { - NSLBERI_FREE( *bv ); - *bv = NULL; - return( LBER_DEFAULT ); - } - - /* - * len is being demoted to a long here -- possible conversion error - */ - if ( ber_read( ber, (*bv)->bv_val, len ) != (ber_slen_t) len ) { - NSLBERI_FREE( (*bv)->bv_val ); - (*bv)->bv_val = NULL; - NSLBERI_FREE( *bv ); - *bv = NULL; - return( LBER_DEFAULT ); - } - - ((*bv)->bv_val)[len] = '\0'; - (*bv)->bv_len = len; - -#ifdef STR_TRANSLATION - if ( len > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) != 0 - && ber->ber_decode_translate_proc != NULL ) { - ++len; - if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val), - &len, 1 ) != 0 ) { - NSLBERI_FREE( (*bv)->bv_val ); - (*bv)->bv_val = NULL; - NSLBERI_FREE( *bv ); - *bv = NULL; - return( LBER_DEFAULT ); - } - (*bv)->bv_len = len - 1; - } -#endif /* STR_TRANSLATION */ - - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_bitstringa( BerElement *ber, char **buf, ber_len_t *blen ) -{ - ber_len_t datalen; - ber_tag_t tag; - unsigned char unusedbits; - - if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - --datalen; - - if ( (datalen > (ber->ber_end - ber->ber_ptr)) || - ( (*buf = (char *)NSLBERI_MALLOC((size_t)datalen )) == NULL ) ) - return( LBER_DEFAULT ); - - if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) { - NSLBERI_FREE( *buf ); - *buf = NULL; - return( LBER_DEFAULT ); - } - - /* - * datalen is being demoted to a long here -- possible conversion error - */ - if ( ber_read( ber, *buf, datalen ) != (ber_slen_t) datalen ) { - NSLBERI_FREE( *buf ); - *buf = NULL; - return( LBER_DEFAULT ); - } - - *blen = datalen * 8 - unusedbits; - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_null( BerElement *ber ) -{ - ber_len_t len; - ber_tag_t tag; - - if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) - return( LBER_DEFAULT ); - - if ( len != 0 ) - return( LBER_DEFAULT ); - - return( tag ); -} - -ber_tag_t -LDAP_CALL -ber_get_boolean( BerElement *ber, ber_int_t *boolval ) -{ - int rc; - - rc = ber_get_int( ber, boolval ); - - return( rc ); -} - -ber_tag_t -LDAP_CALL -ber_first_element( BerElement *ber, ber_len_t *len, char **last ) -{ - /* skip the sequence header, use the len to mark where to stop */ - if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { - return( LBER_ERROR ); - } - - *last = ber->ber_ptr + *len; - - if ( *last == ber->ber_ptr ) { - return( LBER_END_OF_SEQORSET ); - } - - return( ber_peek_tag( ber, len ) ); -} - -ber_tag_t -LDAP_CALL -ber_next_element( BerElement *ber, ber_len_t *len, char *last ) -{ - if ( ber->ber_ptr == last ) { - return( LBER_END_OF_SEQORSET ); - } - - return( ber_peek_tag( ber, len ) ); -} - -/* VARARGS */ -ber_tag_t -LDAP_C -ber_scanf( BerElement *ber, const char *fmt, ... ) -{ - va_list ap; - char *last, *p; - char *s, **ss, ***sss; - struct berval ***bv, **bvp, *bval; - int *i, j; - ber_int_t *l, rc, tag; - ber_tag_t *t; - ber_len_t len; - size_t array_size; - - va_start( ap, fmt ); - -#ifdef LDAP_DEBUG - if ( lber_debug & 64 ) { - char msg[80]; - sprintf( msg, "ber_scanf fmt (%s) ber:\n", fmt ); - ber_err_print( msg ); - ber_dump( ber, 1 ); - } -#endif - for ( rc = 0, p = (char *) fmt; *p && rc != LBER_DEFAULT; p++ ) { - switch ( *p ) { - case 'a': /* octet string - allocate storage as needed */ - ss = va_arg( ap, char ** ); - rc = ber_get_stringa( ber, ss ); - break; - - case 'b': /* boolean */ - i = va_arg( ap, int * ); - rc = ber_get_boolean( ber, i ); - break; - - case 'e': /* enumerated */ - case 'i': /* int */ - l = va_arg( ap, ber_slen_t * ); - rc = ber_get_int( ber, l ); - break; - - case 'l': /* length of next item */ - l = va_arg( ap, ber_slen_t * ); - rc = ber_peek_tag( ber, (ber_len_t *)l ); - break; - - case 'n': /* null */ - rc = ber_get_null( ber ); - break; - - case 's': /* octet string - in a buffer */ - s = va_arg( ap, char * ); - l = va_arg( ap, ber_slen_t * ); - rc = ber_get_stringb( ber, s, (ber_len_t *)l ); - break; - - case 'o': /* octet string in a supplied berval */ - bval = va_arg( ap, struct berval * ); - ber_peek_tag( ber, &bval->bv_len ); - rc = ber_get_stringa( ber, &bval->bv_val ); - break; - - case 'O': /* octet string - allocate & include length */ - bvp = va_arg( ap, struct berval ** ); - rc = ber_get_stringal( ber, bvp ); - break; - - case 'B': /* bit string - allocate storage as needed */ - ss = va_arg( ap, char ** ); - l = va_arg( ap, ber_slen_t * ); /* for length, in bits */ - rc = ber_get_bitstringa( ber, ss, (ber_len_t *)l ); - break; - - case 't': /* tag of next item */ - t = va_arg( ap, ber_tag_t * ); - *t = rc = ber_peek_tag( ber, &len ); - break; - - case 'T': /* skip tag of next item */ - t = va_arg( ap, ber_tag_t * ); - *t = rc = ber_skip_tag( ber, &len ); - break; - - case 'v': /* sequence of strings */ - sss = va_arg( ap, char *** ); - *sss = NULL; - j = 0; - array_size = 0; - for ( tag = ber_first_element( ber, &len, &last ); - tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET - && rc != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - if ( *sss == NULL ) { - /* Make room for at least 15 strings */ - *sss = (char **)NSLBERI_MALLOC(16 * sizeof(char *) ); - if (!*sss) { - rc = LBER_DEFAULT; - break; /* out of memory - cannot continue */ - } - array_size = 16; - } else { - char **save_sss = *sss; - if ( (size_t)(j+2) > array_size) { - /* We'v overflowed our buffer */ - *sss = (char **)NSLBERI_REALLOC( *sss, (array_size * 2) * sizeof(char *) ); - array_size = array_size * 2; - } - if (!*sss) { - rc = LBER_DEFAULT; - ber_svecfree(save_sss); - break; /* out of memory - cannot continue */ - } - } - (*sss)[j] = NULL; - rc = ber_get_stringa( ber, &((*sss)[j]) ); - j++; - } - if ( rc != LBER_DEFAULT && - tag != LBER_END_OF_SEQORSET ) { - rc = LBER_DEFAULT; - } - if ( *sss && (j > 0) ) { - (*sss)[j] = NULL; - } - break; - - case 'V': /* sequence of strings + lengths */ - bv = va_arg( ap, struct berval *** ); - *bv = NULL; - j = 0; - for ( tag = ber_first_element( ber, &len, &last ); - tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET - && rc != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - if ( *bv == NULL ) { - *bv = (struct berval **)NSLBERI_MALLOC( - 2 * sizeof(struct berval *) ); - if (!*bv) { - rc = LBER_DEFAULT; - break; /* out of memory - cannot continue */ - } - } else { - struct berval **save_bv = *bv; - *bv = (struct berval **)NSLBERI_REALLOC( - *bv, - (j + 2) * sizeof(struct berval *) ); - if (!*bv) { - rc = LBER_DEFAULT; - ber_bvecfree(save_bv); - break; /* out of memory - cannot continue */ - } - } - rc = ber_get_stringal( ber, &((*bv)[j]) ); - j++; - } - if ( rc != LBER_DEFAULT && - tag != LBER_END_OF_SEQORSET ) { - rc = LBER_DEFAULT; - } - if ( *bv && (j > 0) ) { - (*bv)[j] = NULL; - } - break; - - case 'x': /* skip the next element - whatever it is */ - if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) - break; - ber->ber_ptr += len; - break; - - case '{': /* begin sequence */ - case '[': /* begin set */ - if ( *(p + 1) != 'v' && *(p + 1) != 'V' ) - rc = ber_skip_tag( ber, &len ); - break; - - case '}': /* end sequence */ - case ']': /* end set */ - break; - - default: - { - char msg[80]; - sprintf( msg, "unknown fmt %c\n", *p ); - ber_err_print( msg ); - } - rc = LBER_DEFAULT; - break; - } - } - - va_end( ap ); - - if (rc == LBER_DEFAULT) { - va_start( ap, fmt ); - for ( p--; fmt < p && *fmt; fmt++ ) { - switch ( *fmt ) { - case 'a': /* octet string - allocate storage as needed */ - ss = va_arg( ap, char ** ); - NSLBERI_FREE(*ss); - *ss = NULL; - break; - - case 'b': /* boolean */ - i = va_arg( ap, int * ); - break; - - case 'e': /* enumerated */ - case 'i': /* int */ - l = va_arg( ap, ber_slen_t * ); - break; - - case 'l': /* length of next item */ - l = va_arg( ap, ber_slen_t * ); - break; - - case 'n': /* null */ - break; - - case 's': /* octet string - in a buffer */ - s = va_arg( ap, char * ); - l = va_arg( ap, ber_slen_t * ); - break; - - case 'o': /* octet string in a supplied berval */ - bval = va_arg( ap, struct berval * ); - if (bval->bv_val) NSLBERI_FREE(bval->bv_val); - memset(bval, 0, sizeof(struct berval)); - break; - - case 'O': /* octet string - allocate & include length */ - bvp = va_arg( ap, struct berval ** ); - ber_bvfree(*bvp); - bvp = NULL; - break; - - case 'B': /* bit string - allocate storage as needed */ - ss = va_arg( ap, char ** ); - l = va_arg( ap, ber_slen_t * ); /* for length, in bits */ - if (*ss) NSLBERI_FREE(*ss); - *ss = NULL; - break; - - case 't': /* tag of next item */ - t = va_arg( ap, ber_tag_t * ); - break; - - case 'T': /* skip tag of next item */ - t = va_arg( ap, ber_tag_t * ); - break; - - case 'v': /* sequence of strings */ - sss = va_arg( ap, char *** ); - ber_svecfree(*sss); - *sss = NULL; - break; - - case 'V': /* sequence of strings + lengths */ - bv = va_arg( ap, struct berval *** ); - ber_bvecfree(*bv); - *bv = NULL; - break; - - case 'x': /* skip the next element - whatever it is */ - break; - - case '{': /* begin sequence */ - case '[': /* begin set */ - break; - - case '}': /* end sequence */ - case ']': /* end set */ - break; - - default: - break; - } - } /* for */ - va_end( ap ); - } /* if */ - - return( rc ); -} - -void -LDAP_CALL -ber_bvfree( struct berval *bv ) -{ - if ( bv != NULL ) { - if ( bv->bv_val != NULL ) { - NSLBERI_FREE( bv->bv_val ); - } - NSLBERI_FREE( (char *) bv ); - } -} - -void -LDAP_CALL -ber_bvecfree( struct berval **bv ) -{ - int i; - - if ( bv != NULL ) { - for ( i = 0; bv[i] != NULL; i++ ) { - ber_bvfree( bv[i] ); - } - NSLBERI_FREE( (char *) bv ); - } -} - -struct berval * -LDAP_CALL -ber_bvdup( const struct berval *bv ) -{ - struct berval *new; - - if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) - == NULL ) { - return( NULL ); - } - if ( bv->bv_val == NULL ) { - new->bv_val = NULL; - new->bv_len = 0; - } else { - if ( (new->bv_val = (char *)NSLBERI_MALLOC( bv->bv_len + 1 )) - == NULL ) { - NSLBERI_FREE( new ); - new = NULL; - return( NULL ); - } - SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len ); - new->bv_val[bv->bv_len] = '\0'; - new->bv_len = bv->bv_len; - } - - return( new ); -} - -void -LDAP_CALL -ber_svecfree( char **vals ) -{ - int i; - - if ( vals == NULL ) - return; - for ( i = 0; vals[i] != NULL; i++ ) - NSLBERI_FREE( vals[i] ); - NSLBERI_FREE( (char *) vals ); -} - -#ifdef STR_TRANSLATION -void -LDAP_CALL -ber_set_string_translators( - BerElement *ber, - BERTranslateProc encode_proc, - BERTranslateProc decode_proc -) -{ - ber->ber_encode_translate_proc = encode_proc; - ber->ber_decode_translate_proc = decode_proc; -} -#endif /* STR_TRANSLATION */ diff --git a/ldap/c-sdk/libraries/liblber/dtest.c b/ldap/c-sdk/libraries/liblber/dtest.c deleted file mode 100644 index 71f13d45a8..0000000000 --- a/ldap/c-sdk/libraries/liblber/dtest.c +++ /dev/null @@ -1,113 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ -/* dtest.c - lber decoding test program */ - -#include -#include -#ifdef MACOS -#include -#include -#else /* MACOS */ -#ifdef _WIN32 -#include -#else -#include -#include -#endif /* _WIN32 */ -#endif /* MACOS */ -#include "lber.h" - -int -SSL_Recv( int s, char *b, unsigned l, int dummy ) -{ - return( read( s, b, l ) ); -} - -SSL_Send( int s, char *b, unsigned l, int dummy ) -{ - return( write( s, b, l ) ); -} - -static void usage( char *name ) -{ - fprintf( stderr, "usage: %s < berfile\n", name ); -} - -main( int argc, char **argv ) -{ - long i, fd; - ber_len_t len; - ber_tag_t tag; - BerElement *ber; - Sockbuf *sb; - extern int lber_debug; - - lber_debug = 255; - if ( argc > 1 ) { - usage( argv[0] ); - exit( 1 ); - } - - sb = ber_sockbuf_alloc(); - fd = 0; - ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_DESC, &fd ); - - if ( (ber = der_alloc()) == NULL ) { - perror( "ber_alloc" ); - exit( 1 ); - } - - if ( (tag = ber_get_next( sb, &len, ber )) == LBER_ERROR ) { - perror( "ber_get_next" ); - exit( 1 ); - } - printf( "message has tag 0x%x and length %ld\n", tag, len ); - - return( 0 ); -} diff --git a/ldap/c-sdk/libraries/liblber/encode.c b/ldap/c-sdk/libraries/liblber/encode.c deleted file mode 100644 index 1c47b12a02..0000000000 --- a/ldap/c-sdk/libraries/liblber/encode.c +++ /dev/null @@ -1,699 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ - -/* encode.c - ber output encoding routines */ - -#include "lber-int.h" - -static int -ber_calc_taglen( ber_tag_t tag ) -{ - int i; - ber_int_t mask; - - /* find the first non-all-zero byte in the tag */ - for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { - mask = (0xff << (i * 8)); - /* not all zero */ - if ( tag & mask ) - break; - } - - return( i + 1 ); -} - -static int -ber_put_tag( BerElement *ber, ber_tag_t tag, int nosos ) -{ - int taglen; - ber_tag_t ntag; - - taglen = ber_calc_taglen( tag ); - - ntag = LBER_HTONL( tag ); - - return( ber_write( ber, ((char *) &ntag) + sizeof(ber_int_t) - taglen, - taglen, nosos ) ); -} - -static int -ber_calc_lenlen( ber_len_t len ) -{ - /* - * short len if it's less than 128 - one byte giving the len, - * with bit 8 0. - */ - - if ( len <= 0x7F ) - return( 1 ); - - /* - * long len otherwise - one byte with bit 8 set, giving the - * length of the length, followed by the length itself. - */ - - if ( len <= 0xFF ) - return( 2 ); - if ( len <= 0xFFFF ) - return( 3 ); - if ( len <= 0xFFFFFF ) - return( 4 ); - - return( 5 ); -} - -static int -ber_put_len( BerElement *ber, ber_len_t len, int nosos ) -{ - int i; - char lenlen; - ber_int_t mask; - ber_len_t netlen; - - /* - * short len if it's less than 128 - one byte giving the len, - * with bit 8 0. - */ - - if ( len <= 127 ) { - netlen = LBER_HTONL( len ); - return( ber_write( ber, (char *) &netlen + sizeof(ber_int_t) - 1, - 1, nosos ) ); - } - - /* - * long len otherwise - one byte with bit 8 set, giving the - * length of the length, followed by the length itself. - */ - - /* find the first non-all-zero byte */ - for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { - mask = (0xff << (i * 8)); - /* not all zero */ - if ( len & mask ) - break; - } - lenlen = ++i; - if ( lenlen > 4 ) - return( -1 ); - lenlen |= 0x80; - - /* write the length of the length */ - if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) - return( -1 ); - - /* write the length itself */ - netlen = LBER_HTONL( len ); - if ( ber_write( ber, (char *) &netlen + (sizeof(ber_int_t) - i), i, nosos ) - != i ) - return( -1 ); - - return( i + 1 ); -} - -static int -ber_put_int_or_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) -{ - int i, sign, taglen; - int len, lenlen; - ber_int_t netnum, mask; - - sign = (num < 0); - - /* - * high bit is set - look for first non-all-one byte - * high bit is clear - look for first non-all-zero byte - */ - for ( i = sizeof(ber_int_t) - 1; i > 0; i-- ) { - mask = (0xff << (i * 8)); - - if ( sign ) { - /* not all ones */ - if ( (num & mask) != mask ) - break; - } else { - /* not all zero */ - if ( num & mask ) - break; - } - } - - /* - * we now have the "leading byte". if the high bit on this - * byte matches the sign bit, we need to "back up" a byte. - */ - mask = (num & (0x80 << (i * 8))); - if ( (mask && !sign) || (sign && !mask) ) - i++; - - len = i + 1; - - if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) - return( -1 ); - - if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) - return( -1 ); - i++; - netnum = LBER_HTONL( num ); - if ( ber_write( ber, (char *) &netnum + (sizeof(ber_int_t) - i), i, 0 ) - == i) - /* length of tag + length + contents */ - return( taglen + lenlen + i ); - - return( -1 ); -} - -int -LDAP_CALL -ber_put_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) -{ - if ( tag == LBER_DEFAULT ) - tag = LBER_ENUMERATED; - - return( ber_put_int_or_enum( ber, num, tag ) ); -} - -int -LDAP_CALL -ber_put_int( BerElement *ber, ber_int_t num, ber_tag_t tag ) -{ - if ( tag == LBER_DEFAULT ) - tag = LBER_INTEGER; - - return( ber_put_int_or_enum( ber, num, tag ) ); -} - -int -LDAP_CALL -ber_put_ostring( BerElement *ber, char *str, ber_len_t len, - ber_tag_t tag ) -{ - int taglen, lenlen, rc; -#ifdef STR_TRANSLATION - int free_str; -#endif /* STR_TRANSLATION */ - - if ( tag == LBER_DEFAULT ) - tag = LBER_OCTETSTRING; - - if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) - return( -1 ); - -#ifdef STR_TRANSLATION - if ( len > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) != 0 - && ber->ber_encode_translate_proc != NULL ) { - if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 ) - != 0 ) { - return( -1 ); - } - free_str = 1; - } else { - free_str = 0; - } -#endif /* STR_TRANSLATION */ - - /* - * Note: below is a spot where we limit ber_write - * to signed long (instead of unsigned long) - */ - - if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 || - ber_write( ber, str, len, 0 ) != (ber_int_t) len ) { - rc = -1; - } else { - /* return length of tag + length + contents */ - rc = taglen + lenlen + len; - } - -#ifdef STR_TRANSLATION - if ( free_str ) { - NSLBERI_FREE( str ); - } -#endif /* STR_TRANSLATION */ - - return( rc ); -} - -int -LDAP_CALL -ber_put_string( BerElement *ber, char *str, ber_tag_t tag ) -{ - return( ber_put_ostring( ber, str, (ber_len_t) strlen( str ), tag )); -} - -int -LDAP_CALL -ber_put_bitstring( BerElement *ber, char *str, - ber_len_t blen /* in bits */, ber_tag_t tag ) -{ - int taglen, lenlen, len; - unsigned char unusedbits; - - if ( tag == LBER_DEFAULT ) - tag = LBER_BITSTRING; - - if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) - return( -1 ); - - len = ( blen + 7 ) / 8; - unusedbits = (unsigned char) (len * 8 - blen); - if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 ) - return( -1 ); - - if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 ) - return( -1 ); - - if ( ber_write( ber, str, len, 0 ) != len ) - return( -1 ); - - /* return length of tag + length + unused bit count + contents */ - return( taglen + 1 + lenlen + len ); -} - -int -LDAP_CALL -ber_put_null( BerElement *ber, ber_tag_t tag ) -{ - int taglen; - - if ( tag == LBER_DEFAULT ) - tag = LBER_NULL; - - if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) - return( -1 ); - - if ( ber_put_len( ber, 0, 0 ) != 1 ) - return( -1 ); - - return( taglen + 1 ); -} - -int -LDAP_CALL -ber_put_boolean( BerElement *ber, ber_int_t boolval, ber_tag_t tag ) -{ - int taglen; - unsigned char trueval = 0xff; - unsigned char falseval = 0x00; - - if ( tag == LBER_DEFAULT ) - tag = LBER_BOOLEAN; - - if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) - return( -1 ); - - if ( ber_put_len( ber, 1, 0 ) != 1 ) - return( -1 ); - - if ( ber_write( ber, (char *)(boolval ? &trueval : &falseval), 1, 0 ) - != 1 ) - return( -1 ); - - return( taglen + 2 ); -} - -#define FOUR_BYTE_LEN 5 - - -/* the idea here is roughly this: we maintain a stack of these Seqorset - * structures. This is pushed when we see the beginning of a new set or - * sequence. It is popped when we see the end of a set or sequence. - * Since we don't want to malloc and free these structures all the time, - * we pre-allocate a small set of them within the ber element structure. - * thus we need to spot when we've overflowed this stack and fall back to - * malloc'ing instead. - */ -static int -ber_start_seqorset( BerElement *ber, ber_tag_t tag ) -{ - Seqorset *new_sos; - - /* can we fit into the local stack ? */ - if (ber->ber_sos_stack_posn < SOS_STACK_SIZE) { - /* yes */ - new_sos = &ber->ber_sos_stack[ber->ber_sos_stack_posn]; - } else { - /* no */ - if ( (new_sos = (Seqorset *)NSLBERI_MALLOC( sizeof(Seqorset))) - == NULLSEQORSET ) { - return( -1 ); - } - } - ber->ber_sos_stack_posn++; - - if ( ber->ber_sos == NULLSEQORSET ) - new_sos->sos_first = ber->ber_ptr; - else - new_sos->sos_first = ber->ber_sos->sos_ptr; - - /* Set aside room for a 4 byte length field */ - new_sos->sos_ptr = new_sos->sos_first + ber_calc_taglen( tag ) + FOUR_BYTE_LEN; - new_sos->sos_tag = tag; - - new_sos->sos_next = ber->ber_sos; - new_sos->sos_clen = 0; - - ber->ber_sos = new_sos; - if (ber->ber_sos->sos_ptr > ber->ber_end) { - nslberi_ber_realloc(ber, ber->ber_sos->sos_ptr - ber->ber_end); - } - return( 0 ); -} - -int -LDAP_CALL -ber_start_seq( BerElement *ber, ber_tag_t tag ) -{ - if ( tag == LBER_DEFAULT ) - tag = LBER_SEQUENCE; - - return( ber_start_seqorset( ber, tag ) ); -} - -int -LDAP_CALL -ber_start_set( BerElement *ber, ber_tag_t tag ) -{ - if ( tag == LBER_DEFAULT ) - tag = LBER_SET; - - return( ber_start_seqorset( ber, tag ) ); -} - -static int -ber_put_seqorset( BerElement *ber ) -{ - ber_len_t len, netlen; - int taglen, lenlen; - unsigned char ltag = 0x80 + FOUR_BYTE_LEN - 1; - Seqorset *next; - Seqorset **sos = &ber->ber_sos; - - if ( *sos == NULL ) { - /* No sequence or set to put... fatal error. */ - return( -1 ); - } - - /* - * If this is the toplevel sequence or set, we need to actually - * write the stuff out. Otherwise, it's already been put in - * the appropriate buffer and will be written when the toplevel - * one is written. In this case all we need to do is update the - * length and tag. - */ - - len = (*sos)->sos_clen; - netlen = LBER_HTONL( len ); - if ( sizeof(ber_int_t) > 4 && len > 0xFFFFFFFF ) - return( -1 ); - - if ( ber->ber_options & LBER_OPT_USE_DER ) { - lenlen = ber_calc_lenlen( len ); - } else { - lenlen = FOUR_BYTE_LEN; - } - - if ( (next = (*sos)->sos_next) == NULLSEQORSET ) { - /* write the tag */ - if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 ) - return( -1 ); - - if ( ber->ber_options & LBER_OPT_USE_DER ) { - /* Write the length in the minimum # of octets */ - if ( ber_put_len( ber, len, 1 ) == -1 ) - return( -1 ); - - if (lenlen != FOUR_BYTE_LEN) { - /* - * We set aside FOUR_BYTE_LEN bytes for - * the length field. Move the data if - * we don't actually need that much - */ - SAFEMEMCPY( (*sos)->sos_first + taglen + - lenlen, (*sos)->sos_first + taglen + - FOUR_BYTE_LEN, len ); - } - } else { - /* Fill FOUR_BYTE_LEN bytes for length field */ - /* one byte of length length */ - if ( ber_write( ber, (char *)<ag, 1, 1 ) != 1 ) - return( -1 ); - - /* the length itself */ - if ( ber_write( ber, (char *) &netlen + sizeof(ber_int_t) - - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 ) - != FOUR_BYTE_LEN - 1 ) - return( -1 ); - } - /* The ber_ptr is at the set/seq start - move it to the end */ - ber->ber_ptr += len; - } else { - ber_tag_t ntag; - - /* the tag */ - taglen = ber_calc_taglen( (*sos)->sos_tag ); - ntag = LBER_HTONL( (*sos)->sos_tag ); - SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag + - sizeof(ber_int_t) - taglen, taglen ); - - if ( ber->ber_options & LBER_OPT_USE_DER ) { - ltag = (lenlen == 1) ? (unsigned char)len : - (unsigned char) (0x80 + (lenlen - 1)); - } - - /* one byte of length length */ - SAFEMEMCPY( (*sos)->sos_first + 1, <ag, 1 ); - - if ( ber->ber_options & LBER_OPT_USE_DER ) { - if (lenlen > 1) { - /* Write the length itself */ - SAFEMEMCPY( (*sos)->sos_first + 2, - (char *)&netlen + sizeof(ber_uint_t) - - (lenlen - 1), - lenlen - 1 ); - } - if (lenlen != FOUR_BYTE_LEN) { - /* - * We set aside FOUR_BYTE_LEN bytes for - * the length field. Move the data if - * we don't actually need that much - */ - SAFEMEMCPY( (*sos)->sos_first + taglen + - lenlen, (*sos)->sos_first + taglen + - FOUR_BYTE_LEN, len ); - } - } else { - /* the length itself */ - SAFEMEMCPY( (*sos)->sos_first + taglen + 1, - (char *) &netlen + sizeof(ber_int_t) - - (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 ); - } - - next->sos_clen += (taglen + lenlen + len); - next->sos_ptr += (taglen + lenlen + len); - } - - /* we're done with this seqorset, so free it up */ - /* was this one from the local stack ? */ - if (ber->ber_sos_stack_posn <= SOS_STACK_SIZE) { - /* yes */ - } else { - /* no */ - NSLBERI_FREE( (char *) (*sos) ); - } - ber->ber_sos_stack_posn--; - *sos = next; - - return( taglen + lenlen + len ); -} - -int -LDAP_CALL -ber_put_seq( BerElement *ber ) -{ - return( ber_put_seqorset( ber ) ); -} - -int -LDAP_CALL -ber_put_set( BerElement *ber ) -{ - return( ber_put_seqorset( ber ) ); -} - -/* VARARGS */ -int -LDAP_C -ber_printf( BerElement *ber, const char *fmt, ... ) -{ - va_list ap; - char *s, **ss; - struct berval *bval, **bv; - int rc, i; - ber_len_t len; - - va_start( ap, fmt ); - -#ifdef LDAP_DEBUG - if ( lber_debug & 64 ) { - char msg[80]; - sprintf( msg, "ber_printf fmt (%s)\n", fmt ); - ber_err_print( msg ); - } -#endif - - for ( rc = 0; *fmt && rc != -1; fmt++ ) { - switch ( *fmt ) { - case 'b': /* boolean */ - i = va_arg( ap, int ); - rc = ber_put_boolean( ber, i, ber->ber_tag ); - break; - - case 'i': /* int */ - i = va_arg( ap, int ); - rc = ber_put_int( ber, (ber_int_t)i, ber->ber_tag ); - break; - - case 'e': /* enumeration */ - i = va_arg( ap, int ); - rc = ber_put_enum( ber, (ber_int_t)i, ber->ber_tag ); - break; - - case 'n': /* null */ - rc = ber_put_null( ber, ber->ber_tag ); - break; - - case 'o': /* octet string (non-null terminated) */ - s = va_arg( ap, char * ); - len = va_arg( ap, int ); - rc = ber_put_ostring( ber, s, len, ber->ber_tag ); - break; - - case 'O': /* berval octet string */ - if( ( bval = va_arg( ap, struct berval * ) ) == NULL ) - break; - if( bval->bv_len == 0 ) { - rc = ber_put_ostring( ber, "", 0, ber->ber_tag ); - } else { - rc = ber_put_ostring( ber, bval->bv_val, bval->bv_len, - ber->ber_tag ); - } - break; - - case 's': /* string */ - s = va_arg( ap, char * ); - rc = ber_put_string( ber, s, ber->ber_tag ); - break; - - case 'B': /* bit string */ - s = va_arg( ap, char * ); - len = va_arg( ap, int ); /* in bits */ - rc = ber_put_bitstring( ber, s, len, ber->ber_tag ); - break; - - case 't': /* tag for the next element */ - ber->ber_tag = va_arg( ap, ber_tag_t ); - ber->ber_usertag = 1; - break; - - case 'v': /* vector of strings */ - if ( (ss = va_arg( ap, char ** )) == NULL ) - break; - for ( i = 0; ss[i] != NULL; i++ ) { - if ( (rc = ber_put_string( ber, ss[i], - ber->ber_tag )) == -1 ) - break; - } - break; - - case 'V': /* sequences of strings + lengths */ - if ( (bv = va_arg( ap, struct berval ** )) == NULL ) - break; - for ( i = 0; bv[i] != NULL; i++ ) { - if ( (rc = ber_put_ostring( ber, bv[i]->bv_val, - bv[i]->bv_len, ber->ber_tag )) == -1 ) - break; - } - break; - - case '{': /* begin sequence */ - rc = ber_start_seq( ber, ber->ber_tag ); - break; - - case '}': /* end sequence */ - rc = ber_put_seqorset( ber ); - break; - - case '[': /* begin set */ - rc = ber_start_set( ber, ber->ber_tag ); - break; - - case ']': /* end set */ - rc = ber_put_seqorset( ber ); - break; - - default: { - char msg[80]; - sprintf( msg, "unknown fmt %c\n", *fmt ); - ber_err_print( msg ); - rc = -1; - break; - } - } - - if ( ber->ber_usertag == 0 ) - ber->ber_tag = LBER_DEFAULT; - else - ber->ber_usertag = 0; - } - - va_end( ap ); - - return( rc ); -} diff --git a/ldap/c-sdk/libraries/liblber/etest.c b/ldap/c-sdk/libraries/liblber/etest.c deleted file mode 100644 index f2bab358fc..0000000000 --- a/ldap/c-sdk/libraries/liblber/etest.c +++ /dev/null @@ -1,193 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ - -/* test.c - lber encoding test program */ - -#include -#include -#ifdef MACOS -#include -#include -#include -#include -#else /* MACOS */ -#include -#ifdef _WIN32 -#include -#else -#include -#endif /* _WIN32 */ -#endif /* MACOS */ -#include "lber.h" - -int -SSL_Recv( int s, char *b, unsigned l, int dummy ) -{ - return( read( s, b, l ) ); -} - -SSL_Send( int s, char *b, unsigned l, int dummy ) -{ - return( write( s, b, l ) ); -} - -int -getline( char *prompt, char c, char *buf, int bsize ) -{ - char *p; - - if ( prompt != NULL ) { - fprintf( stderr, "%s: ", prompt ); - } else { - fprintf( stderr, "enter value for '%c': ", c ); - } - if ( fgets( buf, bsize, stdin ) == NULL ) { - return( -1 ); - } - if ( (p = strchr( buf, '\n' )) != NULL ) { - *p = '\0'; - } - - return( 0 ); -} - - -static void usage( char *name ) -{ - fprintf( stderr, "usage: %s fmtstring\n", name ); -} - -main( int argc, char **argv ) -{ - int rc, fd; - char *s, *p; - void *arg1, *arg2; - Sockbuf *sb; - BerElement *ber; - char fmt[2]; - char buf[BUFSIZ]; - extern int lber_debug; - - lber_debug = 255; - if ( argc < 2 ) { - usage( argv[0] ); - exit( 1 ); - } - - sb = ber_sockbuf_alloc(); - fd = 1; - ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_DESC, &fd ); - - if ( (ber = der_alloc()) == NULL ) { - perror( "ber_alloc" ); - exit( 1 ); - } - - rc = 0; - fmt[1] = '\0'; - for ( s = argv[1]; *s; s++ ) { - switch ( *s ) { - case 'i': /* int */ - case 'b': /* boolean */ - case 'e': /* enumeration */ - getline( NULL, *s, buf, sizeof(buf) ); - arg1 = (void *) atoi( buf ); - break; - - case 'n': /* null */ - arg1 = NULL; - break; - - case 'o': /* octet string (non-null terminated) */ - getline( NULL, *s, buf, sizeof(buf) ); - arg1 = (void *) buf; - arg2 = (void *) strlen( buf ); - break; - - case 's': /* string */ - getline( NULL, *s, buf, sizeof(buf) ); - arg1 = (void *) buf; - break; - - case 'B': /* bit string */ - getline( NULL, *s, buf, sizeof(buf) ); - arg1 = (void *) buf; - arg2 = (void *) strlen( buf ); - break; - - case 't': /* tag for the next element */ - getline( NULL, *s, buf, sizeof(buf) ); - arg1 = (void *) buf; - break; - - case '{': /* begin sequence */ - case '}': /* end sequence */ - case '[': /* begin set */ - case ']': /* end set */ - break; - - default: - fprintf( stderr, "unknown fmt %c\n", *s ); - rc = -1; - break; - } - - fmt[0] = *s; - if ( ber_printf( ber, fmt, arg1, arg2 ) == -1 ) { - fprintf( stderr, "ber_printf\n" ); - exit( 1 ); - } - } - - if ( ber_flush( sb, ber, 1 ) != 0 ) { - perror( "ber_flush" ); - rc = -1; - } - - return( rc ); -} diff --git a/ldap/c-sdk/libraries/liblber/idtest.c b/ldap/c-sdk/libraries/liblber/idtest.c deleted file mode 100644 index e6f8fa4ae7..0000000000 --- a/ldap/c-sdk/libraries/liblber/idtest.c +++ /dev/null @@ -1,100 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ - -/* idtest.c - ber decoding test program using isode libraries */ - -#include -#include -#include - -static usage( char *name ) -{ - fprintf( stderr, "usage: %s\n", name ); -} - -main( int argc, char **argv ) -{ - PE pe; - PS psin, psout, pserr; - - /* read the pe from standard in */ - if ( (psin = ps_alloc( std_open )) == NULLPS ) { - perror( "ps_alloc" ); - exit( 1 ); - } - if ( std_setup( psin, stdin ) == NOTOK ) { - perror( "std_setup" ); - exit( 1 ); - } - /* write the pe to standard out */ - if ( (psout = ps_alloc( std_open )) == NULLPS ) { - perror( "ps_alloc" ); - exit( 1 ); - } - if ( std_setup( psout, stdout ) == NOTOK ) { - perror( "std_setup" ); - exit( 1 ); - } - /* pretty print it to standard error */ - if ( (pserr = ps_alloc( std_open )) == NULLPS ) { - perror( "ps_alloc" ); - exit( 1 ); - } - if ( std_setup( pserr, stderr ) == NOTOK ) { - perror( "std_setup" ); - exit( 1 ); - } - - while ( (pe = ps2pe( psin )) != NULLPE ) { - pe2pl( pserr, pe ); - pe2ps( psout, pe ); - } - - exit( 0 ); -} diff --git a/ldap/c-sdk/libraries/liblber/io.c b/ldap/c-sdk/libraries/liblber/io.c deleted file mode 100644 index fc81a9deeb..0000000000 --- a/ldap/c-sdk/libraries/liblber/io.c +++ /dev/null @@ -1,1757 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ -/* io.c - ber general i/o routines */ - -#include "lber-int.h" - -#define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \ - (unsigned char)*sb->sb_ber.ber_ptr++ : \ - ber_filbuf( sb, len )) - -# ifdef macintosh -/* - * MacTCP/OpenTransport - */ -# define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL ) -# define MAX_WRITE 65535 -# define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (lsb_sd, b, l, 0 ) -# else /* _WIN32 */ -/* - * everything else (Unix/BSD 4.3 socket API) - */ -# define BerWrite( sb, b, l ) write( sb->sb_sd, b, l ) -# define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \ - (struct sockaddr *)sb->sb_fromaddr, \ - (al = sizeof(struct sockaddr), &al)) -# define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \ - (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr)) -# endif /* _WIN32 */ -# endif /* macintosh */ - -#ifndef udp_read -#define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED -#define udp_write( sb, b, l ) CLDAP NOT SUPPORTED -#endif /* udp_read */ - -#define EXBUFSIZ 1024 -size_t lber_bufsize = EXBUFSIZ; - -#ifdef LDAP_DEBUG -int lber_debug; -#endif - -/* - * function prototypes - */ -static void nslberi_install_compat_io_fns( Sockbuf *sb ); -static int nslberi_extread_compat( int s, void *buf, int len, - struct lextiof_socket_private *arg ); -static int nslberi_extwrite_compat( int s, const void *buf, int len, - struct lextiof_socket_private *arg ); -static ber_tag_t get_tag( Sockbuf *sb, BerElement *ber); -static ber_len_t get_ber_len( BerElement *ber); -static ber_len_t read_len_in_ber( Sockbuf *sb, BerElement *ber); - -/* - * internal global structure for memory allocation callback functions - */ -static struct lber_memalloc_fns nslberi_memalloc_fns; - - -/* - * buffered read from "sb". - * returns value of first character read on success and -1 on error. - */ -static int -ber_filbuf( Sockbuf *sb, ber_slen_t len ) -{ - ssize_t rc; -#ifdef CLDAP - int addrlen; -#endif /* CLDAP */ - - if ( sb->sb_ber.ber_buf == NULL ) { - if ( (sb->sb_ber.ber_buf = (char *)NSLBERI_MALLOC( - READBUFSIZ )) == NULL ) { - return( -1 ); - } - sb->sb_ber.ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; - sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf; - sb->sb_ber.ber_end = sb->sb_ber.ber_buf; - } - - if ( sb->sb_naddr > 0 ) { -#ifdef CLDAP - rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen ); -#ifdef LDAP_DEBUG - if ( lber_debug ) { - char msg[80]; - sprintf( msg, "ber_filbuf udp_read %d bytes\n", - rc ); - ber_err_print( msg ); - if ( lber_debug > 1 && rc > 0 ) - lber_bprint( sb->sb_ber.ber_buf, rc ); - } -#endif /* LDAP_DEBUG */ -#else /* CLDAP */ - rc = -1; -#endif /* CLDAP */ - } else { - if ( sb->sb_ext_io_fns.lbextiofn_read != NULL ) { - rc = sb->sb_ext_io_fns.lbextiofn_read( - sb->sb_sd, sb->sb_ber.ber_buf, - ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) - && (len < READBUFSIZ)) ? len : READBUFSIZ, - sb->sb_ext_io_fns.lbextiofn_socket_arg ); - } else { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return( -1 ); -#else - rc = read( sb->sb_sd, sb->sb_ber.ber_buf, - ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) - && (len < READBUFSIZ)) ? len : READBUFSIZ ); -#endif - } - } - - if ( rc > 0 ) { - sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1; - sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc; - return( (unsigned char)*sb->sb_ber.ber_buf ); - } - - return( -1 ); -} - - -static ber_int_t -BerRead( Sockbuf *sb, char *buf, ber_slen_t len ) -{ - int c; - ber_int_t nread = 0; - - while (len > 0) - { - ber_int_t inberbuf = sb->sb_ber.ber_end - sb->sb_ber.ber_ptr; - if (inberbuf > 0) - { - size_t tocopy = len > inberbuf ? inberbuf : len; - SAFEMEMCPY(buf, sb->sb_ber.ber_ptr, tocopy); - buf += tocopy; - sb->sb_ber.ber_ptr += tocopy; - nread += tocopy; - len -= tocopy; - } - else - { - c = ber_filbuf(sb, len); - if (c < 0) - { - if (nread > 0) - break; - else - return c; - } - *buf++ = c; - nread++; - len--; - } - } - return (nread); -} - - -/* - * Note: ber_read() only uses the ber_end and ber_ptr elements of ber. - * Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on - * that fact, so if this code is changed to use any additional elements of - * the ber structure, those functions will need to be changed as well. - */ -ber_int_t -LDAP_CALL -ber_read( BerElement *ber, char *buf, ber_len_t len ) -{ - ber_len_t actuallen; - ber_uint_t nleft; - - nleft = ber->ber_end - ber->ber_ptr; - actuallen = nleft < len ? nleft : len; - - SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen ); - - ber->ber_ptr += actuallen; - - return( (ber_int_t)actuallen ); -} - -/* - * enlarge the ber buffer. - * return 0 on success, -1 on error. - */ -int -nslberi_ber_realloc( BerElement *ber, ber_len_t len ) -{ - ber_uint_t need, have, total; - size_t have_bytes; - Seqorset *s; - ber_int_t off; - char *oldbuf; - int freeoldbuf = 0; - - ber->ber_buf_reallocs++; - - have_bytes = ber->ber_end - ber->ber_buf; - have = have_bytes / lber_bufsize; - need = (len < lber_bufsize ? 1 : (len + (lber_bufsize - 1)) / lber_bufsize); - total = have * lber_bufsize + need * lber_bufsize * ber->ber_buf_reallocs; - - oldbuf = ber->ber_buf; - - if (ber->ber_buf == NULL) { - if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( (size_t)total )) - == NULL ) { - return( -1 ); - } - ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; - } else { - if ( !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { - freeoldbuf = 1; - } - /* transition to malloc'd buffer */ - if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( - (size_t)total )) == NULL ) { - return( -1 ); - } - ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; - /* copy existing data into new malloc'd buffer */ - SAFEMEMCPY( ber->ber_buf, oldbuf, have_bytes ); - } - - ber->ber_end = ber->ber_buf + total; - - /* - * If the stinking thing was moved, we need to go through and - * reset all the sos and ber pointers. Offsets would've been - * a better idea... oh well. - */ - - if ( ber->ber_buf != oldbuf ) { - ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); - - for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) { - off = s->sos_first - oldbuf; - s->sos_first = ber->ber_buf + off; - - off = s->sos_ptr - oldbuf; - s->sos_ptr = ber->ber_buf + off; - } - - if ( freeoldbuf && oldbuf ) { - NSLBERI_FREE( oldbuf ); - } - } - - return( 0 ); -} - -/* - * returns "len" on success and -1 on failure. - */ -ber_int_t -LDAP_CALL -ber_write( BerElement *ber, char *buf, ber_len_t len, int nosos ) -{ - if ( nosos || ber->ber_sos == NULL ) { - if ( ber->ber_ptr + len > ber->ber_end ) { - if ( nslberi_ber_realloc( ber, len ) != 0 ) - return( -1 ); - } - SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len ); - ber->ber_ptr += len; - return( len ); - } else { - if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) { - if ( nslberi_ber_realloc( ber, len ) != 0 ) - return( -1 ); - } - SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len ); - ber->ber_sos->sos_ptr += len; - ber->ber_sos->sos_clen += len; - return( len ); - } -} - -void -LDAP_CALL -ber_free( BerElement *ber, int freebuf ) -{ - if ( ber != NULL ) { - if ( freebuf && - !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { - NSLBERI_FREE(ber->ber_buf); - } - NSLBERI_FREE( (char *) ber ); - } -} - -/* - * return >= 0 on success, -1 on failure. - */ -int -LDAP_CALL -ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) -{ - ssize_t nwritten = 0, towrite, rc; - int i = 0; - - if (ber->ber_rwptr == NULL) { - ber->ber_rwptr = ber->ber_buf; - } else if (ber->ber_rwptr >= ber->ber_end) { - /* we will use the ber_rwptr to continue an exited flush, - so if rwptr is not within the buffer we return an error. */ - return( -1 ); - } - - /* writev section - for iDAR only!!! */ - if (sb->sb_ext_io_fns.lbextiofn_writev != NULL) { - - /* add the sizes of the different buffers to write with writev */ - for (towrite = 0, i = 0; i < BER_ARRAY_QUANTITY; ++i) { - /* don't add lengths of null buffers - writev will ignore them */ - if (ber->ber_struct[i].ldapiov_base) { - towrite += ber->ber_struct[i].ldapiov_len; - } - } - - rc = sb->sb_ext_io_fns.lbextiofn_writev(sb->sb_sd, ber->ber_struct, BER_ARRAY_QUANTITY, - sb->sb_ext_io_fns.lbextiofn_socket_arg); - - if ( freeit ) - ber_free( ber, 1 ); - - if (rc >= 0) { - /* return the number of bytes TO BE written */ - return (towrite - rc); - } else { - /* otherwise it's an error */ - return (rc); - } - } /* end writev section */ - - towrite = ber->ber_ptr - ber->ber_rwptr; - -#ifdef LDAP_DEBUG - if ( lber_debug ) { - char msg[80]; - sprintf( msg, "ber_flush: %d bytes to sd %ld%s\n", (int)towrite, - sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" - : "" ); - ber_err_print( msg ); - if ( lber_debug > 1 ) - lber_bprint( ber->ber_rwptr, towrite ); - } -#endif -#if !defined(macintosh) && !defined(DOS) - if ( sb->sb_options & (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY) ) { - rc = write( sb->sb_copyfd, ber->ber_buf, towrite ); - if ( sb->sb_options & LBER_SOCKBUF_OPT_TO_FILE_ONLY ) { - return( (int)rc ); - } - } -#endif - - nwritten = 0; - do { - if (sb->sb_naddr > 0) { -#ifdef CLDAP - rc = udp_write( sb, ber->ber_buf + nwritten, - (size_t)towrite ); -#else /* CLDAP */ - rc = -1; -#endif /* CLDAP */ - if ( rc <= 0 ) - return( -1 ); - /* fake error if write was not atomic */ - if (rc < towrite) { -#if !defined( macintosh ) && !defined( DOS ) - errno = EMSGSIZE; /* For Win32, see portable.h */ -#endif - return( -1 ); - } - } else { - if ( sb->sb_ext_io_fns.lbextiofn_write != NULL ) { - if ( (rc = sb->sb_ext_io_fns.lbextiofn_write( - sb->sb_sd, ber->ber_rwptr, (size_t)towrite, - sb->sb_ext_io_fns.lbextiofn_socket_arg )) - <= 0 ) { - return( -1 ); - } - } else { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return( -1 ); -#else - if ( (rc = BerWrite( sb, ber->ber_rwptr, - (size_t) towrite )) <= 0 ) { - return( -1 ); - } -#endif - } - } - towrite -= rc; - nwritten += rc; - ber->ber_rwptr += rc; - } while ( towrite > 0 ); - - if ( freeit ) - ber_free( ber, 1 ); - - return( 0 ); -} - - -/* we pre-allocate a buffer to save the extra malloc later */ -BerElement * -LDAP_CALL -ber_alloc_t( int options ) -{ - BerElement *ber; - - if ( (ber = (BerElement*)NSLBERI_CALLOC( 1, - sizeof(struct berelement) + lber_bufsize )) == NULL ) { - return( NULL ); - } - - /* - * for compatibility with the C LDAP API standard, we recognize - * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. - */ - if ( options & LBER_USE_DER ) { - options &= ~LBER_USE_DER; - options |= LBER_OPT_USE_DER; - } - - ber->ber_tag = LBER_DEFAULT; - ber->ber_options = options; - ber->ber_buf = (char*)ber + sizeof(struct berelement); - ber->ber_ptr = ber->ber_buf; - ber->ber_end = ber->ber_buf + lber_bufsize; - ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; - - return( ber ); -} - - -BerElement * -LDAP_CALL -ber_alloc() -{ - return( ber_alloc_t( 0 ) ); -} - -BerElement * -LDAP_CALL -der_alloc() -{ - return( ber_alloc_t( LBER_OPT_USE_DER ) ); -} - -BerElement * -LDAP_CALL -ber_dup( BerElement *ber ) -{ - BerElement *new; - - if ( (new = ber_alloc()) == NULL ) - return( NULL ); - - *new = *ber; - - return( new ); -} - - -void -LDAP_CALL -ber_init_w_nullchar( BerElement *ber, int options ) -{ - (void) memset( (char *)ber, '\0', sizeof(struct berelement) ); - ber->ber_tag = LBER_DEFAULT; - - /* - * For compatibility with the C LDAP API standard, we recognize - * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. - */ - if ( options & LBER_USE_DER ) { - options &= ~LBER_USE_DER; - options |= LBER_OPT_USE_DER; - } - - ber->ber_options = options; -} - -void -LDAP_CALL -ber_reset( BerElement *ber, int was_writing ) -{ - if ( was_writing ) { - ber->ber_end = ber->ber_ptr; - ber->ber_ptr = ber->ber_buf; - } else { - ber->ber_ptr = ber->ber_end; - } - - ber->ber_rwptr = NULL; - ber->ber_tag_len_read = 0; - - memset(ber->ber_struct, 0, BER_CONTENTS_STRUCT_SIZE); -} - -/* Returns the length of the ber buffer so far, - taking into account sequences/sets also. - CAUTION: Returns 0 on null buffers as well - as 0 on empty buffers! -*/ -size_t -LDAP_CALL -ber_get_buf_datalen( BerElement *ber ) -{ - size_t datalen; - - if ( ( ber == NULL) || ( ber->ber_buf == NULL) || ( ber->ber_ptr == NULL ) ) { - datalen = 0; - } else if (ber->ber_sos == NULLSEQORSET) { - /* there are no sequences or sets yet, - so just subtract ptr from the beginning of the ber buffer */ - datalen = ber->ber_ptr - ber->ber_buf; - } else { - /* sequences exist, so just take the ptr of the sequence - on top of the stack and subtract the beginning of the - buffer from it */ - datalen = ber->ber_sos->sos_ptr - ber->ber_buf; - } - - return datalen; -} - -/* - if buf is 0 then malloc a buffer of length size - returns > 0 on success, 0 otherwise -*/ -int -LDAP_CALL -ber_stack_init(BerElement *ber, int options, char * buf, - size_t size) -{ - if (NULL == ber) - return 0; - - memset(ber, 0, sizeof(*ber)); - - /* - * for compatibility with the C LDAP API standard, we recognize - * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. - */ - - if ( options & LBER_USE_DER ) { - options &= ~LBER_USE_DER; - options |= LBER_OPT_USE_DER; - } - - ber->ber_tag = LBER_DEFAULT; - ber->ber_options = options; - - if ( ber->ber_buf && !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { - NSLBERI_FREE(ber->ber_buf); - } - - if (buf) { - ber->ber_buf = ber->ber_ptr = buf; - ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; - } else { - ber->ber_buf = ber->ber_ptr = (char *) NSLBERI_MALLOC(size); - } - - ber->ber_end = ber->ber_buf + size; - - return ber->ber_buf != 0; -} - -/* - * This call allows to release only the data part of - * the target Sockbuf. - * Other info of this Sockbuf are kept unchanged. - */ -void -LDAP_CALL -ber_sockbuf_free_data(Sockbuf *p) -{ - if ( p != NULL ) { - if ( p->sb_ber.ber_buf != NULL && - !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { - NSLBERI_FREE( p->sb_ber.ber_buf ); - p->sb_ber.ber_buf = NULL; - } - } -} - -/* simply returns ber_buf in the ber ... - explicitly for DS MMR only... -*/ -char * -LDAP_CALL -ber_get_buf_databegin (BerElement * ber) -{ - if (NULL != ber) { - return ber->ber_buf; - } else { - return NULL; - } -} - -#ifdef LDAP_DEBUG - -void -ber_dump( BerElement *ber, int inout ) -{ - char msg[128]; - sprintf( msg, "ber_dump: buf 0x%p, ptr 0x%p, rwptr 0x%p, end 0x%p\n", - ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end ); - ber_err_print( msg ); - if ( inout == 1 ) { - sprintf( msg, " current len %ld, contents:\n", - (long)(ber->ber_end - ber->ber_ptr) ); - ber_err_print( msg ); - lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr ); - } else { - sprintf( msg, " current len %ld, contents:\n", - (long)(ber->ber_ptr - ber->ber_buf) ); - ber_err_print( msg ); - lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf ); - } -} - -void -ber_sos_dump( Seqorset *sos ) -{ - char msg[80]; - ber_err_print ( "*** sos dump ***\n" ); - while ( sos != NULLSEQORSET ) { - sprintf( msg, "ber_sos_dump: clen %d first 0x%p ptr 0x%p\n", - sos->sos_clen, sos->sos_first, sos->sos_ptr ); - ber_err_print( msg ); - sprintf( msg, " current len %ld contents:\n", - (long)(sos->sos_ptr - sos->sos_first) ); - ber_err_print( msg ); - lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first ); - - sos = sos->sos_next; - } - ber_err_print( "*** end dump ***\n" ); -} - -#endif - -/* return the tag - LBER_DEFAULT returned means trouble - * assumes the tag is only one byte! */ -static ber_tag_t -get_tag( Sockbuf *sb, BerElement *ber) -{ - unsigned char xbyte; - - if ( (BerRead( sb, (char *) &xbyte, 1 )) != 1 ) { - return( LBER_DEFAULT ); - } - - /* we only handle small (one byte) tags */ - if ( (xbyte & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK ) { - return( LBER_DEFAULT ); - } - - ber->ber_tag_contents[0] = xbyte; - ber->ber_struct[BER_STRUCT_TAG].ldapiov_len = 1; - return((ber_tag_t)xbyte); -} - - -/* Error checking? */ -/* Takes a ber and returns the actual length */ -static ber_len_t -get_ber_len( BerElement *ber) -{ - int noctets; - ber_len_t len = 0; - char xbyte; - - xbyte = ber->ber_len_contents[0]; - - /* long form */ - if (xbyte & 0x80) { - noctets = (int) (xbyte & 0x7f); - if (noctets >= MAX_LEN_SIZE) { - return(LBER_DEFAULT); - } - SAFEMEMCPY((char*) &len + sizeof(ber_len_t) - noctets, &ber->ber_len_contents[1], noctets); - len = LBER_NTOHL(len); - return(len); - } else { - return((ber_len_t)(xbyte)); - } -} - -/* LBER_DEFAULT means trouble - reads in the length, stores it in ber->ber_struct, and returns get_ber_len */ -static ber_len_t -read_len_in_ber( Sockbuf *sb, BerElement *ber) -{ - unsigned char xbyte; - int noctets; - int rc = 0, read_result = 0; - - /* - * Next, read the length. The first byte contains the length - * of the length. If bit 8 is set, the length is the long - * form, otherwise it's the short form. We don't allow a - * length that's greater than what we can hold in a ber_int_t - */ - if ( ber->ber_tag_len_read == 1) { - /* the length of the length hasn't been read yet */ - if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) { - return( LBER_DEFAULT ); - } - ber->ber_tag_len_read = 2; - ber->ber_len_contents[0] = xbyte; - } else { - rc = ber->ber_tag_len_read - 2; - xbyte = ber->ber_len_contents[0]; - } - - /* long form of the length value */ - if ( xbyte & 0x80 ) { - noctets = (xbyte & 0x7f); - if ( noctets >= MAX_LEN_SIZE ) - return( LBER_DEFAULT ); - while (rc < noctets) { - read_result = BerRead( sb, &(ber->ber_len_contents[1]) + rc, noctets - rc ); - if (read_result <= 0) { - ber->ber_tag_len_read = rc + 2; /* so we can continue later - include tag and lenlen */ - return( LBER_DEFAULT ); - } - rc += read_result; - } - ber->ber_tag_len_read = rc + 2; /* adds tag (1 byte) and lenlen (1 byte) */ - ber->ber_struct[BER_STRUCT_LEN].ldapiov_len = 1 + noctets; - } else { /* short form of the length value */ - ber->ber_struct[BER_STRUCT_LEN].ldapiov_len = 1; - } - return(get_ber_len(ber)); -} - - -ber_tag_t -LDAP_CALL -ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber ) -{ - ber_len_t newlen; - ber_len_t toread; - ber_int_t rc; - ber_len_t orig_taglen_read = 0; - char * orig_rwptr = ber->ber_rwptr ? ber->ber_rwptr : ber->ber_buf; - -#ifdef LDAP_DEBUG - if ( lber_debug ) - ber_err_print( "ber_get_next\n" ); -#endif - - /* - * When rwptr is NULL this signifies that the tag and length have not been - * read in their entirety yet. (if at all) - */ - if ( ber->ber_rwptr == NULL ) { - - /* first save the amount we previously read, so we know what to return in len. */ - orig_taglen_read = ber->ber_tag_len_read; - - /* read the tag - if tag_len_read is greater than 0, then it has already been read. */ - if (ber->ber_tag_len_read == 0) { - if ((ber->ber_tag = get_tag(sb, ber)) == LBER_DEFAULT ) { - *len = 0; - return( LBER_DEFAULT ); - } - - ber->ber_tag_contents[0] = (char)ber->ber_tag; /* we only handle 1 byte tags */ - ber->ber_tag_len_read = 1; - - /* check for validity */ - if((sb->sb_options & LBER_SOCKBUF_OPT_VALID_TAG) && - (ber->ber_tag != sb->sb_valid_tag)) { - *len = 1; /* we just read the tag so far */ - return( LBER_DEFAULT); - } - } - - /* read the length */ - if ((newlen = read_len_in_ber(sb, ber)) == LBER_DEFAULT ) { - *len = ber->ber_tag_len_read - orig_taglen_read; - return( LBER_DEFAULT ); - } - - /* - * Finally, malloc a buffer for the contents and read it in. - * It's this buffer that's passed to all the other ber decoding - * routines. - */ - -#if defined( DOS ) && !( defined( _WIN32 ) || defined(XP_OS2) ) - if ( newlen > 65535 ) { /* DOS can't allocate > 64K */ - return( LBER_DEFAULT ); - } -#endif /* DOS && !_WIN32 */ - - if ( ( sb->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) - && newlen > sb->sb_max_incoming ) { - return( LBER_DEFAULT ); - } - - /* check to see if we already have enough memory allocated */ - if ( ((ber_len_t) ber->ber_end - (ber_len_t) ber->ber_buf) < newlen) { - if ( ber->ber_buf && !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { - NSLBERI_FREE(ber->ber_buf); - } - if ( (ber->ber_buf = (char *)NSLBERI_CALLOC( 1,(size_t)newlen )) - == NULL ) { - return( LBER_DEFAULT ); - } - ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; - orig_rwptr = ber->ber_buf; - } - - - ber->ber_len = newlen; - ber->ber_ptr = ber->ber_buf; - ber->ber_end = ber->ber_buf + newlen; - ber->ber_rwptr = ber->ber_buf; - ber->ber_tag_len_read = 0; /* now that rwptr is set, this doesn't matter */ - } - - /* OK, we've malloc-ed the buffer; now read the rest of the expected length */ - toread = (ber_len_t)ber->ber_end - (ber_len_t)ber->ber_rwptr; - do { - if ( (rc = BerRead( sb, ber->ber_rwptr, (ber_int_t)toread )) <= 0 ) { - *len = (ber_len_t) ber->ber_rwptr - (ber_len_t) orig_rwptr; - return( LBER_DEFAULT ); - } - - toread -= rc; - ber->ber_rwptr += rc; - } while ( toread > 0 ); - -#ifdef LDAP_DEBUG - if ( lber_debug ) { - char msg[80]; - sprintf( msg, "ber_get_next: tag 0x%x len %d contents:\n", - ber->ber_tag, ber->ber_len ); - ber_err_print( msg ); - if ( lber_debug > 1 ) - ber_dump( ber, 1 ); - } -#endif - - *len = (ber_len_t) ber->ber_rwptr - (ber_len_t) orig_rwptr; - ber->ber_rwptr = NULL; - ber->ber_struct[BER_STRUCT_VAL].ldapiov_len = ber->ber_len; - return( ber->ber_tag ); -} - -Sockbuf * -LDAP_CALL -ber_sockbuf_alloc() -{ - return( (Sockbuf *)NSLBERI_CALLOC( 1, sizeof(struct sockbuf) ) ); -} - -void -LDAP_CALL -ber_sockbuf_free(Sockbuf *p) -{ - if ( p != NULL ) { - if ( p->sb_ber.ber_buf != NULL && - !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { - NSLBERI_FREE( p->sb_ber.ber_buf ); - } - NSLBERI_FREE(p); - } -} - -/* - * return 0 on success and -1 on error - */ -int -LDAP_CALL -ber_set_option( struct berelement *ber, int option, void *value ) -{ - - /* - * memory allocation callbacks are global, so it is OK to pass - * NULL for ber. Handle this as a special case. - */ - if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { - /* struct copy */ - nslberi_memalloc_fns = *((struct lber_memalloc_fns *)value); - return( 0 ); - } - - /* - * lber_debug is global, so it is OK to pass - * NULL for ber. Handle this as a special case. - */ - if ( option == LBER_OPT_DEBUG_LEVEL ) { -#ifdef LDAP_DEBUG - lber_debug = *(int *)value; -#endif - return( 0 ); - } - - /* - * lber_bufsize is global, so it is OK to pass - * NULL for ber. Handle this as a special case. - */ - if ( option == LBER_OPT_BUFSIZE ) { - if ( *(size_t *)value > EXBUFSIZ ) { - lber_bufsize = *(size_t *)value; - } - return( 0 ); - } - - /* - * all the rest require a non-NULL ber - */ - if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { - return( -1 ); - } - - switch ( option ) { - case LBER_OPT_USE_DER: - case LBER_OPT_TRANSLATE_STRINGS: - if ( value != NULL ) { - ber->ber_options |= option; - } else { - ber->ber_options &= ~option; - } - break; - case LBER_OPT_REMAINING_BYTES: - ber->ber_end = ber->ber_ptr + *((ber_len_t *)value); - break; - case LBER_OPT_TOTAL_BYTES: - ber->ber_end = ber->ber_buf + *((ber_len_t *)value); - break; - case LBER_OPT_BYTES_TO_WRITE: - ber->ber_ptr = ber->ber_buf + *((ber_len_t *)value); - break; - default: - return( -1 ); - } - - return( 0 ); -} - -/* - * return 0 on success and -1 on error - */ -int -LDAP_CALL -ber_get_option( struct berelement *ber, int option, void *value ) -{ - /* - * memory callocation callbacks are global, so it is OK to pass - * NULL for ber. Handle this as a special case - */ - if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { - /* struct copy */ - *((struct lber_memalloc_fns *)value) = nslberi_memalloc_fns; - return( 0 ); - } - - /* - * lber_debug is global, so it is OK to pass - * NULL for ber. Handle this as a special case. - */ - if ( option == LBER_OPT_DEBUG_LEVEL ) { -#ifdef LDAP_DEBUG - *(int *)value = lber_debug; -#endif - return( 0 ); - } - - /* - * lber_bufsize is global, so it is OK to pass - * NULL for ber. Handle this as a special case. - */ - if ( option == LBER_OPT_BUFSIZE ) { - *(size_t *)value = lber_bufsize; - return( 0 ); - } - - /* - * all the rest require a non-NULL ber - */ - if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { - return( -1 ); - } - - switch ( option ) { - case LBER_OPT_USE_DER: - case LBER_OPT_TRANSLATE_STRINGS: - *((int *) value) = (ber->ber_options & option); - break; - case LBER_OPT_REMAINING_BYTES: - *((ber_len_t *) value) = ber->ber_end - ber->ber_ptr; - break; - case LBER_OPT_TOTAL_BYTES: - *((ber_len_t *) value) = ber->ber_end - ber->ber_buf; - break; - case LBER_OPT_BYTES_TO_WRITE: - *((ber_len_t *) value) = ber->ber_ptr - ber->ber_buf; - break; - default: - return( -1 ); - } - - return( 0 ); -} - -/* - * return 0 on success and -1 on error - */ -int -LDAP_CALL -ber_sockbuf_set_option( Sockbuf *sb, int option, void *value ) -{ - struct lber_x_ext_io_fns *extiofns; - - if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { - return( -1 ); - } - - /* check for a NULL value for certain options. */ - if (NULL == value) { - switch ( option ) { - case LBER_SOCKBUF_OPT_TO_FILE: - case LBER_SOCKBUF_OPT_TO_FILE_ONLY: - case LBER_SOCKBUF_OPT_NO_READ_AHEAD: - case LBER_SOCKBUF_OPT_READ_FN: - case LBER_SOCKBUF_OPT_WRITE_FN: - case LBER_SOCKBUF_OPT_EXT_IO_FNS: - case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: - /* do nothing - it's OK to have a NULL value for these options */ - break; - default: - return( -1 ); - } - } - - switch ( option ) { - case LBER_SOCKBUF_OPT_VALID_TAG: - sb->sb_valid_tag= *((ber_tag_t *) value); - /* use NULL to reset */ - if ( value != NULL ) { - sb->sb_options |= option; - } else { - sb->sb_options &= ~option; - } - break; - case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: - if ( value != NULL ) { - sb->sb_max_incoming = *((ber_len_t *) value); - sb->sb_options |= option; - } else { - /* setting the max incoming to 0 seems to be the only - way to tell the callers of ber_sockbuf_get_option - that this option isn't set. */ - sb->sb_max_incoming = 0; - sb->sb_options &= ~option; - } - break; - case LBER_SOCKBUF_OPT_TO_FILE: - case LBER_SOCKBUF_OPT_TO_FILE_ONLY: - case LBER_SOCKBUF_OPT_NO_READ_AHEAD: - if ( value != NULL ) { - sb->sb_options |= option; - } else { - sb->sb_options &= ~option; - } - break; - case LBER_SOCKBUF_OPT_DESC: - sb->sb_sd = *((LBER_SOCKET *) value); - break; - case LBER_SOCKBUF_OPT_COPYDESC: - sb->sb_copyfd = *((LBER_SOCKET *) value); - break; - case LBER_SOCKBUF_OPT_READ_FN: - sb->sb_io_fns.lbiof_read = (LDAP_IOF_READ_CALLBACK *) value; - nslberi_install_compat_io_fns( sb ); - break; - case LBER_SOCKBUF_OPT_WRITE_FN: - sb->sb_io_fns.lbiof_write = (LDAP_IOF_WRITE_CALLBACK *) value; - nslberi_install_compat_io_fns( sb ); - break; - case LBER_SOCKBUF_OPT_EXT_IO_FNS: - extiofns = (struct lber_x_ext_io_fns *) value; - if ( extiofns == NULL ) { /* remove */ - (void)memset( (char *)&sb->sb_ext_io_fns, '\0', - sizeof(sb->sb_ext_io_fns )); - } else if ( extiofns->lbextiofn_size - == LBER_X_EXTIO_FNS_SIZE ) { - /* struct copy */ - sb->sb_ext_io_fns = *extiofns; - } else if ( extiofns->lbextiofn_size - == LBER_X_EXTIO_FNS_SIZE_REV0 ) { - /* backwards compatiblity for older struct */ - sb->sb_ext_io_fns.lbextiofn_size = - LBER_X_EXTIO_FNS_SIZE; - sb->sb_ext_io_fns.lbextiofn_read = - extiofns->lbextiofn_read; - sb->sb_ext_io_fns.lbextiofn_write = - extiofns->lbextiofn_write; - sb->sb_ext_io_fns.lbextiofn_writev = NULL; - sb->sb_ext_io_fns.lbextiofn_socket_arg = - extiofns->lbextiofn_socket_arg; - } else { - return( -1 ); - } - break; - case LBER_SOCKBUF_OPT_SOCK_ARG: - sb->sb_ext_io_fns.lbextiofn_socket_arg = - (struct lextiof_socket_private *) value; - break; - default: - return( -1 ); - } - - return( 0 ); -} - -/* - * return 0 on success and -1 on error - */ -int -LDAP_CALL -ber_sockbuf_get_option( Sockbuf *sb, int option, void *value ) -{ - struct lber_x_ext_io_fns *extiofns; - - if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb ) || (NULL == value)) { - return( -1 ); - } - - switch ( option ) { - case LBER_SOCKBUF_OPT_VALID_TAG: - *((ber_tag_t *) value) = sb->sb_valid_tag; - break; - case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: - *((ber_len_t *) value) = sb->sb_max_incoming; - break; - case LBER_SOCKBUF_OPT_TO_FILE: - case LBER_SOCKBUF_OPT_TO_FILE_ONLY: - case LBER_SOCKBUF_OPT_NO_READ_AHEAD: - *((int *) value) = (sb->sb_options & option); - break; - case LBER_SOCKBUF_OPT_DESC: - *((LBER_SOCKET *) value) = sb->sb_sd; - break; - case LBER_SOCKBUF_OPT_COPYDESC: - *((LBER_SOCKET *) value) = sb->sb_copyfd; - break; - case LBER_SOCKBUF_OPT_READ_FN: - *((LDAP_IOF_READ_CALLBACK **) value) - = sb->sb_io_fns.lbiof_read; - break; - case LBER_SOCKBUF_OPT_WRITE_FN: - *((LDAP_IOF_WRITE_CALLBACK **) value) - = sb->sb_io_fns.lbiof_write; - break; - case LBER_SOCKBUF_OPT_EXT_IO_FNS: - extiofns = (struct lber_x_ext_io_fns *) value; - if ( extiofns == NULL ) { - return( -1 ); - } else if ( extiofns->lbextiofn_size - == LBER_X_EXTIO_FNS_SIZE ) { - /* struct copy */ - *extiofns = sb->sb_ext_io_fns; - } else if ( extiofns->lbextiofn_size - == LBER_X_EXTIO_FNS_SIZE_REV0 ) { - /* backwards compatiblity for older struct */ - extiofns->lbextiofn_read = sb->sb_ext_io_fns.lbextiofn_read; - extiofns->lbextiofn_write = sb->sb_ext_io_fns.lbextiofn_write; - extiofns->lbextiofn_socket_arg = sb->sb_ext_io_fns.lbextiofn_socket_arg; - } else { - return( -1 ); - } - break; - case LBER_SOCKBUF_OPT_SOCK_ARG: - *((struct lextiof_socket_private **)value) = sb->sb_ext_io_fns.lbextiofn_socket_arg; - break; - default: - return( -1 ); - } - - return( 0 ); -} - - -/* new dboreham code below: */ - -struct byte_buffer { - unsigned char *p; - int offset; - int length; -}; -typedef struct byte_buffer byte_buffer; - - -/* This call allocates us a BerElement structure plus some extra memory. - * It returns a pointer to the BerElement, plus a pointer to the extra memory. - * This routine also allocates a ber data buffer within the same block, thus - * saving a call to calloc later when we read data. - */ -void* -LDAP_CALL -ber_special_alloc(size_t size, BerElement **ppBer) -{ - char *mem = NULL; - - /* Make sure mem size requested is aligned */ - if (0 != ( size & 0x03 )) { - size += (sizeof(ber_int_t) - (size & 0x03)); - } - - mem = NSLBERI_MALLOC(sizeof(struct berelement) + lber_bufsize + size ); - if (NULL == mem) { - return NULL; - } - *ppBer = (BerElement*) (mem + size); - memset(*ppBer,0,sizeof(struct berelement)); - (*ppBer)->ber_tag = LBER_DEFAULT; - (*ppBer)->ber_buf = mem + size + sizeof(struct berelement); - (*ppBer)->ber_ptr = (*ppBer)->ber_buf; - (*ppBer)->ber_end = (*ppBer)->ber_buf + lber_bufsize; - (*ppBer)->ber_flags = LBER_FLAG_NO_FREE_BUFFER; - return (void*)mem; -} - -void -LDAP_CALL -ber_special_free(void* buf, BerElement *ber) -{ - if (!(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { - NSLBERI_FREE(ber->ber_buf); - } - NSLBERI_FREE( buf ); -} - -/* Copy up to bytes_to_read bytes from b into return_buffer. - * Returns a count of bytes copied (always >= 0). - */ -static int -read_bytes(byte_buffer *b, unsigned char *return_buffer, int bytes_to_read) -{ - /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */ - int bytes_to_copy = 0; - - if (bytes_to_read <= (b->length - b->offset) ) { - bytes_to_copy = bytes_to_read; - } else { - bytes_to_copy = (b->length - b->offset); - } - if (1 == bytes_to_copy) { - *return_buffer = *(b->p+b->offset++); - } else if (bytes_to_copy <= 0) { - bytes_to_copy = 0; /* never return a negative result */ - } else { - SAFEMEMCPY(return_buffer,b->p+b->offset,bytes_to_copy); - b->offset += bytes_to_copy; - } - return bytes_to_copy; -} - -/* return the tag - LBER_DEFAULT returned means trouble */ -static ber_tag_t -get_buffer_tag(byte_buffer *sb ) -{ - unsigned char xbyte; - ber_tag_t tag; - char *tagp; - int i; - - if ( (i = read_bytes( sb, &xbyte, 1 )) != 1 ) { - return( LBER_DEFAULT ); - } - - if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { - return( (ber_uint_t) xbyte ); - } - - tagp = (char *) &tag; - tagp[0] = xbyte; - for ( i = 1; i < sizeof(ber_int_t); i++ ) { - if ( read_bytes( sb, &xbyte, 1 ) != 1 ) - return( LBER_DEFAULT ); - - tagp[i] = xbyte; - - if ( ! (xbyte & LBER_MORE_TAG_MASK) ) - break; - } - - /* tag too big! */ - if ( i == sizeof(ber_int_t) ) - return( LBER_DEFAULT ); - - /* want leading, not trailing 0's */ - return( tag >> (sizeof(ber_int_t) - i - 1) ); -} - -/* Like ber_get_next, but from a byte buffer the caller already has. */ -/* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */ -/* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */ -/* and is here for backward compatibility. This new function allows us to pass */ -/* the Sockbuf structure along */ - -ber_uint_t -LDAP_CALL -ber_get_next_buffer( void *buffer, size_t buffer_size, ber_len_t *len, - BerElement *ber, ber_uint_t *Bytes_Scanned ) -{ - return (ber_get_next_buffer_ext( buffer, buffer_size, len, ber, - Bytes_Scanned, NULL)); -} - -/* - * Returns the tag of the message or LBER_ return code if an error occurs. - * - * If there was not enough data in the buffer to complete the message this - * is a "soft" error. In this case, *Bytes_Scanned is set to a positive - * number and return code is set to LBER_DEFAULT. - * - * On overflow condition when the length is either bigger than ber_uint_t - * type or the value preset via LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE option, - * *Bytes_Scanned is set to zero and return code is set to LBER_OVERFLOW. - * - * For backward compatibility errno is also set on these error conditions: - * - * EINVAL - LBER_SOCKBUF_OPT_VALID_TAG option set but tag doesnt match. - * EMSGSIZE - an overflow condition as described above for LBER_OVERFLOW. - */ -ber_uint_t -LDAP_CALL -ber_get_next_buffer_ext( void *buffer, size_t buffer_size, ber_len_t *len, - BerElement *ber, ber_uint_t *Bytes_Scanned, Sockbuf *sock ) -{ - ber_tag_t tag = 0; - ber_len_t netlen; - ber_len_t toread; - unsigned char lc; - ssize_t rc; - int noctets, diff; - byte_buffer sb = {0}; - - - /* - * Any ber element looks like this: tag length contents. - * Assuming everything's ok, we return the tag byte (we - * can assume a single byte), return the length in len, - * and the rest of the undecoded element in buf. - * - * Assumptions: - * 1) small tags (less than 128) - * 2) definite lengths - * 3) primitive encodings used whenever possible - */ - - /* - * first time through - malloc the buffer, set up ptrs, and - * read the tag and the length and as much of the rest as we can - */ - - sb.p = buffer; - sb.length = buffer_size; - - if ( ber->ber_rwptr == NULL ) { - - /* - * First, we read the tag. - */ - - /* if we have been called before with a fragment not - * containing a complete length, we have no rwptr but - * a tag already - */ - if ( ber->ber_tag == LBER_DEFAULT ) { - if ( (tag = get_buffer_tag( &sb )) == LBER_DEFAULT ) { - goto premature_exit; - } - ber->ber_tag = tag; - } - - if((sock->sb_options & LBER_SOCKBUF_OPT_VALID_TAG) && - (ber->ber_tag != sock->sb_valid_tag)) { -#if !defined( macintosh ) && !defined( DOS ) - errno = EINVAL; -#endif - goto error_exit; - } - - /* If we have been called before with an incomplete length, - * the fragment of the length read is in ber->ber_len_contents - * ber->ber_tag_len_read is the # of bytes of the length available - * from a previous fragment - */ - - if (ber->ber_tag_len_read) { - int nbytes; - - noctets = ((ber->ber_len_contents[0]) & 0x7f); - diff = noctets + 1 /* tag */ - ber->ber_tag_len_read; - - if ( (nbytes = read_bytes( &sb, (unsigned char *) &ber->ber_len_contents[0] + - ber->ber_tag_len_read, diff )) != diff ) { - - if (nbytes > 0) - ber->ber_tag_len_read+=nbytes; - - goto premature_exit; - } - *len = get_ber_len(ber); /* cast ber->ber_len_contents to unsigned long */ - - } else { - /* - * Next, read the length. The first byte contains the length - * of the length. If bit 8 is set, the length is the long - * form, otherwise it's the short form. We don't allow a - * length that's greater than what we can hold in an unsigned - * long. - */ - - *len = netlen = 0; - if ( read_bytes( &sb, &lc, 1 ) != 1 ) { - goto premature_exit; - } - if ( lc & 0x80 ) { - int nbytes; - - noctets = (lc & 0x7f); - if ( noctets > sizeof(ber_uint_t) ) { -#if !defined( macintosh ) && !defined( DOS ) - errno = EMSGSIZE; -#endif - *Bytes_Scanned = 0; - return(LBER_OVERFLOW); - } - diff = sizeof(ber_uint_t) - noctets; - if ( (nbytes = read_bytes( &sb, (unsigned char *)&netlen + diff, - noctets )) != noctets ) { - /* - * The length is in long form and we don't get it in one - * fragment, so stash partial length in the ber element - * for later use - */ - - ber->ber_tag_len_read = nbytes + 1; - ber->ber_len_contents[0]=lc; - memset(&(ber->ber_len_contents[1]), 0, sizeof(ber_uint_t)); - SAFEMEMCPY(&(ber->ber_len_contents[1]), (unsigned char *)&netlen + diff, nbytes); - - goto premature_exit; - } - *len = LBER_NTOHL( netlen ); - } else { - *len = lc; - } - } - - ber->ber_len = *len; - /* length fully decoded */ - ber->ber_tag_len_read=0; - /* - * Finally, malloc a buffer for the contents and read it in. - * It's this buffer that's passed to all the other ber decoding - * routines. - */ - -#if defined( DOS ) && !defined( _WIN32 ) - if ( *len > 65535 ) { /* DOS can't allocate > 64K */ - goto premature_exit; - } -#endif /* DOS && !_WIN32 */ - - if ( (sock != NULL) && - ( sock->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) - && (*len > sock->sb_max_incoming) ) { -#if !defined( macintosh ) && !defined( DOS ) - errno = EMSGSIZE; -#endif - *Bytes_Scanned = 0; - return( LBER_OVERFLOW ); - } - - if ( ber->ber_buf + *len > ber->ber_end ) { - if ( nslberi_ber_realloc( ber, *len ) != 0 ) - goto error_exit; - } - ber->ber_ptr = ber->ber_buf; - ber->ber_end = ber->ber_buf + *len; - ber->ber_rwptr = ber->ber_buf; - } - - toread = (ber_len_t)ber->ber_end - (ber_len_t)ber->ber_rwptr; - do { - if ( (rc = read_bytes( &sb, (unsigned char *)ber->ber_rwptr, - (ber_int_t)toread )) <= 0 ) { - goto premature_exit; - } - - toread -= rc; - ber->ber_rwptr += rc; - } while ( toread > 0 ); - - *len = ber->ber_len; - *Bytes_Scanned = sb.offset; - return( ber->ber_tag ); - -premature_exit: - /* - * we're here because we hit the end of the buffer before seeing - * all of the PDU - */ - *Bytes_Scanned = sb.offset; - return(LBER_DEFAULT); - -error_exit: - *Bytes_Scanned = 0; - return(LBER_DEFAULT); -} - - -/* 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 routine returns 0 on success and -1 on error. - * The use of ber_flatten on a BerElement in which all '{' and '}' - * format modifiers have not been properly matched can result in a - * berval whose contents are not a valid BER encoding. - * Note that the ber_ptr is not modified. - */ -int -LDAP_CALL -ber_flatten( BerElement *ber, struct berval **bvPtr ) -{ - struct berval *new; - ber_len_t len; - - /* allocate a struct berval */ - if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) - == NULL ) { - return( -1 ); - } - - /* - * Copy everything from the BerElement's ber_buf to ber_ptr - * into the berval structure. - */ - if ( ber == NULL ) { - new->bv_val = NULL; - new->bv_len = 0; - } else { - len = ber->ber_ptr - ber->ber_buf; - if ( ( new->bv_val = (char *)NSLBERI_MALLOC( len + 1 )) == NULL ) { - ber_bvfree( new ); - return( -1 ); - } - SAFEMEMCPY( new->bv_val, ber->ber_buf, (size_t)len ); - new->bv_val[len] = '\0'; - new->bv_len = len; - } - - /* set bvPtr pointer to point to the returned berval */ - *bvPtr = new; - - return( 0 ); -} - - -/* - * The ber_init function constructs and returns a new BerElement - * containing a copy of the data in the bv argument. ber_init - * returns the null pointer on error. - */ -BerElement * -LDAP_CALL -ber_init( const struct berval *bv ) -{ - BerElement *ber; - - /* construct BerElement */ - if (( ber = ber_alloc_t( 0 )) != NULLBER ) { - /* copy data from the bv argument into BerElement */ - /* XXXmcs: had to cast unsigned long bv_len to long */ - if ( (ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) - != (ber_slen_t)bv->bv_len ) { - ber_free( ber, 1 ); - return( NULL ); - } - } - - /* - * reset ber_ptr back to the beginning of buffer so that this new - * and initialized ber element can be READ - */ - ber_reset( ber, 1); - - /* - * return a ptr to a new BerElement containing a copy of the data - * in the bv argument or a null pointer on error - */ - return( ber ); -} - - -/* - * memory allocation functions. - */ -void * -nslberi_malloc( size_t size ) -{ - return( nslberi_memalloc_fns.lbermem_malloc == NULL ? - malloc( size ) : - nslberi_memalloc_fns.lbermem_malloc( size )); -} - - -void * -nslberi_calloc( size_t nelem, size_t elsize ) -{ - return( nslberi_memalloc_fns.lbermem_calloc == NULL ? - calloc( nelem, elsize ) : - nslberi_memalloc_fns.lbermem_calloc( nelem, elsize )); -} - - -void * -nslberi_realloc( void *ptr, size_t size ) -{ - return( nslberi_memalloc_fns.lbermem_realloc == NULL ? - realloc( ptr, size ) : - nslberi_memalloc_fns.lbermem_realloc( ptr, size )); -} - - -void -nslberi_free( void *ptr ) -{ - if ( nslberi_memalloc_fns.lbermem_free == NULL ) { - free( ptr ); - } else { - nslberi_memalloc_fns.lbermem_free( ptr ); - } -} - - -/* - ****************************************************************************** - * functions to bridge the gap between new extended I/O functions that are - * installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS, - * ... ). - * - * the basic strategy is to use the new extended arg to hold a pointer to the - * Sockbuf itself so we can find the old functions and call them. - * note that the integer socket s passed in is not used. we use the sb_sd - * from the Sockbuf itself because it is the correct type. - */ -static int -nslberi_extread_compat( int s, void *buf, int len, - struct lextiof_socket_private *arg ) -{ - Sockbuf *sb = (Sockbuf *)arg; - - return( sb->sb_io_fns.lbiof_read( sb->sb_sd, buf, len )); -} - - -static int -nslberi_extwrite_compat( int s, const void *buf, int len, - struct lextiof_socket_private *arg ) -{ - Sockbuf *sb = (Sockbuf *)arg; - - return( sb->sb_io_fns.lbiof_write( sb->sb_sd, buf, len )); -} - - -/* - * Install I/O compatiblity functions. This can't fail. - */ -static void -nslberi_install_compat_io_fns( Sockbuf *sb ) -{ - sb->sb_ext_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - sb->sb_ext_io_fns.lbextiofn_read = nslberi_extread_compat; - sb->sb_ext_io_fns.lbextiofn_write = nslberi_extwrite_compat; - sb->sb_ext_io_fns.lbextiofn_writev = NULL; - sb->sb_ext_io_fns.lbextiofn_socket_arg = (void *)sb; -} -/* - * end of compat I/O functions - ****************************************************************************** - */ diff --git a/ldap/c-sdk/libraries/liblber/lber-int.h b/ldap/c-sdk/libraries/liblber/lber-int.h deleted file mode 100644 index 24b15bdc5f..0000000000 --- a/ldap/c-sdk/libraries/liblber/lber-int.h +++ /dev/null @@ -1,305 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * 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. - */ -/* lbet-int.h - internal header file for liblber */ - -#ifndef _LBERINT_H -#define _LBERINT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#ifdef macintosh -# include "ldap-macos.h" -#else /* macintosh */ -#if !defined(BSDI) && !defined(DARWIN) && !defined(FREEBSD) && !defined(OPENBSD) -# include -#endif -# include -# include -#if defined(SUNOS4) || defined(SCOOS) -# include -#endif -#if defined( _WINDOWS ) -# define WIN32_LEAN_AND_MEAN -# include -# include -# define ssize_t SSIZE_T -# include -/* No stderr in a 16-bit Windows DLL */ -# if defined(_WINDLL) && !defined(_WIN32) -# define USE_DBG_WIN -# endif -# else -/* # include */ -# include -# include -#if !defined(XP_OS2) && !defined(DARWIN) -# include -#endif -# endif /* defined( _WINDOWS ) */ -#endif /* macintosh */ - -#include -#include -#include "portable.h" - -#ifdef _WINDOWS -# if defined(FD_SETSIZE) -# else -# define FD_SETSIZE 256 /* set it before winsock sets it to 64! */ -# endif -#include -#include -#endif /* _WINDOWS */ - -#ifdef XP_OS2 -#include -#endif /* XP_OS2 */ - -/* No stderr in a 16-bit Windows DLL */ -#if defined(_WINDLL) && !defined(_WIN32) -#define stderr NULL -#endif - -#include "lber.h" - -#ifdef macintosh -#define NSLDAPI_LBER_SOCKET_IS_PTR -#endif - -#define OLD_LBER_SEQUENCE 0x10 /* w/o constructed bit - broken */ -#define OLD_LBER_SET 0x11 /* w/o constructed bit - broken */ - -#ifndef _IFP -#define _IFP -typedef int (LDAP_C LDAP_CALLBACK *IFP)(); -#endif - -typedef struct seqorset { - ber_len_t sos_clen; - ber_tag_t sos_tag; - char *sos_first; - char *sos_ptr; - struct seqorset *sos_next; -} Seqorset; -#define NULLSEQORSET ((Seqorset *) 0) - -#define SOS_STACK_SIZE 8 /* depth of the pre-allocated sos structure stack */ - -#define MAX_TAG_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the tag */ -#define MAX_LEN_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the length */ -#define MAX_VALUE_PREFIX_SIZE (2 + sizeof(ber_int_t)) /* 1 byte for the tag and 1 for the len (msgid) */ -#define BER_ARRAY_QUANTITY 7 /* 0:Tag 1:Length 2:Value-prefix 3:Value 4:Value-suffix */ -#define BER_STRUCT_TAG 0 /* 5:ControlA 6:ControlB */ -#define BER_STRUCT_LEN 1 -#define BER_STRUCT_PRE 2 -#define BER_STRUCT_VAL 3 -#define BER_STRUCT_SUF 4 -#define BER_STRUCT_CO1 5 -#define BER_STRUCT_CO2 6 - -struct berelement { - ldap_x_iovec ber_struct[BER_ARRAY_QUANTITY]; /* See above */ - - char ber_tag_contents[MAX_TAG_SIZE]; - char ber_len_contents[MAX_LEN_SIZE]; - char ber_pre_contents[MAX_VALUE_PREFIX_SIZE]; - char ber_suf_contents[MAX_LEN_SIZE+1]; - - char *ber_buf; /* update the value value when writing in case realloc is called */ - char *ber_ptr; - char *ber_end; - struct seqorset *ber_sos; - ber_len_t ber_tag_len_read; - ber_tag_t ber_tag; /* Remove me someday */ - ber_len_t ber_len; /* Remove me someday */ - int ber_usertag; - char ber_options; - char *ber_rwptr; - BERTranslateProc ber_encode_translate_proc; - BERTranslateProc ber_decode_translate_proc; - int ber_flags; -#define LBER_FLAG_NO_FREE_BUFFER 1 /* don't free ber_buf */ - unsigned int ber_buf_reallocs; /* realloc counter */ - int ber_sos_stack_posn; - Seqorset ber_sos_stack[SOS_STACK_SIZE]; -}; - -#define BER_CONTENTS_STRUCT_SIZE (sizeof(ldap_x_iovec) * BER_ARRAY_QUANTITY) - -#define NULLBER ((BerElement *)NULL) - -#ifdef LDAP_DEBUG -void ber_dump( BerElement *ber, int inout ); -#endif - - - -/* - * structure for read/write I/O callback functions. - */ -struct nslberi_io_fns { - LDAP_IOF_READ_CALLBACK *lbiof_read; - LDAP_IOF_WRITE_CALLBACK *lbiof_write; -}; - - -/* - * Old structure for use with LBER_SOCKBUF_OPT_EXT_IO_FNS: - */ -struct lber_x_ext_io_fns_rev0 { - /* lbextiofn_size should always be set to LBER_X_EXTIO_FNS_SIZE */ - int lbextiofn_size; - LDAP_X_EXTIOF_READ_CALLBACK *lbextiofn_read; - LDAP_X_EXTIOF_WRITE_CALLBACK *lbextiofn_write; - struct lextiof_socket_private *lbextiofn_socket_arg; -}; -#define LBER_X_EXTIO_FNS_SIZE_REV0 sizeof(struct lber_x_ext_io_fns_rev0) - - - -struct sockbuf { - LBER_SOCKET sb_sd; - BerElement sb_ber; - int sb_naddr; /* > 0 implies using CLDAP (UDP) */ - void *sb_useaddr; /* pointer to sockaddr to use next */ - void *sb_fromaddr; /* pointer to message source sockaddr */ - void **sb_addrs; /* actually an array of pointers to - sockaddrs */ - - int sb_options; /* to support copying ber elements */ - LBER_SOCKET sb_copyfd; /* for LBER_SOCKBUF_OPT_TO_FILE* opts */ - ber_len_t sb_max_incoming; - ber_tag_t sb_valid_tag; /* valid tag to accept */ - struct nslberi_io_fns - sb_io_fns; /* classic I/O callback functions */ - - struct lber_x_ext_io_fns - sb_ext_io_fns; /* extended I/O callback functions */ -}; -#define NULLSOCKBUF ((Sockbuf *)NULL) - -/* needed by libldap, even in non-DEBUG builds */ -void ber_err_print( char *data ); - -#ifndef NSLBERI_LBER_INT_FRIEND -/* - * Everything from this point on is excluded if NSLBERI_LBER_INT_FRIEND is - * defined. The code under ../libraries/libldap defines this. - */ - -#define READBUFSIZ 8192 - -/* - * macros used to check validity of data structures and parameters - */ -#define NSLBERI_VALID_BERELEMENT_POINTER( ber ) \ - ( (ber) != NULLBER ) - -#define NSLBERI_VALID_SOCKBUF_POINTER( sb ) \ - ( (sb) != NULLSOCKBUF ) - -#define LBER_HTONL( l ) htonl( l ) -#define LBER_NTOHL( l ) ntohl( l ) - -/* function prototypes */ -#ifdef LDAP_DEBUG -void lber_bprint( char *data, int len ); -#endif -void ber_err_print( char *data ); -void *nslberi_malloc( size_t size ); -void *nslberi_calloc( size_t nelem, size_t elsize ); -void *nslberi_realloc( void *ptr, size_t size ); -void nslberi_free( void *ptr ); -int nslberi_ber_realloc( BerElement *ber, ber_len_t len ); - -/* blame: dboreham - * slapd spends much of its time doing memcpy's for the ber code. - * Most of these are single-byte, so we special-case those and speed - * things up considerably. - */ - -#ifdef sunos4 -#define THEMEMCPY( d, s, n ) bcopy( s, d, n ) -#else /* sunos4 */ -#define THEMEMCPY( d, s, n ) memmove( d, s, n ) -#endif /* sunos4 */ - -#ifdef SAFEMEMCPY -#undef SAFEMEMCPY -#define SAFEMEMCPY(d,s,n) if (1 == n) *((char*)d) = *((char*)s); else THEMEMCPY(d,s,n); -#endif - -/* - * Memory allocation done in liblber should all go through one of the - * following macros. This is so we can plug-in alternative memory - * allocators, etc. as the need arises. - */ -#define NSLBERI_MALLOC( size ) nslberi_malloc( size ) -#define NSLBERI_CALLOC( nelem, elsize ) nslberi_calloc( nelem, elsize ) -#define NSLBERI_REALLOC( ptr, size ) nslberi_realloc( ptr, size ) -#define NSLBERI_FREE( ptr ) nslberi_free( ptr ) - -/* allow the library to access the debug variable */ - -extern int lber_debug; - -#endif /* !NSLBERI_LBER_INT_FRIEND */ - - -#ifdef __cplusplus -} -#endif -#endif /* _LBERINT_H */ diff --git a/ldap/c-sdk/libraries/liblber/moz.build b/ldap/c-sdk/libraries/liblber/moz.build deleted file mode 100644 index 8a344a4739..0000000000 --- a/ldap/c-sdk/libraries/liblber/moz.build +++ /dev/null @@ -1,23 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include('/ldap/ldap-sdk.mozbuild') - -Library('lber60') - -SOURCES += [ - 'bprint.c', - 'decode.c', - 'encode.c', - 'io.c', -] - -DEFINES['USE_WAITPID'] = True -DEFINES['NEEDPROTOS'] = True - -LOCAL_INCLUDES += [ - '/ldap/c-sdk/include' -] - diff --git a/ldap/c-sdk/libraries/libldap/abandon.c b/ldap/c-sdk/libraries/libldap/abandon.c deleted file mode 100644 index a514cfd895..0000000000 --- a/ldap/c-sdk/libraries/libldap/abandon.c +++ /dev/null @@ -1,303 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * abandon.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -static int do_abandon( LDAP *ld, int origid, int msgid, - LDAPControl **serverctrls, LDAPControl **clientctrls ); -static int nsldapi_send_abandon_message( LDAP *ld, LDAPConn *lc, - BerElement *ber, int abandon_msgid ); - -/* - * ldap_abandon - perform an ldap abandon operation. Parameters: - * - * ld LDAP descriptor - * msgid The message id of the operation to abandon - * - * ldap_abandon returns 0 if everything went ok, -1 otherwise. - * - * Example: - * ldap_abandon( ld, msgid ); - */ -int -LDAP_CALL -ldap_abandon( LDAP *ld, int msgid ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, "4e65747363617065\n", msgid, 0, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, "466f726576657221\n", msgid, 0, 0 ); - - if ( ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS ) { - return( 0 ); - } - - return( -1 ); -} - - -/* - * LDAPv3 extended abandon. - * Returns an LDAP error code. - */ -int -LDAP_CALL -ldap_abandon_ext( LDAP *ld, int msgid, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - rc = do_abandon( ld, msgid, msgid, serverctrls, clientctrls ); - - /* - * XXXmcs should use cache function pointers to hook in memcache - */ - ldap_memcache_abandon( ld, msgid ); - - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - - return( rc ); -} - - -/* - * Abandon all outstanding requests for msgid (included child requests - * spawned when chasing referrals). This function calls itself recursively. - * No locking is done is this function so it must be done by the caller. - * Returns an LDAP error code and sets it in LDAP *ld as well - */ -static int -do_abandon( LDAP *ld, int origid, int msgid, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - BerElement *ber; - int i, bererr, lderr, sendabandon; - LDAPRequest *lr = NULL; - - /* - * An abandon request looks like this: - * AbandonRequest ::= MessageID - */ - LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", - origid, msgid, 0 ); - - /* optimistic */ - lderr = LDAP_SUCCESS; - - /* - * Find the request that we are abandoning. Don't send an - * abandon message unless there is something to abandon. - */ - sendabandon = 0; - for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { - if ( lr->lr_msgid == msgid ) { /* this message */ - if ( origid == msgid && lr->lr_parent != NULL ) { - /* don't let caller abandon child requests! */ - lderr = LDAP_PARAM_ERROR; - goto set_errorcode_and_return; - } - if ( lr->lr_status == LDAP_REQST_INPROGRESS ) { - /* - * We only need to send an abandon message if - * the request is in progress. - */ - sendabandon = 1; - } - break; - } - if ( lr->lr_origid == msgid ) { /* child: abandon it */ - (void)do_abandon( ld, msgid, lr->lr_msgid, - serverctrls, clientctrls ); - /* we ignore errors from child abandons... */ - } - } - - if ( ldap_msgdelete( ld, msgid ) == 0 ) { - /* we had all the results and deleted them */ - goto set_errorcode_and_return; - } - - if ( lr != NULL && sendabandon ) { - /* create a message to send */ - if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) == - LDAP_SUCCESS ) { - int abandon_msgid; - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - abandon_msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); -#ifdef CLDAP - if ( ld->ld_dbp->sb_naddr > 0 ) { - bererr = ber_printf( ber, "{isti", - abandon_msgid, ld->ld_cldapdn, - LDAP_REQ_ABANDON, msgid ); - } else { -#endif /* CLDAP */ - bererr = ber_printf( ber, "{iti", - abandon_msgid, LDAP_REQ_ABANDON, msgid ); -#ifdef CLDAP - } -#endif /* CLDAP */ - - if ( bererr == -1 || - ( lderr = nsldapi_put_controls( ld, serverctrls, - 1, ber )) != LDAP_SUCCESS ) { - lderr = LDAP_ENCODING_ERROR; - ber_free( ber, 1 ); - } else { - /* try to send the message */ - lderr = nsldapi_send_abandon_message( ld, - lr->lr_conn, ber, abandon_msgid ); - } - } - } - - if ( lr != NULL ) { - /* - * Always call nsldapi_free_connection() so that the connection's - * ref count is correctly decremented. It is OK to always pass - * 1 for the "unbind" parameter because doing so will only affect - * connections that resulted from a child request (because the - * default connection's ref count never goes to zero). - */ - nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL, - 0 /* do not force */, 1 /* send unbind before closing */ ); - - /* - * Free the entire request chain if we finished abandoning everything. - */ - if ( origid == msgid ) { - nsldapi_free_request( ld, lr, 0 ); - } - } - - /* - * Record the abandoned message ID (used to discard any server responses - * that arrive later). - */ - LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); - if ( ld->ld_abandoned == NULL ) { - if ( (ld->ld_abandoned = (int *)NSLDAPI_MALLOC( 2 - * sizeof(int) )) == NULL ) { - lderr = LDAP_NO_MEMORY; - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - goto set_errorcode_and_return; - } - i = 0; - } else { - for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) - ; /* NULL */ - if ( (ld->ld_abandoned = (int *)NSLDAPI_REALLOC( (char *) - ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) { - lderr = LDAP_NO_MEMORY; - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - goto set_errorcode_and_return; - } - } - ld->ld_abandoned[i] = msgid; - ld->ld_abandoned[i + 1] = -1; - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - -set_errorcode_and_return: - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - return( lderr ); -} - -/* - * Try to send the abandon message that is encoded in ber. Returns an - * LDAP result code. - */ -static int -nsldapi_send_abandon_message( LDAP *ld, LDAPConn *lc, BerElement *ber, - int abandon_msgid ) -{ - int lderr = LDAP_SUCCESS; - int err = 0; - - err = nsldapi_send_ber_message( ld, lc->lconn_sb, - ber, 1 /* free ber */, 0 /* will not handle EPIPE */ ); - if ( err == -2 ) { - /* - * "Would block" error. Queue the abandon as - * a pending request. - */ - LDAPRequest *lr; - - lr = nsldapi_new_request( lc, ber, abandon_msgid, - 0 /* no response expected */ ); - if ( lr == NULL ) { - lderr = LDAP_NO_MEMORY; - ber_free( ber, 1 ); - } else { - lr->lr_status = LDAP_REQST_WRITING; - nsldapi_queue_request_nolock( ld, lr ); - ++lc->lconn_pending_requests; - nsldapi_iostatus_interest_write( ld, - lc->lconn_sb ); - } - } else if ( err != 0 ) { - /* - * Fatal error (not a "would block" error). - */ - lderr = LDAP_SERVER_DOWN; - ber_free( ber, 1 ); - } - - return( lderr ); -} diff --git a/ldap/c-sdk/libraries/libldap/add.c b/ldap/c-sdk/libraries/libldap/add.c deleted file mode 100644 index 0cb5dbfb5f..0000000000 --- a/ldap/c-sdk/libraries/libldap/add.c +++ /dev/null @@ -1,225 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * add.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_add - initiate an ldap add operation. Parameters: - * - * ld LDAP descriptor - * dn DN of the entry to add - * mods List of attributes for the entry. This is a null- - * terminated array of pointers to LDAPMod structures. - * only the type and values in the structures need be - * filled in. - * - * Example: - * LDAPMod *attrs[] = { - * { 0, "cn", { "babs jensen", "babs", 0 } }, - * { 0, "sn", { "jensen", 0 } }, - * { 0, "objectClass", { "person", 0 } }, - * 0 - * } - * msgid = ldap_add( ld, dn, attrs ); - */ -int -LDAP_CALL -ldap_add( LDAP *ld, const char *dn, LDAPMod **attrs ) -{ - int msgid; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_add\n", 0, 0, 0 ); - - if ( ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ) - == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - - -/* - * LDAPv3 extended add. - * Returns an LDAP error code. - */ -int -LDAP_CALL -ldap_add_ext( LDAP *ld, const char *dn, LDAPMod **attrs, - LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) -{ - BerElement *ber; - int i, rc, lderr; - - /* - * An add request looks like this: - * AddRequest ::= SEQUENCE { - * entry DistinguishedName, - * attrs SEQUENCE OF SEQUENCE { - * type AttributeType, - * values SET OF AttributeValue - * } - * } - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) - { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( attrs ) - || msgidp == NULL ) { - lderr = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - return( lderr ); - } - - if ( dn == NULL ) { - dn = ""; - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* see if we should add to the cache */ - if ( ld->ld_cache_on && ld->ld_cache_add != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_add)( ld, *msgidp, LDAP_REQ_ADD, dn, - attrs )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( lderr ); - } - - if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_ADD, dn ) - == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - /* for each attribute in the entry... */ - for ( i = 0; attrs[i] != NULL; i++ ) { - if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { - rc = ber_printf( ber, "{s[V]}", attrs[i]->mod_type, - attrs[i]->mod_bvalues ); - } else { - rc = ber_printf( ber, "{s[v]}", attrs[i]->mod_type, - attrs[i]->mod_values ); - } - if ( rc == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - } - - if ( ber_printf( ber, "}}" ) == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( lderr ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_ADD, - (char *) dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -int -LDAP_CALL -ldap_add_s( LDAP *ld, const char *dn, LDAPMod **attrs ) -{ - return( ldap_add_ext_s( ld, dn, attrs, NULL, NULL )); -} - -int LDAP_CALL -ldap_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs, - LDAPControl **serverctrls, LDAPControl **clientctrls ) -{ - int err, msgid; - LDAPMessage *res; - - if (( err = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, - &msgid )) != LDAP_SUCCESS ) { - return( err ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - return( ldap_result2error( ld, res, 1 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/authzidctrl.c b/ldap/c-sdk/libraries/libldap/authzidctrl.c deleted file mode 100644 index 69b776cdc4..0000000000 --- a/ldap/c-sdk/libraries/libldap/authzidctrl.c +++ /dev/null @@ -1,157 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): abobrov@sun.com - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_create_authzid_control: - -Parameters are - -ld LDAP pointer to the desired connection - -ctl_iscritical Indicates whether the control is critical of not. - If this field is non-zero, the operation will only be - carried out if the control is recognized by the server - and/or client - -ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_authzid_control ( - LDAP *ld, - const char ctl_iscritical, - LDAPControl **ctrlp - ) -{ - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_AUTHZID_REQ, - NULL, 0, ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - -/* ldap_parse_authzid_control: - -Parameters are - -ld LDAP pointer to the desired connection - -ctrlp An array of controls obtained from calling - ldap_parse_result on the set of results - returned by the server - -authzid authorization identity, as defined in - RFC 2829, section 9. -*/ - -int -LDAP_CALL -ldap_parse_authzid_control ( - LDAP *ld, - LDAPControl **ctrlp, - char **authzid - ) -{ - int i, foundAUTHZIDControl; - char *authzidp = NULL; - LDAPControl *AUTHZIDCtrlp = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { - return( LDAP_PARAM_ERROR ); - } - - /* find the control in the list of controls if it exists */ - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - foundAUTHZIDControl = 0; - for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundAUTHZIDControl )); i++ ) { - foundAUTHZIDControl = !strcmp( ctrlp[i]->ldctl_oid, - LDAP_CONTROL_AUTHZID_RES ); - } - - /* - * The control is only included in a bind response if the resultCode - * for the bind operation is success. - */ - if ( !foundAUTHZIDControl ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } else { - /* let local var point to the control */ - AUTHZIDCtrlp = ctrlp[i-1]; - } - - /* - * If the bind request succeeded and resulted in an identity (not anonymous), - * the controlValue contains the authorization identity (authzid), as - * defined in [AUTH] section 9, granted to the requestor. If the bind - * request resulted in an anonymous association, the controlValue field - * is a string of zero length. If the bind request resulted in more - * than one authzid, the primary authzid is returned in the controlValue - * field. - */ - if ( AUTHZIDCtrlp && AUTHZIDCtrlp->ldctl_value.bv_val && - AUTHZIDCtrlp->ldctl_value.bv_len ) { - authzidp = ( (char *)NSLDAPI_MALLOC( - ( AUTHZIDCtrlp->ldctl_value.bv_len + 1 ) ) ); - if ( authzidp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - STRLCPY( authzidp, AUTHZIDCtrlp->ldctl_value.bv_val, - ( AUTHZIDCtrlp->ldctl_value.bv_len + 1 ) ); - *authzid = authzidp; - } else { - authzid = NULL; - } - - return( LDAP_SUCCESS ); -} diff --git a/ldap/c-sdk/libraries/libldap/bind.c b/ldap/c-sdk/libraries/libldap/bind.c deleted file mode 100644 index 8b5504be31..0000000000 --- a/ldap/c-sdk/libraries/libldap/bind.c +++ /dev/null @@ -1,170 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * bind.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_bind - bind to the ldap server. The dn and password - * of the entry to which to bind are supplied, along with the authentication - * method to use. The msgid of the bind request is returned on success, - * -1 if there's trouble. Note, the kerberos support assumes the user already - * has a valid tgt for now. ldap_result() should be called to find out the - * outcome of the bind request. - * - * Example: - * ldap_bind( ld, "cn=manager, o=university of michigan, c=us", "secret", - * LDAP_AUTH_SIMPLE ) - */ - -int -LDAP_CALL -ldap_bind( LDAP *ld, const char *dn, const char *passwd, int authmethod ) -{ - /* - * The bind request looks like this: - * BindRequest ::= SEQUENCE { - * version INTEGER, - * name DistinguishedName, -- who - * authentication CHOICE { - * simple [0] OCTET STRING -- passwd - * } - * } - * all wrapped up in an LDAPMessage sequence. - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); - } - - switch ( authmethod ) { - case LDAP_AUTH_SIMPLE: - return( ldap_simple_bind( ld, dn, passwd ) ); - - default: - LDAP_SET_LDERRNO( ld, LDAP_AUTH_UNKNOWN, NULL, NULL ); - return( -1 ); - } -} - -/* - * ldap_bind_s - bind to the ldap server. The dn and password - * of the entry to which to bind are supplied, along with the authentication - * method to use. This routine just calls whichever bind routine is - * appropriate and returns the result of the bind (e.g. LDAP_SUCCESS or - * some other error indication). Note, the kerberos support assumes the - * user already has a valid tgt for now. - * - * Examples: - * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * "secret", LDAP_AUTH_SIMPLE ) - * ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * NULL, LDAP_AUTH_KRBV4 ) - */ -int -LDAP_CALL -ldap_bind_s( LDAP *ld, const char *dn, const char *passwd, int authmethod ) -{ - int err; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_bind_s\n", 0, 0, 0 ); - - switch ( authmethod ) { - case LDAP_AUTH_SIMPLE: - return( ldap_simple_bind_s( ld, dn, passwd ) ); - - default: - err = LDAP_AUTH_UNKNOWN; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } -} - - -void -LDAP_CALL -ldap_set_rebind_proc( LDAP *ld, LDAP_REBINDPROC_CALLBACK *rebindproc, - void *arg ) -{ - if ( ld == NULL ) { - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - ld = &nsldapi_ld_defaults; - } - - if ( NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - ld->ld_rebind_fn = rebindproc; - ld->ld_rebind_arg = arg; - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - } -} - - -/* - * return a pointer to the bind DN for the default connection (a copy is - * not made). If there is no bind DN available, NULL is returned. - */ -char * -nsldapi_get_binddn( LDAP *ld ) -{ - char *binddn; - - binddn = NULL; /* default -- assume they are not bound */ - - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - if ( NULL != ld->ld_defconn && LDAP_CONNST_CONNECTED == - ld->ld_defconn->lconn_status && ld->ld_defconn->lconn_bound ) { - if (( binddn = ld->ld_defconn->lconn_binddn ) == NULL ) { - binddn = ""; - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - - return( binddn ); -} diff --git a/ldap/c-sdk/libraries/libldap/cache.c b/ldap/c-sdk/libraries/libldap/cache.c deleted file mode 100644 index 54195e5fe3..0000000000 --- a/ldap/c-sdk/libraries/libldap/cache.c +++ /dev/null @@ -1,145 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993 The Regents of the University of Michigan. - * All rights reserved. - */ -/* - * cache.c - generic caching support for LDAP - */ - -#include "ldap-int.h" - -/* - * ldap_cache_flush - flush part of the LDAP cache. returns an - * ldap error code (LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT, etc.). - */ - -int -LDAP_CALL -ldap_cache_flush( LDAP *ld, const char *dn, const char *filter ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( dn == NULL ) { - dn = ""; - } - - return( (ld->ld_cache_flush)( ld, dn, filter ) ); -} - -/* - * nsldapi_add_result_to_cache - add an ldap entry we just read off the network - * to the ldap cache. this routine parses the ber for the entry and - * constructs the appropriate add request. this routine calls the - * cache add routine to actually add the entry. - */ - -void -nsldapi_add_result_to_cache( LDAP *ld, LDAPMessage *m ) -{ - char *dn; - LDAPMod **mods; - int i, max, rc; - char *a; - BerElement *ber; - char buf[50]; - struct berval bv; - struct berval *bvp[2]; - - LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_add_result_to_cache id %d type %d\n", - m->lm_msgid, m->lm_msgtype, 0 ); - if ( m->lm_msgtype != LDAP_RES_SEARCH_ENTRY || - ld->ld_cache_add == NULL ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_add_result_to_cache not added\n", 0, 0, 0 ); - return; - } - -#define GRABSIZE 5 - - dn = ldap_get_dn( ld, m ); - mods = (LDAPMod **)NSLDAPI_MALLOC( GRABSIZE * sizeof(LDAPMod *) ); - max = GRABSIZE; - for ( i = 0, a = ldap_first_attribute( ld, m, &ber ); a != NULL; - a = ldap_next_attribute( ld, m, ber ), i++ ) { - if ( i == (max - 1) ) { - max += GRABSIZE; - mods = (LDAPMod **)NSLDAPI_REALLOC( mods, - sizeof(LDAPMod *) * max ); - } - - mods[i] = (LDAPMod *)NSLDAPI_CALLOC( 1, sizeof(LDAPMod) ); - mods[i]->mod_op = LDAP_MOD_BVALUES; - mods[i]->mod_type = a; - mods[i]->mod_bvalues = ldap_get_values_len( ld, m, a ); - } - if ( ber != NULL ) { - ber_free( ber, 0 ); - } - if (( rc = LDAP_GET_LDERRNO( ld, NULL, NULL )) != LDAP_SUCCESS ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_add_result_to_cache error: failed to construct mod list (%s)\n", - ldap_err2string( rc ), 0, 0 ); - ldap_mods_free( mods, 1 ); - return; - } - - /* update special cachedtime attribute */ - if ( i == (max - 1) ) { - max++; - mods = (LDAPMod **)NSLDAPI_REALLOC( mods, - sizeof(LDAPMod *) * max ); - } - mods[i] = (LDAPMod *)NSLDAPI_CALLOC( 1, sizeof(LDAPMod) ); - mods[i]->mod_op = LDAP_MOD_BVALUES; - mods[i]->mod_type = "cachedtime"; - sprintf( buf, "%ld", time( NULL ) ); - bv.bv_val = buf; - bv.bv_len = strlen( buf ); - bvp[0] = &bv; - bvp[1] = NULL; - mods[i]->mod_bvalues = bvp; - mods[++i] = NULL; - - /* msgid of -1 means don't send the result */ - rc = (ld->ld_cache_add)( ld, -1, m->lm_msgtype, dn, mods ); - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_add_result_to_cache added (rc %d)\n", rc, 0, 0 ); -} diff --git a/ldap/c-sdk/libraries/libldap/charray.c b/ldap/c-sdk/libraries/libldap/charray.c deleted file mode 100644 index 043f99e8aa..0000000000 --- a/ldap/c-sdk/libraries/libldap/charray.c +++ /dev/null @@ -1,248 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* charray.c - routines for dealing with char * arrays */ - - -#include "ldap-int.h" - -/* - * Add s at the end of the array of strings *a. - * Return 0 for success, -1 for failure. - */ -int -LDAP_CALL -ldap_charray_add( - char ***a, - char *s -) -{ - int n; - - if ( *a == NULL ) { - *a = (char **)NSLDAPI_MALLOC( 2 * sizeof(char *) ); - if ( *a == NULL ) { - return -1; - } - n = 0; - } else { - for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { - ; /* NULL */ - } - - *a = (char **)NSLDAPI_REALLOC( (char *) *a, - (n + 2) * sizeof(char *) ); - if ( *a == NULL ) { - return -1; - } - } - - (*a)[n++] = s; - (*a)[n] = NULL; - return 0; -} - -/* - * Add array of strings s at the end of the array of strings *a. - * Return 0 for success, -1 for failure. - */ -int -LDAP_CALL -ldap_charray_merge( - char ***a, - char **s -) -{ - int i, n, nn; - - if ( (s == NULL) || (s[0] == NULL) ) - return 0; - - for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { - ; /* NULL */ - } - for ( nn = 0; s[nn] != NULL; nn++ ) { - ; /* NULL */ - } - - *a = (char **)NSLDAPI_REALLOC( (char *) *a, - (n + nn + 1) * sizeof(char *) ); - if ( *a == NULL ) { - return -1; - } - - for ( i = 0; i < nn; i++ ) { - (*a)[n + i] = s[i]; - } - (*a)[n + nn] = NULL; - return 0; -} - -void -LDAP_CALL -ldap_charray_free( char **array ) -{ - char **a; - - if ( array == NULL ) { - return; - } - - for ( a = array; *a != NULL; a++ ) { - if ( *a != NULL ) { - NSLDAPI_FREE( *a ); - } - } - NSLDAPI_FREE( (char *) array ); -} - -int -LDAP_CALL -ldap_charray_inlist( - char **a, - char *s -) -{ - int i; - - if ( a == NULL ) - return( 0 ); - - for ( i = 0; a[i] != NULL; i++ ) { - if ( strcasecmp( s, a[i] ) == 0 ) { - return( 1 ); - } - } - - return( 0 ); -} - -/* - * Duplicate the array of strings a, return NULL upon any memory failure. - */ -char ** -LDAP_CALL -ldap_charray_dup( char **a ) -{ - int i; - char **new; - - for ( i = 0; a[i] != NULL; i++ ) - ; /* NULL */ - - new = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) ); - if ( new == NULL ) { - return NULL; - } - - for ( i = 0; a[i] != NULL; i++ ) { - new[i] = nsldapi_strdup( a[i] ); - if ( new[i] == NULL ) { - int j; - - for ( j = 0; j < i; j++ ) - NSLDAPI_FREE( new[j] ); - NSLDAPI_FREE( new ); - return NULL; - } - } - new[i] = NULL; - - return( new ); -} - -/* - * Tokenize the string str, return NULL upon any memory failure. - * XXX: on many platforms this function is not thread safe because it - * uses strtok(). - */ -char ** -LDAP_CALL -ldap_str2charray( char *str, char *brkstr ) - /* This implementation fails if brkstr contains multibyte characters. - But it works OK if str is UTF-8 and brkstr is 7-bit ASCII. - */ -{ - char **res; - char *s; - int i; -#ifdef HAVE_STRTOK_R /* defined in portable.h */ - char *lasts; -#endif - - i = 1; - for ( s = str; *s; s++ ) { - if ( strchr( brkstr, *s ) != NULL ) { - i++; - } - } - - res = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) ); - if ( res == NULL ) { - return NULL; - } - i = 0; - for ( s = STRTOK( str, brkstr, &lasts ); s != NULL; s = STRTOK( NULL, - brkstr, &lasts ) ) { - res[i++] = nsldapi_strdup( s ); - if ( res[i - 1] == NULL ) { - int j; - - for ( j = 0; j < (i - 1); j++ ) - NSLDAPI_FREE( res[j] ); - NSLDAPI_FREE( res ); - return NULL; - } - } - res[i] = NULL; - - return( res ); -} - -int -LDAP_CALL -ldap_charray_position( char **a, char *s ) -{ - int i; - - for ( i = 0; a[i] != NULL; i++ ) { - if ( strcasecmp( s, a[i] ) == 0 ) { - return( i ); - } - } - - return( -1 ); -} diff --git a/ldap/c-sdk/libraries/libldap/charset.c b/ldap/c-sdk/libraries/libldap/charset.c deleted file mode 100644 index 23bad239be..0000000000 --- a/ldap/c-sdk/libraries/libldap/charset.c +++ /dev/null @@ -1,1845 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * charset.c - */ - -#include "ldap-int.h" - -#ifdef STR_TRANSLATION - -void -ldap_set_string_translators( LDAP *ld, BERTranslateProc encode_proc, - BERTranslateProc decode_proc ) -{ - if ( ld == NULL ) { - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - ld = &nsldapi_ld_defaults; - } - - if ( NSLDAPI_VALID_LDAP_POINTER( ld )) { - 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 ) -{ - char *optionsp; - - if ( ld == NULL ) { - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - ld = &nsldapi_ld_defaults; - } - - optionsp = ( entry == NULLMSG ) ? &ld->ld_lberoptions : - &entry->lm_ber->ber_options; - - if ( enable ) { - *optionsp |= LBER_OPT_TRANSLATE_STRINGS; - } else { - *optionsp &= ~LBER_OPT_TRANSLATE_STRINGS; - } -} - - -int -ldap_translate_from_t61( LDAP *ld, char **bufp, unsigned long *lenp, - int free_input ) -{ - if ( ld->ld_lber_decode_translate_proc == NULL ) { - return( LDAP_SUCCESS ); - } - - return( (*ld->ld_lber_decode_translate_proc)( bufp, lenp, free_input )); -} - - -int -ldap_translate_to_t61( LDAP *ld, char **bufp, unsigned long *lenp, - int free_input ) -{ - if ( ld->ld_lber_encode_translate_proc == NULL ) { - 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; - -#ifdef NEEDPROTOS -static Byte *c_to_hh( Byte *o, Byte c ); -static Byte *c_to_cc( Byte *o, Couple *cc, Byte c ); -static int hh_to_c( Byte *h ); -static Byte *cc_to_t61( Byte *o, Byte *s ); -#else /* NEEDPROTOS */ -static Byte *c_to_hh(); -static Byte *c_to_cc(); -static int hh_to_c(); -static Byte *cc_to_t61(); -#endif /* NEEDPROTOS */ - -/* - Character choosed as base in diacritics alone: NO-BREAK SPACE. - (The standard say it must be a blank space, 0x20.) -*/ -#define ALONE 0xA0 - -static 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 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 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 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 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 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 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 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 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 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, 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, unsigned long *buflenp, int free_input ) -{ - Byte *s, *oo, *o; - unsigned int n; - int c; - unsigned long len; - Couple *cc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_t61_to_8859 input length: %ld\n", - *buflenp, 0, 0 ); - - len = *buflenp; - s = (Byte *) *bufp; - - if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, len )) == NULL ) { - NSLDAPI_FREE( o ); - return( 1 ); - } - - if ( free_input ) { - NSLDAPI_FREE( *bufp ); - } - *bufp = (char *) oo; - *buflenp = len; - return( 0 ); -} - - -static int -hh_to_c( 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, 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, unsigned long *buflenp, int free_input ) -{ - Byte *s, *oo, *o, *aux; - int c; - unsigned long len; - Couple *cc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_8859_to_t61 input length: %ld\n", - *buflenp, 0, 0 ); - - len = *buflenp; - s = (Byte *) *bufp; - - if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, len )) == NULL ) { - NSLDAPI_FREE( o ); - return( 1 ); - } - - if ( free_input ) { - NSLDAPI_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( ++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 ) -Byte *s; -{ - Byte *o, *oo; - Byte n; - - if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, strlen( o ) + 1 )) == NULL ) { - NSLDAPI_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 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; - Couple *cc; - - if ( (o = oo = (Byte *)NSLDAPI_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 *)NSLDAPI_REALLOC( o, strlen( o ) + 1 )) == NULL ) { - NSLDAPI_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/ldap/c-sdk/libraries/libldap/cldap.c b/ldap/c-sdk/libraries/libldap/cldap.c deleted file mode 100644 index 829d34c287..0000000000 --- a/ldap/c-sdk/libraries/libldap/cldap.c +++ /dev/null @@ -1,585 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990, 1994 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * cldap.c - synchronous, retrying interface to the cldap protocol - */ - - -#ifdef CLDAP - -XXX not MT-safe XXX - -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990, 1994 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif - -#include -#include -#include -#ifdef macintosh -#include -#include "macos.h" -#else /* macintosh */ -#ifdef DOS -#include "msdos.h" -#else /* DOS */ -#ifdef _WINDOWS -#include -#else /* _WINDOWS */ -#include -#include -#include -#include -#include -#endif /* _WINDOWS */ -#endif /* DOS */ -#endif /* macintosh */ - -#include "ldap-int.h" - -#define DEF_CLDAP_TIMEOUT 3 -#define DEF_CLDAP_TRIES 4 - -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK ((unsigned long) 0x7f000001) -#endif - - -struct cldap_retinfo { - int cri_maxtries; - int cri_try; - int cri_useaddr; - long cri_timeout; -}; - -#ifdef NEEDPROTOS -static int add_addr( LDAP *ld, struct sockaddr *sap ); -static int cldap_result( LDAP *ld, int msgid, LDAPMessage **res, - struct cldap_retinfo *crip, char *base ); -static int cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber, - LDAPMessage **res, char *base ); -#else /* NEEDPROTOS */ -static int add_addr(); -static int cldap_result(); -static int cldap_parsemsg(); -#endif /* NEEDPROTOS */ - -/* - * cldap_open - initialize and connect to an ldap server. A magic cookie to - * be used for future communication is returned on success, NULL on failure. - * - * Example: - * LDAP *ld; - * ld = cldap_open( hostname, port ); - */ - -LDAP * -cldap_open( char *host, int port ) -{ - int s; - ldap_x_in_addr_t address; - struct sockaddr_in sock; - struct hostent *hp; - LDAP *ld; - char *p; - int i; - - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_open\n", 0, 0, 0 ); - - if ( port == 0 ) { - port = LDAP_PORT; - } - - if ( (s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) { - return( NULL ); - } - - sock.sin_addr.s_addr = 0; - sock.sin_family = AF_INET; - sock.sin_port = 0; - if ( bind(s, (struct sockaddr *) &sock, sizeof(sock)) < 0) { - close( s ); - return( NULL ); - } - - if (( ld = ldap_init( host, port )) == NULL ) { - close( s ); - return( NULL ); - } - if ( (ld->ld_sbp->sb_fromaddr = (void *)NSLDAPI_CALLOC( 1, - sizeof( struct sockaddr ))) == NULL ) { - NSLDAPI_FREE( ld ); - close( s ); - return( NULL ); - } - ld->ld_sbp->sb_sd = s; - ld->ld_sbp->sb_naddr = 0; - ld->ld_version = LDAP_VERSION2; - - sock.sin_family = AF_INET; - sock.sin_port = htons( port ); - - /* - * 'host' may be a space-separated list. - */ - if ( host != NULL ) { - for ( ; host != NULL; host = p ) { - if (( p = strchr( host, ' ' )) != NULL ) { - for (*p++ = '\0'; *p == ' '; p++) { - ; - } - } - - if ( (address = inet_addr( host )) == -1 ) { -/* XXXmcs: need to use DNS callbacks here XXX */ -XXX - if ( (hp = gethostbyname( host )) == NULL ) { - LDAP_SET_ERRNO( ld, EHOSTUNREACH ); - continue; - } - - for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) { - SAFEMEMCPY( (char *)&sock.sin_addr.s_addr, - (char *)hp->h_addr_list[ i ], - sizeof(sock.sin_addr.s_addr)); - if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { - close( s ); - NSLDAPI_FREE( ld ); - return( NULL ); - } - } - - } else { - sock.sin_addr.s_addr = address; - if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { - close( s ); - NSLDAPI_FREE( ld ); - return( NULL ); - } - } - - if ( ld->ld_host == NULL ) { - ld->ld_host = nsldapi_strdup( host ); - } - } - - } else { - address = INADDR_LOOPBACK; - sock.sin_addr.s_addr = htonl( address ); - if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) { - close( s ); - NSLDAPI_FREE( ld ); - return( NULL ); - } - } - - if ( ld->ld_sbp->sb_addrs == NULL - || ( ld->ld_defconn = nsldapi_new_connection( ld, NULL, 1,0,0 )) == NULL ) { - NSLDAPI_FREE( ld ); - return( NULL ); - } - - ld->ld_sbp->sb_useaddr = ld->ld_sbp->sb_addrs[ 0 ]; - cldap_setretryinfo( ld, 0, 0 ); - -#ifdef LDAP_DEBUG - putchar( '\n' ); - for ( i = 0; i < ld->ld_sbp->sb_naddr; ++i ) { - LDAPDebug( LDAP_DEBUG_TRACE, "end of cldap_open address %d is %s\n", - i, inet_ntoa( ((struct sockaddr_in *) - ld->ld_sbp->sb_addrs[ i ])->sin_addr ), 0 ); - } -#endif - - return( ld ); -} - - - -void -cldap_close( LDAP *ld ) -{ - ldap_ld_free( ld, NULL, NULL, 0 ); -} - - -void -cldap_setretryinfo( LDAP *ld, int tries, int timeout ) -{ - ld->ld_cldaptries = ( tries <= 0 ) ? DEF_CLDAP_TRIES : tries; - ld->ld_cldaptimeout = ( timeout <= 0 ) ? DEF_CLDAP_TIMEOUT : timeout; -} - - -int -cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs, - int attrsonly, LDAPMessage **res, char *logdn ) -{ - int ret, msgid; - struct cldap_retinfo cri; - - *res = NULLMSG; - - (void) memset( &cri, 0, sizeof( cri )); - - if ( logdn != NULL ) { - ld->ld_cldapdn = logdn; - } else if ( ld->ld_cldapdn == NULL ) { - ld->ld_cldapdn = ""; - } - - do { - if ( cri.cri_try != 0 ) { - --ld->ld_msgid; /* use same id as before */ - } - ld->ld_sbp->sb_useaddr = ld->ld_sbp->sb_addrs[ cri.cri_useaddr ]; - - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n", - cri.cri_try, inet_ntoa( ((struct sockaddr_in *) - ld->ld_sbp->sb_useaddr)->sin_addr ), 0 ); - - if ( (msgid = ldap_search( ld, base, scope, filter, attrs, - attrsonly )) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } -#ifndef NO_CACHE - if ( ld->ld_cache != NULL && ld->ld_responses != NULL ) { - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_search_s res from cache\n", - 0, 0, 0 ); - *res = ld->ld_responses; - ld->ld_responses = ld->ld_responses->lm_next; - return( ldap_result2error( ld, *res, 0 )); - } -#endif /* NO_CACHE */ - ret = cldap_result( ld, msgid, res, &cri, base ); - } while (ret == -1); - - return( ret ); -} - - -static int -add_addr( LDAP *ld, struct sockaddr *sap ) -{ - struct sockaddr *newsap, **addrs; - - if (( newsap = (struct sockaddr *)NSLDAPI_MALLOC( - sizeof( struct sockaddr ))) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - - if ( ld->ld_sbp->sb_naddr == 0 ) { - addrs = (struct sockaddr **)NSLDAPI_MALLOC( sizeof(struct sockaddr *)); - } else { - addrs = (struct sockaddr **)NSLDAPI_REALLOC( ld->ld_sbp->sb_addrs, - ( ld->ld_sbp->sb_naddr + 1 ) * sizeof(struct sockaddr *)); - } - - if ( addrs == NULL ) { - NSLDAPI_FREE( newsap ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - - SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr )); - addrs[ ld->ld_sbp->sb_naddr++ ] = newsap; - ld->ld_sbp->sb_addrs = (void **)addrs; - return( 0 ); -} - - -static int -cldap_result( LDAP *ld, int msgid, LDAPMessage **res, - struct cldap_retinfo *crip, char *base ) -{ - Sockbuf *sb = ld->ld_sbp; - BerElement ber; - char *logdn; - int ret, fromaddr, i; - ber_int_t id; - struct timeval tv; - - fromaddr = -1; - - if ( crip->cri_try == 0 ) { - crip->cri_maxtries = ld->ld_cldaptries * sb->sb_naddr; - crip->cri_timeout = ld->ld_cldaptimeout; - crip->cri_useaddr = 0; - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_result tries %d timeout %d\n", - ld->ld_cldaptries, ld->ld_cldaptimeout, 0 ); - } - - if ((tv.tv_sec = crip->cri_timeout / sb->sb_naddr) < 1 ) { - tv.tv_sec = 1; - } - tv.tv_usec = 0; - - LDAPDebug( LDAP_DEBUG_TRACE, - "cldap_result waiting up to %d seconds for a response\n", - tv.tv_sec, 0, 0 ); - ber_init_w_nullchar( &ber, 0 ); - nsldapi_set_ber_options( ld, &ber ); - - if ( cldap_getmsg( ld, &tv, &ber ) == -1 ) { - ret = LDAP_GET_LDERRNO( ld, NULL, NULL ); - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_getmsg returned -1 (%d)\n", - ret, 0, 0 ); - } else if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "cldap_result timed out\n", 0, 0, 0 ); - /* - * It timed out; is it time to give up? - */ - if ( ++crip->cri_try >= crip->cri_maxtries ) { - ret = LDAP_TIMEOUT; - --crip->cri_try; - } else { - if ( ++crip->cri_useaddr >= sb->sb_naddr ) { - /* - * new round: reset address to first one and - * double the timeout - */ - crip->cri_useaddr = 0; - crip->cri_timeout <<= 1; - } - ret = -1; - } - - } else { - /* - * Got a response. It should look like: - * { msgid, logdn, { searchresponse...}} - */ - logdn = NULL; - - if ( ber_scanf( &ber, "ia", &id, &logdn ) == LBER_ERROR ) { - NSLDAPI_FREE( ber.ber_buf ); /* gack! */ - ret = LDAP_DECODING_ERROR; - LDAPDebug( LDAP_DEBUG_TRACE, - "cldap_result: ber_scanf returned LBER_ERROR (%d)\n", - ret, 0, 0 ); - } else if ( id != msgid ) { - NSLDAPI_FREE( ber.ber_buf ); /* gack! */ - LDAPDebug( LDAP_DEBUG_TRACE, - "cldap_result: looking for msgid %d; got %ld\n", - msgid, id, 0 ); - ret = -1; /* ignore and keep looking */ - } else { - /* - * got a result: determine which server it came from - * decode into ldap message chain - */ - for ( fromaddr = 0; fromaddr < sb->sb_naddr; ++fromaddr ) { - if ( memcmp( &((struct sockaddr_in *) - sb->sb_addrs[ fromaddr ])->sin_addr, - &((struct sockaddr_in *)sb->sb_fromaddr)->sin_addr, - sizeof( struct in_addr )) == 0 ) { - break; - } - } - ret = cldap_parsemsg( ld, msgid, &ber, res, base ); - NSLDAPI_FREE( ber.ber_buf ); /* gack! */ - LDAPDebug( LDAP_DEBUG_TRACE, - "cldap_result got result (%d)\n", ret, 0, 0 ); - } - - if ( logdn != NULL ) { - NSLDAPI_FREE( logdn ); - } - } - - - /* - * If we are giving up (successfully or otherwise) then - * abandon any outstanding requests. - */ - if ( ret != -1 ) { - i = crip->cri_try; - if ( i >= sb->sb_naddr ) { - i = sb->sb_naddr - 1; - } - - for ( ; i >= 0; --i ) { - if ( i == fromaddr ) { - continue; - } - sb->sb_useaddr = sb->sb_addrs[ i ]; - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n", - msgid, inet_ntoa( ((struct sockaddr_in *) - sb->sb_useaddr)->sin_addr ), 0 ); - (void) ldap_abandon( ld, msgid ); - } - } - - LDAP_SET_LDERRNO( ld, ret, NULL, NULL ); - return( ret ); -} - - -static int -cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber, - LDAPMessage **res, char *base ) -{ - ber_tag_t tag; - ber_len_t len; - int baselen, slen, rc; - char *dn, *p, *cookie; - LDAPMessage *chain, *prev, *ldm; - struct berval *bv; - - rc = LDAP_DECODING_ERROR; /* pessimistic */ - ldm = chain = prev = NULLMSG; - baselen = ( base == NULL ) ? 0 : strlen( base ); - bv = NULL; - - for ( tag = ber_first_element( ber, &len, &cookie ); - tag != LBER_ERROR && tag != LBER_END_OF_SEQOFSET - && rc != LDAP_SUCCESS; - tag = ber_next_element( ber, &len, cookie )) { - if (( ldm = (LDAPMessage *)NSLDAPI_CALLOC( 1, sizeof(LDAPMessage))) - == NULL ) { - rc = LDAP_NO_MEMORY; - break; /* return with error */ - } else if (( rc = nsldapi_alloc_ber_with_options( ld, &ldm->lm_ber )) - != LDAP_SUCCESS ) { - break; /* return with error*/ - } - ldm->lm_msgid = msgid; - ldm->lm_msgtype = tag; - - if ( tag == LDAP_RES_SEARCH_RESULT ) { - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg got search result\n", - 0, 0, 0 ); - - if ( ber_get_stringal( ber, &bv ) == LBER_DEFAULT ) { - break; /* return w/error */ - } - - if ( ber_printf( ldm->lm_ber, "to", tag, bv->bv_val, - bv->bv_len ) == -1 ) { - break; /* return w/error */ - } - ber_bvfree( bv ); - bv = NULL; - rc = LDAP_SUCCESS; - - } else if ( tag == LDAP_RES_SEARCH_ENTRY ) { - if ( ber_scanf( ber, "{aO", &dn, &bv ) == LBER_ERROR ) { - break; /* return w/error */ - } - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg entry %s\n", dn, 0, 0 ); - if ( dn != NULL && *(dn + ( slen = strlen(dn)) - 1) == '*' && - baselen > 0 ) { - /* - * substitute original searchbase for trailing '*' - */ - if (( p = (char *)NSLDAPI_MALLOC( slen + baselen )) == NULL ) { - rc = LDAP_NO_MEMORY; - NSLDAPI_FREE( dn ); - break; /* return w/error */ - } - strcpy( p, dn ); - strcpy( p + slen - 1, base ); - NSLDAPI_FREE( dn ); - dn = p; - } - - if ( ber_printf( ldm->lm_ber, "t{so}", tag, dn, bv->bv_val, - bv->bv_len ) == -1 ) { - break; /* return w/error */ - } - NSLDAPI_FREE( dn ); - ber_bvfree( bv ); - bv = NULL; - - } else { - LDAPDebug( LDAP_DEBUG_TRACE, "cldap_parsemsg got unknown tag %d\n", - tag, 0, 0 ); - rc = LDAP_PROTOCOL_ERROR; - break; /* return w/error */ - } - - /* Reset message ber so we can read from it later. Gack! */ - ldm->lm_ber->ber_end = ldm->lm_ber->ber_ptr; - ldm->lm_ber->ber_ptr = ldm->lm_ber->ber_buf; - -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { - char msg[80]; - sprintf( msg, "cldap_parsemsg add message id %d type %d:\n", - ldm->lm_msgid, ldm->lm_msgtype ); - ber_err_print( msg ); - ber_dump( ldm->lm_ber, 1 ); - } -#endif /* LDAP_DEBUG */ - -#ifndef NO_CACHE - if ( ld->ld_cache != NULL ) { - nsldapi_add_result_to_cache( ld, ldm ); - } -#endif /* NO_CACHE */ - - if ( chain == NULL ) { - chain = ldm; - } else { - prev->lm_chain = ldm; - } - prev = ldm; - ldm = NULL; - } - - /* dispose of any leftovers */ - if ( ldm != NULL ) { - if ( ldm->lm_ber != NULLBER ) { - ber_free( ldm->lm_ber, 1 ); - } - NSLDAPI_FREE( ldm ); - } - if ( bv != NULL ) { - ber_bvfree( bv ); - } - - /* return chain, calling result2error if we got anything at all */ - *res = chain; - return(( *res == NULLMSG ) ? rc : ldap_result2error( ld, *res, 0 )); -} -#endif /* CLDAP */ diff --git a/ldap/c-sdk/libraries/libldap/compare.c b/ldap/c-sdk/libraries/libldap/compare.c deleted file mode 100644 index 6ccd0e8aa5..0000000000 --- a/ldap/c-sdk/libraries/libldap/compare.c +++ /dev/null @@ -1,194 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * compare.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_compare - perform an ldap compare operation. The dn - * of the entry to compare to and the attribute and value to compare (in - * attr and value) are supplied. The msgid of the response is returned. - * - * Example: - * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) - */ -int -LDAP_CALL -ldap_compare( LDAP *ld, const char *dn, const char *attr, const char *value ) -{ - int msgid; - struct berval bv; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 ); - - bv.bv_val = (char *)value; - bv.bv_len = ( value == NULL ) ? 0 : strlen( value ); - - if ( ldap_compare_ext( ld, dn, attr, &bv, NULL, NULL, &msgid ) - == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - -int -LDAP_CALL -ldap_compare_ext( LDAP *ld, const char *dn, const char *attr, - const struct berval *bvalue, LDAPControl **serverctrls, - LDAPControl **clientctrls, int *msgidp ) -{ - BerElement *ber; - int rc, lderr; - - /* The compare request looks like this: - * CompareRequest ::= SEQUENCE { - * entry DistinguishedName, - * ava SEQUENCE { - * type AttributeType, - * value AttributeValue - * } - * } - * and must be wrapped in an LDAPMessage. - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare_ext\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - if ( attr == NULL || bvalue == NULL || bvalue->bv_len == 0 - || msgidp == NULL ) { - lderr = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - return( lderr ); - } - - if ( dn == NULL ) { - dn = ""; - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* check the cache */ - if ( ld->ld_cache_on && ld->ld_cache_compare != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_compare)( ld, *msgidp, - LDAP_REQ_COMPARE, dn, attr, bvalue )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( lderr ); - } - - if ( ber_printf( ber, "{it{s{so}}", *msgidp, LDAP_REQ_COMPARE, dn, - attr, bvalue->bv_val, bvalue->bv_len ) - == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( lderr ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_COMPARE, - (char *)dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -int -LDAP_CALL -ldap_compare_s( LDAP *ld, const char *dn, const char *attr, - const char *value ) -{ - struct berval bv; - - bv.bv_val = (char *)value; - bv.bv_len = ( value == NULL ) ? 0 : strlen( value ); - - return( ldap_compare_ext_s( ld, dn, attr, &bv, NULL, NULL )); -} - -int -LDAP_CALL -ldap_compare_ext_s( LDAP *ld, const char *dn, const char *attr, - const struct berval *bvalue, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - int err, msgid; - LDAPMessage *res; - - if (( err = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, - clientctrls, &msgid )) != LDAP_SUCCESS ) { - return( err ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) - == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - return( ldap_result2error( ld, res, 1 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/compat.c b/ldap/c-sdk/libraries/libldap/compat.c deleted file mode 100644 index 94e58ca7a3..0000000000 --- a/ldap/c-sdk/libraries/libldap/compat.c +++ /dev/null @@ -1,108 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1994 The Regents of the University of Michigan. - * All rights reserved. - */ -/* - * compat.c - compatibility routines. - * - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -#if defined( HPUX10 ) && defined( _REENTRANT ) && !defined(HPUX11) -extern int h_errno; - -struct hostent * -nsldapi_compat_gethostbyname_r( const char *name, struct hostent *result, - char *buffer, int buflen, int *h_errnop ) -{ - struct hostent_data *hep; - - if ( buflen < sizeof(struct hostent_data)) { /* sanity check */ - *h_errnop = NO_RECOVERY; /* XXX best error code to use? */ - return( NULL ); - } - - hep = (struct hostent_data *)buffer; - hep->current = NULL; - - if ( gethostbyname_r( name, result, hep ) == -1) { - *h_errnop = h_errno; /* XXX don't see anywhere else to get this */ - return NULL; - } - return result; -} - -char * -nsldapi_compat_ctime_r( const time_t *clock, char *buf, int buflen ) -{ - NSLDAPI_CTIME1( clock, buf, buflen ); - return buf; -} -#endif /* HPUX10 && _REENTRANT && !HPUX11 */ - -#if defined(LINUX) || defined(AIX) || defined(HPUX) || defined(_WINDOWS) -/* - * Copies src to the dstsize buffer at dst. The copy will never - * overflow the destination buffer and the buffer will always be null - * terminated. - */ -size_t nsldapi_compat_strlcpy(char *dst, const char *src, size_t len) -{ - size_t slen = strlen(src); - size_t copied; - - if (len == 0) - return (slen); - - if (slen >= len) - copied = len - 1; - else - copied = slen; - SAFEMEMCPY(dst, src, copied); - dst[copied] = '\0'; - return (slen); -} -#endif diff --git a/ldap/c-sdk/libraries/libldap/control.c b/ldap/c-sdk/libraries/libldap/control.c deleted file mode 100644 index 5f2eb73758..0000000000 --- a/ldap/c-sdk/libraries/libldap/control.c +++ /dev/null @@ -1,559 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* control.c - routines to handle ldapv3 controls */ - -#include "ldap-int.h" - -static LDAPControl *ldap_control_dup( LDAPControl *ctrl ); -static int ldap_control_copy_contents( LDAPControl *ctrl_dst, - LDAPControl *ctrl_src ); - -/* - * Append a list of LDAPv3 controls to ber. If ctrls is NULL, use default - * set of controls from ld. - * Return an LDAP error code (LDAP_SUCCESS if all goes well). - * If closeseq is non-zero, we do an extra ber_put_seq() as well. - */ -int -nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq, - BerElement *ber ) -{ - LDAPControl *c; - int rc, i; - - rc = LDAP_ENCODING_ERROR; /* the most popular error */ - - /* if no controls were passed in, use global list from LDAP * */ - LDAP_MUTEX_LOCK( ld, LDAP_CTRL_LOCK ); - if ( ctrls == NULL ) { - ctrls = ld->ld_servercontrols; - } - - /* if there are no controls then we are done */ - if ( ctrls == NULL || ctrls[ 0 ] == NULL ) { - goto clean_exit; - } - - /* - * If we're using LDAPv2 or earlier we can't send any controls, so - * we just ignore them unless one is marked critical, in which case - * we return an error. - */ - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - for ( i = 0; ctrls != NULL && ctrls[i] != NULL; i++ ) { - if ( ctrls[i]->ldctl_iscritical ) { - rc = LDAP_NOT_SUPPORTED; - goto error_exit; - } - } - goto clean_exit; - } - - /* - * encode the controls as a Sequence of Sequence - */ - if ( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) { - goto error_exit; - } - - for ( i = 0; ctrls[i] != NULL; i++ ) { - c = ctrls[i]; - - if ( ber_printf( ber, "{s", c->ldctl_oid ) == -1 ) { - goto error_exit; - } - - /* criticality is "BOOLEAN DEFAULT FALSE" */ - /* therefore, it should only be encoded if it exists AND is TRUE */ - if ( c->ldctl_iscritical ) { - if ( ber_printf( ber, "b", (int)c->ldctl_iscritical ) - == -1 ) { - goto error_exit; - } - } - - if ( c->ldctl_value.bv_val != NULL ) { - if ( ber_printf( ber, "o", c->ldctl_value.bv_val, - c->ldctl_value.bv_len ) - == -1 ) { - goto error_exit; - } - } - - if ( ber_put_seq( ber ) == -1 ) { - goto error_exit; - } - } - - if ( ber_put_seq( ber ) == -1 ) { - goto error_exit; - } - -clean_exit: - LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK ); - if ( closeseq && ber_put_seq( ber ) == -1 ) { - goto error_exit; - } - return( LDAP_SUCCESS ); - -error_exit: - LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK ); - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - - -/* - * Pull controls out of "ber" (if any present) and return them in "controlsp." - * Returns an LDAP error code. - */ -int -nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp ) -{ - LDAPControl *newctrl; - ber_tag_t tag; - ber_len_t len; - int rc, maxcontrols, curcontrols; - char *last; - - /* - * Each LDAPMessage can have a set of controls appended - * to it. Controls are used to extend the functionality - * of an LDAP operation (e.g., add an attribute size limit - * to the search operation). These controls look like this: - * - * Controls ::= SEQUENCE OF Control - * - * Control ::= SEQUENCE { - * controlType LDAPOID, - * criticality BOOLEAN DEFAULT FALSE, - * controlValue OCTET STRING - * } - */ - LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 ); - - *controlsp = NULL; - - /* - * check to see if controls were included - */ - if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) { - return( LDAP_DECODING_ERROR ); /* unexpected error */ - } - if ( len == 0 ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_get_controls no controls\n", 0, 0, 0 ); - return( LDAP_SUCCESS ); /* no controls */ - } - if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { - if ( tag == LBER_ERROR ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n", - 0, 0, 0 ); - return( LDAP_DECODING_ERROR ); /* decoding error */ - } - /* - * We found something other than controls. This should never - * happen in LDAPv3, but we don't treat this is a hard error -- - * we just ignore the extra stuff. - */ - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n", - tag, 0, 0 ); - return( LDAP_SUCCESS ); - } - - maxcontrols = curcontrols = 0; - for ( tag = ber_first_element( ber, &len, &last ); - tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; - tag = ber_next_element( ber, &len, last ) ) { - if ( curcontrols >= maxcontrols - 1 ) { -#define CONTROL_GRABSIZE 5 - maxcontrols += CONTROL_GRABSIZE; - *controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC( - (char *)*controlsp, maxcontrols * - sizeof(struct ldapcontrol *) ); - if ( *controlsp == NULL ) { - rc = LDAP_NO_MEMORY; - goto free_and_return; - } - } - if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1, - sizeof(LDAPControl))) == NULL ) { - rc = LDAP_NO_MEMORY; - goto free_and_return; - } - - (*controlsp)[curcontrols++] = newctrl; - (*controlsp)[curcontrols] = NULL; - - if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid ) - == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - goto free_and_return; - } - - /* the criticality is optional */ - if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) { - int aint; - - if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - goto free_and_return; - } - newctrl->ldctl_iscritical = (char)aint; /* XXX lossy cast */ - } else { - /* absent is synonomous with FALSE */ - newctrl->ldctl_iscritical = 0; - } - - /* the control value is optional */ - if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) { - if ( ber_scanf( ber, "o", &newctrl->ldctl_value ) - == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - goto free_and_return; - } - } else { - (newctrl->ldctl_value).bv_val = NULL; - (newctrl->ldctl_value).bv_len = 0; - } - - } - - if ( tag == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - goto free_and_return; - } - - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 ); - return( LDAP_SUCCESS ); - -free_and_return:; - ldap_controls_free( *controlsp ); - *controlsp = NULL; - LDAPDebug( LDAP_DEBUG_TRACE, - "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 ); - return( rc ); -} - -/* - * Skips forward in a ber to find a control tag, then calls on - * nsldapi_get_controls() to parse them into an LDAPControl list. - * Returns an LDAP error code. - */ -int -nsldapi_find_controls( BerElement *ber, LDAPControl ***controlsp ) -{ - ber_tag_t tag; - ber_len_t len; - - if ( ber == NULLBER ) { - return( LDAP_DECODING_ERROR ); - } - - tag = ber_peek_tag( ber, &len ); - - while( tag != LDAP_TAG_CONTROLS && tag != LBER_DEFAULT ) { - tag = ber_skip_tag( ber, &len ); - /* Skip ahead to the next sequence */ - ber->ber_ptr += len; - tag = ber_peek_tag( ber, &len ); - } - - return( nsldapi_get_controls( ber, controlsp ) ); -} - - -void -LDAP_CALL -ldap_control_free( LDAPControl *ctrl ) -{ - if ( ctrl != NULL ) { - if ( ctrl->ldctl_oid != NULL ) { - NSLDAPI_FREE( ctrl->ldctl_oid ); - } - if ( ctrl->ldctl_value.bv_val != NULL ) { - NSLDAPI_FREE( ctrl->ldctl_value.bv_val ); - } - NSLDAPI_FREE( (char *)ctrl ); - } -} - - -void -LDAP_CALL -ldap_controls_free( LDAPControl **ctrls ) -{ - int i; - - if ( ctrls != NULL ) { - for ( i = 0; ctrls[i] != NULL; i++ ) { - ldap_control_free( ctrls[i] ); - } - NSLDAPI_FREE( (char *)ctrls ); - } -} - -LDAPControl * -LDAP_CALL -ldap_find_control( const char *oid, LDAPControl **ctrls ) -{ - int i, foundControl; - LDAPControl *Ctrlp = NULL; - - /* find the control in the list of controls if it exists */ - if ( ctrls == NULL ) { - return ( NULL ); - } - foundControl = 0; - for ( i = 0; (( ctrls[i] != NULL ) && ( !foundControl )); i++ ) { - foundControl = !strcmp( ctrls[i]->ldctl_oid, oid ); - } - if ( !foundControl ) { - return ( NULL ); - } else { - /* let local var point to the control */ - Ctrlp = ctrls[i-1]; - } - - return( Ctrlp ); -} - -#if 0 -LDAPControl ** -LDAP_CALL -ldap_control_append( LDAPControl **ctrl_src, LDAPControl *ctrl ) -{ - int nctrls = 0; - LDAPControl **ctrlp; - int i; - - if ( NULL == ctrl ) - return ( NULL ); - - /* Count the existing controls */ - if ( NULL != ctrl_src ) { - while( NULL != ctrl_src[nctrls] ) { - nctrls++; - } - } - - /* allocate the new control structure */ - if ( ( ctrlp = (LDAPControl **)NSLDAPI_MALLOC( sizeof(LDAPControl *) - * (nctrls + 2) ) ) == NULL ) { - return( NULL ); - } - memset( ctrlp, 0, sizeof(*ctrlp) * (nctrls + 2) ); - - for( i = 0; i < (nctrls + 1); i++ ) { - if ( i < nctrls ) { - ctrlp[i] = ldap_control_dup( ctrl_src[i] ); - } else { - ctrlp[i] = ldap_control_dup( ctrl ); - } - if ( NULL == ctrlp[i] ) { - ldap_controls_free( ctrlp ); - return( NULL ); - } - } - return ctrlp; -} -#endif /* 0 */ - - -/* - * Replace *ldctrls with a copy of newctrls. - * returns 0 if successful. - * return -1 if not and set error code inside LDAP *ld. - */ -int -nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, LDAPControl **newctrls ) -{ - int count; - - if ( *ldctrls != NULL ) { - ldap_controls_free( *ldctrls ); - } - - if ( newctrls == NULL || newctrls[0] == NULL ) { - *ldctrls = NULL; - return( 0 ); - } - - for ( count = 0; newctrls[ count ] != NULL; ++count ) { - ; - } - - if (( *ldctrls = (LDAPControl **)NSLDAPI_MALLOC(( count + 1 ) * - sizeof( LDAPControl *))) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - (*ldctrls)[ count ] = NULL; - - for ( count = 0; newctrls[ count ] != NULL; ++count ) { - if (( (*ldctrls)[ count ] = - ldap_control_dup( newctrls[ count ] )) == NULL ) { - ldap_controls_free( *ldctrls ); - *ldctrls = NULL; - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - } - - return( 0 ); -} - - -/* - * return a malloc'd copy of "ctrl" (NULL if memory allocation fails) - */ -static LDAPControl * -/* LDAP_CALL */ /* keep this routine internal for now */ -ldap_control_dup( LDAPControl *ctrl ) -{ - LDAPControl *rctrl; - - if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl ))) - == NULL ) { - return( NULL ); - } - - if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) { - NSLDAPI_FREE( rctrl ); - return( NULL ); - } - - return( rctrl ); -} - - -/* - * duplicate the contents of "ctrl_src" and place in "ctrl_dst" - */ -static int -/* LDAP_CALL */ /* keep this routine internal for now */ -ldap_control_copy_contents( LDAPControl *ctrl_dst, LDAPControl *ctrl_src ) -{ - size_t len; - - if ( NULL == ctrl_dst || NULL == ctrl_src ) { - return( LDAP_PARAM_ERROR ); - } - - ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical; - - /* fill in the fields of this new control */ - if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid )) - == NULL ) { - return( LDAP_NO_MEMORY ); - } - - len = (size_t)(ctrl_src->ldctl_value).bv_len; - if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) { - ctrl_dst->ldctl_value.bv_len = 0; - ctrl_dst->ldctl_value.bv_val = NULL; - } else { - ctrl_dst->ldctl_value.bv_len = len; - if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len )) - == NULL ) { - NSLDAPI_FREE( ctrl_dst->ldctl_oid ); - return( LDAP_NO_MEMORY ); - } - SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val, - ctrl_src->ldctl_value.bv_val, len ); - } - - return ( LDAP_SUCCESS ); -} - - - -/* - * build an allocated LDAPv3 control. Returns an LDAP error code. - */ -int -nsldapi_build_control( char *oid, BerElement *ber, int freeber, char iscritical, - LDAPControl **ctrlp ) -{ - int rc; - struct berval *bvp; - - if ( ber == NULL ) { - bvp = NULL; - } else { - /* allocate struct berval with contents of the BER encoding */ - rc = ber_flatten( ber, &bvp ); - if ( freeber ) { - ber_free( ber, 1 ); - } - if ( rc == -1 ) { - return( LDAP_NO_MEMORY ); - } - } - - /* allocate the new control structure */ - if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl))) - == NULL ) { - if ( bvp != NULL ) { - ber_bvfree( bvp ); - } - return( LDAP_NO_MEMORY ); - } - - /* fill in the fields of this new control */ - (*ctrlp)->ldctl_iscritical = iscritical; - if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) { - NSLDAPI_FREE( *ctrlp ); - if ( bvp != NULL ) { - ber_bvfree( bvp ); - } - return( LDAP_NO_MEMORY ); - } - - if ( bvp == NULL ) { - (*ctrlp)->ldctl_value.bv_len = 0; - (*ctrlp)->ldctl_value.bv_val = NULL; - } else { - (*ctrlp)->ldctl_value = *bvp; /* struct copy */ - NSLDAPI_FREE( bvp ); /* free container, not contents! */ - } - - return( LDAP_SUCCESS ); -} diff --git a/ldap/c-sdk/libraries/libldap/countvalues.c b/ldap/c-sdk/libraries/libldap/countvalues.c deleted file mode 100644 index 90e9e0adc6..0000000000 --- a/ldap/c-sdk/libraries/libldap/countvalues.c +++ /dev/null @@ -1,67 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * countvalues.c - */ - -#include "ldap-int.h" - -int -LDAP_CALL -ldap_count_values( char **vals ) -{ - int i; - - if ( vals == NULL ) - return( 0 ); - - for ( i = 0; vals[i] != NULL; i++ ) - ; /* NULL */ - - return( i ); -} - -int -LDAP_CALL -ldap_count_values_len( struct berval **vals ) -{ - return( ldap_count_values( (char **) vals ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/delete.c b/ldap/c-sdk/libraries/libldap/delete.c deleted file mode 100644 index 531761371b..0000000000 --- a/ldap/c-sdk/libraries/libldap/delete.c +++ /dev/null @@ -1,169 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * delete.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_delete - initiate an ldap delete operation. Parameters: - * - * ld LDAP descriptor - * dn DN of the object to delete - * - * Example: - * msgid = ldap_delete( ld, dn ); - */ -int -LDAP_CALL -ldap_delete( LDAP *ld, const char *dn ) -{ - int msgid; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_delete\n", 0, 0, 0 ); - - if ( ldap_delete_ext( ld, dn, NULL, NULL, &msgid ) == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - -int -LDAP_CALL -ldap_delete_ext( LDAP *ld, const char *dn, LDAPControl **serverctrls, - LDAPControl **clientctrls, int *msgidp ) -{ - BerElement *ber; - int rc, lderr; - - /* - * A delete request looks like this: - * DelRequet ::= DistinguishedName, - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_delete_ext\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) - { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - if ( dn == NULL ) { - dn = ""; - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* see if we should add to the cache */ - if ( ld->ld_cache_on && ld->ld_cache_delete != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_delete)( ld, *msgidp, LDAP_REQ_DELETE, - dn )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( lderr ); - } - - if ( ber_printf( ber, "{its", *msgidp, LDAP_REQ_DELETE, dn ) - == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( lderr ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_DELETE, - (char *)dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -int -LDAP_CALL -ldap_delete_s( LDAP *ld, const char *dn ) -{ - return( ldap_delete_ext_s( ld, dn, NULL, NULL )); -} - -int -LDAP_CALL -ldap_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - int err, msgid; - LDAPMessage *res; - - if (( err = ldap_delete_ext( ld, dn, serverctrls, clientctrls, - &msgid )) != LDAP_SUCCESS ) { - return( err ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - return( ldap_result2error( ld, res, 1 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/disptmpl.c b/ldap/c-sdk/libraries/libldap/disptmpl.c deleted file mode 100644 index 17fc71944b..0000000000 --- a/ldap/c-sdk/libraries/libldap/disptmpl.c +++ /dev/null @@ -1,770 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993, 1994 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. - */ -/* - * disptmpl.c: display template library routines for LDAP clients - */ - -#include "ldap-int.h" -#include "disptmpl.h" - -static void free_disptmpl( struct ldap_disptmpl *tmpl ); -static int read_next_tmpl( char **bufp, long *blenp, - struct ldap_disptmpl **tmplp, int dtversion ); - -static char *tmploptions[] = { - "addable", "modrdn", - "altview", - NULL -}; - - -static unsigned long tmploptvals[] = { - LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN, - LDAP_DTMPL_OPT_ALTVIEW, -}; - - -static char *itemtypes[] = { - "cis", "mls", "dn", - "bool", "jpeg", "jpegbtn", - "fax", "faxbtn", "audiobtn", - "time", "date", "url", - "searchact", "linkact", "adddnact", - "addact", "verifyact", "mail", - NULL -}; - -static unsigned long itemsynids[] = { - LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN, - LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON, - LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON, - LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL, - LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION, - LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR, -}; - - -static char *itemoptions[] = { - "ro", "sort", - "1val", "hide", - "required", "hideiffalse", - NULL -}; - - -static unsigned long itemoptvals[] = { - LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, - LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, - LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, -}; - - -#define ADDEF_CONSTANT "constant" -#define ADDEF_ADDERSDN "addersdn" - - -int -LDAP_CALL -ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) -{ - FILE *fp; - char *buf; - long rlen, len; - int rc, eof; - - *tmpllistp = NULLDISPTMPL; - - if (( fp = NSLDAPI_FOPEN( file, "r" )) == NULL ) { - return( LDAP_TMPL_ERR_FILE ); - } - - if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ - fclose( fp ); - return( LDAP_TMPL_ERR_FILE ); - } - - len = ftell( fp ); - - if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ - fclose( fp ); - return( LDAP_TMPL_ERR_FILE ); - } - - if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { - fclose( fp ); - return( LDAP_TMPL_ERR_MEM ); - } - - rlen = fread( buf, 1, (size_t)len, fp ); - eof = feof( fp ); - fclose( fp ); - - if ( rlen != len && !eof ) { /* error: didn't get the whole file */ - NSLDAPI_FREE( buf ); - return( LDAP_TMPL_ERR_FILE ); - } - - rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); - NSLDAPI_FREE( buf ); - - return( rc ); -} - - -int -LDAP_CALL -ldap_init_templates_buf( char *buf, long buflen, - struct ldap_disptmpl **tmpllistp ) -{ - int rc = 0, version; - char **toks; - struct ldap_disptmpl *prevtmpl, *tmpl; - - *tmpllistp = prevtmpl = NULLDISPTMPL; - - if ( nsldapi_next_line_tokens( &buf, &buflen, &toks ) != 2 || - strcasecmp( toks[ 0 ], "version" ) != 0 ) { - nsldapi_free_strarray( toks ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - version = atoi( toks[ 1 ] ); - nsldapi_free_strarray( toks ); - if ( version != LDAP_TEMPLATE_VERSION ) { - return( LDAP_TMPL_ERR_VERSION ); - } - - while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl, - version )) == 0 && tmpl != NULLDISPTMPL ) { - if ( prevtmpl == NULLDISPTMPL ) { - *tmpllistp = tmpl; - } else { - prevtmpl->dt_next = tmpl; - } - prevtmpl = tmpl; - } - - if ( rc != 0 ) { - ldap_free_templates( *tmpllistp ); - } - - return( rc ); -} - - - -void -LDAP_CALL -ldap_free_templates( struct ldap_disptmpl *tmpllist ) -{ - struct ldap_disptmpl *tp, *nexttp; - - if ( tmpllist != NULL ) { - for ( tp = tmpllist; tp != NULL; tp = nexttp ) { - nexttp = tp->dt_next; - free_disptmpl( tp ); - } - } -} - - -static void -free_disptmpl( struct ldap_disptmpl *tmpl ) -{ - if ( tmpl != NULL ) { - if ( tmpl->dt_name != NULL ) { - NSLDAPI_FREE( tmpl->dt_name ); - } - - if ( tmpl->dt_pluralname != NULL ) { - NSLDAPI_FREE( tmpl->dt_pluralname ); - } - - if ( tmpl->dt_iconname != NULL ) { - NSLDAPI_FREE( tmpl->dt_iconname ); - } - - if ( tmpl->dt_authattrname != NULL ) { - NSLDAPI_FREE( tmpl->dt_authattrname ); - } - - if ( tmpl->dt_defrdnattrname != NULL ) { - NSLDAPI_FREE( tmpl->dt_defrdnattrname ); - } - - if ( tmpl->dt_defaddlocation != NULL ) { - NSLDAPI_FREE( tmpl->dt_defaddlocation ); - } - - if ( tmpl->dt_oclist != NULL ) { - struct ldap_oclist *ocp, *nextocp; - - for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { - nextocp = ocp->oc_next; - nsldapi_free_strarray( ocp->oc_objclasses ); - NSLDAPI_FREE( ocp ); - } - } - - if ( tmpl->dt_adddeflist != NULL ) { - struct ldap_adddeflist *adp, *nextadp; - - for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) { - nextadp = adp->ad_next; - if( adp->ad_attrname != NULL ) { - NSLDAPI_FREE( adp->ad_attrname ); - } - if( adp->ad_value != NULL ) { - NSLDAPI_FREE( adp->ad_value ); - } - NSLDAPI_FREE( adp ); - } - } - - if ( tmpl->dt_items != NULL ) { - struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp; - - for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) { - nextrowp = rowp->ti_next_in_col; - for ( colp = rowp; colp != NULL; colp = nextcolp ) { - nextcolp = colp->ti_next_in_row; - if ( colp->ti_attrname != NULL ) { - NSLDAPI_FREE( colp->ti_attrname ); - } - if ( colp->ti_label != NULL ) { - NSLDAPI_FREE( colp->ti_label ); - } - if ( colp->ti_args != NULL ) { - nsldapi_free_strarray( colp->ti_args ); - } - NSLDAPI_FREE( colp ); - } - } - } - - NSLDAPI_FREE( tmpl ); - } -} - - -struct ldap_disptmpl * -LDAP_CALL -ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ) -{ - return( tmpllist ); -} - - -struct ldap_disptmpl * -LDAP_CALL -ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, - struct ldap_disptmpl *tmpl ) -{ - return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next ); -} - - -struct ldap_disptmpl * -LDAP_CALL -ldap_name2template( char *name, struct ldap_disptmpl *tmpllist ) -{ - struct ldap_disptmpl *dtp; - - for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; - dtp = ldap_next_disptmpl( tmpllist, dtp )) { - if ( strcasecmp( name, dtp->dt_name ) == 0 ) { - return( dtp ); - } - } - - return( NULLDISPTMPL ); -} - - -struct ldap_disptmpl * -LDAP_CALL -ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist ) -{ - struct ldap_disptmpl *dtp; - struct ldap_oclist *oclp; - int i, j, needcnt, matchcnt; - - if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) { - return( NULLDISPTMPL ); - } - - for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; - dtp = ldap_next_disptmpl( tmpllist, dtp )) { - for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST; - oclp = oclp->oc_next ) { - needcnt = matchcnt = 0; - for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) { - for ( j = 0; oclist[ j ] != NULL; ++j ) { - if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] ) - == 0 ) { - ++matchcnt; - } - } - ++needcnt; - } - - if ( matchcnt == needcnt ) { - return( dtp ); - } - } - } - - return( NULLDISPTMPL ); -} - - -struct ldap_tmplitem * -LDAP_CALL -ldap_first_tmplrow( struct ldap_disptmpl *tmpl ) -{ - return( tmpl->dt_items ); -} - - -struct ldap_tmplitem * -LDAP_CALL -ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) -{ - return( row == NULLTMPLITEM ? row : row->ti_next_in_col ); -} - - -struct ldap_tmplitem * -LDAP_CALL -ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) -{ - return( row ); -} - - -struct ldap_tmplitem * -LDAP_CALL -ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, - struct ldap_tmplitem *col ) -{ - return( col == NULLTMPLITEM ? col : col->ti_next_in_row ); -} - - -char ** -LDAP_CALL -ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, - int exclude, unsigned long syntaxmask ) -{ -/* - * this routine should filter out duplicate attributes... - */ - struct ldap_tmplitem *tirowp, *ticolp; - int i, attrcnt, memerr; - char **attrs; - - attrcnt = 0; - memerr = 0; - - if (( attrs = (char **)NSLDAPI_MALLOC( sizeof( char * ))) == NULL ) { - return( NULL ); - } - - if ( includeattrs != NULL ) { - for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { - if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) * - sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = - nsldapi_strdup( includeattrs[ i ] )) == NULL ) { - memerr = 1; - } else { - attrs[ attrcnt ] = NULL; - } - } - } - - for ( tirowp = ldap_first_tmplrow( tmpl ); - !memerr && tirowp != NULLTMPLITEM; - tirowp = ldap_next_tmplrow( tmpl, tirowp )) { - for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); - ticolp != NULLTMPLITEM; - ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { - - if ( syntaxmask != 0 ) { - if (( exclude && - ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || - ( !exclude && - ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { - continue; - } - } - - if ( ticolp->ti_attrname != NULL ) { - if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) - * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = - nsldapi_strdup( ticolp->ti_attrname )) == NULL ) { - memerr = 1; - } else { - attrs[ attrcnt ] = NULL; - } - } - } - } - - if ( memerr || attrcnt == 0 ) { - for ( i = 0; i < attrcnt; ++i ) { - if ( attrs[ i ] != NULL ) { - NSLDAPI_FREE( attrs[ i ] ); - } - } - - NSLDAPI_FREE( (char *)attrs ); - return( NULL ); - } - - return( attrs ); -} - - -static int -read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp, - int dtversion ) -{ - int i, j, tokcnt, samerow, adsource; - char **toks, *itemopts; - struct ldap_disptmpl *tmpl = NULL; - struct ldap_oclist *ocp = NULL, *prevocp = NULL; - struct ldap_adddeflist *adp = NULL, *prevadp = NULL; - struct ldap_tmplitem *rowp = NULL, *ip = NULL, *previp = NULL; - - /* - * template name comes first - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); - } - - if (( tmpl = (struct ldap_disptmpl *)NSLDAPI_CALLOC( 1, - sizeof( struct ldap_disptmpl ))) == NULL ) { - nsldapi_free_strarray( toks ); - return( LDAP_TMPL_ERR_MEM ); - } - tmpl->dt_name = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * template plural name comes next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - tmpl->dt_pluralname = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * template icon name is next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - tmpl->dt_iconname = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * template options come next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) < 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - for ( i = 0; toks[ i ] != NULL; ++i ) { - for ( j = 0; tmploptions[ j ] != NULL; ++j ) { - if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) { - tmpl->dt_options |= tmploptvals[ j ]; - } - } - } - nsldapi_free_strarray( toks ); - - /* - * object class list is next - */ - while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { - if (( ocp = (struct ldap_oclist *)NSLDAPI_CALLOC( 1, - sizeof( struct ldap_oclist ))) == NULL ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_MEM ); - } - ocp->oc_objclasses = toks; - if ( tmpl->dt_oclist == NULL ) { - tmpl->dt_oclist = ocp; - } else { - prevocp->oc_next = ocp; - } - prevocp = ocp; - } - if ( tokcnt < 0 ) { - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - - /* - * read name of attribute to authenticate as - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - if ( toks[ 0 ][ 0 ] != '\0' ) { - tmpl->dt_authattrname = toks[ 0 ]; - } else { - NSLDAPI_FREE( toks[ 0 ] ); - } - NSLDAPI_FREE( (char *)toks ); - - /* - * read default attribute to use for RDN - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - tmpl->dt_defrdnattrname = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * read default location for new entries - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - if ( toks[ 0 ][ 0 ] != '\0' ) { - tmpl->dt_defaddlocation = toks[ 0 ]; - } else { - NSLDAPI_FREE( toks[ 0 ] ); - } - NSLDAPI_FREE( (char *)toks ); - - /* - * read list of rules used to define default values for new entries - */ - while (( tokcnt = nsldapi_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 ) { - adsource = LDAP_ADSRC_ADDERSDN; - } else { - adsource = 0; - } - if ( adsource == 0 || tokcnt < 2 || - ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || - ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - - if (( adp = (struct ldap_adddeflist *)NSLDAPI_CALLOC( 1, - sizeof( struct ldap_adddeflist ))) == NULL ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_MEM ); - } - adp->ad_source = adsource; - adp->ad_attrname = toks[ 1 ]; - if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) { - adp->ad_value = toks[ 2 ]; - } - NSLDAPI_FREE( toks[ 0 ] ); - NSLDAPI_FREE( (char *)toks ); - - if ( tmpl->dt_adddeflist == NULL ) { - tmpl->dt_adddeflist = adp; - } else { - prevadp->ad_next = adp; - } - prevadp = adp; - } - - /* - * item list is next - */ - samerow = 0; - while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { - if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { - if ( tokcnt < 4 ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - - if (( ip = (struct ldap_tmplitem *)NSLDAPI_CALLOC( 1, - sizeof( struct ldap_tmplitem ))) == NULL ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_MEM ); - } - - /* - * find syntaxid from config file string - */ - while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) { - *itemopts++ = '\0'; - for ( i = 0; itemoptions[ i ] != NULL; ++i ) { - if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) { - break; - } - } - if ( itemoptions[ i ] == NULL ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - ip->ti_options |= itemoptvals[ i ]; - } - - for ( i = 0; itemtypes[ i ] != NULL; ++i ) { - if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) { - break; - } - } - if ( itemtypes[ i ] == NULL ) { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - - NSLDAPI_FREE( toks[ 0 ] ); - NSLDAPI_FREE( toks[ 1 ] ); - ip->ti_syntaxid = itemsynids[ i ]; - ip->ti_label = toks[ 2 ]; - if ( toks[ 3 ][ 0 ] == '\0' ) { - ip->ti_attrname = NULL; - NSLDAPI_FREE( toks[ 3 ] ); - } else { - ip->ti_attrname = toks[ 3 ]; - } - if ( toks[ 4 ] != NULL ) { /* extra args. */ - for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { - ; - } - if (( ip->ti_args = (char **)NSLDAPI_CALLOC( i + 1, - sizeof( char * ))) == NULL ) { - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_MEM ); - } - for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { - ip->ti_args[ i ] = toks[ i + 4 ]; - } - } - NSLDAPI_FREE( (char *)toks ); - - if ( tmpl->dt_items == NULL ) { - tmpl->dt_items = rowp = ip; - } else if ( samerow ) { - previp->ti_next_in_row = ip; - } else { - rowp->ti_next_in_col = ip; - rowp = ip; - } - previp = ip; - samerow = 0; - } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { - nsldapi_free_strarray( toks ); - samerow = 1; - } else { - nsldapi_free_strarray( toks ); - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - } - if ( tokcnt < 0 ) { - free_disptmpl( tmpl ); - return( LDAP_TMPL_ERR_SYNTAX ); - } - - *tmplp = tmpl; - return( 0 ); -} - - -struct tmplerror { - int e_code; - char *e_reason; -}; - -static struct tmplerror ldap_tmplerrlist[] = { - { LDAP_TMPL_ERR_VERSION, "Bad template version" }, - { LDAP_TMPL_ERR_MEM, "Out of memory" }, - { LDAP_TMPL_ERR_SYNTAX, "Bad template syntax" }, - { LDAP_TMPL_ERR_FILE, "File error reading template" }, - { -1, 0 } -}; - -char * -LDAP_CALL -ldap_tmplerr2string( int err ) -{ - int i; - - for ( i = 0; ldap_tmplerrlist[i].e_code != -1; i++ ) { - if ( err == ldap_tmplerrlist[i].e_code ) - return( ldap_tmplerrlist[i].e_reason ); - } - - return( "Unknown error" ); -} diff --git a/ldap/c-sdk/libraries/libldap/dllmain.c b/ldap/c-sdk/libraries/libldap/dllmain.c deleted file mode 100644 index b51c16caa4..0000000000 --- a/ldap/c-sdk/libraries/libldap/dllmain.c +++ /dev/null @@ -1,178 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Microsoft Windows specifics for LIBLDAP DLL - */ -#include "ldap.h" -#include "lber.h" - - -#ifdef _WIN32 -/* Lifted from Q125688 - * How to Port a 16-bit DLL to a Win32 DLL - * on the MSVC 4.0 CD - */ -BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - /* Code from LibMain inserted here. Return TRUE to keep the - DLL loaded or return FALSE to fail loading the DLL. - - You may have to modify the code in your original LibMain to - account for the fact that it may be called more than once. - You will get one DLL_PROCESS_ATTACH for each process that - loads the DLL. This is different from LibMain which gets - called only once when the DLL is loaded. The only time this - is critical is when you are using shared data sections. - If you are using shared data sections for statically - allocated data, you will need to be careful to initialize it - only once. Check your code carefully. - - Certain one-time initializations may now need to be done for - each process that attaches. You may also not need code from - your original LibMain because the operating system may now - be doing it for you. - */ - /* - * 16 bit code calls UnlockData() - * which is mapped to UnlockSegment in windows.h - * in 32 bit world UnlockData is not defined anywhere - * UnlockSegment is mapped to GlobalUnfix in winbase.h - * and the docs for both UnlockSegment and GlobalUnfix say - * ".. function is oboslete. Segments have no meaning - * in the 32-bit environment". So we do nothing here. - */ - /* If we are building a version that includes the security libraries, - * we have to initialize Winsock here. If not, we can defer until the - * first real socket call is made (in mozock.c). - */ -#ifdef LINK_SSL - { - WSADATA wsaData; - WSAStartup(0x0101, &wsaData); - } -#endif - - break; - - case DLL_THREAD_ATTACH: - /* Called each time a thread is created in a process that has - already loaded (attached to) this DLL. Does not get called - for each thread that exists in the process before it loaded - the DLL. - - Do thread-specific initialization here. - */ - break; - - case DLL_THREAD_DETACH: - /* Same as above, but called when a thread in the process - exits. - - Do thread-specific cleanup here. - */ - break; - - case DLL_PROCESS_DETACH: - /* Code from _WEP inserted here. This code may (like the - LibMain) not be necessary. Check to make certain that the - operating system is not doing it for you. - */ -#ifdef LINK_SSL - WSACleanup(); -#endif - - break; - } - /* The return value is only used for DLL_PROCESS_ATTACH; all other - conditions are ignored. */ - return TRUE; // successful DLL_PROCESS_ATTACH -} -#else -int CALLBACK -LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) -{ - /*UnlockData( 0 );*/ - return( 1 ); -} - -BOOL CALLBACK __loadds WEP(BOOL fSystemExit) -{ - WSACleanup(); - return TRUE; -} - -#endif - -#ifdef LDAP_DEBUG -#ifndef _WIN32 -#include -#include - -void LDAP_C LDAPDebug( int level, char* fmt, ... ) -{ - static char debugBuf[1024]; - - if (ldap_debug & level) - { - va_list ap; - va_start (ap, fmt); - _snprintf (debugBuf, sizeof(debugBuf), fmt, ap); - va_end (ap); - - OutputDebugString (debugBuf); - } -} -#endif -#endif - -#ifndef _WIN32 - -/* The 16-bit version of the RTL does not implement perror() */ - -#include - -void perror( const char *msg ) -{ - char buf[128]; - wsprintf( buf, "%s: error %d\n", msg, WSAGetLastError()) ; - OutputDebugString( buf ); -} - -#endif diff --git a/ldap/c-sdk/libraries/libldap/dsparse.c b/ldap/c-sdk/libraries/libldap/dsparse.c deleted file mode 100644 index 22d411617c..0000000000 --- a/ldap/c-sdk/libraries/libldap/dsparse.c +++ /dev/null @@ -1,227 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993, 1994 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. - */ -/* - * dsparse.c: parsing routines used by display template and search - * preference file library routines for LDAP clients. - * - */ - -#include "ldap-int.h" - -static int next_line( char **bufp, long *blenp, char **linep ); -static char *next_token( char ** sp ); - -int -nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp ) -{ - char *p, *line, *token, **toks; - int rc, tokcnt; - - *toksp = NULL; - - if (( rc = next_line( bufp, blenp, &line )) <= 0 ) { - return( rc ); - } - - if (( toks = (char **)NSLDAPI_CALLOC( 1, sizeof( char * ))) == NULL ) { - NSLDAPI_FREE( line ); - return( -1 ); - } - tokcnt = 0; - - p = line; - while (( token = next_token( &p )) != NULL ) { - if (( toks = (char **)NSLDAPI_REALLOC( toks, ( tokcnt + 2 ) * - sizeof( char * ))) == NULL ) { - NSLDAPI_FREE( (char *)toks ); - NSLDAPI_FREE( line ); - return( -1 ); - } - toks[ tokcnt ] = token; - toks[ ++tokcnt ] = NULL; - } - - if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) { - tokcnt = 0; - nsldapi_free_strarray( toks ); - toks = NULL; - } - - NSLDAPI_FREE( line ); - - if ( tokcnt == 0 ) { - if ( toks != NULL ) { - NSLDAPI_FREE( (char *)toks ); - } - } else { - *toksp = toks; - } - - return( tokcnt ); -} - - -static int -next_line( char **bufp, long *blenp, char **linep ) -{ - char *linestart, *line, *p; - long plen; - - linestart = *bufp; - p = *bufp; - plen = *blenp; - - do { - for ( linestart = p; plen > 0; ++p, --plen ) { - if ( *p == '\r' ) { - if ( plen > 1 && *(p+1) == '\n' ) { - ++p; - --plen; - } - break; - } - - if ( *p == '\n' ) { - if ( plen > 1 && *(p+1) == '\r' ) { - ++p; - --plen; - } - break; - } - } - ++p; - --plen; - } while ( plen > 0 && ( *linestart == '#' || linestart + 1 == p )); - - - *bufp = p; - *blenp = plen; - - - if ( plen <= 0 ) { - *linep = NULL; - return( 0 ); /* end of file */ - } - - if (( line = NSLDAPI_MALLOC( p - linestart )) == NULL ) { - *linep = NULL; - return( -1 ); /* fatal error */ - } - - SAFEMEMCPY( line, linestart, p - linestart ); - line[ p - linestart - 1 ] = '\0'; - *linep = line; - return( strlen( line )); -} - - -static char * -next_token( char **sp ) -{ - int in_quote = 0; - char *p, *tokstart, *t; - - if ( **sp == '\0' ) { - return( NULL ); - } - - p = *sp; - - while ( ldap_utf8isspace( p )) { /* skip leading white space */ - ++p; - } - - if ( *p == '\0' ) { - return( NULL ); - } - - if ( *p == '\"' ) { - in_quote = 1; - ++p; - } - t = tokstart = p; - - for ( ;; ) { - if ( *p == '\0' || ( ldap_utf8isspace( p ) && !in_quote )) { - if ( *p != '\0' ) { - ++p; - } - *t++ = '\0'; /* end of token */ - break; - } - - if ( *p == '\"' ) { - in_quote = !in_quote; - ++p; - } else { - *t++ = *p++; - } - } - - *sp = p; - - if ( t == tokstart ) { - return( NULL ); - } - - return( nsldapi_strdup( tokstart )); -} - - -void -nsldapi_free_strarray( char **sap ) -{ - int i; - - if ( sap != NULL ) { - for ( i = 0; sap[ i ] != NULL; ++i ) { - NSLDAPI_FREE( sap[ i ] ); - } - NSLDAPI_FREE( (char *)sap ); - } -} diff --git a/ldap/c-sdk/libraries/libldap/error.c b/ldap/c-sdk/libraries/libldap/error.c deleted file mode 100644 index 82cbb56cb7..0000000000 --- a/ldap/c-sdk/libraries/libldap/error.c +++ /dev/null @@ -1,490 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -struct ldaperror { - int e_code; - char *e_reason; -}; - -static struct ldaperror ldap_errlist[] = { - { LDAP_SUCCESS, "Success" }, - { LDAP_OPERATIONS_ERROR, "Operations error" }, - { LDAP_PROTOCOL_ERROR, "Protocol error" }, - { LDAP_TIMELIMIT_EXCEEDED, "Timelimit exceeded" }, - { LDAP_SIZELIMIT_EXCEEDED, "Sizelimit exceeded" }, - { LDAP_COMPARE_FALSE, "Compare false" }, - { LDAP_COMPARE_TRUE, "Compare true" }, - { LDAP_STRONG_AUTH_NOT_SUPPORTED, "Authentication method not supported" }, - { LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required" }, - { LDAP_PARTIAL_RESULTS, "Partial results and referral received" }, - { LDAP_REFERRAL, "Referral received" }, - { LDAP_ADMINLIMIT_EXCEEDED, "Administrative limit exceeded" }, - { LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Unavailable critical extension" }, - { LDAP_CONFIDENTIALITY_REQUIRED, "Confidentiality required" }, - { LDAP_SASL_BIND_IN_PROGRESS, "SASL bind in progress" }, - - { LDAP_NO_SUCH_ATTRIBUTE, "No such attribute" }, - { LDAP_UNDEFINED_TYPE, "Undefined attribute type" }, - { LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching" }, - { LDAP_CONSTRAINT_VIOLATION, "Constraint violation" }, - { LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists" }, - { LDAP_INVALID_SYNTAX, "Invalid syntax" }, - - { 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_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" }, - - { LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" }, - { LDAP_INVALID_CREDENTIALS, "Invalid credentials" }, - { LDAP_INSUFFICIENT_ACCESS, "Insufficient access" }, - { LDAP_BUSY, "DSA is busy" }, - { LDAP_UNAVAILABLE, "DSA is unavailable" }, - { LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform" }, - { LDAP_LOOP_DETECT, "Loop detected" }, - { LDAP_SORT_CONTROL_MISSING, "Sort Control is missing" }, - { LDAP_INDEX_RANGE_ERROR, "Search results exceed the range specified by the offsets" }, - - { LDAP_NAMING_VIOLATION, "Naming violation" }, - { LDAP_OBJECT_CLASS_VIOLATION, "Object class violation" }, - { LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf" }, - { LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN" }, - { LDAP_ALREADY_EXISTS, "Already exists" }, - { LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class" }, - { LDAP_RESULTS_TOO_LARGE, "Results too large" }, - { LDAP_AFFECTS_MULTIPLE_DSAS, "Affects multiple servers" }, - - { LDAP_OTHER, "Unknown error" }, - { LDAP_SERVER_DOWN, "Can't contact LDAP server" }, - { LDAP_LOCAL_ERROR, "Local error" }, - { LDAP_ENCODING_ERROR, "Encoding error" }, - { LDAP_DECODING_ERROR, "Decoding error" }, - { LDAP_TIMEOUT, "Timed out" }, - { LDAP_AUTH_UNKNOWN, "Unknown authentication method" }, - { LDAP_FILTER_ERROR, "Bad search filter" }, - { LDAP_USER_CANCELLED, "User cancelled operation" }, - { LDAP_PARAM_ERROR, "Bad parameter to an ldap routine" }, - { LDAP_NO_MEMORY, "Out of memory" }, - { LDAP_CONNECT_ERROR, "Can't connect to the LDAP server" }, - { LDAP_NOT_SUPPORTED, "Not supported by this version of the LDAP protocol" }, - { LDAP_CONTROL_NOT_FOUND, "Requested LDAP control not found" }, - { LDAP_NO_RESULTS_RETURNED, "No results returned" }, - { LDAP_MORE_RESULTS_TO_RETURN, "More results to return" }, - { LDAP_CLIENT_LOOP, "Client detected loop" }, - { LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral hop limit exceeded" }, - { -1, 0 } -}; - -char * -LDAP_CALL -ldap_err2string( int err ) -{ - int i; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 ); - - for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { - if ( err == ldap_errlist[i].e_code ) - return( ldap_errlist[i].e_reason ); - } - - return( "Unknown error" ); -} - - -static char * -nsldapi_safe_strerror( int e ) -{ - char *s; - - if (( s = strerror( e )) == NULL ) { - s = "unknown error"; - } - - return( s ); -} - - -void -LDAP_CALL -ldap_perror( LDAP *ld, const char *s ) -{ - int i, err; - char *matched = NULL; - char *errmsg = NULL; - char *separator; - char msg[1024]; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 ); - - if ( s == NULL ) { - s = separator = ""; - } else { - separator = ": "; - } - - if ( ld == NULL ) { - snprintf( msg, sizeof( msg ), - "%s%s%s", s, separator, nsldapi_safe_strerror( errno ) ); - ber_err_print( msg ); - return; - } - - LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); - err = LDAP_GET_LDERRNO( ld, &matched, &errmsg ); - for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { - if ( err == ldap_errlist[i].e_code ) { - snprintf( msg, sizeof( msg ), - "%s%s%s", s, separator, ldap_errlist[i].e_reason ); - ber_err_print( msg ); - if ( err == LDAP_CONNECT_ERROR ) { - ber_err_print( " - " ); - ber_err_print( nsldapi_safe_strerror( - LDAP_GET_ERRNO( ld ))); - } - ber_err_print( "\n" ); - if ( matched != NULL && *matched != '\0' ) { - snprintf( msg, sizeof( msg ), - "%s%smatched: %s\n", s, separator, matched ); - ber_err_print( msg ); - } - if ( errmsg != NULL && *errmsg != '\0' ) { - snprintf( msg, sizeof( msg ), - "%s%sadditional info: %s\n", s, separator, errmsg ); - ber_err_print( msg ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); - return; - } - } - snprintf( msg, sizeof( msg ), - "%s%sNot an LDAP errno %d\n", s, separator, err ); - ber_err_print( msg ); - LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); -} - -int -LDAP_CALL -ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) -{ - int lderr_parse, lderr; - - lderr_parse = ldap_parse_result( ld, r, &lderr, NULL, NULL, NULL, - NULL, freeit ); - - if ( lderr_parse != LDAP_SUCCESS ) { - return( lderr_parse ); - } - - return( lderr ); -} - -int -LDAP_CALL -ldap_get_lderrno( LDAP *ld, char **m, char **s ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); /* punt */ - } - - if ( ld->ld_get_lderrno_fn == NULL ) { - if ( m != NULL ) { - *m = ld->ld_matched; - } - if ( s != NULL ) { - *s = ld->ld_error; - } - return( ld->ld_errno ); - } else { - return( ld->ld_get_lderrno_fn( m, s, ld->ld_lderrno_arg ) ); - } -} - - -/* - * Note: there is no need for callers of ldap_set_lderrno() to lock the - * ld mutex. If applications intend to share an LDAP session handle - * between threads they *must* perform their own locking around the - * session handle or they must install a "set lderrno" thread callback - * function. - * - */ -int -LDAP_CALL -ldap_set_lderrno( LDAP *ld, int e, char *m, char *s ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ld->ld_set_lderrno_fn != NULL ) { - ld->ld_set_lderrno_fn( e, m, s, ld->ld_lderrno_arg ); - } else { - LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); - ld->ld_errno = e; - if ( ld->ld_matched ) { - NSLDAPI_FREE( ld->ld_matched ); - } - ld->ld_matched = m; - if ( ld->ld_error ) { - NSLDAPI_FREE( ld->ld_error ); - } - ld->ld_error = s; - LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); - } - - return( LDAP_SUCCESS ); -} - - -/* - * Returns an LDAP error that says whether parse succeeded. The error code - * from the LDAP result itself is returned in the errcodep result parameter. - * If any of the result params. (errcodep, matchednp, errmsgp, referralsp, - * or serverctrlsp) are NULL we don't return that info. - */ -int -LDAP_CALL -ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep, char **matchednp, - char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, - int freeit ) -{ - LDAPMessage *lm; - int err, errcode; - char *m, *e; - m = e = NULL; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || - !NSLDAPI_VALID_LDAPMESSAGE_POINTER( res )) { - return( LDAP_PARAM_ERROR ); - } - - /* skip over entries and references to find next result in this chain */ - for ( lm = res; lm != NULL; lm = lm->lm_chain ) { - if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && - lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { - break; - } - } - - if ( lm == NULL ) { - err = LDAP_NO_RESULTS_RETURNED; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - err = nsldapi_parse_result( ld, lm->lm_msgtype, lm->lm_ber, &errcode, - &m, &e, referralsp, serverctrlsp ); - - if ( err == LDAP_SUCCESS ) { - if ( errcodep != NULL ) { - *errcodep = errcode; - } - if ( matchednp != NULL ) { - *matchednp = nsldapi_strdup( m ); - } - if ( errmsgp != NULL ) { - *errmsgp = nsldapi_strdup( e ); - } - - /* - * if there are more result messages in the chain, arrange to - * return the special LDAP_MORE_RESULTS_TO_RETURN "error" code. - */ - for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) { - if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && - lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { - err = LDAP_MORE_RESULTS_TO_RETURN; - break; - } - } - } else { - /* In this case, m and e were already freed by ber_scanf */ - m = e = NULL; - } - - if ( freeit ) { - ldap_msgfree( res ); - } - - LDAP_SET_LDERRNO( ld, ( err == LDAP_SUCCESS ) ? errcode : err, m, e ); - - /* nsldapi_parse_result set m and e, so we have to delete them if they exist. - Only delete them if they haven't been reused for matchednp or errmsgp. - if ( err == LDAP_SUCCESS ) { - if ( (m != NULL) && (matchednp == NULL) ) { - NSLDAPI_FREE( m ); - } - if ( (e != NULL) && (errmsgp == NULL) ) { - NSLDAPI_FREE( e ); - } - } */ - - return( err ); -} - -/* - * returns an LDAP error code indicating success or failure of parsing - * does NOT set any error information inside "ld" - */ -int -nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, int *errcodep, - char **matchednp, char **errmsgp, char ***referralsp, - LDAPControl ***serverctrlsp ) -{ - BerElement ber; - ber_len_t len; - ber_int_t errcode; - int berrc, err; - char *m, *e; - - /* - * Parse the result message. LDAPv3 result messages look like this: - * - * LDAPResult ::= SEQUENCE { - * resultCode ENUMERATED { ... }, - * matchedDN LDAPDN, - * errorMessage LDAPString, - * referral [3] Referral OPTIONAL - * opSpecificStuff OPTIONAL - * } - * - * all wrapped up in an LDAPMessage sequence which looks like this: - * LDAPMessage ::= SEQUENCE { - * messageID MessageID, - * LDAPResult CHOICE { ... }, // message type - * controls [0] Controls OPTIONAL - * } - * - * LDAPv2 messages don't include referrals or controls. - * LDAPv1 messages don't include matchedDN, referrals, or controls. - * - * ldap_result() pulls out the message id, so by the time a result - * message gets here we are sitting at the start of the LDAPResult. - */ - - err = LDAP_SUCCESS; /* optimistic */ - m = e = NULL; - if ( matchednp != NULL ) { - *matchednp = NULL; - } - if ( errmsgp != NULL ) { - *errmsgp = NULL; - } - if ( referralsp != NULL ) { - *referralsp = NULL; - } - if ( serverctrlsp != NULL ) { - *serverctrlsp = NULL; - } - ber = *rber; /* struct copy */ - - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION2 ) { - berrc = ber_scanf( &ber, "{ia}", &errcode, &e ); - } else { - if (( berrc = ber_scanf( &ber, "{iaa", &errcode, &m, &e )) - != LBER_ERROR ) { - /* check for optional referrals */ - if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_REFERRAL ) { - if ( referralsp == NULL ) { - /* skip referrals */ - berrc = ber_scanf( &ber, "x" ); - } else { - /* suck out referrals */ - berrc = ber_scanf( &ber, "v", - referralsp ); - } - } else if ( referralsp != NULL ) { - *referralsp = NULL; - } - } - - if ( berrc != LBER_ERROR ) { - /* - * skip past optional operation-specific elements: - * bind results - serverSASLcreds - * extendedop results - OID plus value - */ - if ( msgtype == LDAP_RES_BIND ) { - if ( ber_peek_tag( &ber, &len ) == - LDAP_TAG_SASL_RES_CREDS ) { - berrc = ber_scanf( &ber, "x" ); - } - } else if ( msgtype == LDAP_RES_EXTENDED ) { - if ( ber_peek_tag( &ber, &len ) == - LDAP_TAG_EXOP_RES_OID ) { - berrc = ber_scanf( &ber, "x" ); - } - if ( berrc != LBER_ERROR && - ber_peek_tag( &ber, &len ) == - LDAP_TAG_EXOP_RES_VALUE ) { - berrc = ber_scanf( &ber, "x" ); - } - } - } - - /* pull out controls (if requested and any are present) */ - if ( berrc != LBER_ERROR && serverctrlsp != NULL && - ( berrc = ber_scanf( &ber, "}" )) != LBER_ERROR ) { - err = nsldapi_get_controls( &ber, serverctrlsp ); - } - } - - if ( berrc == LBER_ERROR && err == LDAP_SUCCESS ) { - err = LDAP_DECODING_ERROR; - } - - if ( errcodep != NULL ) { - *errcodep = errcode; - } - if ( matchednp != NULL ) { - *matchednp = m; - } else if ( m != NULL ) { - NSLDAPI_FREE( m ); - } - if ( errmsgp != NULL ) { - *errmsgp = e; - } else if ( e != NULL ) { - NSLDAPI_FREE( e ); - } - - return( err ); -} diff --git a/ldap/c-sdk/libraries/libldap/extendop.c b/ldap/c-sdk/libraries/libldap/extendop.c deleted file mode 100644 index f1a92afcd5..0000000000 --- a/ldap/c-sdk/libraries/libldap/extendop.c +++ /dev/null @@ -1,275 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -/* - * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation. - * the oid and data of the extended operation are supplied. Returns an - * LDAP error code. - * - * Example: - * struct berval exdata; - * char *exoid; - * int err, msgid; - * ... fill in oid and data ... - * err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid ); - */ - -int -LDAP_CALL -ldap_extended_operation( - LDAP *ld, - const char *exoid, - const struct berval *exdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp -) -{ - BerElement *ber; - int rc, msgid; - - /* - * the ldapv3 extended operation request looks like this: - * - * ExtendedRequest ::= [APPLICATION 23] SEQUENCE { - * requestName LDAPOID, - * requestValue OCTET STRING - * } - * - * all wrapped up in an LDAPMessage sequence. - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - - /* only ldapv3 or higher can do extended operations */ - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - rc = LDAP_NOT_SUPPORTED; - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - } - - if ( msgidp == NULL || exoid == NULL || *exoid == '\0' ) { - rc = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - -#if 0 - if ( ld->ld_cache_on && ld->ld_cache_extendedop != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_extendedop)( ld, msgid, - LDAP_REQ_EXTENDED, exoid, cred )) != 0 ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( rc ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } -#endif - - /* create a message to send */ - if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( rc ); - } - - /* fill it in */ - if ( exdata ) { - if ( ber_printf( ber, "{it{tsto}", msgid, LDAP_REQ_EXTENDED, - LDAP_TAG_EXOP_REQ_OID, exoid, LDAP_TAG_EXOP_REQ_VALUE, - exdata->bv_val, exdata->bv_len ) == -1 ) { - rc = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - ber_free( ber, 1 ); - return( rc ); - } - } else { /* some implementations are pretty strict on empty values */ - if ( ber_printf( ber, "{it{ts}", msgid, LDAP_REQ_EXTENDED, - LDAP_TAG_EXOP_REQ_OID, exoid ) == -1 ) { - rc = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - ber_free( ber, 1 ); - return( rc ); - } - } - - if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( rc ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL, - ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - - -/* - * ldap_extended_operation_s - perform an arbitrary ldapv3 extended operation. - * the oid and data of the extended operation are supplied. LDAP_SUCCESS - * is returned upon success, the ldap error code otherwise. - * - * Example: - * struct berval exdata, exretval; - * char *exoid; - * int rc; - * ... fill in oid and data ... - * rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval ); - */ -int -LDAP_CALL -ldap_extended_operation_s( - LDAP *ld, - const char *requestoid, - const struct berval *requestdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - char **retoidp, - struct berval **retdatap -) -{ - int err, msgid; - LDAPMessage *result; - - if (( err = ldap_extended_operation( ld, requestoid, requestdata, - serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) { - return( err ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) - == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if (( err = ldap_parse_extended_result( ld, result, retoidp, retdatap, - 0 )) != LDAP_SUCCESS ) { - ldap_msgfree( result ); - return( err ); - } - - return( ldap_result2error( ld, result, 1 ) ); -} - - -/* - * Pull the oid returned by the server and the data out of an extended - * operation result. Return an LDAP error code. - */ -int -LDAP_CALL -ldap_parse_extended_result( - LDAP *ld, - LDAPMessage *res, - char **retoidp, /* may be NULL */ - struct berval **retdatap, /* may be NULL */ - int freeit -) -{ - struct berelement ber; - ber_len_t len; - ber_int_t err; - char *m, *e, *roid; - struct berval *rdata; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) { - return( LDAP_PARAM_ERROR ); - } - - m = e = NULL; - ber = *(res->lm_ber); - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) { - goto decoding_error; - } - roid = NULL; - if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { - if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) { - goto decoding_error; - } - } - if ( retoidp != NULL ) { - *retoidp = roid; - } else if ( roid != NULL ) { - NSLDAPI_FREE( roid ); - } - - rdata = NULL; - if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { - if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) { - goto decoding_error; - } - } - if ( retdatap != NULL ) { - *retdatap = rdata; - } else if ( rdata != NULL ) { - ber_bvfree( rdata ); - } - - LDAP_SET_LDERRNO( ld, err, m, e ); - - if ( freeit ) { - ldap_msgfree( res ); - } - - return( LDAP_SUCCESS ); - -decoding_error:; - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( LDAP_DECODING_ERROR ); -} diff --git a/ldap/c-sdk/libraries/libldap/free.c b/ldap/c-sdk/libraries/libldap/free.c deleted file mode 100644 index 821ebad10c..0000000000 --- a/ldap/c-sdk/libraries/libldap/free.c +++ /dev/null @@ -1,156 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1994 The Regents of the University of Michigan. - * All rights reserved. - */ -/* - * free.c - some free routines are included here to avoid having to - * link in lots of extra code when not using certain features - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -void -LDAP_CALL -ldap_getfilter_free( LDAPFiltDesc *lfdp ) -{ - LDAPFiltList *flp, *nextflp; - LDAPFiltInfo *fip, *nextfip; - - if ( lfdp == NULL ) { - return; - } - - for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = nextflp ) { - for ( fip = flp->lfl_ilist; fip != NULL; fip = nextfip ) { - nextfip = fip->lfi_next; - NSLDAPI_FREE( fip->lfi_filter ); - NSLDAPI_FREE( fip->lfi_desc ); - NSLDAPI_FREE( fip ); - } - nextflp = flp->lfl_next; - NSLDAPI_FREE( flp->lfl_pattern ); - NSLDAPI_FREE( flp->lfl_delims ); - NSLDAPI_FREE( flp->lfl_tag ); - NSLDAPI_FREE( flp ); - } - - if ( lfdp->lfd_curval != NULL ) { - NSLDAPI_FREE( lfdp->lfd_curval ); - } - if ( lfdp->lfd_curvalcopy != NULL ) { - NSLDAPI_FREE( lfdp->lfd_curvalcopy ); - } - if ( lfdp->lfd_curvalwords != NULL ) { - NSLDAPI_FREE( lfdp->lfd_curvalwords ); - } - if ( lfdp->lfd_filtprefix != NULL ) { - NSLDAPI_FREE( lfdp->lfd_filtprefix ); - } - if ( lfdp->lfd_filtsuffix != NULL ) { - NSLDAPI_FREE( lfdp->lfd_filtsuffix ); - } - - NSLDAPI_FREE( lfdp ); -} - - -/* - * free a null-terminated array of pointers to mod structures. the - * structures are freed, not the array itself, unless the freemods - * flag is set. - */ -void -LDAP_CALL -ldap_mods_free( LDAPMod **mods, int freemods ) -{ - int i; - - if ( !NSLDAPI_VALID_LDAPMOD_ARRAY( mods )) { - return; - } - - for ( i = 0; mods[i] != NULL; i++ ) { - if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) { - if ( mods[i]->mod_bvalues != NULL ) { - ber_bvecfree( mods[i]->mod_bvalues ); - } - } else if ( mods[i]->mod_values != NULL ) { - ldap_value_free( mods[i]->mod_values ); - } - if ( mods[i]->mod_type != NULL ) { - NSLDAPI_FREE( mods[i]->mod_type ); - } - NSLDAPI_FREE( (char *) mods[i] ); - } - - if ( freemods ) - NSLDAPI_FREE( (char *) mods ); -} - - -/* - * ldap_memfree() is needed to ensure that memory allocated by the C runtime - * assocated with libldap is freed by the same runtime code. - */ -void -LDAP_CALL -ldap_memfree( void *s ) -{ - if ( s != NULL ) { - NSLDAPI_FREE( s ); - } -} - - -/* - * ldap_ber_free() is just a cover for ber_free() - * ber_free() checks for ber == NULL, so we don't bother. - */ -void -LDAP_CALL -ldap_ber_free( BerElement *ber, int freebuf ) -{ - ber_free( ber, freebuf ); -} diff --git a/ldap/c-sdk/libraries/libldap/freevalues.c b/ldap/c-sdk/libraries/libldap/freevalues.c deleted file mode 100644 index 29a0ea03f6..0000000000 --- a/ldap/c-sdk/libraries/libldap/freevalues.c +++ /dev/null @@ -1,73 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * freevalues.c - */ - -#include "ldap-int.h" - -void -LDAP_CALL -ldap_value_free( char **vals ) -{ - int i; - - if ( vals == NULL ) - return; - for ( i = 0; vals[i] != NULL; i++ ) - NSLDAPI_FREE( vals[i] ); - NSLDAPI_FREE( (char *) vals ); -} - -void -LDAP_CALL -ldap_value_free_len( struct berval **vals ) -{ - int i; - - if ( vals == NULL ) - return; - for ( i = 0; vals[i] != NULL; i++ ) { - NSLDAPI_FREE( vals[i]->bv_val ); - NSLDAPI_FREE( vals[i] ); - } - NSLDAPI_FREE( (char *) vals ); -} diff --git a/ldap/c-sdk/libraries/libldap/friendly.c b/ldap/c-sdk/libraries/libldap/friendly.c deleted file mode 100644 index d7b5dc65d7..0000000000 --- a/ldap/c-sdk/libraries/libldap/friendly.c +++ /dev/null @@ -1,151 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * friendly.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -char * -LDAP_CALL -ldap_friendly_name( char *filename, char *name, FriendlyMap *map ) -{ - int i, entries; - FILE *fp; - char *s; - char buf[BUFSIZ]; - - if ( map == NULL ) { - return( name ); - } - if ( NULL == name) - { - return (name); - } - - if ( *map == NULL ) { - if ( (fp = NSLDAPI_FOPEN( filename, "r" )) == NULL ) - return( name ); - - entries = 0; - while ( fgets( buf, sizeof(buf), fp ) != NULL ) { - if ( buf[0] != '#' ) - entries++; - } - rewind( fp ); - - if ( (*map = (FriendlyMap)NSLDAPI_MALLOC( (entries + 1) * - sizeof(struct friendly) )) == NULL ) { - fclose( fp ); - return( name ); - } - - i = 0; - while ( fgets( buf, sizeof(buf), fp ) != NULL && i < entries ) { - if ( buf[0] == '#' ) - continue; - - if ( (s = strchr( buf, '\n' )) != NULL ) - *s = '\0'; - - if ( (s = strchr( buf, '\t' )) == NULL ) - continue; - *s++ = '\0'; - - if ( *s == '"' ) { - int esc = 0, found = 0; - - for ( ++s; *s && !found; s++ ) { - switch ( *s ) { - case '\\': - esc = 1; - break; - case '"': - if ( !esc ) - found = 1; - /* FALL */ - default: - esc = 0; - break; - } - } - } - - (*map)[i].f_unfriendly = nsldapi_strdup( buf ); - (*map)[i].f_friendly = nsldapi_strdup( s ); - i++; - } - - fclose( fp ); - (*map)[i].f_unfriendly = NULL; - } - - for ( i = 0; (*map)[i].f_unfriendly != NULL; i++ ) { - if ( strcasecmp( name, (*map)[i].f_unfriendly ) == 0 ) - return( (*map)[i].f_friendly ); - } - return( name ); -} - - -void -LDAP_CALL -ldap_free_friendlymap( FriendlyMap *map ) -{ - struct friendly* pF; - - if ( map == NULL || *map == NULL ) { - return; - } - - for ( pF = *map; pF->f_unfriendly; pF++ ) { - NSLDAPI_FREE( pF->f_unfriendly ); - NSLDAPI_FREE( pF->f_friendly ); - } - NSLDAPI_FREE( *map ); - *map = NULL; -} diff --git a/ldap/c-sdk/libraries/libldap/getattr.c b/ldap/c-sdk/libraries/libldap/getattr.c deleted file mode 100644 index fbe688fea3..0000000000 --- a/ldap/c-sdk/libraries/libldap/getattr.c +++ /dev/null @@ -1,150 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * getattr.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - - -static unsigned long -bytes_remaining( BerElement *ber ) -{ - ber_len_t len; - - if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) { - return( 0 ); /* not sure what else to do.... */ - } - return( len ); -} - - -char * -LDAP_CALL -ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **ber ) -{ - char *attr; - int err; - ber_len_t seqlength; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULL ); /* punt */ - } - - if ( ber == NULL || !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( NULL ); - } - - if ( nsldapi_alloc_ber_with_options( ld, ber ) != LDAP_SUCCESS ) { - return( NULL ); - } - - **ber = *entry->lm_ber; - - attr = NULL; /* pessimistic */ - err = LDAP_DECODING_ERROR; /* ditto */ - - /* - * Skip past the sequence, dn, and sequence of sequence. - * Reset number of bytes remaining so we confine the rest of our - * decoding to the current sequence. - */ - if ( ber_scanf( *ber, "{xl{", &seqlength ) != LBER_ERROR && - ber_set_option( *ber, LBER_OPT_REMAINING_BYTES, &seqlength ) - == 0 ) { - /* snarf the attribute type, and skip the set of values, - * leaving us positioned right before the next attribute - * type/value sequence. - */ - if ( ber_scanf( *ber, "{ax}", &attr ) != LBER_ERROR || - bytes_remaining( *ber ) == 0 ) { - err = LDAP_SUCCESS; - } - } - - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - if ( attr == NULL || err != LDAP_SUCCESS ) { - ber_free( *ber, 0 ); - *ber = NULL; - } - return( attr ); -} - -/* ARGSUSED */ -char * -LDAP_CALL -ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) -{ - char *attr; - int err; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULL ); /* punt */ - } - - if ( ber == NULL || !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( NULL ); - } - - attr = NULL; /* pessimistic */ - err = LDAP_DECODING_ERROR; /* ditto */ - - /* skip sequence, snarf attribute type, skip values */ - if ( ber_scanf( ber, "{ax}", &attr ) != LBER_ERROR || - bytes_remaining( ber ) == 0 ) { - err = LDAP_SUCCESS; - } - - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( attr ); -} diff --git a/ldap/c-sdk/libraries/libldap/getdn.c b/ldap/c-sdk/libraries/libldap/getdn.c deleted file mode 100644 index 4fab52cc6d..0000000000 --- a/ldap/c-sdk/libraries/libldap/getdn.c +++ /dev/null @@ -1,371 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1994 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * getdn.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -char * -LDAP_CALL -ldap_get_dn( LDAP *ld, LDAPMessage *entry ) -{ - char *dn; - struct berelement tmp; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULL ); /* punt */ - } - - if ( !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( NULL ); - } - - tmp = *entry->lm_ber; /* struct copy */ - if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( NULL ); - } - - return( dn ); -} - -char * -LDAP_CALL -ldap_dn2ufn( const char *dn ) -{ - char *p, *ufn, *r; - size_t plen; - int state; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); - - if ( dn == NULL ) { - dn = ""; - } - - if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL ) - return( nsldapi_strdup( (char *)dn )); - - ufn = nsldapi_strdup( ++p ); - -#define INQUOTE 1 -#define OUTQUOTE 2 - state = OUTQUOTE; - for ( p = ufn, r = ufn; *p; p += plen ) { - plen = 1; - switch ( *p ) { - case '\\': - if ( *++p == '\0' ) - plen=0; - else { - *r++ = '\\'; - r += (plen = LDAP_UTF8COPY(r,p)); - } - break; - case '"': - if ( state == INQUOTE ) - state = OUTQUOTE; - else - state = INQUOTE; - *r++ = *p; - break; - case ';': - case ',': - if ( state == OUTQUOTE ) - *r++ = ','; - else - *r++ = *p; - break; - case '=': - if ( state == INQUOTE ) - *r++ = *p; - else { - char *rsave = r; - LDAP_UTF8DEC(r); - *rsave = '\0'; - while ( !ldap_utf8isspace( r ) && *r != ';' - && *r != ',' && r > ufn ) - LDAP_UTF8DEC(r); - LDAP_UTF8INC(r); - - if ( strcasecmp( r, "c" ) - && strcasecmp( r, "o" ) - && strcasecmp( r, "ou" ) - && strcasecmp( r, "st" ) - && strcasecmp( r, "l" ) - && strcasecmp( r, "dc" ) - && strcasecmp( r, "uid" ) - && strcasecmp( r, "cn" ) ) { - r = rsave; - *r++ = '='; - } - } - break; - default: - r += (plen = LDAP_UTF8COPY(r,p)); - break; - } - } - *r = '\0'; - - return( ufn ); -} - -char ** -LDAP_CALL -ldap_explode_dns( const char *dn ) -{ - int ncomps, maxcomps; - char *s, *cpydn; - char **rdns; -#ifdef HAVE_STRTOK_R /* defined in portable.h */ - char *lasts; -#endif - - if ( dn == NULL ) { - dn = ""; - } - - if ( (rdns = (char **)NSLDAPI_MALLOC( 8 * sizeof(char *) )) == NULL ) { - return( NULL ); - } - - maxcomps = 8; - ncomps = 0; - cpydn = nsldapi_strdup( (char *)dn ); - for ( s = STRTOK( cpydn, "@.", &lasts ); s != NULL; - s = STRTOK( NULL, "@.", &lasts ) ) { - if ( ncomps == maxcomps ) { - maxcomps *= 2; - if ( (rdns = (char **)NSLDAPI_REALLOC( rdns, maxcomps * - sizeof(char *) )) == NULL ) { - NSLDAPI_FREE( cpydn ); - return( NULL ); - } - } - rdns[ncomps++] = nsldapi_strdup( s ); - } - rdns[ncomps] = NULL; - NSLDAPI_FREE( cpydn ); - - return( rdns ); -} - -#define LDAP_DN 1 -#define LDAP_RDN 2 - -static char ** -ldap_explode( const char *dn, const int notypes, const int nametype ) -{ - char *p, *q, *rdnstart, **rdns = NULL; - size_t plen = 0; - int state = 0; - int count = 0; - int startquote = 0; - int endquote = 0; - int len = 0; - int goteq = 0; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_explode\n", 0, 0, 0 ); - - if ( dn == NULL ) { - dn = ""; - } - -#if 0 - if ( ldap_is_dns_dn( dn ) ) { - return( ldap_explode_dns( dn ) ); - } -#endif - - while ( ldap_utf8isspace( (char *)dn )) { /* ignore leading spaces */ - ++dn; - } - - p = rdnstart = (char *) dn; - state = OUTQUOTE; - - do { - p += plen; - plen = 1; - switch ( *p ) { - case '\\': - if ( *++p == '\0' ) - p--; - else - plen = LDAP_UTF8LEN(p); - break; - case '"': - if ( state == INQUOTE ) - state = OUTQUOTE; - else - state = INQUOTE; - break; - case '+': if ( nametype != LDAP_RDN ) break; - case ';': - case ',': - case '\0': - if ( state == OUTQUOTE ) { - /* - * semicolon and comma are not valid RDN - * separators. - */ - if ( nametype == LDAP_RDN && - ( *p == ';' || *p == ',' || !goteq)) { - ldap_charray_free( rdns ); - return NULL; - } - if ( (*p == ',' || *p == ';') && !goteq ) { - /* If we get here, we have a case similar - * to =,,= - * This is not a valid dn */ - ldap_charray_free( rdns ); - return NULL; - } - goteq = 0; - ++count; - if ( rdns == NULL ) { - if (( rdns = (char **)NSLDAPI_MALLOC( 8 - * sizeof( char *))) == NULL ) - return( NULL ); - } else if ( count >= 8 ) { - if (( rdns = (char **)NSLDAPI_REALLOC( - rdns, (count+1) * - sizeof( char *))) == NULL ) - return( NULL ); - } - rdns[ count ] = NULL; - endquote = 0; - if ( notypes ) { - for ( q = rdnstart; - q < p && *q != '='; ++q ) { - ; - } - if ( q < p ) { /* *q == '=' */ - rdnstart = ++q; - } - if ( *rdnstart == '"' ) { - startquote = 1; - ++rdnstart; - } - - if ( (*(p-1) == '"') && startquote ) { - endquote = 1; - --p; - } - } - - len = p - rdnstart; - if (( rdns[ count-1 ] = (char *)NSLDAPI_CALLOC( - 1, len + 1 )) != NULL ) { - SAFEMEMCPY( rdns[ count-1 ], rdnstart, - len ); - if ( !endquote ) { - /* trim trailing spaces unless - * they are properly escaped */ - while ( len > 0 && - ldap_utf8isspace( - &rdns[count-1][len-1] ) && - ((len == 1) || (rdns[count-1][len-2] != '\\'))) { - --len; - } - } - rdns[ count-1 ][ len ] = '\0'; - } - - /* - * Don't forget to increment 'p' back to where - * it should be. If we don't, then we will - * never get past an "end quote." - */ - if ( endquote == 1 ) - p++; - - rdnstart = *p ? p + 1 : p; - while ( ldap_utf8isspace( rdnstart )) - ++rdnstart; - } - break; - case '=': - if ( state == OUTQUOTE ) { - goteq = 1; - } - /* FALL */ - default: - plen = LDAP_UTF8LEN(p); - break; - } - } while ( *p ); - - return( rdns ); -} - -char ** -LDAP_CALL -ldap_explode_dn( const char *dn, const int notypes ) -{ - return( ldap_explode( dn, notypes, LDAP_DN ) ); -} - -char ** -LDAP_CALL -ldap_explode_rdn( const char *rdn, const int notypes ) -{ - return( ldap_explode( rdn, notypes, LDAP_RDN ) ); -} - -int -LDAP_CALL -ldap_is_dns_dn( const char *dn ) -{ - return( dn != NULL && dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL && - strchr( dn, ',' ) == NULL ); -} diff --git a/ldap/c-sdk/libraries/libldap/getdxbyname.c b/ldap/c-sdk/libraries/libldap/getdxbyname.c deleted file mode 100644 index d706144586..0000000000 --- a/ldap/c-sdk/libraries/libldap/getdxbyname.c +++ /dev/null @@ -1,279 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * nsldapi_getdxbyname - retrieve DX records from the DNS (from - * TXT records for now) - */ - -#include - -#ifdef LDAP_DNS - -XXX not MT-safe XXX - -#include -#include - -#ifdef macintosh -#include -#include "macos.h" -#endif /* macintosh */ - -#ifdef _WINDOWS -#include -#endif - -#if !defined(macintosh) && !defined(DOS) && !defined( _WINDOWS ) -#include -#include -#include -#include -#include -#include -#include -#include -#endif -#include "ldap-int.h" - -#if defined( DOS ) -#include "msdos.h" -#endif /* DOS */ - - -#ifdef NEEDPROTOS -static char ** decode_answer( unsigned char *answer, int len ); -#else /* NEEDPROTOS */ -static char **decode_answer(); -#endif /* NEEDPROTOS */ - -extern int h_errno; -extern char *h_errlist[]; - - -#define MAX_TO_SORT 32 - - -/* - * nsldapi_getdxbyname - lookup DNS DX records for domain and return an ordered - * array. - */ -char ** -nsldapi_getdxbyname( char *domain ) -{ - unsigned char buf[ PACKETSZ ]; - char **dxs; - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_getdxbyname( %s )\n", domain, 0, 0 ); - - memset( buf, 0, sizeof( buf )); - - /* XXX not MT safe XXX */ - if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0 - || ( rc > sizeof( buf )) - || ( dxs = decode_answer( buf, rc )) == NULL ) { - /* - * punt: return list consisting of the original domain name only - */ - if (( dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ))) == NULL || - ( dxs[ 0 ] = nsldapi_strdup( domain )) == NULL ) { - if ( dxs != NULL ) { - NSLDAPI_FREE( dxs ); - } - dxs = NULL; - } else { - dxs[ 1 ] = NULL; - } - } - - return( dxs ); -} - - -static char ** -decode_answer( unsigned char *answer, int 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 - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { -/* __p_query( answer ); */ - } -#endif /* LDAP_DEBUG */ - - dxs = NULL; - hp = (HEADER *)answer; - eom = answer + len; - - if ( len < sizeof( *hp ) ) { - h_errno = NO_RECOVERY; - return( NULL ); - } - - 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 */ - if ( p + 3 * INT16SZ + INT32SZ > eom ) { - err = NO_RECOVERY; - continue; - } - type = _getshort( p ); - p += INT16SZ; - class = _getshort( p ); - p += INT16SZ; - p += INT32SZ; /* skip over TTL */ - rr_len = _getshort( p ); - p += INT16SZ; - if ( p + rr_len > eom ) { - err = NO_RECOVERY; - continue; - } - if ( class == C_IN && type == T_TXT ) { - int i, n, 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( *r )) { - ++r; - --txt_len; - } - pref = 0; - while ( isdigit( *r )) { - pref *= 10; - pref += ( *r - '0' ); - ++r; - --txt_len; - } - if ( dx_count < MAX_TO_SORT - 1 ) { - dx_pref[ dx_count ] = pref; - } - while ( isspace( *r )) { - ++r; - --txt_len; - } - if ( dx_count == 0 ) { - dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * )); - } else { - dxs = (char **)NSLDAPI_REALLOC( dxs, - ( dx_count + 2 ) * sizeof( char * )); - } - if ( dxs == NULL || ( dxs[ dx_count ] = - (char *)NSLDAPI_CALLOC( 1, txt_len + 1 )) - == NULL ) { - err = NO_RECOVERY; - continue; - } - SAFEMEMCPY( 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_DNS */ diff --git a/ldap/c-sdk/libraries/libldap/geteffectiverightsctrl.c b/ldap/c-sdk/libraries/libldap/geteffectiverightsctrl.c deleted file mode 100644 index f03fdc4416..0000000000 --- a/ldap/c-sdk/libraries/libldap/geteffectiverightsctrl.c +++ /dev/null @@ -1,109 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_create_geteffectiveRights_control - - Create Effective Rights control. - - Parameters are - - ld LDAP pointer to the desired connection - - authzid RFC2829 section 9, eg "dn:". - NULL or empty string means get bound user's rights, - just "dn:" means get anonymous user's rights. - - attrlist additional attributes for which rights info is - requrested. NULL means "just the ones returned - with the search operation". - - ctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client - - ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_geteffectiveRights_control ( - LDAP *ld, - const char *authzid, - const char **attrlist, - const char ctl_iscritical, - LDAPControl **ctrlp -) -{ - BerElement *ber; - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - if (NULL == authzid) - { - authzid = ""; - } - - /* create a ber package to hold the controlValue */ - if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - if ( LBER_ERROR == ber_printf( ber, "{s{v}}", authzid, attrlist ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, ber, 1, - ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - -} - - diff --git a/ldap/c-sdk/libraries/libldap/getentry.c b/ldap/c-sdk/libraries/libldap/getentry.c deleted file mode 100644 index fb999265b9..0000000000 --- a/ldap/c-sdk/libraries/libldap/getentry.c +++ /dev/null @@ -1,141 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * getentry.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -LDAPMessage * -LDAP_CALL -ldap_first_entry( LDAP *ld, LDAPMessage *chain ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || chain == NULLMSG ) { - return( NULLMSG ); - } - - if ( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { - return( chain ); - } - - return( ldap_next_entry( ld, chain )); -} - - -LDAPMessage * -LDAP_CALL -ldap_next_entry( LDAP *ld, LDAPMessage *entry ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || entry == NULLMSG ) { - return( NULLMSG ); - } - - for ( entry = entry->lm_chain; entry != NULLMSG; - entry = entry->lm_chain ) { - if ( entry->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { - return( entry ); - } - } - - return( NULLMSG ); -} - -int -LDAP_CALL -ldap_count_entries( LDAP *ld, LDAPMessage *chain ) -{ - int i; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); - } - - for ( i = 0; chain != NULL; chain = chain->lm_chain ) { - if ( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { - ++i; - } - } - - return( i ); -} - - -int -LDAP_CALL -ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry, - LDAPControl ***serverctrlsp ) -{ - int rc; - BerElement tmpber; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_entry_controls\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry ) - || serverctrlsp == NULL ) { - rc = LDAP_PARAM_ERROR; - goto report_error_and_return; - } - - *serverctrlsp = NULL; - tmpber = *entry->lm_ber; /* struct copy */ - - /* skip past dn and entire attribute/value list */ - if ( ber_scanf( &tmpber, "{xx" ) == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - goto report_error_and_return; - } - - rc = nsldapi_get_controls( &tmpber, serverctrlsp ); - -report_error_and_return: - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libldap/getfilter.c b/ldap/c-sdk/libraries/libldap/getfilter.c deleted file mode 100644 index ff2ee77f91..0000000000 --- a/ldap/c-sdk/libraries/libldap/getfilter.c +++ /dev/null @@ -1,553 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * getfilter.c -- optional add-on to libldap - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" -#include "regex.h" - -static int break_into_words( char *str, char *delims, char ***wordsp ); - -#if !defined( macintosh ) && !defined( DOS ) -extern char * LDAP_CALL re_comp(); -#endif - -#define FILT_MAX_LINE_LEN 1024 - -LDAPFiltDesc * -LDAP_CALL -ldap_init_getfilter( char *fname ) -{ - FILE *fp; - char *buf; - long rlen, len; - int eof; - LDAPFiltDesc *lfdp; - - if (( fp = NSLDAPI_FOPEN( fname, "r" )) == NULL ) { - return( NULL ); - } - - if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ - fclose( fp ); - return( NULL ); - } - - len = ftell( fp ); - - if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ - fclose( fp ); - return( NULL ); - } - - if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { - fclose( fp ); - return( NULL ); - } - - rlen = fread( buf, 1, (size_t)len, fp ); - eof = feof( fp ); - fclose( fp ); - - if ( rlen != len && !eof ) { /* error: didn't get the whole file */ - NSLDAPI_FREE( buf ); - return( NULL ); - } - - - lfdp = ldap_init_getfilter_buf( buf, rlen ); - NSLDAPI_FREE( buf ); - - return( lfdp ); -} - - -LDAPFiltDesc * -LDAP_CALL -ldap_init_getfilter_buf( char *buf, long buflen ) -{ - LDAPFiltDesc *lfdp; - LDAPFiltList *flp, *nextflp; - LDAPFiltInfo *fip, *nextfip; - char *errmsg, *tag, **tok; - int tokcnt, i; - - if ( (buf == NULL) || (buflen < 0) || - ( lfdp = (LDAPFiltDesc *)NSLDAPI_CALLOC(1, sizeof( LDAPFiltDesc))) - == NULL ) { - return( NULL ); - } - - flp = nextflp = NULL; - fip = NULL; - tag = NULL; - - while ( buflen > 0 && ( tokcnt = nsldapi_next_line_tokens( &buf, &buflen, - &tok )) > 0 ) { - switch( tokcnt ) { - case 1: /* tag line */ - if ( tag != NULL ) { - NSLDAPI_FREE( tag ); - } - tag = tok[ 0 ]; - NSLDAPI_FREE( tok ); - break; - case 4: - case 5: /* start of filter info. list */ - if (( nextflp = (LDAPFiltList *)NSLDAPI_CALLOC( 1, - sizeof( LDAPFiltList ))) == NULL ) { - ldap_getfilter_free( lfdp ); - return( NULL ); - } - nextflp->lfl_tag = nsldapi_strdup( tag ); - nextflp->lfl_pattern = tok[ 0 ]; - if (( errmsg = re_comp( nextflp->lfl_pattern )) != NULL ) { - char msg[512]; - ldap_getfilter_free( lfdp ); - snprintf( msg, sizeof(msg), - "bad regular expression \"%s\" - %s\n", - nextflp->lfl_pattern, errmsg ); - ber_err_print( msg ); - nsldapi_free_strarray( tok ); - return( NULL ); - } - - nextflp->lfl_delims = tok[ 1 ]; - nextflp->lfl_ilist = NULL; - nextflp->lfl_next = NULL; - if ( flp == NULL ) { /* first one */ - lfdp->lfd_filtlist = nextflp; - } else { - flp->lfl_next = nextflp; - } - flp = nextflp; - fip = NULL; - for ( i = 2; i < 5; ++i ) { - tok[ i - 2 ] = tok[ i ]; - } - /* fall through */ - - case 2: - case 3: /* filter, desc, and optional search scope */ - if ( nextflp != NULL ) { /* add to info list */ - if (( nextfip = (LDAPFiltInfo *)NSLDAPI_CALLOC( 1, - sizeof( LDAPFiltInfo ))) == NULL ) { - ldap_getfilter_free( lfdp ); - nsldapi_free_strarray( tok ); - return( NULL ); - } - if ( fip == NULL ) { /* first one */ - nextflp->lfl_ilist = nextfip; - } else { - fip->lfi_next = nextfip; - } - fip = nextfip; - nextfip->lfi_next = NULL; - nextfip->lfi_filter = tok[ 0 ]; - nextfip->lfi_desc = tok[ 1 ]; - if ( tok[ 2 ] != NULL ) { - if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) { - nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; - } else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) { - nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL; - } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) { - nextfip->lfi_scope = LDAP_SCOPE_BASE; - } else { - nsldapi_free_strarray( tok ); - ldap_getfilter_free( lfdp ); - return( NULL ); - } - NSLDAPI_FREE( tok[ 2 ] ); - tok[ 2 ] = NULL; - } else { - nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */ - } - nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL && - strchr( tok[ 0 ], '~' ) == NULL ); - NSLDAPI_FREE( tok ); - } - break; - - default: - nsldapi_free_strarray( tok ); - ldap_getfilter_free( lfdp ); - return( NULL ); - } - } - - if ( tag != NULL ) { - NSLDAPI_FREE( tag ); - } - - return( lfdp ); -} - - -int -LDAP_CALL -ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix, char *suffix ) -{ - if ( lfdp == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - if ( lfdp->lfd_filtprefix != NULL ) { - NSLDAPI_FREE( lfdp->lfd_filtprefix ); - } - lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : nsldapi_strdup( prefix ); - - if ( lfdp->lfd_filtsuffix != NULL ) { - NSLDAPI_FREE( lfdp->lfd_filtsuffix ); - } - lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : nsldapi_strdup( suffix ); - - return( LDAP_SUCCESS ); -} - - -/* - * ldap_setfilteraffixes() is deprecated -- use ldap_set_filter_additions() - */ -void -LDAP_CALL -ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix ) -{ - (void)ldap_set_filter_additions( lfdp, prefix, suffix ); -} - - -LDAPFiltInfo * -LDAP_CALL -ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value ) -{ - LDAPFiltList *flp; - - if ( lfdp == NULL || tagpat == NULL || value == NULL ) { - return( NULL ); /* punt */ - } - - if ( lfdp->lfd_curvalcopy != NULL ) { - NSLDAPI_FREE( lfdp->lfd_curvalcopy ); - NSLDAPI_FREE( lfdp->lfd_curvalwords ); - } - - NSLDAPI_FREE(lfdp->lfd_curval); - if ((lfdp->lfd_curval = nsldapi_strdup(value)) == NULL) { - return( NULL ); - } - - lfdp->lfd_curfip = NULL; - - for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) { - if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1 - && re_comp( flp->lfl_pattern ) == NULL - && re_exec( lfdp->lfd_curval ) == 1 ) { - lfdp->lfd_curfip = flp->lfl_ilist; - break; - } - } - - if ( lfdp->lfd_curfip == NULL ) { - return( NULL ); - } - - if (( lfdp->lfd_curvalcopy = nsldapi_strdup( value )) == NULL ) { - return( NULL ); - } - - if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims, - &lfdp->lfd_curvalwords ) < 0 ) { - NSLDAPI_FREE( lfdp->lfd_curvalcopy ); - lfdp->lfd_curvalcopy = NULL; - return( NULL ); - } - - return( ldap_getnextfilter( lfdp )); -} - - -LDAPFiltInfo * -LDAP_CALL -ldap_getnextfilter( LDAPFiltDesc *lfdp ) -{ - LDAPFiltInfo *fip; - - if ( lfdp == NULL || ( fip = lfdp->lfd_curfip ) == NULL ) { - return( NULL ); - } - - lfdp->lfd_curfip = fip->lfi_next; - - ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter, - lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL, - lfdp->lfd_curval, lfdp->lfd_curvalwords ); - lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter; - lfdp->lfd_retfi.lfi_desc = fip->lfi_desc; - lfdp->lfd_retfi.lfi_scope = fip->lfi_scope; - lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact; - - return( &lfdp->lfd_retfi ); -} - - -static char* -filter_add_strn( char *f, char *flimit, char *v, size_t vlen ) - /* Copy v into f. If flimit is too small, return NULL; - * otherwise return (f + vlen). - */ -{ - auto size_t flen = flimit - f; - if ( vlen > flen ) { /* flimit is too small */ - if ( flen > 0 ) SAFEMEMCPY( f, v, flen ); - return NULL; - } - if ( vlen > 0 ) SAFEMEMCPY( f, v, vlen ); - return f + vlen; -} - -static char* -filter_add_value( char *f, char *flimit, char *v, int escape_all ) - /* Copy v into f, but with parentheses escaped. But only escape * and \ - * if escape_all is non-zero so that either "*" or "\2a" can be used in - * v, with different meanings. - * If flimit is too small, return NULL; otherwise - * return (f + the number of bytes copied). - */ -{ - auto char x[4]; - auto size_t slen; - while ( f && *v ) { - switch ( *v ) { - case '*': - if ( escape_all ) { - f = filter_add_strn( f, flimit, "\\2a", 3 ); - v++; - } else { - if ( f < flimit ) { - *f++ = *v++; - } else { - f = NULL; /* overflow */ - } - } - break; - - case '(': - case ')': - sprintf( x, "\\%02x", (unsigned)*v ); - f = filter_add_strn( f, flimit, x, 3 ); - v++; - break; - - case '\\': - if ( escape_all ) { - f = filter_add_strn( f, flimit, "\\5c", 3 ); - v++; - } else { - slen = (ldap_utf8isxdigit( v+1 ) && - ldap_utf8isxdigit( v+2 )) ? 3 : (v[1] ? 2 : 1); - f = filter_add_strn( f, flimit, v, slen ); - v += slen; - } - break; - - default: - if ( f < flimit ) { - *f++ = *v++; - } else { - f = NULL; /* overflow */ - } - break; - } - } - return f; -} - -int -LDAP_CALL -ldap_create_filter( char *filtbuf, unsigned long buflen, char *pattern, - char *prefix, char *suffix, char *attr, char *value, char **valwords ) -{ - char *p, *f, *flimit; - int i, wordcount, wordnum, endwordnum, escape_all; - - /* - * there is some confusion on what to create for a filter if - * attr or value are null pointers. For now we just leave them - * as TO BE DEALT with - */ - - if ( filtbuf == NULL || buflen == 0 || pattern == NULL ){ - return( LDAP_PARAM_ERROR ); - } - - if ( valwords == NULL ) { - wordcount = 0; - } else { - for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) { - ; - } - } - - f = filtbuf; - flimit = filtbuf + buflen - 1; - - if ( prefix != NULL ) { - f = filter_add_strn( f, flimit, prefix, strlen( prefix )); - } - - for ( p = pattern; f != NULL && *p != '\0'; ++p ) { - if ( *p == '%' ) { - ++p; - if ( *p == 'v' || *p == 'e' ) { - escape_all = ( *p == 'e' ); - if ( ldap_utf8isdigit( p+1 )) { - ++p; - wordnum = *p - '1'; - if ( *(p+1) == '-' ) { - ++p; - if ( ldap_utf8isdigit( p+1 )) { - ++p; - endwordnum = *p - '1'; /* e.g., "%v2-4" */ - if ( endwordnum > wordcount - 1 ) { - endwordnum = wordcount - 1; - } - } else { - endwordnum = wordcount - 1; /* e.g., "%v2-" */ - } - } else { - endwordnum = wordnum; /* e.g., "%v2" */ - } - - if ( wordcount > 0 ) { - for ( i = wordnum; i <= endwordnum; ++i ) { - if ( i > wordnum ) { /* add blank btw words */ - f = filter_add_strn( f, flimit, " ", 1 ); - if ( f == NULL ) break; - } - f = filter_add_value( f, flimit, valwords[ i ], - escape_all ); - if ( f == NULL ) break; - } - } - } else if ( *(p+1) == '$' ) { - ++p; - if ( wordcount > 0 ) { - wordnum = wordcount - 1; - f = filter_add_value( f, flimit, - valwords[ wordnum ], escape_all ); - } - } else if ( value != NULL ) { - f = filter_add_value( f, flimit, value, escape_all ); - } - } else if ( *p == 'a' && attr != NULL ) { - f = filter_add_strn( f, flimit, attr, strlen( attr )); - } else { - *f++ = *p; - } - } else { - *f++ = *p; - } - if ( f > flimit ) { /* overflow */ - f = NULL; - } - } - - if ( suffix != NULL && f != NULL) { - f = filter_add_strn( f, flimit, suffix, strlen( suffix )); - } - - if ( f == NULL ) { - *flimit = '\0'; - return( LDAP_SIZELIMIT_EXCEEDED ); - } - *f = '\0'; - return( LDAP_SUCCESS ); -} - - -/* - * ldap_build_filter() is deprecated -- use ldap_create_filter() instead - */ -void -LDAP_CALL -ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern, - char *prefix, char *suffix, char *attr, char *value, char **valwords ) -{ - (void)ldap_create_filter( filtbuf, buflen, pattern, prefix, suffix, attr, - value, valwords ); -} - - -static int -break_into_words( char *str, char *delims, char ***wordsp ) -{ - char *word, **words; - int count; - char *lasts; - - if (( words = (char **)NSLDAPI_CALLOC( 1, sizeof( char * ))) == NULL ) { - return( -1 ); - } - count = 0; - words[ count ] = NULL; - - word = ldap_utf8strtok_r( str, delims, &lasts ); - while ( word != NULL ) { - if (( words = (char **)NSLDAPI_REALLOC( words, - ( count + 2 ) * sizeof( char * ))) == NULL ) { - return( -1 ); - } - - words[ count ] = word; - words[ ++count ] = NULL; - word = ldap_utf8strtok_r( NULL, delims, &lasts ); - } - - *wordsp = words; - return( count ); -} diff --git a/ldap/c-sdk/libraries/libldap/getoption.c b/ldap/c-sdk/libraries/libldap/getoption.c deleted file mode 100644 index 73e21a2dc9..0000000000 --- a/ldap/c-sdk/libraries/libldap/getoption.c +++ /dev/null @@ -1,475 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -#define LDAP_GET_BITOPT( ld, bit ) \ - ((ld)->ld_options & bit ) != 0 ? 1 : 0 - -static int nsldapi_get_api_info( LDAPAPIInfo *aip ); -static int nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ); - - -int -LDAP_CALL -ldap_get_option( LDAP *ld, int option, void *optdata ) -{ - int rc = 0; - - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - - /* - * optdata MUST be a valid pointer... - */ - if (NULL == optdata) - { - return(LDAP_PARAM_ERROR); - } - /* - * process global options (not associated with an LDAP session handle) - */ - if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) { - /* struct copy */ - *((struct ldap_memalloc_fns *)optdata) = nsldapi_memalloc_fns; - return( 0 ); - } - - if ( option == LDAP_OPT_API_INFO ) { - rc = nsldapi_get_api_info( (LDAPAPIInfo *)optdata ); - if ( rc != LDAP_SUCCESS ) { - if ( ld != NULL ) { - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - } - return( -1 ); - } - return( 0 ); - } - /* - * LDAP_OPT_DEBUG_LEVEL is global - */ - if (LDAP_OPT_DEBUG_LEVEL == option) - { -#ifdef LDAP_DEBUG - *((int *) optdata) = ldap_debug; -#endif /* LDAP_DEBUG */ - return ( 0 ); - } - - /* - * if ld is NULL, arrange to return options from our default settings - */ - if ( ld == NULL ) { - ld = &nsldapi_ld_defaults; - } - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); /* punt */ - } - - - if (ld != &nsldapi_ld_defaults) - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - switch( option ) { -#ifdef LDAP_DNS - case LDAP_OPT_DNS: - *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_DNS ); - break; -#endif - - case LDAP_OPT_REFERRALS: - *((int *) optdata) = - LDAP_GET_BITOPT( ld, LDAP_BITOPT_REFERRALS ); - break; - - case LDAP_OPT_SSL: - *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_SSL ); - break; - - case LDAP_OPT_RESTART: - *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_RESTART ); - break; - - case LDAP_OPT_RECONNECT: - *((int *) optdata) = - LDAP_GET_BITOPT( ld, LDAP_BITOPT_RECONNECT ); - break; - - case LDAP_OPT_NOREBIND: - *((int *) optdata) = - LDAP_GET_BITOPT( ld, LDAP_BITOPT_NOREBIND ); - break; - -#ifdef LDAP_ASYNC_IO - case LDAP_OPT_ASYNC_CONNECT: - *((int *) optdata) = - LDAP_GET_BITOPT( ld, LDAP_BITOPT_ASYNC ); - break; -#endif /* LDAP_ASYNC_IO */ - - /* stuff in the sockbuf */ - case LDAP_X_OPT_SOCKBUF: - *((Sockbuf **) optdata) = ld->ld_sbp; - break; - - case LDAP_OPT_DESC: - if ( ber_sockbuf_get_option( ld->ld_sbp, - LBER_SOCKBUF_OPT_DESC, optdata ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - rc = -1; - } - break; - - /* fields in the LDAP structure */ - case LDAP_OPT_DEREF: - *((int *) optdata) = ld->ld_deref; - break; - case LDAP_OPT_SIZELIMIT: - *((int *) optdata) = ld->ld_sizelimit; - break; - case LDAP_OPT_TIMELIMIT: - *((int *) optdata) = ld->ld_timelimit; - break; - case LDAP_OPT_REFERRAL_HOP_LIMIT: - *((int *) optdata) = ld->ld_refhoplimit; - break; - case LDAP_OPT_PROTOCOL_VERSION: - *((int *) optdata) = ld->ld_version; - break; - case LDAP_OPT_SERVER_CONTROLS: - /* fall through */ - case LDAP_OPT_CLIENT_CONTROLS: - *((LDAPControl ***)optdata) = NULL; - /* nsldapi_dup_controls returns -1 and sets lderrno on error */ - rc = nsldapi_dup_controls( ld, (LDAPControl ***)optdata, - ( option == LDAP_OPT_SERVER_CONTROLS ) ? - ld->ld_servercontrols : ld->ld_clientcontrols ); - break; - - /* rebind proc */ - case LDAP_OPT_REBIND_FN: - *((LDAP_REBINDPROC_CALLBACK **) optdata) = ld->ld_rebind_fn; - break; - case LDAP_OPT_REBIND_ARG: - *((void **) optdata) = ld->ld_rebind_arg; - break; - - /* i/o function pointers */ - case LDAP_OPT_IO_FN_PTRS: - if ( ld->ld_io_fns_ptr == NULL ) { - memset( optdata, 0, sizeof( struct ldap_io_fns )); - } else { - /* struct copy */ - *((struct ldap_io_fns *)optdata) = *(ld->ld_io_fns_ptr); - } - break; - - /* extended i/o function pointers */ - case LDAP_X_OPT_EXTIO_FN_PTRS: - if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) { - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close = ld->ld_extclose_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect = ld->ld_extconnect_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read = ld->ld_extread_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write = ld->ld_extwrite_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll = ld->ld_extpoll_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle = ld->ld_extnewhandle_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle = ld->ld_extdisposehandle_fn; - ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg = ld->ld_ext_session_arg; - } else if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == - LDAP_X_EXTIO_FNS_SIZE ) { - /* struct copy */ - *((struct ldap_x_ext_io_fns *) optdata) = ld->ld_ext_io_fns; - } else { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - rc = -1; - } - break; - - /* get socketargp in extended i/o function */ - case LDAP_X_OPT_SOCKETARG: - if ( ber_sockbuf_get_option( ld->ld_sbp,LBER_SOCKBUF_OPT_SOCK_ARG, optdata) - != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - rc = -1; - } - break; - - /* thread function pointers */ - case LDAP_OPT_THREAD_FN_PTRS: - /* struct copy */ - *((struct ldap_thread_fns *) optdata) = ld->ld_thread; - break; - - /* extra thread function pointers */ - case LDAP_OPT_EXTRA_THREAD_FN_PTRS: - /* struct copy */ - *((struct ldap_extra_thread_fns *) optdata) = ld->ld_thread2; - break; - - /* DNS function pointers */ - case LDAP_OPT_DNS_FN_PTRS: - /* struct copy */ - *((struct ldap_dns_fns *) optdata) = ld->ld_dnsfn; - break; - - /* cache function pointers */ - case LDAP_OPT_CACHE_FN_PTRS: - /* struct copy */ - *((struct ldap_cache_fns *) optdata) = ld->ld_cache; - break; - case LDAP_OPT_CACHE_STRATEGY: - *((int *) optdata) = ld->ld_cache_strategy; - break; - case LDAP_OPT_CACHE_ENABLE: - *((int *) optdata) = ld->ld_cache_on; - break; - - case LDAP_OPT_ERROR_NUMBER: - *((int *) optdata) = LDAP_GET_LDERRNO( ld, NULL, NULL ); - break; - - case LDAP_OPT_ERROR_STRING: - (void)LDAP_GET_LDERRNO( ld, NULL, (char **)optdata ); - *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); - break; - - case LDAP_OPT_MATCHED_DN: - (void)LDAP_GET_LDERRNO( ld, (char **)optdata, NULL ); - *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); - break; - - case LDAP_OPT_PREFERRED_LANGUAGE: - if ( NULL != ld->ld_preferred_language ) { - *((char **) optdata) = - nsldapi_strdup(ld->ld_preferred_language); - } else { - *((char **) optdata) = NULL; - } - break; - - case LDAP_OPT_API_FEATURE_INFO: - rc = nsldapi_get_feature_info( (LDAPAPIFeatureInfo *)optdata ); - if ( rc != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - rc = -1; - } - break; - - case LDAP_OPT_HOST_NAME: - *((char **) optdata) = nsldapi_strdup( ld->ld_defhost ); - break; - - case LDAP_X_OPT_CONNECT_TIMEOUT: - *((int *) optdata) = ld->ld_connect_timeout; - break; - -#ifdef LDAP_SASLIO_HOOKS - /* SASL options */ - case LDAP_OPT_X_SASL_MECH: - *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_mech); - break; - case LDAP_OPT_X_SASL_REALM: - *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_realm); - break; - case LDAP_OPT_X_SASL_AUTHCID: - *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authcid); - break; - case LDAP_OPT_X_SASL_AUTHZID: - *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authzid); - break; - case LDAP_OPT_X_SASL_SSF: - { - int sc; - sasl_ssf_t *ssf; - sasl_conn_t *ctx; - if( ld->ld_defconn == NULL ) { - return -1; - } - ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sasl_ctx); - if ( ctx == NULL ) { - return -1; - } - sc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); - if ( sc != SASL_OK ) { - return -1; - } - *((sasl_ssf_t *) optdata) = *ssf; - } - break; - case LDAP_OPT_X_SASL_SSF_MIN: - *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.min_ssf; - break; - case LDAP_OPT_X_SASL_SSF_MAX: - *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.max_ssf; - break; - case LDAP_OPT_X_SASL_MAXBUFSIZE: - *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.maxbufsize; - break; - case LDAP_OPT_X_SASL_SSF_EXTERNAL: - case LDAP_OPT_X_SASL_SECPROPS: - /* - * These options are write only. Making these options - * read/write would expose semi-private interfaces of libsasl - * for which there are no cross platform/standardized - * definitions. - */ - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - rc = -1; - break; -#endif - - default: - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - rc = -1; - } - if (ld != &nsldapi_ld_defaults) - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - return( rc ); -} - - -/* - * Table of extended API features we support. - * The first field is the version of the info. strcuture itself; we do not - * use the ones from this table so it is okay to leave as zero. - */ -static LDAPAPIFeatureInfo nsldapi_extensions[] = { - { 0, "SERVER_SIDE_SORT", LDAP_API_FEATURE_SERVER_SIDE_SORT }, - { 0, "VIRTUAL_LIST_VIEW", LDAP_API_FEATURE_VIRTUAL_LIST_VIEW }, - { 0, "PERSISTENT_SEARCH", LDAP_API_FEATURE_PERSISTENT_SEARCH }, - { 0, "PROXY_AUTHORIZATION", LDAP_API_FEATURE_PROXY_AUTHORIZATION }, - { 0, "X_LDERRNO", LDAP_API_FEATURE_X_LDERRNO }, - { 0, "X_MEMCACHE", LDAP_API_FEATURE_X_MEMCACHE }, - { 0, "X_IO_FUNCTIONS", LDAP_API_FEATURE_X_IO_FUNCTIONS }, - { 0, "X_EXTIO_FUNCTIONS", LDAP_API_FEATURE_X_EXTIO_FUNCTIONS }, - { 0, "X_DNS_FUNCTIONS", LDAP_API_FEATURE_X_DNS_FUNCTIONS }, - { 0, "X_MEMALLOC_FUNCTIONS", LDAP_API_FEATURE_X_MEMALLOC_FUNCTIONS }, - { 0, "X_THREAD_FUNCTIONS", LDAP_API_FEATURE_X_THREAD_FUNCTIONS }, - { 0, "X_EXTHREAD_FUNCTIONS", LDAP_API_FEATURE_X_EXTHREAD_FUNCTIONS }, - { 0, "X_GETLANGVALUES", LDAP_API_FEATURE_X_GETLANGVALUES }, - { 0, "X_CLIENT_SIDE_SORT", LDAP_API_FEATURE_X_CLIENT_SIDE_SORT }, - { 0, "X_URL_FUNCTIONS", LDAP_API_FEATURE_X_URL_FUNCTIONS }, - { 0, "X_FILTER_FUNCTIONS", LDAP_API_FEATURE_X_FILTER_FUNCTIONS }, -}; - -#define NSLDAPI_EXTENSIONS_COUNT \ - (sizeof(nsldapi_extensions)/sizeof(LDAPAPIFeatureInfo)) - -/* - * Retrieve information about this implementation of the LDAP API. - * Returns an LDAP error code. - */ -static int -nsldapi_get_api_info( LDAPAPIInfo *aip ) -{ - int i; - - if ( aip == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - aip->ldapai_api_version = LDAP_API_VERSION; - - if ( aip->ldapai_info_version != LDAP_API_INFO_VERSION ) { - aip->ldapai_info_version = LDAP_API_INFO_VERSION; - return( LDAP_PARAM_ERROR ); - } - - aip->ldapai_protocol_version = LDAP_VERSION_MAX; - aip->ldapai_vendor_version = LDAP_VENDOR_VERSION; - - if (( aip->ldapai_vendor_name = nsldapi_strdup( LDAP_VENDOR_NAME )) - == NULL ) { - return( LDAP_NO_MEMORY ); - } - - if ( NSLDAPI_EXTENSIONS_COUNT < 1 ) { - aip->ldapai_extensions = NULL; - } else { - if (( aip->ldapai_extensions = NSLDAPI_CALLOC( - NSLDAPI_EXTENSIONS_COUNT + 1, sizeof(char *))) == NULL ) { - NSLDAPI_FREE( aip->ldapai_vendor_name ); - aip->ldapai_vendor_name = NULL; - return( LDAP_NO_MEMORY ); - } - - for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { - if (( aip->ldapai_extensions[i] = nsldapi_strdup( - nsldapi_extensions[i].ldapaif_name )) == NULL ) { - ldap_value_free( aip->ldapai_extensions ); - NSLDAPI_FREE( aip->ldapai_vendor_name ); - aip->ldapai_extensions = NULL; - aip->ldapai_vendor_name = NULL; - return( LDAP_NO_MEMORY ); - } - } - } - - return( LDAP_SUCCESS ); -} - - -/* - * Retrieves information about a specific extended feature of the LDAP API/ - * Returns an LDAP error code. - */ -static int -nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ) -{ - int i; - - if ( fip == NULL || fip->ldapaif_name == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - if ( fip->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION ) { - fip->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; - return( LDAP_PARAM_ERROR ); - } - - for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { - if ( strcmp( fip->ldapaif_name, - nsldapi_extensions[i].ldapaif_name ) == 0 ) { - fip->ldapaif_version = - nsldapi_extensions[i].ldapaif_version; - break; - } - } - - return(( i < NSLDAPI_EXTENSIONS_COUNT ) ? LDAP_SUCCESS - : LDAP_PARAM_ERROR ); -} diff --git a/ldap/c-sdk/libraries/libldap/getvalues.c b/ldap/c-sdk/libraries/libldap/getvalues.c deleted file mode 100644 index cae40d2cdf..0000000000 --- a/ldap/c-sdk/libraries/libldap/getvalues.c +++ /dev/null @@ -1,480 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * getvalues.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - - -static void ** -internal_ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target, - int lencall ) -{ - struct berelement ber; - char *attr; - int rc; - void **vals; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULL ); /* punt */ - } - if ( target == NULL || - !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( NULL ); - } - - ber = *entry->lm_ber; - - /* skip sequence, dn, sequence of, and snag the first attr */ - if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( NULL ); - } - - rc = strcasecmp( (char *)target, attr ); - NSLDAPI_FREE( attr ); - if ( rc != 0 ) { - while ( 1 ) { - if ( ber_scanf( &ber, "x}{a", &attr ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, - NULL, NULL ); - return( NULL ); - } - - rc = strcasecmp( (char *)target, attr ); - if ( rc == 0 ) { - NSLDAPI_FREE( attr ); - break; - } - NSLDAPI_FREE( attr ); - } - } - - /* - * if we get this far, we've found the attribute and are sitting - * just before the set of values. - */ - - if ( lencall ) { - rc = ber_scanf( &ber, "[V]", &vals ); - } else { - rc = ber_scanf( &ber, "[v]", &vals ); - } - - if ( rc == LBER_ERROR ) { - rc = LDAP_DECODING_ERROR; - } else { - rc = LDAP_SUCCESS; - } - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - - return(( rc == LDAP_SUCCESS ) ? vals : NULL ); -} - - -/* For language-sensitive attribute matching, we are looking for a - language tag that looks like one of the following: - - cn - cn;lang-en - cn;lang-en-us - cn;lang-ja - cn;lang-ja-JP-kanji - - The base language specification consists of two letters following - "lang-". After that, there may be additional language-specific - narrowings preceded by a "-". In our processing we go from the - specific to the general, preferring a complete subtype match, but - accepting a partial one. For example: - - For a request for "cn;lang-en-us", we would return cn;lang-en-us - if present, otherwise cn;lang-en if present, otherwise cn. - - Besides the language subtype, there may be other subtypes: - - cn;lang-ja;binary (Unlikely!) - cn;lang-ja;phonetic - - If not in the target, they are ignored. If they are in the target, - they must be in the attribute to match. -*/ -#define LANG_SUBTYPE_INDEX_NONE -1 -#define LANG_SUBTYPE_INDEX_DUPLICATE -2 - -typedef struct { - int start; - int length; -} _SubStringIndex; - -static int -parse_subtypes( const char *target, int *baseLenp, char **langp, - _SubStringIndex **subs, int *nsubtypes ) -{ - int nSubtypes = 0; - int ind = 0; - char *nextToken; - _SubStringIndex *result = NULL; - int langIndex; - int targetLen; - int subtypeStart; - - langIndex = LANG_SUBTYPE_INDEX_NONE; - *subs = NULL; - *langp = NULL; - *baseLenp = 0; - *nsubtypes = 0; - targetLen = strlen( target ); - - /* Parse past base attribute */ - nextToken = strchr( target, ';' ); - if ( NULL != nextToken ) { - subtypeStart = nextToken - target + 1; - *baseLenp = subtypeStart - 1; - } - else { - subtypeStart = targetLen; - *baseLenp = subtypeStart; - } - ind = subtypeStart; - - /* How many subtypes? */ - nextToken = (char *)target + subtypeStart; - while ( nextToken && *nextToken ) { - char *thisToken = nextToken; - nextToken = strchr( thisToken, ';' ); - if ( NULL != nextToken ) - nextToken++; - if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { - /* If there was a previous lang tag, this is illegal! */ - if ( langIndex != LANG_SUBTYPE_INDEX_NONE ) { - langIndex = LANG_SUBTYPE_INDEX_DUPLICATE; - return langIndex; - } - else { - langIndex = nSubtypes; - } - } else { - nSubtypes++; - } - } - /* No language subtype? */ - if ( langIndex < 0 ) - return langIndex; - - /* Allocate array of non-language subtypes */ - if ( nSubtypes > 0 ) { - result = (_SubStringIndex *)NSLDAPI_MALLOC( sizeof(*result) - * nSubtypes ); - memset( result, 0, sizeof(*result) * nSubtypes ); - } - ind = 0; - nSubtypes = 0; - ind = subtypeStart; - nextToken = (char *)target + subtypeStart; - while ( nextToken && *nextToken ) { - char *thisToken = nextToken; - int len; - nextToken = strchr( thisToken, ';' ); - if ( NULL != nextToken ) { - len = nextToken - thisToken; - nextToken++; - } - else { - nextToken = (char *)target + targetLen; - len = nextToken - thisToken; - } - if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { - int i; - *langp = (char *)NSLDAPI_MALLOC( len + 1 ); - for( i = 0; i < len; i++ ) - (*langp)[i] = toupper( target[ind+i] ); - (*langp)[len] = 0; - } - else { - result[nSubtypes].start = thisToken - target; - result[nSubtypes].length = len; - nSubtypes++; - } - } - *subs = result; - *nsubtypes = nSubtypes; - return langIndex; -} - - -static int -check_lang_match( const char *target, const char *baseTarget, - _SubStringIndex *targetTypes, - int ntargetTypes, char *targetLang, char *attr ) -{ - int langIndex; - _SubStringIndex *subtypes; - int baseLen; - char *lang; - int nsubtypes; - int mismatch = 0; - int match = -1; - int i; - - /* Get all subtypes in the attribute name */ - langIndex = parse_subtypes( attr, &baseLen, &lang, &subtypes, &nsubtypes ); - - /* Check if there any required non-language subtypes which are - not in this attribute */ - for( i = 0; i < ntargetTypes; i++ ) { - char *t = (char *)target+targetTypes[i].start; - int tlen = targetTypes[i].length; - int j; - for( j = 0; j < nsubtypes; j++ ) { - char *a = attr + subtypes[j].start; - int alen = subtypes[j].length; - if ( (tlen == alen) && !strncasecmp( t, a, tlen ) ) - break; - } - if ( j >= nsubtypes ) { - mismatch = 1; - break; - } - } - if ( mismatch ) { - if ( NULL != subtypes ) - NSLDAPI_FREE( subtypes ); - if ( NULL != lang ) - NSLDAPI_FREE( lang ); - return -1; - } - - /* If there was no language subtype... */ - if ( langIndex < 0 ) { - if ( NULL != subtypes ) - NSLDAPI_FREE( subtypes ); - if ( NULL != lang ) - NSLDAPI_FREE( lang ); - if ( LANG_SUBTYPE_INDEX_NONE == langIndex ) - return 0; - else - return -1; - } - - /* Okay, now check the language subtag */ - i = 0; - while( targetLang[i] && lang[i] && - (toupper(targetLang[i]) == toupper(lang[i])) ) - i++; - - /* The total length can't be longer than the requested subtype */ - if ( !lang[i] || (lang[i] == ';') ) { - /* If the found subtype is shorter than the requested one, the next - character in the requested one should be "-" */ - if ( !targetLang[i] || (targetLang[i] == '-') ) - match = i; - } - return match; -} - -static int check_base_match( const char *target, char *attr ) -{ - int i = 0; - int rc; - while( target[i] && attr[i] && (toupper(target[i]) == toupper(attr[i])) ) - i++; - rc = ( !target[i] && (!attr[i] || (';' == attr[i])) ); - return rc; -} - -static void ** -internal_ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, - const char *target, char **type, int lencall ) -{ - struct berelement ber; - char *attr = NULL; - int rc; - void **vals = NULL; - int langIndex; - _SubStringIndex *subtypes; - int nsubtypes; - char *baseTarget = NULL; - int bestMatch = 0; - char *lang = NULL; - int len; - int firstAttr = 1; - char *bestType = NULL; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULL ); - } - if ( (target == NULL) || - !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( NULL ); - } - - /* A language check was requested, so see if there really is a - language subtype in the attribute spec */ - langIndex = parse_subtypes( target, &len, &lang, - &subtypes, &nsubtypes ); - if ( langIndex < 0 ) { - if ( NULL != subtypes ) { - NSLDAPI_FREE( subtypes ); - subtypes = NULL; - } - vals = internal_ldap_get_values( ld, entry, target, lencall ); - if ( NULL != type ) - *type = nsldapi_strdup( target ); - return vals; - } else { - /* Get just the base attribute name */ - baseTarget = (char *)NSLDAPI_MALLOC( len + 1 ); - memcpy( baseTarget, target, len ); - baseTarget[len] = 0; - } - - ber = *entry->lm_ber; - - /* Process all attributes in the entry */ - while ( 1 ) { - int foundMatch = 0; - if ( NULL != attr ) - NSLDAPI_FREE( attr ); - if ( firstAttr ) { - firstAttr = 0; - /* skip sequence, dn, sequence of, and snag the first attr */ - if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) { - break; - } - } else { - if ( ber_scanf( &ber, "{a", &attr ) == LBER_ERROR ) { - break; - } - } - - if ( check_base_match( (const char *)baseTarget, attr ) ) { - int thisMatch = check_lang_match( target, baseTarget, - subtypes, nsubtypes, lang, attr ); - if ( thisMatch > bestMatch ) { - if ( vals ) - NSLDAPI_FREE( vals ); - foundMatch = 1; - bestMatch = thisMatch; - if ( NULL != bestType ) - NSLDAPI_FREE( bestType ); - bestType = attr; - attr = NULL; - } - } - if ( foundMatch ) { - if ( lencall ) { - rc = ber_scanf( &ber, "[V]}", &vals ); - } else { - rc = ber_scanf( &ber, "[v]}", &vals ); - } - } else { - ber_scanf( &ber, "x}" ); - } - } - - NSLDAPI_FREE( lang ); - NSLDAPI_FREE( baseTarget ); - NSLDAPI_FREE( subtypes ); - - if ( NULL != type ) - *type = bestType; - else if ( NULL != bestType ) - NSLDAPI_FREE( bestType ); - - if ( NULL == vals ) { - rc = LDAP_DECODING_ERROR; - } else { - rc = LDAP_SUCCESS; - } - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - - return( vals ); -} - - -char ** -LDAP_CALL -ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target ) -{ - return( (char **) internal_ldap_get_values( ld, entry, target, 0 ) ); -} - -struct berval ** -LDAP_CALL -ldap_get_values_len( LDAP *ld, LDAPMessage *entry, const char *target ) -{ - return( (struct berval **) internal_ldap_get_values( ld, entry, target, - 1 ) ); -} - -char ** -LDAP_CALL -ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, const char *target, - char **type ) -{ - return( (char **) internal_ldap_get_lang_values( ld, entry, - target, type, 0 ) ); -} - -struct berval ** -LDAP_CALL -ldap_get_lang_values_len( LDAP *ld, LDAPMessage *entry, const char *target, - char **type ) -{ - return( (struct berval **) internal_ldap_get_lang_values( ld, entry, - target, type, 1 ) ); -} - diff --git a/ldap/c-sdk/libraries/libldap/ldap-int.h b/ldap/c-sdk/libraries/libldap/ldap-int.h deleted file mode 100644 index f64d1b3d3a..0000000000 --- a/ldap/c-sdk/libraries/libldap/ldap-int.h +++ /dev/null @@ -1,888 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#ifndef _LDAPINT_H -#define _LDAPINT_H - -#include -#include -#include -#include -#include -#include -#ifdef hpux -#include -#endif /* hpux */ - -#ifdef _WINDOWS -# define FD_SETSIZE 256 /* number of connections we support */ -# define WIN32_LEAN_AND_MEAN -# include -#elif defined(macintosh) -#include "ldap-macos.h" -#else /* _WINDOWS */ -# include -# include -# include -# include -#if !defined(XP_OS2) && !defined(XP_BEOS) -# include -#endif -# include -#if !defined(hpux) && !defined(SUNOS4) && !defined(XP_BEOS) -# include -#endif /* !defined(hpux) and others */ -#endif /* _WINDOWS */ - -#if defined(IRIX) -#include -#endif /* IRIX */ - -#ifdef XP_BEOS -#define NSLDAPI_AVOID_OS_SOCKETS -#endif - -#define NSLBERI_LBER_INT_FRIEND -#ifdef macintosh -#include "lber-int.h" -#else /* macintosh */ -#include "../liblber/lber-int.h" -#endif /* macintosh */ - -#include "ldap.h" -#include "ldaprot.h" -#include "ldaplog.h" -#include "portable.h" - -#ifdef LDAP_ASYNC_IO -#ifdef NEED_FILIO -#include /* to get FIONBIO for ioctl() call */ -#else /* NEED_FILIO */ -#if !defined( _WINDOWS) && !defined (macintosh) -#include /* to get FIONBIO for ioctl() call */ -#endif /* _WINDOWS && macintosh */ -#endif /* NEED_FILIO */ -#endif /* LDAP_ASYNC_IO */ - -#ifdef USE_SYSCONF -# include -#endif /* USE_SYSCONF */ - -#ifdef LDAP_SASLIO_HOOKS -#include -#define SASL_MAX_BUFF_SIZE 65536 -#define SASL_MIN_BUFF_SIZE 4096 -#endif - -#if !defined(_WINDOWS) && !defined(macintosh) && !defined(BSDI) && \ - !defined(XP_OS2) && !defined(XP_BEOS) && !defined(NTO) && \ - !defined(DARWIN) -#define NSLDAPI_HAVE_POLL 1 -#endif - -/* SSL version, or 0 if not built with SSL */ -#if defined(NET_SSL) -# define SSL_VERSION 3 -#else -# define SSL_VERSION 0 -#endif - - -#define LDAP_URL_URLCOLON "URL:" -#define LDAP_URL_URLCOLON_LEN 4 - -#define LDAP_LDAP_REF_STR LDAP_URL_PREFIX -#define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN -#define LDAP_LDAPS_REF_STR LDAPS_URL_PREFIX -#define LDAP_LDAPS_REF_STR_LEN LDAPS_URL_PREFIX_LEN - -/* default limit on nesting of referrals */ -#define LDAP_DEFAULT_REFHOPLIMIT 5 -#ifdef LDAP_DNS -#define LDAP_DX_REF_STR "dx://" -#define LDAP_DX_REF_STR_LEN 5 -#endif /* LDAP_DNS */ - -typedef enum { - LDAP_CACHE_LOCK, - LDAP_MEMCACHE_LOCK, - LDAP_MSGID_LOCK, - LDAP_REQ_LOCK, - LDAP_RESP_LOCK, - LDAP_ABANDON_LOCK, - LDAP_CTRL_LOCK, - LDAP_OPTION_LOCK, - LDAP_ERR_LOCK, - LDAP_CONN_LOCK, - LDAP_IOSTATUS_LOCK, /* serializes access to ld->ld_iostatus */ - LDAP_RESULT_LOCK, - LDAP_PEND_LOCK, - LDAP_THREADID_LOCK, -#ifdef LDAP_SASLIO_HOOKS - LDAP_SASL_LOCK, -#endif - LDAP_MAX_LOCK -} LDAPLock; - -/* - * This structure represents both ldap messages and ldap responses. - * These are really the same, except in the case of search responses, - * where a response has multiple messages. - */ - -struct ldapmsg { - int lm_msgid; /* the message id */ - ber_tag_t lm_msgtype; /* the message type */ - BerElement *lm_ber; /* the ber encoded message contents */ - struct ldapmsg *lm_chain; /* for search - next msg in the resp */ - struct ldapmsg *lm_next; /* next response */ - int lm_fromcache; /* memcache: origin of message */ -}; - -/* - * structure for tracking LDAP server host, ports, DNs, etc. - */ -typedef struct ldap_server { - char *lsrv_host; - char *lsrv_dn; /* if NULL, use default */ - int lsrv_port; - unsigned long lsrv_options; /* boolean options */ -#define LDAP_SRV_OPT_SECURE 0x01 - struct ldap_server *lsrv_next; -} LDAPServer; - -/* - * structure for representing an LDAP server connection - */ -typedef struct ldap_conn { - Sockbuf *lconn_sb; - BerElement *lconn_ber; /* non-NULL if in midst of msg. */ - int lconn_version; /* LDAP protocol version */ - int lconn_refcnt; - unsigned long lconn_lastused; /* time */ - int lconn_status; -#define LDAP_CONNST_CONNECTING 2 -#define LDAP_CONNST_CONNECTED 3 -#define LDAP_CONNST_DEAD 4 - LDAPServer *lconn_server; - char *lconn_binddn; /* DN of last successful bind */ - int lconn_bound; /* has a bind been done? */ - int lconn_pending_requests; /* count of unsent req*/ - char *lconn_krbinstance; -#ifdef LDAP_SASLIO_HOOKS - sasl_conn_t *lconn_sasl_ctx; /* the sasl connection context */ -#endif /* LDAP_SASLIO_HOOKS */ - struct ldap_conn *lconn_next; -} LDAPConn; - - -/* - * structure used to track outstanding requests - */ -typedef struct ldapreq { - int lr_msgid; /* the message id */ - int lr_status; /* status of request */ -#define LDAP_REQST_INPROGRESS 1 -#define LDAP_REQST_CHASINGREFS 2 -#define LDAP_REQST_WRITING 4 -#define LDAP_REQST_CONNDEAD 5 /* associated conn. has failed */ - int lr_outrefcnt; /* count of outstanding referrals */ - int lr_origid; /* original request's message id */ - int lr_parentcnt; /* count of parent requests */ - ber_tag_t lr_res_msgtype; /* result message type */ - int lr_expect_resp; /* if non-zero, expect a response */ - int lr_res_errno; /* result LDAP errno */ - char *lr_res_error; /* result error string */ - char *lr_res_matched;/* result matched DN string */ - BerElement *lr_ber; /* ber encoded request contents */ - LDAPConn *lr_conn; /* connection used to send request */ - char *lr_binddn; /* request is a bind for this DN */ - struct ldapreq *lr_parent; /* request that spawned this referral */ - struct ldapreq *lr_child; /* list of requests we spawned */ - struct ldapreq *lr_sibling; /* next referral spawned */ - struct ldapreq *lr_prev; /* ld->ld_requests previous request */ - struct ldapreq *lr_next; /* ld->ld_requests next request */ - LDAPControl **lr_res_ctrls; /* result controls */ -} LDAPRequest; - -typedef struct ldappend { - void *lp_sema; /* semaphore to post */ - int lp_msgid; /* message id */ - LDAPMessage *lp_result; /* result storage */ - struct ldappend *lp_prev; /* previous pending */ - struct ldappend *lp_next; /* next pending */ -} LDAPPend; - -/* - * forward declaration for I/O status structure (defined in os-ip.c) - */ -typedef struct nsldapi_iostatus_info NSLDAPIIOStatus; - -/* - * old extended IO structure (before writev callback was added) - */ -struct ldap_x_ext_io_fns_rev0 { - int lextiof_size; - LDAP_X_EXTIOF_CONNECT_CALLBACK *lextiof_connect; - LDAP_X_EXTIOF_CLOSE_CALLBACK *lextiof_close; - LDAP_X_EXTIOF_READ_CALLBACK *lextiof_read; - LDAP_X_EXTIOF_WRITE_CALLBACK *lextiof_write; - LDAP_X_EXTIOF_POLL_CALLBACK *lextiof_poll; - LDAP_X_EXTIOF_NEWHANDLE_CALLBACK *lextiof_newhandle; - LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lextiof_disposehandle; - void *lextiof_session_arg; -}; -#define LDAP_X_EXTIO_FNS_SIZE_REV0 sizeof(struct ldap_x_ext_io_fns_rev0) - - -/* - * Structure representing an ldap connection. - * - * This is an opaque struct; the fields are not visible to - * applications that use the LDAP API. - */ -struct ldap { - struct sockbuf *ld_sbp; /* pointer to socket desc. & buffer */ - char *ld_host; - int ld_version; /* LDAP protocol version */ - char ld_lberoptions; - int ld_deref; - - int ld_timelimit; - int ld_sizelimit; - - struct ldap_filt_desc *ld_filtd; /* from getfilter for ufn searches */ - char *ld_ufnprefix; /* for incomplete ufn's */ - - int ld_errno; - char *ld_error; - char *ld_matched; - int ld_msgid; - - /* Note: the ld_requests list is ordered old to new */ - LDAPRequest *ld_requests; /* list of outstanding requests */ - LDAPMessage *ld_responses; /* list of outstanding responses */ - int *ld_abandoned; /* array of abandoned requests */ - char *ld_cldapdn; /* DN used in connectionless search */ - - int ld_cldaptries; /* connectionless search retry count */ - int ld_cldaptimeout;/* time between retries */ - int ld_refhoplimit; /* limit on referral nesting */ - unsigned long ld_options; /* boolean options */ - -#define LDAP_BITOPT_REFERRALS 0x80000000 -#define LDAP_BITOPT_SSL 0x40000000 -#define LDAP_BITOPT_DNS 0x20000000 -#define LDAP_BITOPT_RESTART 0x10000000 -#define LDAP_BITOPT_RECONNECT 0x08000000 -#define LDAP_BITOPT_ASYNC 0x04000000 -#define LDAP_BITOPT_NOREBIND 0x02000000 - - char *ld_defhost; /* full name of default server */ - int ld_defport; /* port of default server */ - BERTranslateProc ld_lber_encode_translate_proc; - BERTranslateProc ld_lber_decode_translate_proc; - LDAPConn *ld_defconn; /* default connection */ - LDAPConn *ld_conns; /* list of all server connections */ - NSLDAPIIOStatus *ld_iostatus; /* status info. about network sockets */ - LDAP_REBINDPROC_CALLBACK *ld_rebind_fn; - void *ld_rebind_arg; - - /* function pointers, etc. for extended I/O */ - struct ldap_x_ext_io_fns ld_ext_io_fns; -#define ld_extio_size ld_ext_io_fns.lextiof_size -#define ld_extclose_fn ld_ext_io_fns.lextiof_close -#define ld_extconnect_fn ld_ext_io_fns.lextiof_connect -#define ld_extread_fn ld_ext_io_fns.lextiof_read -#define ld_extwrite_fn ld_ext_io_fns.lextiof_write -#define ld_extwritev_fn ld_ext_io_fns.lextiof_writev -#define ld_extpoll_fn ld_ext_io_fns.lextiof_poll -#define ld_extnewhandle_fn ld_ext_io_fns.lextiof_newhandle -#define ld_extdisposehandle_fn ld_ext_io_fns.lextiof_disposehandle -#define ld_ext_session_arg ld_ext_io_fns.lextiof_session_arg - - /* allocated pointer for older I/O functions */ - struct ldap_io_fns *ld_io_fns_ptr; -#define NSLDAPI_USING_CLASSIC_IO_FUNCTIONS( ld ) ((ld)->ld_io_fns_ptr != NULL) - - /* function pointers, etc. for DNS */ - struct ldap_dns_fns ld_dnsfn; -#define ld_dns_extradata ld_dnsfn.lddnsfn_extradata -#define ld_dns_bufsize ld_dnsfn.lddnsfn_bufsize -#define ld_dns_gethostbyname_fn ld_dnsfn.lddnsfn_gethostbyname -#define ld_dns_gethostbyaddr_fn ld_dnsfn.lddnsfn_gethostbyaddr -#define ld_dns_getpeername_fn ld_dnsfn.lddnsfn_getpeername - - /* function pointers, etc. for threading */ - struct ldap_thread_fns ld_thread; -#define ld_mutex_alloc_fn ld_thread.ltf_mutex_alloc -#define ld_mutex_free_fn ld_thread.ltf_mutex_free -#define ld_mutex_lock_fn ld_thread.ltf_mutex_lock -#define ld_mutex_unlock_fn ld_thread.ltf_mutex_unlock -#define ld_get_errno_fn ld_thread.ltf_get_errno -#define ld_set_errno_fn ld_thread.ltf_set_errno -#define ld_get_lderrno_fn ld_thread.ltf_get_lderrno -#define ld_set_lderrno_fn ld_thread.ltf_set_lderrno -#define ld_lderrno_arg ld_thread.ltf_lderrno_arg - void **ld_mutex; - - /* function pointers, etc. for caching */ - int ld_cache_on; - int ld_cache_strategy; - struct ldap_cache_fns ld_cache; -#define ld_cache_config ld_cache.lcf_config -#define ld_cache_bind ld_cache.lcf_bind -#define ld_cache_unbind ld_cache.lcf_unbind -#define ld_cache_search ld_cache.lcf_search -#define ld_cache_compare ld_cache.lcf_compare -#define ld_cache_add ld_cache.lcf_add -#define ld_cache_delete ld_cache.lcf_delete -#if 0 -#define ld_cache_rename ld_cache.lcf_rename -#endif -#define ld_cache_modify ld_cache.lcf_modify -#define ld_cache_modrdn ld_cache.lcf_modrdn -#define ld_cache_abandon ld_cache.lcf_abandon -#define ld_cache_result ld_cache.lcf_result -#define ld_cache_flush ld_cache.lcf_flush -#define ld_cache_arg ld_cache.lcf_arg - - /* ldapv3 controls */ - LDAPControl **ld_servercontrols; - LDAPControl **ld_clientcontrols; - - /* Preferred language */ - char *ld_preferred_language; - - /* MemCache */ - LDAPMemCache *ld_memcache; - - /* Pending results */ - LDAPPend *ld_pend; /* list of pending results */ - - /* extra thread function pointers */ - struct ldap_extra_thread_fns ld_thread2; - - /* - * With the 4.0 and later versions of the LDAP SDK, the extra thread - * functions except for the ld_threadid_fn have been disabled. - * Look at the release notes for the full explanation. - */ -#define ld_mutex_trylock_fn ld_thread2.ltf_mutex_trylock -#define ld_sema_alloc_fn ld_thread2.ltf_sema_alloc -#define ld_sema_free_fn ld_thread2.ltf_sema_free -#define ld_sema_wait_fn ld_thread2.ltf_sema_wait -#define ld_sema_post_fn ld_thread2.ltf_sema_post -#define ld_threadid_fn ld_thread2.ltf_threadid_fn - - /* extra data for mutex handling in referrals */ - void *ld_mutex_threadid[LDAP_MAX_LOCK]; - unsigned long ld_mutex_refcnt[LDAP_MAX_LOCK]; - - /* connect timeout value (milliseconds) */ - int ld_connect_timeout; - -#ifdef LDAP_SASLIO_HOOKS - /* SASL default option settings */ - char *ld_def_sasl_mech; - char *ld_def_sasl_realm; - char *ld_def_sasl_authcid; - char *ld_def_sasl_authzid; - /* SASL Security properties */ - struct sasl_security_properties ld_sasl_secprops; -#endif -}; - -/* allocate/free mutex */ -#define LDAP_MUTEX_ALLOC( ld ) \ - (((ld)->ld_mutex_alloc_fn != NULL) ? (ld)->ld_mutex_alloc_fn() : NULL) - -/* allocate/free mutex */ -#define LDAP_MUTEX_FREE( ld, m ) \ - if ( (ld)->ld_mutex_free_fn != NULL && m != NULL ) { \ - (ld)->ld_mutex_free_fn( m ); \ - } - -/* enter/exit critical sections */ -/* - * The locks assume that the locks are thread safe. XXXmcs: which means??? - * - * Note that we test for both ld_mutex_lock_fn != NULL AND ld_mutex != NULL. - * This is necessary because there is a window in ldap_init() between the - * time we set the ld_mutex_lock_fn pointer and the time we allocate the - * mutexes in which external code COULD be called which COULD make a call to - * something like ldap_get_option(), which uses LDAP_MUTEX_LOCK(). The - * libprldap code does this in its newhandle callback (prldap_newhandle). - */ - -#define LDAP_MUTEX_LOCK(ld, lock) \ - if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \ - if ((ld)->ld_threadid_fn != NULL) { \ - if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \ - (ld)->ld_mutex_refcnt[lock]++; \ - } else { \ - (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \ - (ld)->ld_mutex_threadid[lock] = ld->ld_threadid_fn(); \ - (ld)->ld_mutex_refcnt[lock] = 1; \ - } \ - } else { \ - (ld)->ld_mutex_lock_fn(ld->ld_mutex[lock]); \ - } \ - } - -#define LDAP_MUTEX_UNLOCK(ld, lock) \ - if ((ld)->ld_mutex_lock_fn != NULL && ld->ld_mutex != NULL) { \ - if ((ld)->ld_threadid_fn != NULL) { \ - if ((ld)->ld_mutex_threadid[lock] == (ld)->ld_threadid_fn()) { \ - (ld)->ld_mutex_refcnt[lock]--; \ - if ((ld)->ld_mutex_refcnt[lock] <= 0) { \ - (ld)->ld_mutex_threadid[lock] = (void *) -1; \ - (ld)->ld_mutex_refcnt[lock] = 0; \ - (ld)->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \ - } \ - } \ - } else { \ - ld->ld_mutex_unlock_fn(ld->ld_mutex[lock]); \ - } \ - } - -/* Backward compatibility locks */ -#define LDAP_MUTEX_BC_LOCK( ld, i ) \ - /* the ld_mutex_trylock_fn is always set to NULL */ \ - /* in setoption.c as the extra thread functions were */ \ - /* turned off in the 4.0 SDK. This check will */ \ - /* always be true */ \ - if( (ld)->ld_mutex_trylock_fn == NULL ) { \ - LDAP_MUTEX_LOCK( ld, i ) ; \ - } -#define LDAP_MUTEX_BC_UNLOCK( ld, i ) \ - /* the ld_mutex_trylock_fn is always set to NULL */ \ - /* in setoption.c as the extra thread functions were */ \ - /* turned off in the 4.0 SDK. This check will */ \ - /* always be true */ \ - if( (ld)->ld_mutex_trylock_fn == NULL ) { \ - LDAP_MUTEX_UNLOCK( ld, i ) ; \ - } - -/* allocate/free semaphore */ -#define LDAP_SEMA_ALLOC( ld ) \ - (((ld)->ld_sema_alloc_fn != NULL) ? (ld)->ld_sema_alloc_fn() : NULL) -#define LDAP_SEMA_FREE( ld, m ) \ - if ( (ld)->ld_sema_free_fn != NULL && m != NULL ) { \ - (ld)->ld_sema_free_fn( m ); \ - } - -/* wait/post binary semaphore */ -#define LDAP_SEMA_WAIT( ld, lp ) \ - if ( (ld)->ld_sema_wait_fn != NULL ) { \ - (ld)->ld_sema_wait_fn( lp->lp_sema ); \ - } -#define LDAP_SEMA_POST( ld, lp ) \ - if ( (ld)->ld_sema_post_fn != NULL ) { \ - (ld)->ld_sema_post_fn( lp->lp_sema ); \ - } -#define POST( ld, y, z ) \ - /* the ld_mutex_trylock_fn is always set to NULL */ \ - /* in setoption.c as the extra thread functions were */ \ - /* turned off in the 4.0 SDK. This check will */ \ - /* always be false */ \ - if( (ld)->ld_mutex_trylock_fn != NULL ) { \ - nsldapi_post_result( ld, y, z ); \ - } - -/* get/set errno */ -#ifndef macintosh -#define LDAP_SET_ERRNO( ld, e ) \ - if ( (ld)->ld_set_errno_fn != NULL ) { \ - (ld)->ld_set_errno_fn( e ); \ - } else { \ - errno = e; \ - } -#define LDAP_GET_ERRNO( ld ) \ - (((ld)->ld_get_errno_fn != NULL) ? \ - (ld)->ld_get_errno_fn() : errno) -#else /* macintosh */ -#define LDAP_SET_ERRNO( ld, e ) \ - if ( (ld)->ld_set_errno_fn != NULL ) { \ - (ld)->ld_set_errno_fn( e ); \ - } -#define LDAP_GET_ERRNO( ld ) \ - (((ld)->ld_get_errno_fn != NULL) ? \ - (ld)->ld_get_errno_fn() : 0) -#endif - - -/* get/set ldap-specific errno */ -#define LDAP_SET_LDERRNO( ld, e, m, s ) ldap_set_lderrno( ld, e, m, s ) -#define LDAP_GET_LDERRNO( ld, m, s ) ldap_get_lderrno( ld, m, s ) - -/* - * your standard "mimimum of two values" macro - */ -#define NSLDAPI_MIN(a, b) (((a) < (b)) ? (a) : (b)) - -/* - * handy macro to check whether LDAP struct is set up for CLDAP or not - */ -#define LDAP_IS_CLDAP( ld ) ( ld->ld_sbp->sb_naddr > 0 ) - -/* - * Some Unix error defs. Under CW 7, we can't define OTUNIXERRORS because - * it generates many conflicts with errno.h. Define what we need here. - * These need to be in sync with OpenTransport.h - */ - -#if defined(macintosh) -#define EWOULDBLOCK 35 -#define EHOSTUNREACH 65 -#endif - -/* - * handy macro to check errno "e" for an "in progress" sort of error - */ -#if defined(macintosh) || defined(_WINDOWS) -#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EAGAIN) -#else -#ifdef EAGAIN -#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EINPROGRESS || (e) == EAGAIN) -#else /* EAGAIN */ -#define NSLDAPI_ERRNO_IO_INPROGRESS( e ) ((e) == EWOULDBLOCK || (e) == EINPROGRESS) -#endif /* EAGAIN */ -#endif /* macintosh || _WINDOWS*/ - -/* - * macro to return the LDAP protocol version we are using - */ -#define NSLDAPI_LDAP_VERSION( ld ) ( (ld)->ld_defconn == NULL ? \ - (ld)->ld_version : \ - (ld)->ld_defconn->lconn_version ) - -/* - * Structures used for handling client filter lists. - */ -#define LDAP_FILT_MAXSIZ 1024 - -struct ldap_filt_list { - char *lfl_tag; - char *lfl_pattern; - char *lfl_delims; - struct ldap_filt_info *lfl_ilist; - struct ldap_filt_list *lfl_next; -}; - -struct ldap_filt_desc { - LDAPFiltList *lfd_filtlist; - LDAPFiltInfo *lfd_curfip; - LDAPFiltInfo lfd_retfi; - char lfd_filter[ LDAP_FILT_MAXSIZ ]; - char *lfd_curval; - char *lfd_curvalcopy; - char **lfd_curvalwords; - char *lfd_filtprefix; - char *lfd_filtsuffix; -}; - -/* - * "internal" globals used to track defaults and memory allocation callbacks: - * (the actual definitions are in open.c) - */ -extern struct ldap nsldapi_ld_defaults; -extern struct ldap_memalloc_fns nsldapi_memalloc_fns; -extern int nsldapi_initialized; - - -/* - * Memory allocation done in liblber should all go through one of the - * following macros. This is so we can plug-in alternative memory - * allocators, etc. as the need arises. - */ -#define NSLDAPI_MALLOC( size ) ldap_x_malloc( size ) -#define NSLDAPI_CALLOC( nelem, elsize ) ldap_x_calloc( nelem, elsize ) -#define NSLDAPI_REALLOC( ptr, size ) ldap_x_realloc( ptr, size ) -#define NSLDAPI_FREE( ptr ) ldap_x_free( ptr ) - - -/* - * macros used to check validity of data structures and parameters - */ -#define NSLDAPI_VALID_LDAP_POINTER( ld ) \ - ( (ld) != NULL ) - -#define NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm ) \ - ( (lm) != NULL ) - -#define NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( lm ) \ - ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) - -#define NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( lm ) \ - ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) - -#define NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( lm ) \ - ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_BIND ) - -#define NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( lm ) \ - ( (lm) != NULL && (lm)->lm_msgtype == LDAP_RES_EXTENDED ) - -#define NSLDAPI_VALID_LDAPMOD_ARRAY( mods ) \ - ( (mods) != NULL ) - -#define NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods ) \ - ( (mods) != NULL && (mods)[0] != NULL ) - -#define NSLDAPI_IS_SEARCH_ENTRY( code ) \ - ((code) == LDAP_RES_SEARCH_ENTRY) - -#define NSLDAPI_IS_SEARCH_RESULT( code ) \ - ((code) == LDAP_RES_SEARCH_RESULT) - -#define NSLDAPI_SEARCH_RELATED_RESULT( code ) \ - (NSLDAPI_IS_SEARCH_RESULT( code ) || NSLDAPI_IS_SEARCH_ENTRY( code )) - -/* - * in bind.c - */ -char *nsldapi_get_binddn( LDAP *ld ); - -/* - * in cache.c - */ -void nsldapi_add_result_to_cache( LDAP *ld, LDAPMessage *result ); - -/* - * in dsparse.c - */ -int nsldapi_next_line_tokens( char **bufp, long *blenp, char ***toksp ); -void nsldapi_free_strarray( char **sap ); - -/* - * in error.c - */ -int nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, - int *errcodep, char **matchednp, char **errmsgp, char ***referralsp, - LDAPControl ***serverctrlsp ); - -/* - * in open.c - */ -void nsldapi_initialize_defaults( void ); -void nsldapi_mutex_alloc_all( LDAP *ld ); -void nsldapi_mutex_free_all( LDAP *ld ); -int nsldapi_open_ldap_defconn( LDAP *ld ); -char *nsldapi_strdup( const char *s ); /* if s is NULL, returns NULL */ - -/* - * in os-ip.c - */ -int nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, - int port, int secure, char **krbinstancep ); -void nsldapi_close_connection( LDAP *ld, Sockbuf *sb ); - -int nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout ); -void nsldapi_iostatus_free( LDAP *ld ); -int nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb ); -int nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb ); -int nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb ); -int nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb ); -int nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb ); -int nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb ); -int nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns ); - -/* - * if referral.c - */ -int nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp, - LDAPControl ***serverctrlsp ); - - -/* - * in result.c - */ -int ldap_msgdelete( LDAP *ld, int msgid ); -int nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted, - struct timeval *timeout, LDAPMessage **result ); -int nsldapi_wait_result( LDAP *ld, int msgid, int all, struct timeval *timeout, - LDAPMessage **result ); -int nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result ); - -/* - * in request.c - */ -int nsldapi_send_initial_request( LDAP *ld, int msgid, unsigned long msgtype, - char *dn, BerElement *ber ); -int nsldapi_send_pending_requests_nolock( LDAP *ld, LDAPConn *lc ); -int nsldapi_alloc_ber_with_options( LDAP *ld, BerElement **berp ); -void nsldapi_set_ber_options( LDAP *ld, BerElement *ber ); -int nsldapi_send_ber_message( LDAP *ld, Sockbuf *sb, BerElement *ber, - int freeit, int epipe_handler ); -int nsldapi_send_server_request( LDAP *ld, BerElement *ber, int msgid, - LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc, - char *bindreqdn, int bind ); -LDAPConn *nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, - int connect, int bind ); -LDAPRequest *nsldapi_find_request_by_msgid( LDAP *ld, int msgid ); -LDAPRequest *nsldapi_new_request( LDAPConn *lc, BerElement *ber, int msgid, - int expect_resp ); -void nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn ); -void nsldapi_queue_request_nolock( LDAP *ld, LDAPRequest *lr ); -void nsldapi_free_connection( LDAP *ld, LDAPConn *lc, - LDAPControl **serverctrls, LDAPControl **clientctrls, - int force, int unbind ); -void nsldapi_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); -void nsldapi_dump_requests_and_responses( LDAP *ld ); -int nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, - int *totalcountp, int *chasingcountp ); -int nsldapi_chase_v3_refs( LDAP *ld, LDAPRequest *lr, char **refs, - int is_reference, int *totalcountp, int *chasingcountp ); -int nsldapi_append_referral( LDAP *ld, char **referralsp, char *s ); -void nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb ); - -#ifdef LDAP_SASLIO_HOOKS -/* - * in saslbind.c - */ -int nsldapi_sasl_is_inited(); -int nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg ); -int nsldapi_sasl_secprops( const char *in, - sasl_security_properties_t *secprops ); - -/* - * in saslio.c - */ -int nsldapi_sasl_install( LDAP *ld, LDAPConn *lconn ); -int nsldapi_sasl_open( LDAP *ld, LDAPConn *lconn, sasl_conn_t **ctx, sasl_ssf_t ssf ); - -#endif /* LDAP_SASLIO_HOOKS */ - -/* - * in search.c - */ -int nsldapi_build_search_req( LDAP *ld, const char *base, int scope, - const char *filter, char **attrs, int attrsonly, - LDAPControl **serverctrls, LDAPControl **clientctrls, - int timelimit, int sizelimit, int msgid, BerElement **berp ); - -/* - * in unbind.c - */ -int ldap_ld_free( LDAP *ld, LDAPControl **serverctrls, - LDAPControl **clientctrls, int close ); -int nsldapi_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **serverctrls, - LDAPControl **clientctrls ); - -#ifdef LDAP_DNS -/* - * in getdxbyname.c - */ -char **nsldapi_getdxbyname( char *domain ); - -#endif /* LDAP_DNS */ - -/* - * in unescape.c - */ -void nsldapi_hex_unescape( char *s ); - -/* - * in compat.c - */ -#ifdef hpux -char *nsldapi_compat_ctime_r( const time_t *clock, char *buf, int buflen ); -struct hostent *nsldapi_compat_gethostbyname_r( const char *name, - struct hostent *result, char *buffer, int buflen, int *h_errnop ); -#endif /* hpux */ - -/* - * in control.c - */ -int nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq, - BerElement *ber ); -int nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp ); -int nsldapi_find_controls( BerElement *ber, LDAPControl ***controlsp ); -int nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, - LDAPControl **newctrls ); -int nsldapi_build_control( char *oid, BerElement *ber, int freeber, - char iscritical, LDAPControl **ctrlp ); - - -/* - * in url.c - */ -int nsldapi_url_parse( const char *inurl, LDAPURLDesc **ludpp, - int dn_required ); - - -/* - * in charset.c - * - * If we ever want to expose character set translation functionality to - * users of libldap, all of these prototypes will need to be moved to ldap.h - */ -#ifdef STR_TRANSLATION -void ldap_set_string_translators( LDAP *ld, - BERTranslateProc encode_proc, BERTranslateProc decode_proc ); -int ldap_translate_from_t61( LDAP *ld, char **bufp, - unsigned long *lenp, int free_input ); -int ldap_translate_to_t61( LDAP *ld, char **bufp, - unsigned long *lenp, int free_input ); -void ldap_enable_translation( LDAP *ld, LDAPMessage *entry, - int enable ); -#ifdef LDAP_CHARSET_8859 -int ldap_t61_to_8859( char **bufp, unsigned long *buflenp, - int free_input ); -int ldap_8859_to_t61( char **bufp, unsigned long *buflenp, - int free_input ); -#endif /* LDAP_CHARSET_8859 */ -#endif /* STR_TRANSLATION */ - -/* - * in memcache.h - */ -int ldap_memcache_createkey( LDAP *ld, const char *base, int scope, - const char *filter, char **attrs, int attrsonly, - LDAPControl **serverctrls, LDAPControl **clientctrls, - unsigned long *keyp ); -int ldap_memcache_result( LDAP *ld, int msgid, unsigned long key ); -int ldap_memcache_new( LDAP *ld, int msgid, unsigned long key, - const char *basedn ); -int ldap_memcache_append( LDAP *ld, int msgid, int bLast, LDAPMessage *result ); -int ldap_memcache_abandon( LDAP *ld, int msgid ); - -/* - * in sbind.c - */ -void nsldapi_handle_reconnect( LDAP *ld ); - -#endif /* _LDAPINT_H */ diff --git a/ldap/c-sdk/libraries/libldap/libldap.def b/ldap/c-sdk/libraries/libldap/libldap.def deleted file mode 100644 index dd79389a27..0000000000 --- a/ldap/c-sdk/libraries/libldap/libldap.def +++ /dev/null @@ -1,352 +0,0 @@ -; -; ***** BEGIN LICENSE BLOCK ***** -; Version: MPL 1.1/GPL 2.0/LGPL 2. -; -; The contents of this file are subject to the Mozilla Public License Version -; 1.1 (the "License"); you may not use this file except in compliance with -; the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" basis, -; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -; for the specific language governing rights and limitations under the -; License. -; -; The Original Code is Mozilla Communicator client code. -; -; The Initial Developer of the Original Code is -; Netscape Communications Corporation. -; Portions created by the Initial Developer are Copyright (C) 1996-1999 -; the Initial Developer. All Rights Reserved. -; -; Contributor(s): -; -; Alternatively, the contents of this file may be used under the terms of -; either of the GNU General Public License Version 2 or later (the "GPL"), -; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -; in which case the provisions of the GPL or the LGPL are applicable instead -; of those above. If you wish to allow use of your version of this file only -; under the terms of either the GPL or the LGPL, and not to allow others to -; use your version of this file under the terms of the MPL, indicate your -; decision by deleting the provisions above and replace them with the notice -; and other provisions required by the GPL or the LGPL. If you do not delete -; the provisions above, a recipient may use your version of this file under -; the terms of any one of the MPL, the GPL or the LGPL. -; -; ***** END LICENSE BLOCK ***** - -LIBRARY LDAP60 -VERSION 6.0 -HEAPSIZE 4096 - -EXPORTS -; exports list (generated by genexports.pl) -; - ldap_abandon - ldap_add - ldap_unbind - -; ldap_enable_cache -; ldap_disable_cache -; ldap_destroy_cache -; ldap_flush_cache -; ldap_uncache_entry - - ldap_compare - ldap_delete - ldap_result2error - ldap_err2string - ldap_modify - ldap_modrdn - ldap_open - ldap_first_entry - ldap_next_entry - ldap_get_dn - ldap_dn2ufn - ldap_first_attribute - ldap_next_attribute - ldap_get_values - ldap_get_values_len - ldap_count_entries - ldap_count_values - ldap_value_free - ldap_explode_dn - ldap_result - ldap_msgfree - ldap_search - ldap_add_s - ldap_bind_s - ldap_unbind_s - ldap_delete_s - ldap_modify_s - ldap_modrdn_s - ldap_search_s - ldap_search_st - ldap_compare_s - ldap_ufn_search_c - ldap_ufn_search_s - ldap_init_getfilter - ldap_getfilter_free - ldap_getfirstfilter - ldap_getnextfilter - ldap_simple_bind - ldap_simple_bind_s - ldap_bind - ldap_friendly_name - ldap_free_friendlymap - ldap_ufn_search_ct - -; ldap_set_cache_options -; ldap_uncache_request - - ldap_modrdn2 - ldap_modrdn2_s - ldap_ufn_setfilter - ldap_ufn_setprefix - ldap_ufn_timeout - ldap_init_getfilter_buf - ldap_setfilteraffixes - ldap_sort_entries - ldap_sort_values - ldap_sort_strcasecmp - ldap_count_values_len - ldap_name2template - ldap_value_free_len - -; manually comment and uncomment these five as necessary -; ldap_kerberos_bind1 -; ldap_kerberos_bind2 -; ldap_kerberos_bind_s -; ldap_kerberos_bind1_s -; ldap_kerberos_bind2_s - - ldap_init - ldap_is_dns_dn - ldap_explode_dns - ldap_mods_free - - ldap_is_ldap_url - ldap_free_urldesc - ldap_url_parse - ldap_url_search - ldap_url_search_s - ldap_url_search_st - ldap_set_rebind_proc - ber_skip_tag - ber_peek_tag - ber_get_int - ber_get_stringb - ber_get_stringa - ber_get_stringal - ber_get_bitstringa - ber_get_null - ber_get_boolean - ber_first_element - ber_next_element - ber_scanf - ber_bvfree - ber_bvecfree - ber_put_int - ber_put_ostring - ber_put_string - ber_put_bitstring - ber_put_null - ber_put_boolean - ber_start_seq - ber_start_set - ber_put_seq - ber_put_set - ber_printf - ber_read - ber_write - ber_free - ber_flush - ber_alloc - ber_dup - ber_get_next - ber_get_tag - ber_put_enum - der_alloc - ber_alloc_t - ber_bvdup - ber_init_w_nullchar - ber_reset - ber_get_option - ber_set_option - ber_sockbuf_alloc - ber_sockbuf_get_option - ber_sockbuf_set_option - ber_init - ber_flatten - ber_special_alloc - ber_special_free - ber_get_next_buffer - ber_err_print - ber_sockbuf_free - ber_get_next_buffer_ext - ber_svecfree - ber_get_buf_datalen - ber_get_buf_databegin - ber_stack_init - ber_sockbuf_free_data - - ldap_memfree - ldap_ber_free - - ldap_init_searchprefs - ldap_init_searchprefs_buf - ldap_free_searchprefs - ldap_first_searchobj - ldap_next_searchobj - ldap_build_filter - - 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_entry2text_search - ldap_entry2text - ldap_vals2text - ldap_entry2html - ldap_entry2html_search - ldap_vals2html - ldap_tmplerr2string - ldap_set_option - ldap_get_option - ldap_charray_merge - ldap_get_lderrno - ldap_set_lderrno - ldap_perror - ldap_set_filter_additions - ldap_create_filter - ldap_version - ldap_multisort_entries - ldap_msgid - ldap_explode_rdn - ldap_msgtype - ldap_cache_flush - ldap_str2charray - ldap_charray_add - ldap_charray_dup - ldap_charray_free - -; Windows ordinals 450-469 are reserved for SSL routines - - ldap_charray_inlist - ldap_charray_position - ldap_rename - ldap_rename_s - ldap_utf8len - ldap_utf8next - ldap_utf8prev - ldap_utf8copy - ldap_utf8characters - ldap_utf8strtok_r - ldap_utf8isalnum - ldap_utf8isalpha - ldap_utf8isdigit - ldap_utf8isxdigit - ldap_utf8isspace - ldap_control_free - ldap_controls_free - ldap_sasl_bind - ldap_sasl_bind_s - ldap_parse_sasl_bind_result - ldap_sasl_interactive_bind_s - ldap_sasl_interactive_bind_ext_s -; LDAPv3 simple paging controls are not supported by Netscape at this time. -; 490 ldap_create_page_control -; 491 ldap_parse_page_control - ldap_create_sort_control - ldap_parse_sort_control -; an LDAPv3 language control was proposed but then retracted. -; 494 ldap_create_language_control - ldap_get_lang_values - ldap_get_lang_values_len - ldap_free_sort_keylist - ldap_create_sort_keylist - ldap_utf8getcc - ldap_get_entry_controls - ldap_create_persistentsearch_control - ldap_parse_entrychange_control - ldap_parse_result - ldap_parse_extended_result - ldap_parse_reference - ldap_abandon_ext - ldap_add_ext - ldap_add_ext_s - ldap_modify_ext - ldap_modify_ext_s - ldap_first_message - ldap_next_message - ldap_compare_ext - ldap_compare_ext_s - ldap_delete_ext - ldap_delete_ext_s - ldap_search_ext - ldap_search_ext_s - ldap_extended_operation - ldap_extended_operation_s - ldap_first_reference - ldap_next_reference - ldap_count_references - ldap_count_messages - ldap_create_virtuallist_control - ldap_parse_virtuallist_control - ldap_create_proxyauth_control - ldap_unbind_ext - ldap_x_hostlist_first - ldap_x_hostlist_next - ldap_x_hostlist_statusfree - ldap_x_malloc - ldap_x_calloc - ldap_x_realloc - ldap_x_free -; - ldap_create_proxiedauth_control -; - ldap_create_geteffectiveRights_control -; - ldap_find_control -; - ldap_url_parse_no_defaults -; - ldap_create_userstatus_control - ldap_parse_userstatus_control -; - ldap_create_passwordpolicy_control - ldap_create_passwordpolicy_control_ext - ldap_parse_passwordpolicy_control - ldap_parse_passwordpolicy_control_ext - ldap_passwordpolicy_err2txt -; - ldap_passwd - ldap_parse_passwd - ldap_passwd_s -; - ldap_delete_result_entry - ldap_add_result_entry -; - ldap_whoami - ldap_parse_whoami - ldap_whoami_s -; - ldap_create_authzid_control - ldap_parse_authzid_control -; - ldap_memcache_init - ldap_memcache_set - ldap_memcache_get - ldap_memcache_flush - ldap_memcache_destroy - ldap_memcache_update - ldap_keysort_entries -; -; end of generated exports list. diff --git a/ldap/c-sdk/libraries/libldap/memcache.c b/ldap/c-sdk/libraries/libldap/memcache.c deleted file mode 100644 index 78943408aa..0000000000 --- a/ldap/c-sdk/libraries/libldap/memcache.c +++ /dev/null @@ -1,2244 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * - * memcache.c - routines that implement an in-memory cache. - * - * To Do: 1) ber_dup_ext(). - * 2) referrals and reference? - */ - -#include -#include "ldap-int.h" - -/* - * Extra size allocated to BerElement. - * XXXmcs: must match EXBUFSIZ in liblber/io.c? - */ -#define EXTRA_SIZE 1024 - -/* Mode constants for function memcache_access() */ -#define MEMCACHE_ACCESS_ADD 0 -#define MEMCACHE_ACCESS_APPEND 1 -#define MEMCACHE_ACCESS_APPEND_LAST 2 -#define MEMCACHE_ACCESS_FIND 3 -#define MEMCACHE_ACCESS_DELETE 4 -#define MEMCACHE_ACCESS_DELETE_ALL 5 -#define MEMCACHE_ACCESS_UPDATE 6 -#define MEMCACHE_ACCESS_FLUSH 7 -#define MEMCACHE_ACCESS_FLUSH_ALL 8 -#define MEMCACHE_ACCESS_FLUSH_LRU 9 -#define MEMCACHE_ACCESS_FLUSH_RESULTS 10 - -/* Mode constants for function memcache_adj_size */ -#define MEMCACHE_SIZE_DEDUCT 0 -#define MEMCACHE_SIZE_ADD 1 - -#define MEMCACHE_SIZE_ENTRIES 1 -#define MEMCACHE_SIZE_NON_ENTRIES 2 - -/* Size used for calculation if given size of cache is 0 */ -#define MEMCACHE_DEF_SIZE 131072 /* 128K bytes */ - -/* Index into different list structure */ -#define LIST_TTL 0 -#define LIST_LRU 1 -#define LIST_TMP 2 -#define LIST_TOTAL 3 - -/* Macros to make code more readable */ -#define NSLDAPI_VALID_MEMCACHE_POINTER( cp ) ( (cp) != NULL ) -#define NSLDAPI_STR_NONNULL( s ) ( (s) ? (s) : "" ) -#define NSLDAPI_SAFE_STRLEN( s ) ( (s) ? strlen((s)) + 1 : 1 ) - -/* Macros dealing with mutex */ -#define LDAP_MEMCACHE_MUTEX_LOCK( c ) \ - if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_lock ) { \ - ((c)->ldmemc_lock_fns).ltf_mutex_lock( (c)->ldmemc_lock ); \ - } - -#define LDAP_MEMCACHE_MUTEX_UNLOCK( c ) \ - if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_unlock ) { \ - ((c)->ldmemc_lock_fns).ltf_mutex_unlock( (c)->ldmemc_lock ); \ - } - -#define LDAP_MEMCACHE_MUTEX_ALLOC( c ) \ - ((c) && ((c)->ldmemc_lock_fns).ltf_mutex_alloc ? \ - ((c)->ldmemc_lock_fns).ltf_mutex_alloc() : NULL) - -#define LDAP_MEMCACHE_MUTEX_FREE( c ) \ - if ( (c) && ((c)->ldmemc_lock_fns).ltf_mutex_free ) { \ - ((c)->ldmemc_lock_fns).ltf_mutex_free( (c)->ldmemc_lock ); \ - } - -/* Macros used for triming unnecessary spaces in a basedn */ -#define NSLDAPI_IS_SPACE( c ) \ - (((c) == ' ') || ((c) == '\t') || ((c) == '\n')) - -#define NSLDAPI_IS_SEPARATER( c ) \ - ((c) == ',') - -/* Hash table callback function pointer definition */ -typedef int (*HashFuncPtr)(int table_size, void *key); -typedef int (*PutDataPtr)(void **ppTableData, void *key, void *pData); -typedef int (*GetDataPtr)(void *pTableData, void *key, void **ppData); -typedef int (*RemoveDataPtr)(void **ppTableData, void *key, void **ppData); -typedef int (*MiscFuncPtr)(void **ppTableData, void *key, void *pData); -typedef void (*ClrTableNodePtr)(void **ppTableData, void *pData); - -/* Structure of a node in a hash table */ -typedef struct HashTableNode_struct { - void *pData; -} HashTableNode; - -/* Structure of a hash table */ -typedef struct HashTable_struct { - HashTableNode *table; - int size; - HashFuncPtr hashfunc; - PutDataPtr putdata; - GetDataPtr getdata; - MiscFuncPtr miscfunc; - RemoveDataPtr removedata; - ClrTableNodePtr clrtablenode; -} HashTable; - -/* Structure uniquely identifies a search request */ -typedef struct ldapmemcacheReqId_struct { - LDAP *ldmemcrid_ld; - int ldmemcrid_msgid; -} ldapmemcacheReqId; - -/* Structure representing a ldap handle associated to memcache */ -typedef struct ldapmemcacheld_struct { - LDAP *ldmemcl_ld; - struct ldapmemcacheld_struct *ldmemcl_next; -} ldapmemcacheld; - -/* Structure representing header of a search result */ -typedef struct ldapmemcacheRes_struct { - char *ldmemcr_basedn; - unsigned long ldmemcr_crc_key; - unsigned long ldmemcr_resSize; - unsigned long ldmemcr_timestamp; - LDAPMessage *ldmemcr_resHead; - LDAPMessage *ldmemcr_resTail; - ldapmemcacheReqId ldmemcr_req_id; - struct ldapmemcacheRes_struct *ldmemcr_next[LIST_TOTAL]; - struct ldapmemcacheRes_struct *ldmemcr_prev[LIST_TOTAL]; - struct ldapmemcacheRes_struct *ldmemcr_htable_next; -} ldapmemcacheRes; - -/* Structure for memcache statistics */ -typedef struct ldapmemcacheStats_struct { - unsigned long ldmemcstat_tries; - unsigned long ldmemcstat_hits; -} ldapmemcacheStats; - -/* Structure of a memcache object */ -struct ldapmemcache { - unsigned long ldmemc_ttl; - unsigned long ldmemc_size; - unsigned long ldmemc_size_used; - unsigned long ldmemc_size_entries; - char **ldmemc_basedns; - void *ldmemc_lock; - ldapmemcacheld *ldmemc_lds; - HashTable *ldmemc_resTmp; - HashTable *ldmemc_resLookup; - ldapmemcacheRes *ldmemc_resHead[LIST_TOTAL]; - ldapmemcacheRes *ldmemc_resTail[LIST_TOTAL]; - struct ldap_thread_fns ldmemc_lock_fns; - ldapmemcacheStats ldmemc_stats; -}; - -/* Function prototypes */ -static int memcache_exist(LDAP *ld); -static int memcache_add_to_ld(LDAP *ld, int msgid, LDAPMessage *pMsg); -static int memcache_compare_dn(const char *main_dn, const char *dn, int scope); -static int memcache_dup_message(LDAPMessage *res, int msgid, int fromcache, - LDAPMessage **ppResCopy, unsigned long *pSize); -static BerElement* memcache_ber_dup(BerElement* pBer, unsigned long *pSize); - -static void memcache_trim_basedn_spaces(char *basedn); -static int memcache_validate_basedn(LDAPMemCache *cache, const char *basedn); -static int memcache_get_ctrls_len(LDAPControl **ctrls); -static void memcache_append_ctrls(char *buf, LDAPControl **serverCtrls, - LDAPControl **clientCtrls); -static int memcache_adj_size(LDAPMemCache *cache, unsigned long size, - int usageFlags, int bAdd); -static int memcache_free_entry(LDAPMemCache *cache, ldapmemcacheRes *pRes); -static int memcache_expired(LDAPMemCache *cache, ldapmemcacheRes *pRes, - unsigned long curTime); -static int memcache_add_to_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, - int index); -static int memcache_add_res_to_list(ldapmemcacheRes *pRes, LDAPMessage *pMsg, - unsigned long size); -static int memcache_free_from_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, - int index); -static int memcache_search(LDAP *ld, unsigned long key, LDAPMessage **ppRes); -static int memcache_add(LDAP *ld, unsigned long key, int msgid, - const char *basedn); -static int memcache_append(LDAP *ld, int msgid, LDAPMessage *pRes); -static int memcache_append_last(LDAP *ld, int msgid, LDAPMessage *pRes); -static int memcache_remove(LDAP *ld, int msgid); -#if 0 /* function not used */ -static int memcache_remove_all(LDAP *ld); -#endif /* 0 */ -static int memcache_access(LDAPMemCache *cache, int mode, - void *pData1, void *pData2, void *pData3); -static void memcache_flush(LDAPMemCache *cache, char *dn, int scope, - int flushresults); -#ifdef LDAP_DEBUG -static void memcache_print_list( LDAPMemCache *cache, int index ); -static void memcache_report_statistics( LDAPMemCache *cache ); -#endif /* LDAP_DEBUG */ - -static int htable_calculate_size(int sizelimit); -static int htable_sizeinbytes(HashTable *pTable); -static int htable_put(HashTable *pTable, void *key, void *pData); -static int htable_get(HashTable *pTable, void *key, void **ppData); -static int htable_misc(HashTable *pTable, void *key, void *pData); -static int htable_remove(HashTable *pTable, void *key, void **ppData); -static int htable_removeall(HashTable *pTable, void *pData); -static int htable_create(int size_limit, HashFuncPtr hashf, - PutDataPtr putDataf, GetDataPtr getDataf, - RemoveDataPtr removeDataf, ClrTableNodePtr clrNodef, - MiscFuncPtr miscOpf, HashTable **ppTable); -static int htable_free(HashTable *pTable); - -static int msgid_hashf(int table_size, void *key); -static int msgid_putdata(void **ppTableData, void *key, void *pData); -static int msgid_getdata(void *pTableData, void *key, void **ppData); -static int msgid_removedata(void **ppTableData, void *key, void **ppData); -static int msgid_clear_ld_items(void **ppTableData, void *key, void *pData); -static void msgid_clearnode(void **ppTableData, void *pData); - -static int attrkey_hashf(int table_size, void *key); -static int attrkey_putdata(void **ppTableData, void *key, void *pData); -static int attrkey_getdata(void *pTableData, void *key, void **ppData); -static int attrkey_removedata(void **ppTableData, void *key, void **ppData); -static void attrkey_clearnode(void **ppTableData, void *pData); - -static unsigned long crc32_convert(char *buf, int len); - -/* Create a memcache object. */ -int -LDAP_CALL -ldap_memcache_init( unsigned long ttl, unsigned long size, - char **baseDNs, struct ldap_thread_fns *thread_fns, - LDAPMemCache **cachep ) -{ - unsigned long total_size = 0; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_init\n", 0, 0, 0 ); - - if ( cachep == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - if ((*cachep = (LDAPMemCache*)NSLDAPI_CALLOC(1, - sizeof(LDAPMemCache))) == NULL) { - return ( LDAP_NO_MEMORY ); - } - - total_size += sizeof(LDAPMemCache); - - (*cachep)->ldmemc_ttl = ttl; - (*cachep)->ldmemc_size = size; - (*cachep)->ldmemc_lds = NULL; - - /* Non-zero default size needed for calculating size of hash tables */ - size = (size ? size : MEMCACHE_DEF_SIZE); - - if (thread_fns) { - memcpy(&((*cachep)->ldmemc_lock_fns), thread_fns, - sizeof(struct ldap_thread_fns)); - } else { - memset(&((*cachep)->ldmemc_lock_fns), 0, - sizeof(struct ldap_thread_fns)); - } - - (*cachep)->ldmemc_lock = LDAP_MEMCACHE_MUTEX_ALLOC( *cachep ); - - /* Cache basedns */ - if (baseDNs != NULL) { - - int i; - - for (i = 0; baseDNs[i]; i++) { - ; - } - - (*cachep)->ldmemc_basedns = (char**)NSLDAPI_CALLOC(i + 1, - sizeof(char*)); - - if ((*cachep)->ldmemc_basedns == NULL) { - ldap_memcache_destroy(*cachep); - *cachep = NULL; - return ( LDAP_NO_MEMORY ); - } - - total_size += (i + 1) * sizeof(char*); - - for (i = 0; baseDNs[i]; i++) { - (*cachep)->ldmemc_basedns[i] = nsldapi_strdup(baseDNs[i]); - total_size += strlen(baseDNs[i]) + 1; - } - - (*cachep)->ldmemc_basedns[i] = NULL; - } - - /* Create hash table for temporary cache */ - if (htable_create(size, msgid_hashf, msgid_putdata, msgid_getdata, - msgid_removedata, msgid_clearnode, msgid_clear_ld_items, - &((*cachep)->ldmemc_resTmp)) != LDAP_SUCCESS) { - ldap_memcache_destroy(*cachep); - *cachep = NULL; - return( LDAP_NO_MEMORY ); - } - - total_size += htable_sizeinbytes((*cachep)->ldmemc_resTmp); - - /* Create hash table for primary cache */ - if (htable_create(size, attrkey_hashf, attrkey_putdata, - attrkey_getdata, attrkey_removedata, attrkey_clearnode, - NULL, &((*cachep)->ldmemc_resLookup)) != LDAP_SUCCESS) { - ldap_memcache_destroy(*cachep); - *cachep = NULL; - return( LDAP_NO_MEMORY ); - } - - total_size += htable_sizeinbytes((*cachep)->ldmemc_resLookup); - - /* See if there is enough room so far */ - if (memcache_adj_size(*cachep, total_size, MEMCACHE_SIZE_NON_ENTRIES, - MEMCACHE_SIZE_ADD) != LDAP_SUCCESS) { - ldap_memcache_destroy(*cachep); - *cachep = NULL; - return( LDAP_SIZELIMIT_EXCEEDED ); - } - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_init new cache 0x%p\n", - *cachep, 0, 0 ); - - return( LDAP_SUCCESS ); -} - -/* Associates a ldap handle to a memcache object. */ -int -LDAP_CALL -ldap_memcache_set( LDAP *ld, LDAPMemCache *cache ) -{ - int nRes = LDAP_SUCCESS; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_set\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) - return( LDAP_PARAM_ERROR ); - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - - if (ld->ld_memcache != cache) { - - LDAPMemCache *c = ld->ld_memcache; - ldapmemcacheld *pCur = NULL; - ldapmemcacheld *pPrev = NULL; - - /* First dissociate handle from old cache */ - - LDAP_MEMCACHE_MUTEX_LOCK( c ); - - pCur = (c ? c->ldmemc_lds : NULL); - for (; pCur; pCur = pCur->ldmemcl_next) { - if (pCur->ldmemcl_ld == ld) - break; - pPrev = pCur; - } - - if (pCur) { - - ldapmemcacheReqId reqid; - - reqid.ldmemcrid_ld = ld; - reqid.ldmemcrid_msgid = -1; - htable_misc(c->ldmemc_resTmp, (void*)&reqid, (void*)c); - - if (pPrev) - pPrev->ldmemcl_next = pCur->ldmemcl_next; - else - c->ldmemc_lds = pCur->ldmemcl_next; - NSLDAPI_FREE(pCur); - pCur = NULL; - - memcache_adj_size(c, sizeof(ldapmemcacheld), - MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_DEDUCT); - } - - LDAP_MEMCACHE_MUTEX_UNLOCK( c ); - - ld->ld_memcache = NULL; - - /* Exit if no new cache is specified */ - if (cache == NULL) { - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - return( LDAP_SUCCESS ); - } - - /* Then associate handle with new cache */ - - LDAP_MEMCACHE_MUTEX_LOCK( cache ); - - if ((nRes = memcache_adj_size(cache, sizeof(ldapmemcacheld), - MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_ADD)) != LDAP_SUCCESS) { - LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - return nRes; - } - - pCur = (ldapmemcacheld*)NSLDAPI_CALLOC(1, sizeof(ldapmemcacheld)); - if (pCur == NULL) { - memcache_adj_size(cache, sizeof(ldapmemcacheld), - MEMCACHE_SIZE_NON_ENTRIES, MEMCACHE_SIZE_DEDUCT); - nRes = LDAP_NO_MEMORY; - } else { - pCur->ldmemcl_ld = ld; - pCur->ldmemcl_next = cache->ldmemc_lds; - cache->ldmemc_lds = pCur; - ld->ld_memcache = cache; - } - - LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return nRes; -} - -/* Retrieves memcache with which the ldap handle has been associated. */ -int -LDAP_CALL -ldap_memcache_get( LDAP *ld, LDAPMemCache **cachep ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_get ld: 0x%p\n", ld, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || cachep == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - *cachep = ld->ld_memcache; - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return( LDAP_SUCCESS ); -} - -/* - * Function that stays inside libldap and proactively expires items from - * the given cache. This should be called from a newly created thread since - * it will not return until after ldap_memcache_destroy() is called. - */ -void -LDAP_CALL -ldap_memcache_update( LDAPMemCache *cache ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_update: cache 0x%p\n", - cache, 0, 0 ); - - if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { - return; - } - - LDAP_MEMCACHE_MUTEX_LOCK( cache ); - memcache_access(cache, MEMCACHE_ACCESS_UPDATE, NULL, NULL, NULL); - LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); -} - -/* Removes specified entries from given memcache. Only clears out search - results that included search entries. */ -void -LDAP_CALL -ldap_memcache_flush( LDAPMemCache *cache, char *dn, int scope ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_flush( cache: 0x%p, dn: %s, scope: %d)\n", - cache, ( dn == NULL ) ? "(null)" : dn, scope ); - memcache_flush(cache, dn, scope, 0 /* Don't use result flush mode */); -} - -/* Removes specified entries from given memcache, including search - results that returned no entries. */ -void -LDAP_CALL -ldap_memcache_flush_results( LDAPMemCache *cache, char *dn, int scope ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_flush_results( cache: 0x%p, dn: %s, scope: %d)\n", - cache, ( dn == NULL ) ? "(null)" : dn, scope ); - memcache_flush(cache, dn, scope, 1 /* Use result flush mode */); -} - -/* Destroys the given memcache. */ -void -LDAP_CALL -ldap_memcache_destroy( LDAPMemCache *cache ) -{ - int i = 0; - unsigned long size = sizeof(LDAPMemCache); - ldapmemcacheld *pNode = NULL, *pNextNode = NULL; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_destroy( 0x%p )\n", - cache, 0, 0 ); - - if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { - return; - } - - /* Dissociate all ldap handes from this cache. */ - LDAP_MEMCACHE_MUTEX_LOCK( cache ); - - for (pNode = cache->ldmemc_lds; pNode; pNode = pNextNode, i++) { - LDAP_MUTEX_LOCK( pNode->ldmemcl_ld, LDAP_MEMCACHE_LOCK ); - cache->ldmemc_lds = pNode->ldmemcl_next; - pNode->ldmemcl_ld->ld_memcache = NULL; - LDAP_MUTEX_UNLOCK( pNode->ldmemcl_ld, LDAP_MEMCACHE_LOCK ); - pNextNode = pNode->ldmemcl_next; - NSLDAPI_FREE(pNode); - } - - size += i * sizeof(ldapmemcacheld); - - LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); - - /* Free array of basedns */ - if (cache->ldmemc_basedns) { - for (i = 0; cache->ldmemc_basedns[i]; i++) { - size += strlen(cache->ldmemc_basedns[i]) + 1; - NSLDAPI_FREE(cache->ldmemc_basedns[i]); - } - size += (i + 1) * sizeof(char*); - NSLDAPI_FREE(cache->ldmemc_basedns); - } - - /* Free hash table used for temporary cache */ - if (cache->ldmemc_resTmp) { - size += htable_sizeinbytes(cache->ldmemc_resTmp); - memcache_access(cache, MEMCACHE_ACCESS_DELETE_ALL, NULL, NULL, NULL); - htable_free(cache->ldmemc_resTmp); - } - - /* Free hash table used for primary cache */ - if (cache->ldmemc_resLookup) { - size += htable_sizeinbytes(cache->ldmemc_resLookup); - memcache_access(cache, MEMCACHE_ACCESS_FLUSH_ALL, NULL, NULL, NULL); - htable_free(cache->ldmemc_resLookup); - } - - memcache_adj_size(cache, size, MEMCACHE_SIZE_NON_ENTRIES, - MEMCACHE_SIZE_DEDUCT); - - LDAP_MEMCACHE_MUTEX_FREE( cache ); - - NSLDAPI_FREE(cache); -} - -/************************* Internal API Functions ****************************/ - -/* Creates an integer key by applying the Cyclic Reduntency Check algorithm on - a long string formed by concatenating all the search parameters plus the - current bind DN. The key is used in the cache for looking up cached - entries. It is assumed that the CRC algorithm will generate - different integers from different byte strings. */ -int -ldap_memcache_createkey(LDAP *ld, const char *base, int scope, - const char *filter, char **attrs, - int attrsonly, LDAPControl **serverctrls, - LDAPControl **clientctrls, unsigned long *keyp) -{ - int nRes, i, j, i_smallest; - int len; - int defport; - char buf[50]; - char *tmp, *defhost, *binddn, *keystr, *tmpbase; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (keyp == NULL) ) - return( LDAP_PARAM_ERROR ); - - *keyp = 0; - - if (!memcache_exist(ld)) - return( LDAP_LOCAL_ERROR ); - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); - nRes = memcache_validate_basedn(ld->ld_memcache, base); - LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - if (nRes != LDAP_SUCCESS) - return nRes; - - defhost = NSLDAPI_STR_NONNULL(ld->ld_defhost); - defport = ld->ld_defport; - tmpbase = nsldapi_strdup(NSLDAPI_STR_NONNULL(base)); - memcache_trim_basedn_spaces(tmpbase); - - if ((binddn = nsldapi_get_binddn(ld)) == NULL) - binddn = ""; - - sprintf(buf, "%i\n%i\n%i\n", defport, scope, (attrsonly ? 1 : 0)); - len = NSLDAPI_SAFE_STRLEN(buf) + NSLDAPI_SAFE_STRLEN(tmpbase) + - NSLDAPI_SAFE_STRLEN(filter) + NSLDAPI_SAFE_STRLEN(defhost) + - NSLDAPI_SAFE_STRLEN(binddn); - - if (attrs) { - for (i = 0; attrs[i]; i++) { - - for (i_smallest = j = i; attrs[j]; j++) { - if (strcasecmp(attrs[i_smallest], attrs[j]) > 0) - i_smallest = j; - } - - if (i != i_smallest) { - tmp = attrs[i]; - attrs[i] = attrs[i_smallest]; - attrs[i_smallest] = tmp; - } - - len += NSLDAPI_SAFE_STRLEN(attrs[i]); - } - } else { - len += 1; - } - - len += memcache_get_ctrls_len(serverctrls) + - memcache_get_ctrls_len(clientctrls) + 1; - - if ((keystr = (char*)NSLDAPI_CALLOC(len, sizeof(char))) == NULL) { - NSLDAPI_FREE(defhost); - return( LDAP_NO_MEMORY ); - } - - sprintf(keystr, "%s\n%s\n%s\n%s\n%s\n", binddn, tmpbase, - NSLDAPI_STR_NONNULL(defhost), NSLDAPI_STR_NONNULL(filter), - NSLDAPI_STR_NONNULL(buf)); - - if (attrs) { - for (i = 0; attrs[i]; i++) { - strcat(keystr, NSLDAPI_STR_NONNULL(attrs[i])); - strcat(keystr, "\n"); - } - } else { - strcat(keystr, "\n"); - } - - for (tmp = keystr; *tmp; - *tmp += (*tmp >= 'a' && *tmp <= 'z' ? 'A'-'a' : 0), tmp++) { - ; - } - - memcache_append_ctrls(keystr, serverctrls, clientctrls); - - /* CRC algorithm */ - *keyp = crc32_convert(keystr, len); - - NSLDAPI_FREE(keystr); - NSLDAPI_FREE(tmpbase); - - return LDAP_SUCCESS; -} - -/* Searches the cache for the right cached entries, and if found, attaches - them to the given ldap handle. This function relies on locking by the - caller. */ -int -ldap_memcache_result(LDAP *ld, int msgid, unsigned long key) -{ - int nRes; - LDAPMessage *pMsg = NULL; - - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_result( ld: 0x%p, msgid: %d, key: 0x%8.8lx)\n", - ld, msgid, key ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (msgid < 0) ) { - return( LDAP_PARAM_ERROR ); - } - - if (!memcache_exist(ld)) { - return( LDAP_LOCAL_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); - - /* Search the cache and append the results to ld if found */ - ++ld->ld_memcache->ldmemc_stats.ldmemcstat_tries; - if ((nRes = memcache_search(ld, key, &pMsg)) == LDAP_SUCCESS) { - nRes = memcache_add_to_ld(ld, msgid, pMsg); - ++ld->ld_memcache->ldmemc_stats.ldmemcstat_hits; - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_result: key 0x%8.8lx found in cache\n", - key, 0, 0 ); - } else { - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_result: key 0x%8.8lx not found in cache\n", - key, 0, 0 ); - } - -#ifdef LDAP_DEBUG - memcache_print_list( ld->ld_memcache, LIST_LRU ); - memcache_report_statistics( ld->ld_memcache ); -#endif /* LDAP_DEBUG */ - - LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return nRes; -} - -/* Creates a new header in the cache so that entries arriving from the - directory server can later be cached under the header. */ -int -ldap_memcache_new(LDAP *ld, int msgid, unsigned long key, const char *basedn) -{ - int nRes; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - - if (!memcache_exist(ld)) { - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - return( LDAP_LOCAL_ERROR ); - } - - LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); - nRes = memcache_add(ld, key, msgid, basedn); - LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return nRes; -} - -/* Appends a chain of entries to an existing cache header. Parameter "bLast" - indicates whether there will be more entries arriving for the search in - question. */ -int -ldap_memcache_append(LDAP *ld, int msgid, int bLast, LDAPMessage *result) -{ - int nRes = LDAP_SUCCESS; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_memcache_append( ld: 0x%p, ", ld, 0, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, "msgid %d, bLast: %d, result: 0x%p)\n", - msgid, bLast, result ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || !result ) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - - if (!memcache_exist(ld)) { - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - return( LDAP_LOCAL_ERROR ); - } - - LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); - - if (!bLast) - nRes = memcache_append(ld, msgid, result); - else - nRes = memcache_append_last(ld, msgid, result); - - LDAPDebug( LDAP_DEBUG_TRACE, - "ldap_memcache_append: %s result for msgid %d\n", - ( nRes == LDAP_SUCCESS ) ? "added" : "failed to add", msgid , 0 ); - - LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return nRes; -} - -/* Removes partially cached results for a search as a result of calling - ldap_abandon() by the client. */ -int -ldap_memcache_abandon(LDAP *ld, int msgid) -{ - int nRes; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || (msgid < 0) ) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MEMCACHE_LOCK ); - - if (!memcache_exist(ld)) { - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - return( LDAP_LOCAL_ERROR ); - } - - LDAP_MEMCACHE_MUTEX_LOCK( ld->ld_memcache ); - nRes = memcache_remove(ld, msgid); - LDAP_MEMCACHE_MUTEX_UNLOCK( ld->ld_memcache ); - LDAP_MUTEX_UNLOCK( ld, LDAP_MEMCACHE_LOCK ); - - return nRes; -} - -/*************************** helper functions *******************************/ - -/* Removes extraneous spaces in a basedn so that basedns differ by only those - spaces will be treated as equal. Extraneous spaces are those that - precedes the basedn and those that follow a comma. */ -/* - * XXXmcs: this is a bit too agressive... we need to deal with the fact that - * commas and spaces may be quoted, in which case it is wrong to remove them. - */ -static void -memcache_trim_basedn_spaces(char *basedn) -{ - char *pRead, *pWrite; - - if (!basedn) - return; - - for (pWrite = pRead = basedn; *pRead; ) { - for (; *pRead && NSLDAPI_IS_SPACE(*pRead); pRead++) { - ; - } - for (; *pRead && !NSLDAPI_IS_SEPARATER(*pRead); - *(pWrite++) = *(pRead++)) { - ; - } - *(pWrite++) = (*pRead ? *(pRead++) : *pRead); - } -} - -/* Verifies whether the results of a search should be cached or not by - checking if the search's basedn falls under any of the basedns for which - the memcache is responsible. */ -static int -memcache_validate_basedn(LDAPMemCache *cache, const char *basedn) -{ - int i; - - if ( cache->ldmemc_basedns == NULL ) { - return( LDAP_SUCCESS ); - } - -#if 1 - if (basedn == NULL) { - basedn = ""; - } -#else - /* XXXmcs: I do not understand this code... */ - if (basedn == NULL) - return (cache->ldmemc_basedns && cache->ldmemc_basedns[0] ? - LDAP_OPERATIONS_ERROR : LDAP_SUCCESS); - } -#endif - - for (i = 0; cache->ldmemc_basedns[i]; i++) { - if (memcache_compare_dn(basedn, cache->ldmemc_basedns[i], - LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE) { - return( LDAP_SUCCESS ); - } - } - - return( LDAP_OPERATIONS_ERROR ); -} - -/* Calculates the length of the buffer needed to concatenate the contents of - a ldap control. */ -static int -memcache_get_ctrls_len(LDAPControl **ctrls) -{ - int len = 0, i; - - if (ctrls) { - for (i = 0; ctrls[i]; i++) { - len += strlen(NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)) + - (ctrls[i]->ldctl_value).bv_len + 4; - } - } - - return len; -} - -/* Contenates the contents of client and server controls to a buffer. */ -static void -memcache_append_ctrls(char *buf, LDAPControl **serverCtrls, - LDAPControl **clientCtrls) -{ - int i, j; - char *pCh = buf + strlen(buf); - LDAPControl **ctrls; - - for (j = 0; j < 2; j++) { - - if ((ctrls = (j ? clientCtrls : serverCtrls)) == NULL) - continue; - - for (i = 0; ctrls[i]; i++) { - sprintf(pCh, "%s\n", NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)); - pCh += strlen(NSLDAPI_STR_NONNULL(ctrls[i]->ldctl_oid)) + 1; - if ((ctrls[i]->ldctl_value).bv_len > 0) { - memcpy(pCh, (ctrls[i]->ldctl_value).bv_val, - (ctrls[i]->ldctl_value).bv_len); - pCh += (ctrls[i]->ldctl_value).bv_len; - } - sprintf(pCh, "\n%i\n", (ctrls[i]->ldctl_iscritical ? 1 : 0)); - pCh += 3; - } - } -} - -/* Increases or decreases the size (in bytes) the given memcache currently - uses. If the size goes over the limit, the function returns an error. */ -static int -memcache_adj_size(LDAPMemCache *cache, unsigned long size, - int usageFlags, int bAdd) -{ - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_adj_size: attempting to %s %ld %s bytes...\n", - bAdd ? "add" : "remove", size, - ( usageFlags & MEMCACHE_SIZE_ENTRIES ) ? "entry" : "non-entry" ); - - if (bAdd) { - cache->ldmemc_size_used += size; - if ((cache->ldmemc_size > 0) && - (cache->ldmemc_size_used > cache->ldmemc_size)) { - - if (size > cache->ldmemc_size_entries) { - cache->ldmemc_size_used -= size; - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_adj_size: failed (size > size_entries %ld).\n", - cache->ldmemc_size_entries, 0, 0 ); - return( LDAP_SIZELIMIT_EXCEEDED ); - } - - while (cache->ldmemc_size_used > cache->ldmemc_size) { - if (memcache_access(cache, MEMCACHE_ACCESS_FLUSH_LRU, - NULL, NULL, NULL) != LDAP_SUCCESS) { - cache->ldmemc_size_used -= size; - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_adj_size: failed (LRU flush failed).\n", - 0, 0, 0 ); - return( LDAP_SIZELIMIT_EXCEEDED ); - } - } - } - if (usageFlags & MEMCACHE_SIZE_ENTRIES) - cache->ldmemc_size_entries += size; - } else { - cache->ldmemc_size_used -= size; - assert(cache->ldmemc_size_used >= 0); - if (usageFlags & MEMCACHE_SIZE_ENTRIES) - cache->ldmemc_size_entries -= size; - } - -#ifdef LDAP_DEBUG - if ( cache->ldmemc_size == 0 ) { /* no size limit */ - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_adj_size: succeeded (new size: %ld bytes).\n", - cache->ldmemc_size_used, 0, 0 ); - } else { - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_adj_size: succeeded (new size: %ld bytes, " - "free space: %ld bytes).\n", cache->ldmemc_size_used, - cache->ldmemc_size - cache->ldmemc_size_used, 0 ); - } -#endif /* LDAP_DEBUG */ - - return( LDAP_SUCCESS ); -} - -/* Searches the cache for results for a particular search identified by - parameter "key", which was generated ldap_memcache_createkey(). */ -static int -memcache_search(LDAP *ld, unsigned long key, LDAPMessage **ppRes) -{ - int nRes; - ldapmemcacheRes *pRes; - - *ppRes = NULL; - - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - nRes = memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_FIND, - (void*)&key, (void*)(&pRes), NULL); - - if (nRes != LDAP_SUCCESS) - return nRes; - - *ppRes = pRes->ldmemcr_resHead; - assert((pRes->ldmemcr_req_id).ldmemcrid_msgid == -1); - - return( LDAP_SUCCESS ); -} - -/* Adds a new header into the cache as a place holder for entries - arriving later. */ -static int -memcache_add(LDAP *ld, unsigned long key, int msgid, - const char *basedn) -{ - ldapmemcacheReqId reqid; - - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - reqid.ldmemcrid_msgid = msgid; - reqid.ldmemcrid_ld = ld; - - return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_ADD, - (void*)&key, (void*)&reqid, (void*)basedn); -} - -/* Appends search entries arriving from the dir server to the cache. */ -static int -memcache_append(LDAP *ld, int msgid, LDAPMessage *pRes) -{ - ldapmemcacheReqId reqid; - - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - reqid.ldmemcrid_msgid = msgid; - reqid.ldmemcrid_ld = ld; - - return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_APPEND, - (void*)&reqid, (void*)pRes, NULL); -} - -/* Same as memcache_append(), but the entries being appended are the - last from the dir server. Once all entries for a search have arrived, - the entries are moved from secondary to primary cache, and a time - stamp is given to the entries. */ -static int -memcache_append_last(LDAP *ld, int msgid, LDAPMessage *pRes) -{ - ldapmemcacheReqId reqid; - - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - reqid.ldmemcrid_msgid = msgid; - reqid.ldmemcrid_ld = ld; - - return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_APPEND_LAST, - (void*)&reqid, (void*)pRes, NULL); -} - -/* Removes entries from the temporary cache. */ -static int -memcache_remove(LDAP *ld, int msgid) -{ - ldapmemcacheReqId reqid; - - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - reqid.ldmemcrid_msgid = msgid; - reqid.ldmemcrid_ld = ld; - - return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_DELETE, - (void*)&reqid, NULL, NULL); -} - -#if 0 /* this function is not used */ -/* Wipes out everything in the temporary cache directory. */ -static int -memcache_remove_all(LDAP *ld) -{ - if (!memcache_exist(ld)) - return LDAP_LOCAL_ERROR; - - return memcache_access(ld->ld_memcache, MEMCACHE_ACCESS_DELETE_ALL, - NULL, NULL, NULL); -} -#endif /* 0 */ - -/* Returns TRUE or FALSE */ -static int -memcache_exist(LDAP *ld) -{ - return (ld->ld_memcache != NULL); -} - -/* Attaches cached entries to an ldap handle. */ -static int -memcache_add_to_ld(LDAP *ld, int msgid, LDAPMessage *pMsg) -{ - int nRes = LDAP_SUCCESS; - LDAPMessage **r; - LDAPMessage *pCopy; - - nRes = memcache_dup_message(pMsg, msgid, 1, &pCopy, NULL); - if (nRes != LDAP_SUCCESS) - return nRes; - - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - - for (r = &(ld->ld_responses); *r; r = &((*r)->lm_next)) - if ((*r)->lm_msgid == msgid) - break; - - if (*r) - for (r = &((*r)->lm_chain); *r; r = &((*r)->lm_chain)) { - ; - } - - *r = pCopy; - - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - - return nRes; -} - -/* Check if main_dn is included in {dn, scope} */ -static int -memcache_compare_dn(const char *main_dn, const char *dn, int scope) -{ - int nRes; - char **components = NULL; - char **main_components = NULL; - - components = ldap_explode_dn(dn, 0); - main_components = ldap_explode_dn(main_dn, 0); - - if (!components || !main_components) { - nRes = LDAP_COMPARE_TRUE; - } - else { - - int i, main_i; - - main_i = ldap_count_values(main_components) - 1; - i = ldap_count_values(components) - 1; - - for (; i >= 0 && main_i >= 0; i--, main_i--) { - if (strcasecmp(main_components[main_i], components[i])) - break; - } - - if (i >= 0 && main_i >= 0) { - nRes = LDAP_COMPARE_FALSE; - } - else if (i < 0 && main_i < 0) { - if (scope != LDAP_SCOPE_ONELEVEL) - nRes = LDAP_COMPARE_TRUE; - else - nRes = LDAP_COMPARE_FALSE; - } - else if (main_i < 0) { - nRes = LDAP_COMPARE_FALSE; - } - else { - if (scope == LDAP_SCOPE_BASE) - nRes = LDAP_COMPARE_FALSE; - else if (scope == LDAP_SCOPE_SUBTREE) - nRes = LDAP_COMPARE_TRUE; - else if (main_i == 0) - nRes = LDAP_COMPARE_TRUE; - else - nRes = LDAP_COMPARE_FALSE; - } - } - - if (components) - ldap_value_free(components); - - if (main_components) - ldap_value_free(main_components); - - return nRes; -} - -/* Dup a complete separate copy of a berelement, including the buffers - the berelement points to. */ -static BerElement* -memcache_ber_dup(BerElement* pBer, unsigned long *pSize) -{ - BerElement *p = ber_dup(pBer); - - *pSize = 0; - - if (p) { - - *pSize += sizeof(BerElement) + EXTRA_SIZE; - - if (p->ber_len <= EXTRA_SIZE) { - p->ber_flags |= LBER_FLAG_NO_FREE_BUFFER; - p->ber_buf = (char*)p + sizeof(BerElement); - } else { - p->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; - p->ber_buf = (char*)NSLDAPI_CALLOC(1, p->ber_len); - *pSize += (p->ber_buf ? p->ber_len : 0); - } - - if (p->ber_buf) { - p->ber_ptr = p->ber_buf + (pBer->ber_ptr - pBer->ber_buf); - p->ber_end = p->ber_buf + p->ber_len; - memcpy(p->ber_buf, pBer->ber_buf, p->ber_len); - } else { - ber_free(p, 0); - p = NULL; - *pSize = 0; - } - } - - return p; -} - -/* Dup a entry or a chain of entries. */ -static int -memcache_dup_message(LDAPMessage *res, int msgid, int fromcache, - LDAPMessage **ppResCopy, unsigned long *pSize) -{ - int nRes = LDAP_SUCCESS; - unsigned long ber_size; - LDAPMessage *pCur; - LDAPMessage **ppCurNew; - - *ppResCopy = NULL; - - if (pSize) - *pSize = 0; - - /* Make a copy of res */ - for (pCur = res, ppCurNew = ppResCopy; pCur; - pCur = pCur->lm_chain, ppCurNew = &((*ppCurNew)->lm_chain)) { - - if ((*ppCurNew = (LDAPMessage*)NSLDAPI_CALLOC(1, - sizeof(LDAPMessage))) == NULL) { - nRes = LDAP_NO_MEMORY; - break; - } - - memcpy(*ppCurNew, pCur, sizeof(LDAPMessage)); - (*ppCurNew)->lm_next = NULL; - (*ppCurNew)->lm_ber = memcache_ber_dup(pCur->lm_ber, &ber_size); - (*ppCurNew)->lm_msgid = msgid; - (*ppCurNew)->lm_fromcache = (fromcache != 0); - - if (pSize) - *pSize += sizeof(LDAPMessage) + ber_size; - } - - if ((nRes != LDAP_SUCCESS) && (*ppResCopy != NULL)) { - ldap_msgfree(*ppResCopy); - *ppResCopy = NULL; - if (pSize) - *pSize = 0; - } - - return nRes; -} - -/************************* Cache Functions ***********************/ - -/* Frees a cache header. */ -static int -memcache_free_entry(LDAPMemCache *cache, ldapmemcacheRes *pRes) -{ - if (pRes) { - - unsigned long size = sizeof(ldapmemcacheRes); - - if (pRes->ldmemcr_basedn) { - size += strlen(pRes->ldmemcr_basedn) + 1; - NSLDAPI_FREE(pRes->ldmemcr_basedn); - } - - if (pRes->ldmemcr_resHead) { - size += pRes->ldmemcr_resSize; - ldap_msgfree(pRes->ldmemcr_resHead); - } - - NSLDAPI_FREE(pRes); - - memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, - MEMCACHE_SIZE_DEDUCT); - } - - return( LDAP_SUCCESS ); -} - -/* Detaches a cache header from the list of headers. */ -static int -memcache_free_from_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, int index) -{ - if (pRes->ldmemcr_prev[index]) - pRes->ldmemcr_prev[index]->ldmemcr_next[index] = - pRes->ldmemcr_next[index]; - - if (pRes->ldmemcr_next[index]) - pRes->ldmemcr_next[index]->ldmemcr_prev[index] = - pRes->ldmemcr_prev[index]; - - if (cache->ldmemc_resHead[index] == pRes) - cache->ldmemc_resHead[index] = pRes->ldmemcr_next[index]; - - if (cache->ldmemc_resTail[index] == pRes) - cache->ldmemc_resTail[index] = pRes->ldmemcr_prev[index]; - - pRes->ldmemcr_prev[index] = NULL; - pRes->ldmemcr_next[index] = NULL; - - return( LDAP_SUCCESS ); -} - -/* Inserts a new cache header to a list of headers. */ -static int -memcache_add_to_list(LDAPMemCache *cache, ldapmemcacheRes *pRes, int index) -{ - if (cache->ldmemc_resHead[index]) - cache->ldmemc_resHead[index]->ldmemcr_prev[index] = pRes; - else - cache->ldmemc_resTail[index] = pRes; - - pRes->ldmemcr_prev[index] = NULL; - pRes->ldmemcr_next[index] = cache->ldmemc_resHead[index]; - cache->ldmemc_resHead[index] = pRes; - - return( LDAP_SUCCESS ); -} - -/* Appends a chain of entries to the given cache header. */ -static int -memcache_add_res_to_list(ldapmemcacheRes *pRes, LDAPMessage *pMsg, - unsigned long size) -{ - if (pRes->ldmemcr_resTail) - pRes->ldmemcr_resTail->lm_chain = pMsg; - else - pRes->ldmemcr_resHead = pMsg; - - for (pRes->ldmemcr_resTail = pMsg; - pRes->ldmemcr_resTail->lm_chain; - pRes->ldmemcr_resTail = pRes->ldmemcr_resTail->lm_chain) { - ; - } - - pRes->ldmemcr_resSize += size; - - return( LDAP_SUCCESS ); -} - - -#ifdef LDAP_DEBUG -static void -memcache_print_list( LDAPMemCache *cache, int index ) -{ - char *name; - ldapmemcacheRes *restmp; - - switch( index ) { - case LIST_TTL: - name = "TTL"; - break; - case LIST_LRU: - name = "LRU"; - break; - case LIST_TMP: - name = "TMP"; - break; - case LIST_TOTAL: - name = "TOTAL"; - break; - default: - name = "unknown"; - } - - LDAPDebug( LDAP_DEBUG_TRACE, "memcache 0x%p %s list:\n", - cache, name, 0 ); - for ( restmp = cache->ldmemc_resHead[index]; restmp != NULL; - restmp = restmp->ldmemcr_next[index] ) { - LDAPDebug( LDAP_DEBUG_TRACE, - " key: 0x%8.8lx, ld: 0x%p, msgid: %d\n", - restmp->ldmemcr_crc_key, - restmp->ldmemcr_req_id.ldmemcrid_ld, - restmp->ldmemcr_req_id.ldmemcrid_msgid ); - } - LDAPDebug( LDAP_DEBUG_TRACE, "memcache 0x%p end of %s list.\n", - cache, name, 0 ); -} -#endif /* LDAP_DEBUG */ - -/* Tells whether a cached result has expired. */ -static int -memcache_expired(LDAPMemCache *cache, ldapmemcacheRes *pRes, - unsigned long curTime) -{ - if (!cache->ldmemc_ttl) - return 0; - - return ((unsigned long)difftime( - (time_t)curTime, - (time_t)(pRes->ldmemcr_timestamp)) >= - cache->ldmemc_ttl); -} - -/* Operates the cache in a central place. */ -static int -memcache_access(LDAPMemCache *cache, int mode, - void *pData1, void *pData2, void *pData3) -{ - int nRes = LDAP_SUCCESS; - unsigned long size = 0; - - /* Add a new cache header to the cache. */ - if (mode == MEMCACHE_ACCESS_ADD) { - unsigned long key = *((unsigned long*)pData1); - char *basedn = (char*)pData3; - ldapmemcacheRes *pRes = NULL; - void* hashResult = NULL; - - nRes = htable_get(cache->ldmemc_resTmp, pData2, &hashResult); - if (nRes == LDAP_SUCCESS) - return( LDAP_ALREADY_EXISTS ); - - pRes = (ldapmemcacheRes*)NSLDAPI_CALLOC(1, sizeof(ldapmemcacheRes)); - if (pRes == NULL) - return( LDAP_NO_MEMORY ); - - pRes->ldmemcr_crc_key = key; - pRes->ldmemcr_req_id = *((ldapmemcacheReqId*)pData2); - pRes->ldmemcr_basedn = (basedn ? nsldapi_strdup(basedn) : NULL); - - size += sizeof(ldapmemcacheRes) + strlen(basedn) + 1; - nRes = memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, - MEMCACHE_SIZE_ADD); - if (nRes == LDAP_SUCCESS) - nRes = htable_put(cache->ldmemc_resTmp, pData2, (void*)pRes); - if (nRes == LDAP_SUCCESS) - memcache_add_to_list(cache, pRes, LIST_TMP); - else - memcache_free_entry(cache, pRes); - } - /* Append entries to an existing cache header. */ - else if ((mode == MEMCACHE_ACCESS_APPEND) || - (mode == MEMCACHE_ACCESS_APPEND_LAST)) { - - LDAPMessage *pMsg = (LDAPMessage*)pData2; - LDAPMessage *pCopy = NULL; - ldapmemcacheRes *pRes = NULL; - void* hashResult = NULL; - - nRes = htable_get(cache->ldmemc_resTmp, pData1, &hashResult); - if (nRes != LDAP_SUCCESS) - return nRes; - - pRes = (ldapmemcacheRes*) hashResult; - nRes = memcache_dup_message(pMsg, pMsg->lm_msgid, 0, &pCopy, &size); - if (nRes != LDAP_SUCCESS) { - nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TMP); - memcache_free_entry(cache, pRes); - return nRes; - } - - nRes = memcache_adj_size(cache, size, MEMCACHE_SIZE_ENTRIES, - MEMCACHE_SIZE_ADD); - if (nRes != LDAP_SUCCESS) { - ldap_msgfree(pCopy); - nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TMP); - memcache_free_entry(cache, pRes); - return nRes; - } - - memcache_add_res_to_list(pRes, pCopy, size); - - if (mode == MEMCACHE_ACCESS_APPEND) - return( LDAP_SUCCESS ); - - nRes = htable_remove(cache->ldmemc_resTmp, pData1, NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TMP); - (pRes->ldmemcr_req_id).ldmemcrid_ld = NULL; - (pRes->ldmemcr_req_id).ldmemcrid_msgid = -1; - pRes->ldmemcr_timestamp = (unsigned long)time(NULL); - - if ((nRes = htable_put(cache->ldmemc_resLookup, - (void*)&(pRes->ldmemcr_crc_key), - (void*)pRes)) == LDAP_SUCCESS) { - memcache_add_to_list(cache, pRes, LIST_TTL); - memcache_add_to_list(cache, pRes, LIST_LRU); - } else { - memcache_free_entry(cache, pRes); - } - } - /* Search for cached entries for a particular search. */ - else if (mode == MEMCACHE_ACCESS_FIND) { - - ldapmemcacheRes **ppRes = (ldapmemcacheRes**)pData2; - - nRes = htable_get(cache->ldmemc_resLookup, pData1, (void**)ppRes); - if (nRes != LDAP_SUCCESS) - return nRes; - - if (!memcache_expired(cache, *ppRes, (unsigned long)time(0))) { - memcache_free_from_list(cache, *ppRes, LIST_LRU); - memcache_add_to_list(cache, *ppRes, LIST_LRU); - return( LDAP_SUCCESS ); - } - - nRes = htable_remove(cache->ldmemc_resLookup, pData1, NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, *ppRes, LIST_TTL); - memcache_free_from_list(cache, *ppRes, LIST_LRU); - memcache_free_entry(cache, *ppRes); - nRes = LDAP_NO_SUCH_OBJECT; - *ppRes = NULL; - } - /* Remove cached entries in the temporary cache. */ - else if (mode == MEMCACHE_ACCESS_DELETE) { - - void* hashResult = NULL; - - if ((nRes = htable_remove(cache->ldmemc_resTmp, pData1, - &hashResult)) == LDAP_SUCCESS) { - ldapmemcacheRes *pCurRes = (ldapmemcacheRes*) hashResult; - memcache_free_from_list(cache, pCurRes, LIST_TMP); - memcache_free_entry(cache, pCurRes); - } - } - /* Wipe out the temporary cache. */ - else if (mode == MEMCACHE_ACCESS_DELETE_ALL) { - - nRes = htable_removeall(cache->ldmemc_resTmp, (void*)cache); - } - /* Remove expired entries from primary cache. */ - else if (mode == MEMCACHE_ACCESS_UPDATE) { - - ldapmemcacheRes *pCurRes = cache->ldmemc_resTail[LIST_TTL]; - unsigned long curTime = (unsigned long)time(NULL); - - for (; pCurRes; pCurRes = cache->ldmemc_resTail[LIST_TTL]) { - - if (!memcache_expired(cache, pCurRes, curTime)) - break; - - nRes = htable_remove(cache->ldmemc_resLookup, - (void*)&(pCurRes->ldmemcr_crc_key), NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pCurRes, LIST_TTL); - memcache_free_from_list(cache, pCurRes, LIST_LRU); - memcache_free_entry(cache, pCurRes); - } - } - /* Wipe out the primary cache. */ - else if (mode == MEMCACHE_ACCESS_FLUSH_ALL) { - - ldapmemcacheRes *pCurRes = cache->ldmemc_resHead[LIST_TTL]; - - nRes = htable_removeall(cache->ldmemc_resLookup, (void*)cache); - - for (; pCurRes; pCurRes = cache->ldmemc_resHead[LIST_TTL]) { - memcache_free_from_list(cache, pCurRes, LIST_LRU); - cache->ldmemc_resHead[LIST_TTL] = - cache->ldmemc_resHead[LIST_TTL]->ldmemcr_next[LIST_TTL]; - memcache_free_entry(cache, pCurRes); - } - cache->ldmemc_resTail[LIST_TTL] = NULL; - } - /* Remove cached entries in both primary and temporary cache. */ - else if ((mode == MEMCACHE_ACCESS_FLUSH) || - (mode == MEMCACHE_ACCESS_FLUSH_RESULTS)) { - - int i, list_id, bDone; - int scope = (int)pData2; - char *dn = (char*)pData1; - char *dnTmp; - BerElement ber; - LDAPMessage *pMsg; - ldapmemcacheRes *pRes; - - if (cache->ldmemc_basedns) { - for (i = 0; cache->ldmemc_basedns[i]; i++) { - if ((memcache_compare_dn(cache->ldmemc_basedns[i], dn, - LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE) || - (memcache_compare_dn(dn, cache->ldmemc_basedns[i], - LDAP_SCOPE_SUBTREE) == LDAP_COMPARE_TRUE)) - break; - } - if (cache->ldmemc_basedns[i] == NULL) - return( LDAP_SUCCESS ); - } - - for (i = 0; i < 2; i++) { - - list_id = (i == 0 ? LIST_TTL : LIST_TMP); - - for (pRes = cache->ldmemc_resHead[list_id]; pRes != NULL; - pRes = pRes->ldmemcr_next[list_id]) { - - int foundentries = 0; - - if ((memcache_compare_dn(pRes->ldmemcr_basedn, dn, - LDAP_SCOPE_SUBTREE) != LDAP_COMPARE_TRUE) && - (memcache_compare_dn(dn, pRes->ldmemcr_basedn, - LDAP_SCOPE_SUBTREE) != LDAP_COMPARE_TRUE)) - continue; - - for (pMsg = pRes->ldmemcr_resHead, bDone = 0; - !bDone && pMsg; pMsg = pMsg->lm_chain) { - - if (!NSLDAPI_IS_SEARCH_ENTRY( pMsg->lm_msgtype )) - continue; - foundentries = 1; - ber = *(pMsg->lm_ber); - if (ber_scanf(&ber, "{a", &dnTmp) != LBER_ERROR) { - bDone = (memcache_compare_dn(dnTmp, dn, scope) == - LDAP_COMPARE_TRUE); - ldap_memfree(dnTmp); - } - } - - /* If we're in the result flush mode, and the base matched, and - there were no entries in the result, we'll flush this cache - slot, as opposed to the MEMCACHE_ACCESS_FLUSH mode which does - not flush negative results. */ - if ((mode == MEMCACHE_ACCESS_FLUSH_RESULTS) && !foundentries) { - bDone = 1; - } - - if (!bDone) - continue; - - if (list_id == LIST_TTL) { - nRes = htable_remove(cache->ldmemc_resLookup, - (void*)&(pRes->ldmemcr_crc_key), NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TTL); - memcache_free_from_list(cache, pRes, LIST_LRU); - } else { - nRes = htable_remove(cache->ldmemc_resTmp, - (void*)&(pRes->ldmemcr_req_id), NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TMP); - } - memcache_free_entry(cache, pRes); - } - } - } - /* Flush least recently used entries from cache */ - else if (mode == MEMCACHE_ACCESS_FLUSH_LRU) { - - ldapmemcacheRes *pRes = cache->ldmemc_resTail[LIST_LRU]; - - if (pRes == NULL) - return LDAP_NO_SUCH_OBJECT; - - LDAPDebug( LDAP_DEBUG_TRACE, - "memcache_access FLUSH_LRU: removing key 0x%8.8lx\n", - pRes->ldmemcr_crc_key, 0, 0 ); - nRes = htable_remove(cache->ldmemc_resLookup, - (void*)&(pRes->ldmemcr_crc_key), NULL); - assert(nRes == LDAP_SUCCESS); - memcache_free_from_list(cache, pRes, LIST_TTL); - memcache_free_from_list(cache, pRes, LIST_LRU); - memcache_free_entry(cache, pRes); - } - /* Unknown command */ - else { - nRes = LDAP_PARAM_ERROR; - } - - return nRes; -} - -static void -memcache_flush( LDAPMemCache *cache, char *dn, int scope, int flushresults ) -{ - if ( !NSLDAPI_VALID_MEMCACHE_POINTER( cache )) { - return; - } - - LDAP_MEMCACHE_MUTEX_LOCK( cache ); - - if (!dn) { - memcache_access(cache, MEMCACHE_ACCESS_FLUSH_ALL, NULL, NULL, NULL); - } else { - if (flushresults) { - memcache_access(cache, MEMCACHE_ACCESS_FLUSH_RESULTS, - (void*)dn, (void*)scope, NULL); - } else { - memcache_access(cache, MEMCACHE_ACCESS_FLUSH, - (void*)dn, (void*)scope, NULL); - } - } - - LDAP_MEMCACHE_MUTEX_UNLOCK( cache ); -} - - -#ifdef LDAP_DEBUG -static void -memcache_report_statistics( LDAPMemCache *cache ) -{ - unsigned long hitrate; - - if ( cache->ldmemc_stats.ldmemcstat_tries == 0 ) { - hitrate = 0; - } else { - hitrate = ( 100L * cache->ldmemc_stats.ldmemcstat_hits ) / - cache->ldmemc_stats.ldmemcstat_tries; - } - LDAPDebug( LDAP_DEBUG_STATS, "memcache 0x%p:\n", cache, 0, 0 ); - LDAPDebug( LDAP_DEBUG_STATS, " tries: %ld hits: %ld hitrate: %ld%%\n", - cache->ldmemc_stats.ldmemcstat_tries, - cache->ldmemc_stats.ldmemcstat_hits, hitrate ); - if ( cache->ldmemc_size <= 0 ) { /* no size limit */ - LDAPDebug( LDAP_DEBUG_STATS, " memory bytes used: %ld\n", - cache->ldmemc_size_used, 0, 0 ); - } else { - LDAPDebug( LDAP_DEBUG_STATS, " memory bytes used: %ld free: %ld\n", - cache->ldmemc_size_used, - cache->ldmemc_size - cache->ldmemc_size_used, 0 ); - } -} -#endif /* LDAP_DEBUG */ - -/************************ Hash Table Functions *****************************/ - -/* Calculates size (# of entries) of hash table given the size limit for - the cache. */ -static int -htable_calculate_size(int sizelimit) -{ - int i, j; - int size = (int)(((double)sizelimit / - (double)(sizeof(BerElement) + EXTRA_SIZE)) / 1.5); - - /* Get a prime # */ - size = (size & 0x1 ? size : size + 1); - for (i = 3, j = size / 2; i < j; i++) { - if ((size % i) == 0) { - size += 2; - i = 3; - j = size / 2; - } - } - - return size; -} - -/* Returns the size in bytes of the given hash table. */ -static int -htable_sizeinbytes(HashTable *pTable) -{ - if (!pTable) - return 0; - - return (pTable->size * sizeof(HashTableNode)); -} - -/* Inserts an item into the hash table. */ -static int -htable_put(HashTable *pTable, void *key, void *pData) -{ - int index = pTable->hashfunc(pTable->size, key); - - if (index >= 0 && index < pTable->size) - return pTable->putdata(&(pTable->table[index].pData), key, pData); - - return( LDAP_OPERATIONS_ERROR ); -} - -/* Retrieves an item from the hash table. */ -static int -htable_get(HashTable *pTable, void *key, void **ppData) -{ - int index = pTable->hashfunc(pTable->size, key); - - *ppData = NULL; - - if (index >= 0 && index < pTable->size) - return pTable->getdata(pTable->table[index].pData, key, ppData); - - return( LDAP_OPERATIONS_ERROR ); -} - -/* Performs a miscellaneous operation on a hash table entry. */ -static int -htable_misc(HashTable *pTable, void *key, void *pData) -{ - if (pTable->miscfunc) { - int index = pTable->hashfunc(pTable->size, key); - if (index >= 0 && index < pTable->size) - return pTable->miscfunc(&(pTable->table[index].pData), key, pData); - } - - return( LDAP_OPERATIONS_ERROR ); -} - -/* Removes an item from the hash table. */ -static int -htable_remove(HashTable *pTable, void *key, void **ppData) -{ - int index = pTable->hashfunc(pTable->size, key); - - if (ppData) - *ppData = NULL; - - if (index >= 0 && index < pTable->size) - return pTable->removedata(&(pTable->table[index].pData), key, ppData); - - return( LDAP_OPERATIONS_ERROR ); -} - -/* Removes everything in the hash table. */ -static int -htable_removeall(HashTable *pTable, void *pData) -{ - int i; - - for (i = 0; i < pTable->size; i++) - pTable->clrtablenode(&(pTable->table[i].pData), pData); - - return( LDAP_SUCCESS ); -} - -/* Creates a new hash table. */ -static int -htable_create(int size_limit, HashFuncPtr hashf, - PutDataPtr putDataf, GetDataPtr getDataf, - RemoveDataPtr removeDataf, ClrTableNodePtr clrNodef, - MiscFuncPtr miscOpf, HashTable **ppTable) -{ - size_limit = htable_calculate_size(size_limit); - - if ((*ppTable = (HashTable*)NSLDAPI_CALLOC(1, sizeof(HashTable))) == NULL) - return( LDAP_NO_MEMORY ); - - (*ppTable)->table = (HashTableNode*)NSLDAPI_CALLOC(size_limit, - sizeof(HashTableNode)); - if ((*ppTable)->table == NULL) { - NSLDAPI_FREE(*ppTable); - *ppTable = NULL; - return( LDAP_NO_MEMORY ); - } - - (*ppTable)->size = size_limit; - (*ppTable)->hashfunc = hashf; - (*ppTable)->putdata = putDataf; - (*ppTable)->getdata = getDataf; - (*ppTable)->miscfunc = miscOpf; - (*ppTable)->removedata = removeDataf; - (*ppTable)->clrtablenode = clrNodef; - - return( LDAP_SUCCESS ); -} - -/* Destroys a hash table. */ -static int -htable_free(HashTable *pTable) -{ - NSLDAPI_FREE(pTable->table); - NSLDAPI_FREE(pTable); - return( LDAP_SUCCESS ); -} - -/**************** Hash table callbacks for temporary cache ****************/ - -/* Hash function */ -static int -msgid_hashf(int table_size, void *key) -{ - unsigned code = (unsigned)((ldapmemcacheReqId*)key)->ldmemcrid_ld; - return (((code << 20) + (code >> 12)) % table_size); -} - -/* Called by hash table to insert an item. */ -static int -msgid_putdata(void **ppTableData, void *key, void *pData) -{ - ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; - ldapmemcacheRes *pRes = (ldapmemcacheRes*)pData; - ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; - ldapmemcacheRes *pCurRes = *ppHead; - ldapmemcacheRes *pPrev = NULL; - - for (; pCurRes; pCurRes = pCurRes->ldmemcr_htable_next) { - if ((pCurRes->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) - break; - pPrev = pCurRes; - } - - if (pCurRes) { - for (; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { - if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == - pReqId->ldmemcrid_msgid) - return( LDAP_ALREADY_EXISTS ); - pPrev = pCurRes; - } - pPrev->ldmemcr_next[LIST_TTL] = pRes; - pRes->ldmemcr_prev[LIST_TTL] = pPrev; - pRes->ldmemcr_next[LIST_TTL] = NULL; - } else { - if (pPrev) - pPrev->ldmemcr_htable_next = pRes; - else - *ppHead = pRes; - pRes->ldmemcr_htable_next = NULL; - } - - return( LDAP_SUCCESS ); -} - -/* Called by hash table to retrieve an item. */ -static int -msgid_getdata(void *pTableData, void *key, void **ppData) -{ - ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; - ldapmemcacheRes *pCurRes = (ldapmemcacheRes*)pTableData; - - *ppData = NULL; - - for (; pCurRes; pCurRes = pCurRes->ldmemcr_htable_next) { - if ((pCurRes->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) - break; - } - - if (!pCurRes) - return( LDAP_NO_SUCH_OBJECT ); - - for (; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { - if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == - pReqId->ldmemcrid_msgid) { - *ppData = (void*)pCurRes; - return( LDAP_SUCCESS ); - } - } - - return( LDAP_NO_SUCH_OBJECT ); -} - -/* Called by hash table to remove an item. */ -static int -msgid_removedata(void **ppTableData, void *key, void **ppData) -{ - ldapmemcacheRes *pHead = *((ldapmemcacheRes**)ppTableData); - ldapmemcacheRes *pCurRes = NULL; - ldapmemcacheRes *pPrev = NULL; - ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; - - if (ppData) - *ppData = NULL; - - for (; pHead; pHead = pHead->ldmemcr_htable_next) { - if ((pHead->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) - break; - pPrev = pHead; - } - - if (!pHead) - return( LDAP_NO_SUCH_OBJECT ); - - for (pCurRes = pHead; pCurRes; pCurRes = pCurRes->ldmemcr_next[LIST_TTL]) { - if ((pCurRes->ldmemcr_req_id).ldmemcrid_msgid == - pReqId->ldmemcrid_msgid) - break; - } - - if (!pCurRes) - return( LDAP_NO_SUCH_OBJECT ); - - if (ppData) { - pCurRes->ldmemcr_next[LIST_TTL] = NULL; - pCurRes->ldmemcr_prev[LIST_TTL] = NULL; - pCurRes->ldmemcr_htable_next = NULL; - *ppData = (void*)pCurRes; - } - - if (pCurRes != pHead) { - if (pCurRes->ldmemcr_prev[LIST_TTL]) - pCurRes->ldmemcr_prev[LIST_TTL]->ldmemcr_next[LIST_TTL] = - pCurRes->ldmemcr_next[LIST_TTL]; - if (pCurRes->ldmemcr_next[LIST_TTL]) - pCurRes->ldmemcr_next[LIST_TTL]->ldmemcr_prev[LIST_TTL] = - pCurRes->ldmemcr_prev[LIST_TTL]; - return( LDAP_SUCCESS ); - } - - if (pPrev) { - if (pHead->ldmemcr_next[LIST_TTL]) { - pPrev->ldmemcr_htable_next = pHead->ldmemcr_next[LIST_TTL]; - pHead->ldmemcr_next[LIST_TTL]->ldmemcr_htable_next = - pHead->ldmemcr_htable_next; - } else { - pPrev->ldmemcr_htable_next = pHead->ldmemcr_htable_next; - } - } else { - if (pHead->ldmemcr_next[LIST_TTL]) { - *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_next[LIST_TTL]; - pHead->ldmemcr_next[LIST_TTL]->ldmemcr_htable_next = - pHead->ldmemcr_htable_next; - } else { - *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_htable_next; - } - } - - return( LDAP_SUCCESS ); -} - -/* Called by hash table to remove all cached entries associated to searches - being performed using the given ldap handle. */ -static int -msgid_clear_ld_items(void **ppTableData, void *key, void *pData) -{ - LDAPMemCache *cache = (LDAPMemCache*)pData; - ldapmemcacheRes *pHead = *((ldapmemcacheRes**)ppTableData); - ldapmemcacheRes *pPrev = NULL; - ldapmemcacheRes *pCurRes = NULL; - ldapmemcacheReqId *pReqId = (ldapmemcacheReqId*)key; - - for (; pHead; pHead = pHead->ldmemcr_htable_next) { - if ((pHead->ldmemcr_req_id).ldmemcrid_ld == pReqId->ldmemcrid_ld) - break; - pPrev = pHead; - } - - if (!pHead) - return( LDAP_NO_SUCH_OBJECT ); - - if (pPrev) - pPrev->ldmemcr_htable_next = pHead->ldmemcr_htable_next; - else - *((ldapmemcacheRes**)ppTableData) = pHead->ldmemcr_htable_next; - - for (pCurRes = pHead; pHead; pCurRes = pHead) { - pHead = pHead->ldmemcr_next[LIST_TTL]; - memcache_free_from_list(cache, pCurRes, LIST_TMP); - memcache_free_entry(cache, pCurRes); - } - - return( LDAP_SUCCESS ); -} - -/* Called by hash table for removing all items in the table. */ -static void -msgid_clearnode(void **ppTableData, void *pData) -{ - LDAPMemCache *cache = (LDAPMemCache*)pData; - ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; - ldapmemcacheRes *pSubHead = *ppHead; - ldapmemcacheRes *pCurRes = NULL; - - for (; *ppHead; pSubHead = *ppHead) { - ppHead = &((*ppHead)->ldmemcr_htable_next); - for (pCurRes = pSubHead; pSubHead; pCurRes = pSubHead) { - pSubHead = pSubHead->ldmemcr_next[LIST_TTL]; - memcache_free_from_list(cache, pCurRes, LIST_TMP); - memcache_free_entry(cache, pCurRes); - } - } -} - -/********************* Hash table for primary cache ************************/ - -/* Hash function */ -static int -attrkey_hashf(int table_size, void *key) -{ - return ((*((unsigned long*)key)) % table_size); -} - -/* Called by hash table to insert an item. */ -static int -attrkey_putdata(void **ppTableData, void *key, void *pData) -{ - unsigned long attrkey = *((unsigned long*)key); - ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; - ldapmemcacheRes *pRes = *ppHead; - - for (; pRes; pRes = pRes->ldmemcr_htable_next) { - if (pRes->ldmemcr_crc_key == attrkey) - return( LDAP_ALREADY_EXISTS ); - } - - pRes = (ldapmemcacheRes*)pData; - pRes->ldmemcr_htable_next = *ppHead; - *ppHead = pRes; - - return( LDAP_SUCCESS ); -} - -/* Called by hash table to retrieve an item. */ -static int -attrkey_getdata(void *pTableData, void *key, void **ppData) -{ - unsigned long attrkey = *((unsigned long*)key); - ldapmemcacheRes *pRes = (ldapmemcacheRes*)pTableData; - - for (; pRes; pRes = pRes->ldmemcr_htable_next) { - if (pRes->ldmemcr_crc_key == attrkey) { - *ppData = (void*)pRes; - return( LDAP_SUCCESS ); - } - } - - *ppData = NULL; - - return( LDAP_NO_SUCH_OBJECT ); -} - -/* Called by hash table to remove an item. */ -static int -attrkey_removedata(void **ppTableData, void *key, void **ppData) -{ - unsigned long attrkey = *((unsigned long*)key); - ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; - ldapmemcacheRes *pRes = *ppHead; - ldapmemcacheRes *pPrev = NULL; - - for (; pRes; pRes = pRes->ldmemcr_htable_next) { - if (pRes->ldmemcr_crc_key == attrkey) { - if (ppData) - *ppData = (void*)pRes; - if (pPrev) - pPrev->ldmemcr_htable_next = pRes->ldmemcr_htable_next; - else - *ppHead = pRes->ldmemcr_htable_next; - pRes->ldmemcr_htable_next = NULL; - return( LDAP_SUCCESS ); - } - pPrev = pRes; - } - - if (ppData) - *ppData = NULL; - - return( LDAP_NO_SUCH_OBJECT ); -} - -/* Called by hash table for removing all items in the table. */ -static void -attrkey_clearnode(void **ppTableData, void *pData) -{ - ldapmemcacheRes **ppHead = (ldapmemcacheRes**)ppTableData; - ldapmemcacheRes *pRes = *ppHead; - - (void)pData; - - for (; *ppHead; pRes = *ppHead) { - ppHead = &((*ppHead)->ldmemcr_htable_next); - pRes->ldmemcr_htable_next = NULL; - } -} - -/***************************** CRC algorithm ********************************/ - -/* From http://www.faqs.org/faqs/compression-faq/part1/section-25.html */ - -/* - * Build auxiliary table for parallel byte-at-a-time CRC-32. - */ -#define NSLDAPI_CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ - -static nsldapi_uint_32 crc32_table[256] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; - -/* Initialized first time "crc32()" is called. If you prefer, you can - * statically initialize it at compile time. [Another exercise.] - */ - -static unsigned long -crc32_convert(char *buf, int len) -{ - unsigned char *p; - nsldapi_uint_32 crc; - - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - for (p = (unsigned char *)buf; len > 0; ++p, --len) - crc = ((crc << 8) ^ crc32_table[(crc >> 24) ^ *p]) & 0xffffffff; - - return (unsigned long) ~crc; /* transmit complement, per CRC-32 spec */ -} diff --git a/ldap/c-sdk/libraries/libldap/message.c b/ldap/c-sdk/libraries/libldap/message.c deleted file mode 100644 index bfbd200f87..0000000000 --- a/ldap/c-sdk/libraries/libldap/message.c +++ /dev/null @@ -1,105 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -int -LDAP_CALL -ldap_msgid( LDAPMessage *lm ) -{ - if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm )) { - return( -1 ); - } - - return( lm->lm_msgid ); -} - -int -LDAP_CALL -ldap_msgtype( LDAPMessage *lm ) -{ - if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( lm )) { - return( -1 ); - } - - return( lm->lm_msgtype ); -} - - -LDAPMessage * -LDAP_CALL -ldap_first_message( LDAP *ld, LDAPMessage *chain ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULLMSG ); /* punt */ - } - - return( chain ); -} - - -LDAPMessage * -LDAP_CALL -ldap_next_message( LDAP *ld, LDAPMessage *msg ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( NULLMSG ); /* punt */ - } - - if ( msg == NULLMSG || msg->lm_chain == NULLMSG ) { - return( NULLMSG ); - } - - return( msg->lm_chain ); -} - - -int -LDAP_CALL -ldap_count_messages( LDAP *ld, LDAPMessage *chain ) -{ - int i; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); - } - - for ( i = 0; chain != NULL; chain = chain->lm_chain ) { - i++; - } - - return( i ); -} diff --git a/ldap/c-sdk/libraries/libldap/modify.c b/ldap/c-sdk/libraries/libldap/modify.c deleted file mode 100644 index ea81102c4c..0000000000 --- a/ldap/c-sdk/libraries/libldap/modify.c +++ /dev/null @@ -1,226 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * modify.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_modify - initiate an ldap modify operation. Parameters: - * - * ld LDAP descriptor - * dn DN of the object to modify - * mods List of modifications to make. This is null-terminated - * array of struct ldapmod's, specifying the modifications - * to perform. - * - * Example: - * LDAPMod *mods[] = { - * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, - * { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } }, - * 0 - * } - * msgid = ldap_modify( ld, dn, mods ); - */ -int -LDAP_CALL -ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods ) -{ - int msgid; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 ); - - if ( ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid ) - == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - -int -LDAP_CALL -ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods, - LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) -{ - BerElement *ber; - int i, rc, lderr; - - /* - * A modify request looks like this: - * ModifyRequet ::= SEQUENCE { - * object DistinguishedName, - * modifications SEQUENCE OF SEQUENCE { - * operation ENUMERATED { - * add (0), - * delete (1), - * replace (2) - * }, - * modification SEQUENCE { - * type AttributeType, - * values SET OF AttributeValue - * } - * } - * } - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) - { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods )) { - lderr = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - return( lderr ); - } - if ( dn == NULL ) { - dn = ""; - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* see if we should add to the cache */ - if ( ld->ld_cache_on && ld->ld_cache_modify != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_modify)( ld, *msgidp, LDAP_REQ_MODIFY, - dn, mods )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( lderr ); - } - - if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_MODIFY, dn ) - == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - /* for each modification to be performed... */ - for ( i = 0; mods[i] != NULL; i++ ) { - if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { - rc = ber_printf( ber, "{e{s[V]}}", - mods[i]->mod_op & ~LDAP_MOD_BVALUES, - mods[i]->mod_type, mods[i]->mod_bvalues ); - } else { - rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op, - mods[i]->mod_type, mods[i]->mod_values ); - } - - if ( rc == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - } - - if ( ber_printf( ber, "}}" ) == -1 ) { - lderr = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - ber_free( ber, 1 ); - return( lderr ); - } - - if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( lderr ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODIFY, - (char *)dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -int -LDAP_CALL -ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods ) -{ - return( ldap_modify_ext_s( ld, dn, mods, NULL, NULL )); -} - -int -LDAP_CALL -ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods, - LDAPControl **serverctrls, LDAPControl **clientctrls ) -{ - int msgid, err; - LDAPMessage *res; - - if (( err = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls, - &msgid )) != LDAP_SUCCESS ) { - return( err ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - return( ldap_result2error( ld, res, 1 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/moz.build b/ldap/c-sdk/libraries/libldap/moz.build deleted file mode 100644 index 05c7a6b524..0000000000 --- a/ldap/c-sdk/libraries/libldap/moz.build +++ /dev/null @@ -1,88 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include('/ldap/ldap-sdk.mozbuild') - -SharedLibrary('ldap60') - -SOURCES += [ - 'abandon.c', - 'add.c', - 'authzidctrl.c', - 'bind.c', - 'cache.c', - 'charray.c', - 'charset.c', - 'compare.c', - 'compat.c', - 'control.c', - 'countvalues.c', - 'delete.c', - 'disptmpl.c', - 'dsparse.c', - 'error.c', - 'extendop.c', - 'free.c', - 'freevalues.c', - 'friendly.c', - 'getattr.c', - 'getdn.c', - 'getdxbyname.c', - 'geteffectiverightsctrl.c', - 'getentry.c', - 'getfilter.c', - 'getoption.c', - 'getvalues.c', - 'memcache.c', - 'message.c', - 'modify.c', - 'open.c', - 'os-ip.c', - 'proxyauthctrl.c', - 'psearch.c', - 'pwmodext.c', - 'pwpctrl.c', - 'referral.c', - 'regex.c', - 'rename.c', - 'request.c', - 'reslist.c', - 'result.c', - 'saslbind.c', - 'sbind.c', - 'search.c', - 'setoption.c', - 'sort.c', - 'sortctrl.c', - 'srchpref.c', - 'tmplout.c', - 'ufn.c', - 'unbind.c', - 'unescape.c', - 'url.c', - 'userstatusctrl.c', - 'utf8.c', - 'vlistctrl.c', - 'whoami.c', -] - -if CONFIG['OS_TARGET'] == 'WINNT': - SOURCES += [ - 'dllmain.c', - 'mozock.c', - ] - DEFFILE = SRCDIR + '/libldap.def' - -if CONFIG['OS_TARGET'] != 'WINNT': - DEFINES['USE_WAITPID'] = True - DEFINES['USE_PTHREADS'] = True - -DEFINES['NEEDPROTOS'] = True - -LOCAL_INCLUDES += [ - '/ldap/c-sdk/include' -] - -USE_LIBS += ['lber60'] diff --git a/ldap/c-sdk/libraries/libldap/mozock.c b/ldap/c-sdk/libraries/libldap/mozock.c deleted file mode 100644 index 4f0bc57501..0000000000 --- a/ldap/c-sdk/libraries/libldap/mozock.c +++ /dev/null @@ -1,714 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifdef _WINDOWS -#define FD_SETSIZE 30000 -#endif - -#include -#include -#include - -// Purpose of this file is to implement an intermediate layer to our network -// services, the winsock. -// This intermediate layer will be able to function with and without a working -// winsock being present. -// The attempt to activate the winsock happens as would normally be expected, -// through the calling application's entry point to us, WSAStartup. - - -// Name of the winsock we would like to load. -// Diffs between OSs, Win32s is out in the cold if running 32 bits unless -// they also have a winsock name wsock32.dll. -#ifndef _WIN32 -#define SZWINSOCK "winsock.dll" -#else -#define SZWINSOCK "wsock32.dll" -#endif - -// Here is the enumeration for the winsock functions we have currently -// overridden (needed to run). Add more when needed. -// We use these to access proc addresses, and to hold a table of strings -// to obtain the proc addresses. -enum SockProc { - sp_WSAAsyncGetHostByName = 0, - sp_WSAAsyncSelect, - sp_WSACleanup, - sp_WSAGetLastError, - sp_WSASetLastError, - sp_WSAStartup, - sp___WSAFDIsSet, - sp_accept, - sp_bind, - sp_closesocket, - sp_connect, - sp_gethostbyname, - sp_gethostbyaddr, - sp_gethostname, - sp_getpeername, - sp_getsockname, - sp_getsockopt, - sp_getprotobyname, - sp_htonl, - sp_htons, - sp_inet_addr, - sp_ioctlsocket, - sp_listen, - sp_ntohl, - sp_ntohs, - sp_recv, - sp_select, - sp_send, - sp_setsockopt, - sp_shutdown, - sp_socket, - sp_inet_ntoa, - - sp_MaxProcs // Total count. -}; - -// Array of function names used in GetProcAddress to fill in our -// proc array when needed. -// This array must match the enumerations exactly. -char *spName[(int)sp_MaxProcs] = { - "WSAAsyncGetHostByName", - "WSAAsyncSelect", - "WSACleanup", - "WSAGetLastError", - "WSASetLastError", - "WSAStartup", - "__WSAFDIsSet", - "accept", - "bind", - "closesocket", - "connect", - "gethostbyname", - "gethostbyaddr", - "gethostname", - "getpeername", - "getsockname", - "getsockopt", - "getprotobyname", - "htonl", - "htons", - "inet_addr", - "ioctlsocket", - "listen", - "ntohl", - "ntohs", - "recv", - "select", - "send", - "setsockopt", - "shutdown", - "socket", - "inet_ntoa" -}; - -// Array of proc addresses to the winsock functions. -// These can be NULL, indicating their absence (as in the case we couldn't -// load the winsock.dll or one of the functions wasn't loaded). -// The procs assigned in must corellate with the enumerations exactly. -FARPROC spArray[(int)sp_MaxProcs]; - -// Typedef all the different types of functions that we must cast the -// procs to in order to call without the compiler barfing. -// Prefix is always sp. -// Retval is next, spelled out. -// Parameters in their order are next, spelled out. -typedef int (PASCAL FAR *sp_int_WORD_LPWSADATA)(WORD, LPWSADATA); -typedef int (PASCAL FAR *sp_int_void)(void); -typedef HANDLE (PASCAL FAR *sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)(HWND, unsigned int, const char FAR *, char FAR *, int); -typedef int (PASCAL FAR *sp_int_SOCKET_HWND_uint_long)(SOCKET, HWND, unsigned int, long); -typedef void (PASCAL FAR *sp_void_int)(int); -typedef int (PASCAL FAR *sp_int_SOCKET_fdsetFARp)(SOCKET, fd_set FAR *); -typedef SOCKET(PASCAL FAR *sp_SOCKET_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *); -typedef int (PASCAL FAR *sp_int_SOCKET_csockaddrFARp_int)(SOCKET, const struct sockaddr FAR *, int); -typedef int (PASCAL FAR *sp_int_SOCKET)(SOCKET); -typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp)(const char FAR *); -typedef struct hostent FAR *(PASCAL FAR *sp_hostentFARp_ccharFARp_int_int)(const char FAR *, int, int); -typedef int (PASCAL FAR *sp_int_charFARp_int)(char FAR *, int); -typedef int (PASCAL FAR *sp_int_SOCKET_sockaddrFARp_intFARp)(SOCKET, struct sockaddr FAR *, int FAR *); -typedef int (PASCAL FAR *sp_int_SOCKET_int_int_charFARp_intFARp)(SOCKET, int, int, char FAR *, int FAR *); -typedef u_long (PASCAL FAR *sp_ulong_ulong)(u_long); -typedef u_short (PASCAL FAR *sp_ushort_ushort)(u_short); -typedef unsigned long (PASCAL FAR *sp_ulong_ccharFARp)(const char FAR *); -typedef int (PASCAL FAR *sp_int_SOCKET_long_ulongFARp)(SOCKET, long, u_long FAR *); -typedef int (PASCAL FAR *sp_int_SOCKET_int)(SOCKET, int); -typedef int (PASCAL FAR *sp_int_SOCKET_charFARp_int_int)(SOCKET, char FAR *, int, int); -typedef int (PASCAL FAR *sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)(int,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR*); -typedef int (PASCAL FAR *sp_int_SOCKET_ccharFARp_int_int)(SOCKET, const char FAR *, int, int); -typedef int (PASCAL FAR *sp_int_SOCKET_int_int_ccharFARp_int)(SOCKET, int, int, const char FAR *, int); -typedef SOCKET (PASCAL FAR *sp_SOCKET_int_int_int)(int, int, int); -typedef char FAR * (PASCAL FAR *sp_charFARp_in_addr)(struct in_addr in); -typedef struct protoent FAR * (PASCAL FAR *sp_protoentFARcchar)(const char FAR *); - -// Handle to the winsock, if loaded. -HINSTANCE hWinsock = NULL; - -#ifndef _WIN32 -// Last error code for the winsock. -int ispError = 0; -#endif - - -BOOL IsWinsockLoaded (int sp) -{ - if (hWinsock == NULL) - { - WSADATA wsaData; -#ifdef _WIN32 - static LONG sc_init = 0; - static DWORD sc_done = 0; - static CRITICAL_SECTION sc; -#endif - /* We need to wait here because another thread might be - in the routine already */ -#ifdef _WIN32 - if (0 == InterlockedExchange(&sc_init,1)) { - InitializeCriticalSection(&sc); - sc_done = 1; - } - while (0 == sc_done) Sleep(0); - EnterCriticalSection(&sc); - if (hWinsock == NULL) { -#endif - WSAStartup(0x0101, &wsaData); -#ifdef _WIN32 - } - LeaveCriticalSection(&sc); -#endif - } -// Quick macro to tell if the winsock has actually loaded for a particular -// function. -// Debug version is a little more strict to make sure you get the names right. -#ifdef DEBUG - return hWinsock != NULL && spArray[(int)(sp)] != NULL; -#else // A little faster - return hWinsock != NULL; -#endif -} - -// Here are the functions that we have taken over by not directly linking -// with the winsock import library or importing through the def file. - -/* In win16 we simulate blocking commands as follows. Prior to issuing the - * command we make the socket not-blocking (WSAAsyncSelect does that). - * We then issue the command and see if it would have blocked. If so, we - * yield the processor and go to sleep until an event occurs that unblocks - * us (WSAAsyncSelect allowed us to register what that condition is). We - * keep repeating until we do not get a would-block indication when issuing - * the command. At that time we unregister the notification condition and - * return the result of the command to the caller. - */ - -//#ifndef _WIN32 -#if 0 -#define NON_BLOCKING(command,condition,index,type) \ - type iret; \ - HWND hWndFrame = AfxGetApp()->m_pMainWnd->m_hWnd; \ - while (TRUE) { \ - if (WSAAsyncSelect(s, hWndFrame, msg_NetActivity, condition) \ - == SOCKET_ERROR) { \ - break; \ - } \ - if(IsWinsockLoaded(index)) { \ - iret=command; \ - if (!(iret==SOCKET_ERROR && WSAGetLastError()==WSAEWOULDBLOCK)) { \ - WSAAsyncSelect(s, hWndFrame, msg_NetActivity, 0); \ - return iret; \ - } \ - PR_Yield(); \ - } else { \ - break; \ - } \ - } -#else -#define NON_BLOCKING(command,condition,index,type) \ - if(IsWinsockLoaded(index)) { \ - return command; \ - } -#endif - -int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) { - // Our default return value is failure, though we change this regardless. - int iRetval = WSAVERNOTSUPPORTED; - HINSTANCE MyHandle; - - // Before doing anything, clear out our proc array. - memset(spArray, 0, sizeof(spArray)); - - // attempt to load the real winsock. - MyHandle = LoadLibrary(SZWINSOCK); -#ifdef _WIN32 - if(MyHandle != NULL) { -#else - if(MyHandle > HINSTANCE_ERROR) { -#endif - // Winsock was loaded. - // Get the proc addresses for each needed function next. - int spTraverse; - for(spTraverse = 0; spTraverse < (int)sp_MaxProcs; spTraverse++) { - spArray[spTraverse] = GetProcAddress(MyHandle, spName[spTraverse]); - if ( NULL == spArray[spTraverse] ) - return iRetval;// Bad winsock? Bad function name? - } - - hWinsock = MyHandle; - // AllRight, attempt to make our first proxied call. - if(IsWinsockLoaded(sp_WSAStartup)) { - iRetval = ((sp_int_WORD_LPWSADATA)spArray[sp_WSAStartup])(wVersionRequested, lpWSAData); - } - - // If the return value is still an error at this point, we unload the DLL, - // so that we can act as though nothing happened and the user - // gets no network access. - if(iRetval != 0) { - // Clear out our proc array. - memset(spArray, 0, sizeof(spArray)); - - // Free up the winsock. - FreeLibrary(MyHandle); - MyHandle = NULL; - } - } -#ifndef _WIN32 - else { - // Failed to load. - // Set this to NULL so it is clear. - hWinsock = NULL; - } -#endif - - - // Check our return value, if it isn't success, then we need to fake - // our own winsock implementation. - if(iRetval != 0) { - // We always return success. - iRetval = 0; - - // Fill in the structure. - // Return the version requested as the version supported. - lpWSAData->wVersion = wVersionRequested; - lpWSAData->wHighVersion = wVersionRequested; - - // Fill in a discription. - strcpy(lpWSAData->szDescription, "Mozock DLL internal implementation."); - strcpy(lpWSAData->szSystemStatus, "Winsock running, allowing no network access."); - - // Report a nice round number for sockets and datagram sizes. - lpWSAData->iMaxSockets = 4096; - lpWSAData->iMaxUdpDg = 4096; - - // No vendor information. - lpWSAData->lpVendorInfo = NULL; - } - - return(iRetval); -} - -int PASCAL FAR WSACleanup(void) { - int iRetval = 0; - - // Handling normally or internally. - // When IsWinsockLoaded() is called and hWinsock is NULL, it winds up calling WSAStartup - // which wedges rpcrt4.dll on win95 with some winsock implementations. Bug: 81359. - if(hWinsock && IsWinsockLoaded(sp_WSACleanup)) { - // Call their cleanup routine. - // We could set the return value here, but it is meaning less. - // We always return success. - iRetval = ((sp_int_void)spArray[sp_WSACleanup])(); - //ASSERT(iRetval == 0); - iRetval = 0; - } - - // Wether or not it succeeded, we free off the library here. - // Clear out our proc table too. - memset(spArray, 0, sizeof(spArray)); - if(hWinsock != NULL) { - FreeLibrary(hWinsock); - hWinsock = NULL; - } - - return(iRetval); -} - -HANDLE PASCAL FAR WSAAsyncGetHostByName(HWND hWnd, unsigned int wMsg, const char FAR *name, char FAR *buf, int buflen) { - // Normal or shim. - if(IsWinsockLoaded(sp_WSAAsyncGetHostByName)) { - return(((sp_HANDLE_HWND_uint_ccharFARp_charFARp_int)spArray[sp_WSAAsyncGetHostByName])(hWnd, wMsg, name, buf, buflen)); - } - - // Must return error here. - // Set our last error value to be that the net is down. - WSASetLastError(WSAENETDOWN); - return(NULL); -} - -int PASCAL FAR WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent) { - // Normal or shim. - if(IsWinsockLoaded(sp_WSAAsyncSelect)) { - return(((sp_int_SOCKET_HWND_uint_long)spArray[sp_WSAAsyncSelect])(s, hWnd, wMsg, lEvent)); - } - - // Must return error here. - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR WSAGetLastError(void) { - // See if someone else can handle. - if(IsWinsockLoaded(sp_WSAGetLastError)) { - return(((sp_int_void)spArray[sp_WSAGetLastError])()); - } - -#ifndef _WIN32 - { - // Fake it. - int iRetval = ispError; - ispError = 0; - return(iRetval); - } -#else - // Use default OS handler. - return(GetLastError()); -#endif -} - -void PASCAL FAR WSASetLastError(int iError) { - // See if someone else can handle. - if(IsWinsockLoaded(sp_WSASetLastError)) { - ((sp_void_int)spArray[sp_WSASetLastError])(iError); - return; - } - -#ifndef _WIN32 - // Fake it. - ispError = iError; - return; -#else - // Use default OS handler. - SetLastError(iError); - return; -#endif -} - -int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set) { - int i; - - // See if someone else will handle. - if(IsWinsockLoaded(sp___WSAFDIsSet)) { - return(((sp_int_SOCKET_fdsetFARp)spArray[sp___WSAFDIsSet])(fd, set)); - } - - // Default implementation. - i = set->fd_count; - while (i--) { - if (set->fd_array[i] == fd) { - return 1; - } - } - return 0; -} - -SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen) { - // Internally or shim - NON_BLOCKING( - (((sp_SOCKET_SOCKET_sockaddrFARp_intFARp)spArray[sp_accept])(s, addr, addrlen)), - FD_ACCEPT, sp_accept, SOCKET); - - // Fail. - WSASetLastError(WSAENETDOWN); - return(INVALID_SOCKET); -} - -int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR *name, int namelen) { - // Internally or shim - if(IsWinsockLoaded(sp_bind)) { - return(((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_bind])(s, name, namelen)); - } - - // Fail. - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR closesocket(SOCKET s) { - // Internally or shim. - NON_BLOCKING( - (((sp_int_SOCKET)spArray[sp_closesocket])(s)), - FD_CLOSE, sp_closesocket, int); - - // Error. - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR *name, int namelen) { - // Internally or shim. - if(IsWinsockLoaded(sp_connect)) { - /* This could block and so it would seem that the NON_BLOCK - * macro should be used here. However it was causing a crash - * and so it was decided to allow blocking here instead - */ - return (((sp_int_SOCKET_csockaddrFARp_int)spArray[sp_connect])(s, name, namelen)); - } - - // Err. - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -struct hostent FAR * PASCAL FAR gethostbyname(const char FAR *name) { - if(IsWinsockLoaded(sp_gethostbyname)) { - return(((sp_hostentFARp_ccharFARp)spArray[sp_gethostbyname])(name)); - } - - WSASetLastError(WSAENETDOWN); - return(NULL); -} - -struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR *addr, int len, int type) { - if(IsWinsockLoaded(sp_gethostbyaddr)) { - return(((sp_hostentFARp_ccharFARp_int_int)spArray[sp_gethostbyaddr])(addr, len, type)); - } - - WSASetLastError(WSAENETDOWN); - return(NULL); -} - -int PASCAL FAR gethostname(char FAR *name, int namelen) { - if(IsWinsockLoaded(sp_gethostname)) { - return(((sp_int_charFARp_int)spArray[sp_gethostname])(name, namelen)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR getpeername(SOCKET s, struct sockaddr FAR *name, int FAR *namelen) { - if(IsWinsockLoaded(sp_getpeername)) { - return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getpeername])(s, name, namelen)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR getsockname(SOCKET s, struct sockaddr FAR *name, int FAR *namelen) { - if(IsWinsockLoaded(sp_getsockname)) { - return(((sp_int_SOCKET_sockaddrFARp_intFARp)spArray[sp_getsockname])(s, name, namelen)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR getsockopt(SOCKET s, int level, int optname, char FAR *optval, int FAR *optlen) { - if(IsWinsockLoaded(sp_getsockopt)) { - return(((sp_int_SOCKET_int_int_charFARp_intFARp)spArray[sp_getsockopt])(s, level, optname, optval, optlen)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -struct protoent FAR * PASCAL getprotobyname(const char FAR * name) { - if(IsWinsockLoaded(sp_getprotobyname)) { - return(((sp_protoentFARcchar)spArray[sp_getprotobyname])(name)); - } - - WSASetLastError(WSAENETDOWN); - return NULL; -} - -u_long PASCAL FAR htonl(u_long hostlong) { - if(IsWinsockLoaded(sp_htonl)) { - return(((sp_ulong_ulong)spArray[sp_htonl])(hostlong)); - } - -#ifndef _WIN32 - return - (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) + - ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24)); - -#else - // Just return what was passed in. - return(hostlong); -#endif -} - -u_short PASCAL FAR htons(u_short hostshort) { - if(IsWinsockLoaded(sp_htons)) { - return(((sp_ushort_ushort)spArray[sp_htons])(hostshort)); - } - -#ifndef _WIN32 - return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8)); - -#else - // Just return what was passed in. - return(hostshort); -#endif -} - -u_long PASCAL FAR ntohl(u_long hostlong) { - if(IsWinsockLoaded(sp_ntohl)) { - return(((sp_ulong_ulong)spArray[sp_ntohl])(hostlong)); - } - -#ifndef _WIN32 - return - (((hostlong&0xff)<<24) + ((hostlong&0xff00)<<8) + - ((hostlong&0xff0000)>>8) + ((hostlong&0xff000000)>>24)); - -#else - // Just return what was passed in. - return(hostlong); -#endif -} - -u_short PASCAL FAR ntohs(u_short hostshort) { - if(IsWinsockLoaded(sp_ntohs)) { - return(((sp_ushort_ushort)spArray[sp_ntohs])(hostshort)); - } - -#ifndef _WIN32 - return (((hostshort&0xff)<<8) + ((hostshort&0xff00)>>8)); - -#else - // Just return what was passed in. - return(hostshort); -#endif -} - -unsigned long PASCAL FAR inet_addr(const char FAR *cp) { - if(IsWinsockLoaded(sp_inet_addr)) { - return(((sp_ulong_ccharFARp)spArray[sp_inet_addr])(cp)); - } - - return(INADDR_NONE); -} - -int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) { - if(IsWinsockLoaded(sp_ioctlsocket)) { - return(((sp_int_SOCKET_long_ulongFARp)spArray[sp_ioctlsocket])(s, cmd, argp)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR listen(SOCKET s, int backlog) { - if(IsWinsockLoaded(sp_listen)) { - return(((sp_int_SOCKET_int)spArray[sp_listen])(s, backlog)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags) { - NON_BLOCKING( - (((sp_int_SOCKET_charFARp_int_int)spArray[sp_recv])(s, buf, len, flags)), - FD_READ, sp_recv, int); - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout) { - // If there's nothing to do, stop now before we go off into dll land. - // Optimization, boyz. - if((readfds && readfds->fd_count) || (writefds && writefds->fd_count) || (exceptfds && exceptfds->fd_count)) { - if(IsWinsockLoaded(sp_select)) { - return(((sp_int_int_fdsetFARp_fdsetFARp_fdsetFARp_ctimevalFARp)spArray[sp_select])(nfds,readfds,writefds,exceptfds,timeout)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); - } - - // No need to go to the DLL, there is nothing to do. - return(0); -} - -int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags) { - NON_BLOCKING( - - (((sp_int_SOCKET_ccharFARp_int_int)spArray[sp_send])(s, buf, len, flags)), - FD_WRITE, sp_send, int); - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR setsockopt(SOCKET s, int level, int optname, const char FAR *optval, int optlen) { - if(IsWinsockLoaded(sp_setsockopt)) { - return(((sp_int_SOCKET_int_int_ccharFARp_int)spArray[sp_setsockopt])(s, level, optname, optval, optlen)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -int PASCAL FAR shutdown(SOCKET s, int how) { - if(IsWinsockLoaded(sp_shutdown)) { - return(((sp_int_SOCKET_int)spArray[sp_shutdown])(s, how)); - } - - WSASetLastError(WSAENETDOWN); - return(SOCKET_ERROR); -} - -SOCKET PASCAL FAR socket(int af, int type, int protocol) { - if(IsWinsockLoaded(sp_socket)) { - return(((sp_SOCKET_int_int_int)spArray[sp_socket])(af, type, protocol)); - } - - WSASetLastError(WSAENETDOWN); - return(INVALID_SOCKET); -} - -char FAR * PASCAL FAR inet_ntoa(struct in_addr in) { - if(IsWinsockLoaded(sp_inet_ntoa)) { - return ((sp_charFARp_in_addr)spArray[sp_inet_ntoa])(in); - } - - WSASetLastError(WSAENETDOWN); - return NULL; -} diff --git a/ldap/c-sdk/libraries/libldap/nsprthreadtest.c b/ldap/c-sdk/libraries/libldap/nsprthreadtest.c deleted file mode 100644 index f9af68b423..0000000000 --- a/ldap/c-sdk/libraries/libldap/nsprthreadtest.c +++ /dev/null @@ -1,621 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include -#include -#include - -#define NAME "cn=Directory Manager" -#define PASSWORD "secret99" -#define BASE "dc=example,dc=com" - -static int simplebind( LDAP *ld, char *msg, int tries ); -static void search_thread( void * ); -static void modify_thread( void * ); -static void add_thread( void * ); -static void delete_thread( void * ); -static void set_ld_error(); -static int get_ld_error(); -static void set_errno(); -static int get_errno(); -static void tsd_setup(); -static void *my_mutex_alloc( void ); -static void my_mutex_free( void * ); -static int my_mutex_lock( void * ); -static int my_mutex_unlock( void * ); -static LDAPHostEnt *my_gethostbyname( const char *name, LDAPHostEnt *result, - char *buffer, int buflen, int *statusp, void *extradata ); -static LDAPHostEnt *my_gethostbyaddr( const char *addr, int length, - int type, LDAPHostEnt *result, char *buffer, int buflen, - int *statusp, void *extradata ); -static LDAPHostEnt *copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp, - PRHostEnt *prhp ); - -typedef struct ldapmsgwrapper { - LDAPMessage *lmw_messagep; - struct ldapmsgwrapper *lmw_next; -} ldapmsgwrapper; - - -#define CONNECTION_ERROR( lderr ) ( (lderr) == LDAP_SERVER_DOWN || \ - (lderr) == LDAP_CONNECT_ERROR ) - - -LDAP *ld; -PRUintn tsdindex; -#ifdef LDAP_MEMCACHE -LDAPMemCache *memcache = NULL; -#define MEMCACHE_SIZE (256*1024) /* 256K bytes */ -#define MEMCACHE_TTL (15*60) /* 15 minutes */ -#endif - - -main( int argc, char **argv ) -{ - PRThread *search_tid, *search_tid2, *search_tid3; - PRThread *search_tid4, *modify_tid, *add_tid; - PRThread *delete_tid; - struct ldap_thread_fns tfns; - struct ldap_dns_fns dnsfns; - int rc; - - if ( argc != 3 ) { - fprintf( stderr, "usage: %s host port\n", argv[0] ); - exit( 1 ); - } - - PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0 ); - if ( PR_NewThreadPrivateIndex( &tsdindex, NULL ) != PR_SUCCESS ) { - perror( "PR_NewThreadPrivateIndex" ); - exit( 1 ); - } - tsd_setup(); /* for main thread */ - - if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) { - perror( "ldap_open" ); - exit( 1 ); - } - - /* set thread function pointers */ - memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); - tfns.ltf_mutex_alloc = my_mutex_alloc; - tfns.ltf_mutex_free = my_mutex_free; - tfns.ltf_mutex_lock = my_mutex_lock; - tfns.ltf_mutex_unlock = my_mutex_unlock; - tfns.ltf_get_errno = get_errno; - tfns.ltf_set_errno = set_errno; - tfns.ltf_get_lderrno = get_ld_error; - tfns.ltf_set_lderrno = set_ld_error; - tfns.ltf_lderrno_arg = NULL; - if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns ) - != 0 ) { - ldap_perror( ld, "ldap_set_option: thread functions" ); - exit( 1 ); - } - - /* set DNS function pointers */ - memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) ); - dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; - dnsfns.lddnsfn_gethostbyname = my_gethostbyname; - dnsfns.lddnsfn_gethostbyaddr = my_gethostbyaddr; - if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) - != 0 ) { - ldap_perror( ld, "ldap_set_option: DNS functions" ); - exit( 1 ); - } - -#ifdef LDAP_MEMCACHE - /* create the in-memory cache */ - if (( rc = ldap_memcache_init( MEMCACHE_TTL, MEMCACHE_SIZE, NULL, - &tfns, &memcache )) != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_memcache_init failed - %s\n", - ldap_err2string( rc )); - exit( 1 ); - } - if (( rc = ldap_memcache_set( ld, memcache )) != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_memcache_set failed - %s\n", - ldap_err2string( rc )); - exit( 1 ); - } -#endif - - /* - * set option so that the next call to ldap_simple_bind_s() after - * the server connection is lost will attempt to reconnect. - */ - if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) != 0 ) { - ldap_perror( ld, "ldap_set_option: reconnect" ); - exit( 1 ); - } - - /* initial bind */ - if ( simplebind( ld, "ldap_simple_bind_s/main", 1 ) != LDAP_SUCCESS ) { - exit( 1 ); - } - - /* create the operation threads */ - if ( (search_tid = PR_CreateThread( PR_USER_THREAD, search_thread, - "1", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread search_thread" ); - exit( 1 ); - } - if ( (modify_tid = PR_CreateThread( PR_USER_THREAD, modify_thread, - "2", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread modify_thread" ); - exit( 1 ); - } - if ( (search_tid2 = PR_CreateThread( PR_USER_THREAD, search_thread, - "3", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread search_thread 2" ); - exit( 1 ); - } - if ( (add_tid = PR_CreateThread( PR_USER_THREAD, add_thread, - "4", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread add_thread" ); - exit( 1 ); - } - if ( (search_tid3 = PR_CreateThread( PR_USER_THREAD, search_thread, - "5", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread search_thread 3" ); - exit( 1 ); - } - if ( (delete_tid = PR_CreateThread( PR_USER_THREAD, delete_thread, - "6", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread delete_thread" ); - exit( 1 ); - } - if ( (search_tid4 = PR_CreateThread( PR_USER_THREAD, search_thread, - "7", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, - 0 )) == NULL ) { - perror( "PR_CreateThread search_thread 4" ); - exit( 1 ); - } - - PR_Cleanup(); - return( 0 ); -} - - -static int -simplebind( LDAP *ld, char *msg, int tries ) -{ - int rc; - - while ( tries-- > 0 ) { - rc = ldap_simple_bind_s( ld, NAME, PASSWORD ); - if ( rc != LDAP_SUCCESS ) { - ldap_perror( ld, msg ); - } - if ( tries == 0 || !CONNECTION_ERROR( rc )) { - return( rc ); - } - fprintf( stderr, - "%s: sleeping for 5 secs - will try %d more time(s)...\n", - msg, tries ); - sleep( 5 ); - } - - return( rc ); -} - - -static void -search_thread( void *arg1 ) -{ - LDAPMessage *res; - LDAPMessage *e; - char *a; - char **v; - char *dn; - BerElement *ber; - int i, rc, msgid; - void *tsd; - char *id = arg1; - - printf( "search_thread\n" ); - tsd_setup(); - for ( ;; ) { - printf( "%sSearching...\n", id ); - if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, - "(objectclass=*)", NULL, 0 )) == -1 ) { - ldap_perror( ld, "ldap_search_s" ); - rc = ldap_get_lderrno( ld, NULL, NULL ); - if ( CONNECTION_ERROR( rc ) && simplebind( ld, - "bind-search_thread", 5 ) != LDAP_SUCCESS ) { - return; - } - continue; - } - while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) - == LDAP_RES_SEARCH_ENTRY ) { - for ( e = ldap_first_entry( ld, res ); e != NULL; - e = ldap_next_entry( ld, e ) ) { - dn = ldap_get_dn( ld, e ); - /* printf( "%sdn: %s\n", id, dn ); */ - free( dn ); - for ( a = ldap_first_attribute( ld, e, &ber ); - a != NULL; a = ldap_next_attribute( ld, e, - ber ) ) { - v = ldap_get_values( ld, e, a ); - for ( i = 0; v && v[i] != 0; i++ ) { - /* - printf( "%s%s: %s\n", id, a, - v[i] ); - */ - } - ldap_value_free( v ); - ldap_memfree( a ); - } - if ( ber != NULL ) { - ber_free( ber, 0 ); - } - } - ldap_msgfree( res ); - /* printf( "%s\n", id ); */ - } - - if ( rc == -1 || ldap_result2error( ld, res, 0 ) != - LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_search" ); - } else { - printf( "%sDone with one round\n", id ); - } - - if ( rc == -1 ) { - rc = ldap_get_lderrno( ld, NULL, NULL ); - if ( CONNECTION_ERROR( rc ) && simplebind( ld, - "bind-search_thread", 5 ) != LDAP_SUCCESS ) { - return; - } - } - } -} - -static void -modify_thread( void *arg1 ) -{ - LDAPMessage *res; - LDAPMessage *e; - int i, modentry, entries, msgid, rc; - LDAPMod mod; - LDAPMod *mods[2]; - char *vals[2]; - char *dn; - char *id = arg1; - ldapmsgwrapper *list, *lmwp, *lastlmwp; - - printf( "modify_thread\n" ); - tsd_setup(); - if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, - "(objectclass=*)", NULL, 0 )) == -1 ) { - ldap_perror( ld, "ldap_search_s" ); - exit( 1 ); - } - entries = 0; - list = lastlmwp = NULL; - while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) - == LDAP_RES_SEARCH_ENTRY ) { - entries++; - if (( lmwp = (ldapmsgwrapper *) - malloc( sizeof( ldapmsgwrapper ))) == NULL ) { - perror( "modify_thread: malloc" ); - exit( 1 ); - } - lmwp->lmw_messagep = res; - lmwp->lmw_next = NULL; - if ( lastlmwp == NULL ) { - list = lastlmwp = lmwp; - } else { - lastlmwp->lmw_next = lmwp; - } - lastlmwp = lmwp; - } - if ( rc == -1 || ldap_result2error( ld, res, 0 ) != LDAP_SUCCESS ) { - ldap_perror( ld, "modify_thread: ldap_search" ); - exit( 1 ); - } else { - entries++; - printf( "%sModify got %d entries\n", id, entries ); - } - - mods[0] = &mod; - mods[1] = NULL; - vals[0] = "bar"; - vals[1] = NULL; - for ( ;; ) { - modentry = rand() % entries; - for ( i = 0, lmwp = list; lmwp != NULL && i < modentry; - i++, lmwp = lmwp->lmw_next ) { - /* NULL */ - } - - if ( lmwp == NULL ) { - fprintf( stderr, - "%sModify could not find entry %d of %d\n", - id, modentry, entries ); - continue; - } - e = lmwp->lmw_messagep; - printf( "%sPicked entry %d of %d\n", id, i, entries ); - dn = ldap_get_dn( ld, e ); - mod.mod_op = LDAP_MOD_REPLACE; - mod.mod_type = "description"; - mod.mod_values = vals; - printf( "%sModifying (%s)\n", id, dn ); - if (( rc = ldap_modify_s( ld, dn, mods )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_modify_s" ); - if ( CONNECTION_ERROR( rc ) && simplebind( ld, - "bind-modify_thread", 5 ) != LDAP_SUCCESS ) { - return; - } - } - free( dn ); - } -} - -static void -add_thread( void *arg1 ) -{ - LDAPMod mod[5]; - LDAPMod *mods[6]; - char dn[BUFSIZ], name[40]; - char *cnvals[2], *snvals[2], *ocvals[2]; - int i, rc; - char *id = arg1; - - printf( "add_thread\n" ); - tsd_setup(); - for ( i = 0; i < 5; i++ ) { - mods[i] = &mod[i]; - } - mods[5] = NULL; - mod[0].mod_op = 0; - mod[0].mod_type = "cn"; - mod[0].mod_values = cnvals; - cnvals[1] = NULL; - mod[1].mod_op = 0; - mod[1].mod_type = "sn"; - mod[1].mod_values = snvals; - snvals[1] = NULL; - mod[2].mod_op = 0; - mod[2].mod_type = "objectclass"; - mod[2].mod_values = ocvals; - ocvals[0] = "person"; - ocvals[1] = NULL; - mods[3] = NULL; - - for ( ;; ) { - sprintf( name, "%d", rand() ); - sprintf( dn, "cn=%s, " BASE, name ); - cnvals[0] = name; - snvals[0] = name; - - printf( "%sAdding entry (%s)\n", id, dn ); - if (( rc = ldap_add_s( ld, dn, mods )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_add_s" ); - if ( CONNECTION_ERROR( rc ) && simplebind( ld, - "bind-add_thread", 5 ) != LDAP_SUCCESS ) { - return; - } - } - } -} - -static void -delete_thread( void *arg1 ) -{ - LDAPMessage *res; - char dn[BUFSIZ], name[40]; - int entries, msgid, rc; - char *id = arg1; - - printf( "delete_thread\n" ); - tsd_setup(); - if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE, - "(objectclass=*)", NULL, 0 )) == -1 ) { - ldap_perror( ld, "delete_thread: ldap_search_s" ); - exit( 1 ); - } - entries = 0; - while ( (rc = ldap_result( ld, msgid, 0, NULL, &res )) - == LDAP_RES_SEARCH_ENTRY ) { - entries++; - ldap_msgfree( res ); - } - entries++; - if ( rc == -1 || ldap_result2error( ld, res, 1 ) != LDAP_SUCCESS ) { - ldap_perror( ld, "delete_thread: ldap_search" ); - } else { - printf( "%sDelete got %d entries\n", id, entries ); - } - - for ( ;; ) { - sprintf( name, "%d", rand() ); - sprintf( dn, "cn=%s, " BASE, name ); - - printf( "%sDeleting entry (%s)\n", id, dn ); - if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_delete_s" ); - if ( CONNECTION_ERROR( rc ) && simplebind( ld, - "bind-delete_thread", 5 ) != LDAP_SUCCESS ) { - return; - } - } - } -} - -struct ldap_error { - int le_errno; - char *le_matched; - char *le_errmsg; -}; - -static void -tsd_setup() -{ - void *tsd; - - tsd = (void *) PR_GetThreadPrivate( tsdindex ); - if ( tsd != NULL ) { - fprintf( stderr, "tsd non-null!\n" ); - exit( 1 ); - } - tsd = (void *) calloc( 1, sizeof(struct ldap_error) ); - if ( PR_SetThreadPrivate( tsdindex, tsd ) != 0 ) { - perror( "PR_SetThreadPrivate" ); - exit( 1 ); - } -} - -static void -set_ld_error( int err, char *matched, char *errmsg, void *dummy ) -{ - struct ldap_error *le; - - le = (void *) PR_GetThreadPrivate( tsdindex ); - le->le_errno = err; - if ( le->le_matched != NULL ) { - ldap_memfree( le->le_matched ); - } - le->le_matched = matched; - if ( le->le_errmsg != NULL ) { - ldap_memfree( le->le_errmsg ); - } - le->le_errmsg = errmsg; -} - -static int -get_ld_error( char **matchedp, char **errmsgp, void *dummy ) -{ - struct ldap_error *le; - - le = PR_GetThreadPrivate( tsdindex ); - if ( matchedp != NULL ) { - *matchedp = le->le_matched; - } - if ( errmsgp != NULL ) { - *errmsgp = le->le_errmsg; - } - return( le->le_errno ); -} - -static void -set_errno( int oserrno ) -{ - /* XXXmcs: should this be PR_SetError( oserrno, 0 )? */ - PR_SetError( PR_UNKNOWN_ERROR, oserrno ); -} - -static int -get_errno( void ) -{ - /* XXXmcs: should this be PR_GetError()? */ - return( PR_GetOSError()); -} - -static void * -my_mutex_alloc( void ) -{ - return( (void *)PR_NewLock()); -} - -static void -my_mutex_free( void *mutex ) -{ - PR_DestroyLock( (PRLock *)mutex ); -} - -static int -my_mutex_lock( void *mutex ) -{ - PR_Lock( (PRLock *)mutex ); - return( 0 ); -} - -static int -my_mutex_unlock( void *mutex ) -{ - if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) { - return( -1 ); - } - - return( 0 ); -} - -static LDAPHostEnt * -my_gethostbyname( const char *name, LDAPHostEnt *result, - char *buffer, int buflen, int *statusp, void *extradata ) -{ - PRHostEnt prhent; - - if ( PR_GetHostByName( name, buffer, buflen, - &prhent ) != PR_SUCCESS ) { - return( NULL ); - } - - return( copyPRHostEnt2LDAPHostEnt( result, &prhent )); -} - -static LDAPHostEnt * -my_gethostbyaddr( const char *addr, int length, int type, LDAPHostEnt *result, - char *buffer, int buflen, int *statusp, void *extradata ) -{ - PRHostEnt prhent; - - if ( PR_GetHostByAddr( (PRNetAddr *)addr, buffer, buflen, - &prhent ) != PR_SUCCESS ) { - return( NULL ); - } - - return( copyPRHostEnt2LDAPHostEnt( result, &prhent )); -} - -static LDAPHostEnt * -copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp, PRHostEnt *prhp ) -{ - ldhp->ldaphe_name = prhp->h_name; - ldhp->ldaphe_aliases = prhp->h_aliases; - ldhp->ldaphe_addrtype = prhp->h_addrtype; - ldhp->ldaphe_length = prhp->h_length; - ldhp->ldaphe_addr_list = prhp->h_addr_list; - return( ldhp ); -} diff --git a/ldap/c-sdk/libraries/libldap/open.c b/ldap/c-sdk/libraries/libldap/open.c deleted file mode 100644 index 06cb629cbb..0000000000 --- a/ldap/c-sdk/libraries/libldap/open.c +++ /dev/null @@ -1,912 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * open.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" -#ifdef LDAP_SASLIO_HOOKS -/* Valid for any ANSI C compiler */ -#include -extern sasl_callback_t client_callbacks[]; -#endif - -#define VI_PRODUCTVERSION 3 - -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK ((unsigned long) 0x7f000001) -#endif - -#ifdef LDAP_DEBUG -int ldap_debug = 0; -#endif - -#ifdef _WINDOWS -#define USE_WINDOWS_TLS /* thread local storage */ -#endif - -/* - * global defaults for callbacks are stored here. callers of the API set - * these by passing a NULL "ld" to ldap_set_option(). Everything in - * nsldapi_ld_defaults can be overridden on a per-ld basis as well (the - * memory allocation functions are global to all ld's). - */ -struct ldap nsldapi_ld_defaults; -struct ldap_memalloc_fns nsldapi_memalloc_fns = { 0, 0, 0, 0 }; -int nsldapi_initialized = 0; - -#ifdef USE_PTHREADS -#include -#ifdef VMS -/* -** pthread_self() is not a routine on OpenVMS; it's inline assembler code. -** Since we need a real address which we can stuff away into a table, we need -** to make sure that pthread_self maps to the real pthread_self routine (yes, -** we do have one fortunately). -*/ -#undef pthread_self -#define pthread_self PTHREAD_SELF -extern pthread_t pthread_self (void); -#endif -static pthread_key_t nsldapi_key; -static pthread_mutex_t nsldapi_init_mutex = PTHREAD_MUTEX_INITIALIZER; - -struct nsldapi_ldap_error { - int le_errno; - char *le_matched; - char *le_errmsg; -}; -#elif defined (USE_WINDOWS_TLS) -static DWORD dwTlsIndex; -struct nsldapi_ldap_error { - int le_errno; - char *le_matched; - char *le_errmsg; -}; -#elif defined (_WINDOWS) /* use static tls */ -__declspec ( thread ) int nsldapi_gldaperrno; -__declspec ( thread ) char *nsldapi_gmatched = NULL; -__declspec ( thread ) char *nsldapi_gldaperror = NULL; -#endif /* USE_WINDOWS_TLS */ - - -#ifdef _WINDOWS -#define LDAP_MUTEX_T HANDLE -static LDAP_MUTEX_T nsldapi_init_mutex; - -int -pthread_mutex_init( LDAP_MUTEX_T *mp, void *attr) -{ - if ( (*mp = CreateMutex(NULL, FALSE, NULL)) == NULL ) - return( 1 ); - else - return( 0 ); -} - -static void * -pthread_mutex_alloc( void ) -{ - LDAP_MUTEX_T *mutexp; - - if ( (mutexp = malloc( sizeof(LDAP_MUTEX_T) )) != NULL ) { - pthread_mutex_init( mutexp, NULL ); - } - return( mutexp ); -} - -int -pthread_mutex_destroy( LDAP_MUTEX_T *mp ) -{ - if ( !(CloseHandle(*mp)) ) - return( 1 ); - else - return( 0 ); -} - -static void -pthread_mutex_free( void *mutexp ) -{ - pthread_mutex_destroy( (LDAP_MUTEX_T *) mutexp ); - free( mutexp ); -} - -int -pthread_mutex_lock( LDAP_MUTEX_T *mp ) -{ - if ( (WaitForSingleObject(*mp, INFINITE) != WAIT_OBJECT_0) ) - return( 1 ); - else - return( 0 ); -} - -int -pthread_mutex_unlock( LDAP_MUTEX_T *mp ) -{ - if ( !(ReleaseMutex(*mp)) ) - return( 1 ); - else - return( 0 ); -} - -static int -get_errno( void ) -{ - return errno; -} - -static void -set_errno( int Errno ) -{ - errno = Errno; -} - -#ifdef USE_WINDOWS_TLS -static void -set_ld_error( int err, char *matched, char *errmsg, void *dummy ) -{ - struct nsldapi_ldap_error *le; - void *tsd; - - le = TlsGetValue( dwTlsIndex ); - - if (le == NULL) { - tsd = (void *)calloc(1, sizeof(struct nsldapi_ldap_error)); - TlsSetValue( dwTlsIndex, tsd ); - } - - le = TlsGetValue ( dwTlsIndex ); - - if (le == NULL) - return; - - le->le_errno = err; - - if ( le->le_matched != NULL ) { - ldap_memfree( le->le_matched ); - } - le->le_matched = matched; - - if ( le->le_errmsg != NULL ) { - ldap_memfree( le->le_errmsg ); - } - le->le_errmsg = errmsg; -} - -static int -get_ld_error ( char **matched, char **errmsg, void *dummy ) -{ - struct nsldapi_ldap_error *le; - - le = TlsGetValue( dwTlsIndex ); - if ( matched != NULL ) { - *matched = le->le_matched; - } - - if ( errmsg != NULL ) { - *errmsg = le->le_errmsg; - } - - return( le->le_errno ); -} -#else -static int -get_ld_error( char **LDMatched, char **LDError, void * Args ) -{ - if ( LDMatched != NULL ) - { - *LDMatched = nsldapi_gmatched; - } - if ( LDError != NULL ) - { - *LDError = nsldapi_gldaperror; - } - return nsldapi_gldaperrno; -} - -static void -set_ld_error( int LDErrno, char * LDMatched, char * LDError, - void * Args ) -{ - /* Clean up any previous string storage. */ - if ( nsldapi_gmatched != NULL ) - { - ldap_memfree( nsldapi_gmatched ); - } - if ( nsldapi_gldaperror != NULL ) - { - ldap_memfree( nsldapi_gldaperror ); - } - - nsldapi_gldaperrno = LDErrno; - nsldapi_gmatched = LDMatched; - nsldapi_gldaperror = LDError; -} -#endif /* USE_WINDOWS_TLS */ -#endif /* ! _WINDOWS */ - -#ifdef USE_PTHREADS -static void * -pthread_mutex_alloc( void ) -{ - pthread_mutex_t *mutexp; - - if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { - pthread_mutex_init( mutexp, NULL ); - } - return( mutexp ); -} - -static void -pthread_mutex_free( void *mutexp ) -{ - pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); - free( mutexp ); -} - -static void -set_ld_error( int err, char *matched, char *errmsg, void *dummy ) -{ - struct nsldapi_ldap_error *le; - void *tsd; - - le = pthread_getspecific( nsldapi_key ); - - if (le == NULL) { - tsd = (void *)calloc(1, sizeof(struct nsldapi_ldap_error)); - pthread_setspecific( nsldapi_key, tsd ); - } - - le = pthread_getspecific( nsldapi_key ); - - if (le == NULL) - return; - - le->le_errno = err; - - if ( le->le_matched != NULL ) { - ldap_memfree( le->le_matched ); - } - le->le_matched = matched; - - if ( le->le_errmsg != NULL ) { - ldap_memfree( le->le_errmsg ); - } - le->le_errmsg = errmsg; -} - -static int -get_ld_error( char **matched, char **errmsg, void *dummy ) -{ - struct nsldapi_ldap_error *le; - - le = pthread_getspecific( nsldapi_key ); - - if (le == NULL) - return( LDAP_SUCCESS ); - - if ( matched != NULL ) { - *matched = le->le_matched; - } - if ( errmsg != NULL ) { - *errmsg = le->le_errmsg; - } - return( le->le_errno ); -} - -static void -set_errno( int err ) -{ - errno = err; -} - -static int -get_errno( void ) -{ - return( errno ); -} -#endif /* use_pthreads */ - -#if defined(USE_PTHREADS) || defined(_WINDOWS) -static struct ldap_thread_fns - nsldapi_default_thread_fns = { - (void *(*)(void))pthread_mutex_alloc, - (void (*)(void *))pthread_mutex_free, - (int (*)(void *))pthread_mutex_lock, - (int (*)(void *))pthread_mutex_unlock, - (int (*)(void))get_errno, - (void (*)(int))set_errno, - (int (*)(char **, char **, void *))get_ld_error, - (void (*)(int, char *, char *, void *))set_ld_error, - 0 }; - -static struct ldap_extra_thread_fns - nsldapi_default_extra_thread_fns = { - 0, 0, 0, 0, 0, -#ifdef _WINDOWS - 0 -#else - (void *(*)(void))pthread_self -#endif /* _WINDOWS */ - }; -#endif /* use_pthreads || _windows */ - -void -nsldapi_initialize_defaults( void ) -{ -#ifdef _WINDOWS - pthread_mutex_init( &nsldapi_init_mutex, NULL ); -#endif /* _WINDOWS */ - -#if defined(USE_PTHREADS) || defined(_WINDOWS) - pthread_mutex_lock( &nsldapi_init_mutex ); - - if ( nsldapi_initialized ) { - pthread_mutex_unlock( &nsldapi_init_mutex ); - return; - } -#else - if ( nsldapi_initialized ) { - return; - } -#endif /* use_pthreads || _windows */ - -#ifdef USE_PTHREADS - if ( pthread_key_create(&nsldapi_key, free ) != 0) { - perror("pthread_key_create"); - } -#elif defined(USE_WINDOWS_TLS) - dwTlsIndex = TlsAlloc(); -#endif /* USE_WINDOWS_TLS */ - - memset( &nsldapi_memalloc_fns, 0, sizeof( nsldapi_memalloc_fns )); - memset( &nsldapi_ld_defaults, 0, sizeof( nsldapi_ld_defaults )); - nsldapi_ld_defaults.ld_options = LDAP_BITOPT_REFERRALS; - nsldapi_ld_defaults.ld_version = LDAP_VERSION3; - nsldapi_ld_defaults.ld_lberoptions = LBER_OPT_USE_DER; - nsldapi_ld_defaults.ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; - -#ifdef LDAP_SASLIO_HOOKS - /* SASL default option settings */ - nsldapi_ld_defaults.ld_def_sasl_mech = NULL; - nsldapi_ld_defaults.ld_def_sasl_realm = NULL; - nsldapi_ld_defaults.ld_def_sasl_authcid = NULL; - nsldapi_ld_defaults.ld_def_sasl_authzid = NULL; - /* SASL Security properties */ - nsldapi_ld_defaults.ld_sasl_secprops.max_ssf = UINT_MAX; - nsldapi_ld_defaults.ld_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE; - nsldapi_ld_defaults.ld_sasl_secprops.security_flags = - SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; - - /* SASL mutex function callbacks */ - sasl_set_mutex( - (sasl_mutex_alloc_t *)nsldapi_default_thread_fns.ltf_mutex_alloc, - (sasl_mutex_lock_t *)nsldapi_default_thread_fns.ltf_mutex_lock, - (sasl_mutex_unlock_t *)nsldapi_default_thread_fns.ltf_mutex_unlock, - (sasl_mutex_free_t *)nsldapi_default_thread_fns.ltf_mutex_free ); - - /* SASL memory allocation function callbacks */ - sasl_set_alloc( - (sasl_malloc_t *)ldap_x_malloc, - (sasl_calloc_t *)ldap_x_calloc, - (sasl_realloc_t *)ldap_x_realloc, - (sasl_free_t *)ldap_x_free ); - - /* SASL library initialization */ - if ( sasl_client_init( client_callbacks ) != SASL_OK ) { - nsldapi_initialized = 0; - pthread_mutex_unlock( &nsldapi_init_mutex ); - return; - } -#endif - -#if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET ) - nsldapi_ld_defaults.ld_lberoptions |= LBER_OPT_TRANSLATE_STRINGS; -#if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET - ldap_set_string_translators( &nsldapi_ld_defaults, ldap_8859_to_t61, - ldap_t61_to_8859 ); -#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */ -#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */ - - /* set default connect timeout (in milliseconds) */ - /* this was picked as it is the standard tcp timeout as well */ - nsldapi_ld_defaults.ld_connect_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; - -#if defined(USE_PTHREADS) || defined(_WINDOWS) - /* load up default platform specific locking routines */ - if (ldap_set_option( &nsldapi_ld_defaults, LDAP_OPT_THREAD_FN_PTRS, - (void *)&nsldapi_default_thread_fns) != LDAP_SUCCESS) { - nsldapi_initialized = 0; - pthread_mutex_unlock( &nsldapi_init_mutex ); - return; - } - -#ifndef _WINDOWS - /* load up default threadid function */ - if (ldap_set_option( &nsldapi_ld_defaults, LDAP_OPT_EXTRA_THREAD_FN_PTRS, - (void *)&nsldapi_default_extra_thread_fns) != LDAP_SUCCESS) { - nsldapi_initialized = 0; - pthread_mutex_unlock( &nsldapi_init_mutex ); - return; - } -#endif /* _WINDOWS */ - nsldapi_initialized = 1; - pthread_mutex_unlock( &nsldapi_init_mutex ); -#else - nsldapi_initialized = 1; -#endif /* use_pthreads || _windows */ -} - - -/* - * ldap_version - report version levels for important properties - * This function is deprecated. Use ldap_get_option( ..., LDAP_OPT_API_INFO, - * ... ) instead. - * - * Example: - * LDAPVersion ver; - * ldap_version( &ver ); - * if ( (ver.sdk_version < 100) || (ver.SSL_version < 300) ) - * fprintf( stderr, "LDAP SDK level insufficient\n" ); - * - * or: - * if ( ldap_version(NULL) < 100 ) - * fprintf( stderr, "LDAP SDK level insufficient\n" ); - * - */ - -int -LDAP_CALL -ldap_version( LDAPVersion *ver ) -{ - if ( NULL != ver ) - { - memset( ver, 0, sizeof(*ver) ); - ver->sdk_version = (int)(VI_PRODUCTVERSION * 100); - ver->protocol_version = LDAP_VERSION_MAX * 100; - ver->SSL_version = SSL_VERSION * 100; - /* - * set security to none by default - */ - - ver->security_level = LDAP_SECURITY_NONE; -#if defined(LINK_SSL) -#if defined(NS_DOMESTIC) - ver->security_level = 128; -#elif defined(NSS_EXPORT) - ver->security_level = 40; -#endif -#endif - - } - return (int)(VI_PRODUCTVERSION * 100); -} - -/* - * ldap_open - initialize and connect to an ldap server. 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( hostname, port ); - */ - -LDAP * -LDAP_CALL -ldap_open( const char *host, int port ) -{ - LDAP *ld; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 ); - - if (( ld = ldap_init( host, port )) == NULL ) { - return( NULL ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - ldap_ld_free( ld, NULL, NULL, 0 ); - return( NULL ); - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n", - ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 ); - - return( ld ); -} - - -/* - * ldap_init - initialize the LDAP library. A magic cookie to be used for - * future communication is returned on success, NULL on failure. - * "defhost" may be a space-separated list of hosts or IP addresses - * - * NOTE: If you want to use IPv6, you must use prldap creating a LDAP handle - * with prldap_init instead of ldap_init. Or install the NSPR functions - * by calling prldap_install_routines. (See the nspr samples in examples) - * - * Example: - * LDAP *ld; - * ld = ldap_init( default_hostname, default_port ); - */ -LDAP * -LDAP_CALL -ldap_init( const char *defhost, int defport ) -{ - LDAP *ld; - - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - - if ( defport < 0 || defport > LDAP_PORT_MAX ) { - LDAPDebug( LDAP_DEBUG_ANY, - "ldap_init: port %d is invalid (port numbers must range from 1 to %d)\n", - defport, LDAP_PORT_MAX, 0 ); -#if !defined( macintosh ) && !defined( DOS ) && !defined( BEOS ) - errno = EINVAL; -#endif - return( NULL ); - } - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); - - if ( (ld = (LDAP*)NSLDAPI_MALLOC( sizeof(struct ldap) )) == NULL ) { - return( NULL ); - } - - /* copy defaults */ - SAFEMEMCPY( ld, &nsldapi_ld_defaults, sizeof( struct ldap )); - if ( nsldapi_ld_defaults.ld_io_fns_ptr != NULL ) { - if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_MALLOC( - sizeof( struct ldap_io_fns ))) == NULL ) { - NSLDAPI_FREE( (char *)ld ); - return( NULL ); - } - /* struct copy */ - *(ld->ld_io_fns_ptr) = *(nsldapi_ld_defaults.ld_io_fns_ptr); - } - - /* call the new handle I/O callback if one is defined */ - if ( ld->ld_extnewhandle_fn != NULL ) { - /* - * We always pass the session extended I/O argument to - * the new handle callback. - */ - if ( ld->ld_extnewhandle_fn( ld, ld->ld_ext_session_arg ) - != LDAP_SUCCESS ) { - NSLDAPI_FREE( (char*)ld ); - return( NULL ); - } - } - - /* allocate session-specific resources */ - if (( ld->ld_sbp = ber_sockbuf_alloc()) == NULL || - ( defhost != NULL && - ( ld->ld_defhost = nsldapi_strdup( defhost )) == NULL ) || - ((ld->ld_mutex = (void **) NSLDAPI_CALLOC( LDAP_MAX_LOCK, sizeof(void *))) == NULL )) { - if ( ld->ld_sbp != NULL ) { - ber_sockbuf_free( ld->ld_sbp ); - } - if( ld->ld_mutex != NULL ) { - NSLDAPI_FREE( ld->ld_mutex ); - } - NSLDAPI_FREE( (char*)ld ); - return( NULL ); - } - - /* install Sockbuf I/O functions if set in LDAP * */ - if ( ld->ld_extread_fn != NULL || ld->ld_extwrite_fn != NULL ) { - struct lber_x_ext_io_fns lberiofns; - - memset( &lberiofns, 0, sizeof( lberiofns )); - - lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - lberiofns.lbextiofn_read = ld->ld_extread_fn; - lberiofns.lbextiofn_write = ld->ld_extwrite_fn; - lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; - lberiofns.lbextiofn_socket_arg = NULL; - ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, - (void *)&lberiofns ); - } - - /* allocate mutexes */ - nsldapi_mutex_alloc_all( ld ); - - /* set default port */ - ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport; - - return( ld ); -} - - -void -nsldapi_mutex_alloc_all( LDAP *ld ) -{ - int i; - - if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { - for ( i = 0; ild_mutex[i] = LDAP_MUTEX_ALLOC( ld ); - ld->ld_mutex_threadid[i] = (void *) -1; - ld->ld_mutex_refcnt[i] = 0; - } - } -} - - -void -nsldapi_mutex_free_all( LDAP *ld ) -{ - int i; - - if ( ld != &nsldapi_ld_defaults && ld->ld_mutex != NULL ) { - for ( i = 0; ild_mutex[i] ); - } - } -} - - -/* returns 0 if connection opened and -1 if an error occurs */ -int -nsldapi_open_ldap_defconn( LDAP *ld ) -{ - LDAPServer *srv; - - if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == - NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = - nsldapi_strdup( ld->ld_defhost )) == NULL )) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - srv->lsrv_port = ld->ld_defport; - - if (( ld->ld_options & LDAP_BITOPT_SSL ) != 0 ) { - srv->lsrv_options |= LDAP_SRV_OPT_SECURE; - } - - if (( ld->ld_defconn = nsldapi_new_connection( ld, &srv, 1, 1, 0 )) - == NULL ) { - if ( ld->ld_defhost != NULL ) { - NSLDAPI_FREE( srv->lsrv_host ); - } - NSLDAPI_FREE( (char *)srv ); - return( -1 ); - } - ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ - - return( 0 ); -} - - -struct ldap_x_hostlist_status { - char *lhs_hostlist; - char *lhs_nexthost; - int lhs_defport; -}; - -/* - * Return the first host and port in hostlist (setting *hostp and *portp). - * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). - * Note that a NULL or zero-length hostlist causes the host "127.0.0.1" to - * be returned. - */ -int LDAP_CALL -ldap_x_hostlist_first( const char *hostlist, int defport, char **hostp, - int *portp, struct ldap_x_hostlist_status **statusp ) -{ - - if ( NULL == hostp || NULL == portp || NULL == statusp ) { - return( LDAP_PARAM_ERROR ); - } - - if ( NULL == hostlist || *hostlist == '\0' ) { - *hostp = nsldapi_strdup( "127.0.0.1" ); - if ( NULL == *hostp ) { - return( LDAP_NO_MEMORY ); - } - *portp = defport; - *statusp = NULL; - return( LDAP_SUCCESS ); - } - - *statusp = NSLDAPI_CALLOC( 1, sizeof( struct ldap_x_hostlist_status )); - if ( NULL == *statusp ) { - return( LDAP_NO_MEMORY ); - } - (*statusp)->lhs_hostlist = nsldapi_strdup( hostlist ); - if ( NULL == (*statusp)->lhs_hostlist ) { - return( LDAP_NO_MEMORY ); - } - (*statusp)->lhs_nexthost = (*statusp)->lhs_hostlist; - (*statusp)->lhs_defport = defport; - return( ldap_x_hostlist_next( hostp, portp, *statusp )); -} - -/* - * Return the next host and port in hostlist (setting *hostp and *portp). - * Return value is an LDAP API error code (LDAP_SUCCESS if all goes well). - * If no more hosts are available, LDAP_SUCCESS is returned but *hostp is set - * to NULL. - */ -int LDAP_CALL -ldap_x_hostlist_next( char **hostp, int *portp, - struct ldap_x_hostlist_status *status ) -{ - char *q; - int squarebrackets = 0; - - if ( NULL == hostp || NULL == portp ) { - return( LDAP_PARAM_ERROR ); - } - - if ( NULL == status || NULL == status->lhs_nexthost ) { - *hostp = NULL; - return( LDAP_SUCCESS ); - } - - /* - * skip past leading '[' if present (IPv6 addresses may be surrounded - * with square brackets, e.g., [fe80::a00:20ff:fee5:c0b4]:389 - */ - if ( status->lhs_nexthost[0] == '[' ) { - ++status->lhs_nexthost; - squarebrackets = 1; - } - - /* copy host into *hostp */ - if ( NULL != ( q = strchr( status->lhs_nexthost, ' ' ))) { - size_t len = q - status->lhs_nexthost; - *hostp = NSLDAPI_MALLOC( len + 1 ); - if ( NULL == *hostp ) { - return( LDAP_NO_MEMORY ); - } - strncpy( *hostp, status->lhs_nexthost, len ); - (*hostp)[len] = '\0'; - status->lhs_nexthost += ( len + 1 ); - } else { /* last host */ - *hostp = nsldapi_strdup( status->lhs_nexthost ); - if ( NULL == *hostp ) { - return( LDAP_NO_MEMORY ); - } - status->lhs_nexthost = NULL; - } - - /* - * Look for closing ']' and skip past it before looking for port. - */ - if ( squarebrackets && NULL != ( q = strchr( *hostp, ']' ))) { - *q++ = '\0'; - } else { - q = *hostp; - } - - /* determine and set port */ - if ( NULL != ( q = strchr( q, ':' ))) { - *q++ = '\0'; - *portp = atoi( q ); - } else { - *portp = status->lhs_defport; - } - - return( LDAP_SUCCESS ); -} - - -void LDAP_CALL -ldap_x_hostlist_statusfree( struct ldap_x_hostlist_status *status ) -{ - if ( NULL != status ) { - if ( NULL != status->lhs_hostlist ) { - NSLDAPI_FREE( status->lhs_hostlist ); - } - NSLDAPI_FREE( status ); - } -} - - - -/* - * memory allocation functions. we include these in open.c since every - * LDAP application is likely to pull the rest of the code in this file - * in anyways. - */ -void * -ldap_x_malloc( size_t size ) -{ - return( nsldapi_memalloc_fns.ldapmem_malloc == NULL ? - malloc( size ) : - nsldapi_memalloc_fns.ldapmem_malloc( size )); -} - - -void * -ldap_x_calloc( size_t nelem, size_t elsize ) -{ - return( nsldapi_memalloc_fns.ldapmem_calloc == NULL ? - calloc( nelem, elsize ) : - nsldapi_memalloc_fns.ldapmem_calloc( nelem, elsize )); -} - - -void * -ldap_x_realloc( void *ptr, size_t size ) -{ - return( nsldapi_memalloc_fns.ldapmem_realloc == NULL ? - realloc( ptr, size ) : - nsldapi_memalloc_fns.ldapmem_realloc( ptr, size )); -} - - -void -ldap_x_free( void *ptr ) -{ - if ( nsldapi_memalloc_fns.ldapmem_free == NULL ) { - free( ptr ); - } else { - nsldapi_memalloc_fns.ldapmem_free( ptr ); - } -} - - -/* if s is NULL, returns NULL */ -char * -nsldapi_strdup( const char *s ) -{ - char *p; - - if ( s == NULL || - (p = (char *)NSLDAPI_MALLOC( strlen( s ) + 1 )) == NULL ) - return( NULL ); - - strcpy( p, s ); - - return( p ); -} diff --git a/ldap/c-sdk/libraries/libldap/os-ip.c b/ldap/c-sdk/libraries/libldap/os-ip.c deleted file mode 100644 index 2e70139be3..0000000000 --- a/ldap/c-sdk/libraries/libldap/os-ip.c +++ /dev/null @@ -1,1862 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * os-ip.c -- platform-specific TCP & UDP related code - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -/* - * On platforms where poll() does not exist, we use select(). - * Therefore, we should increase the number of file descriptors - * we can use by #defining FD_SETSIZE to a large number before - * we include or its equivalent. We do not need - * to do this for Windows, because on that platform there is no - * relationship between FD_SETSIZE and the highest numbered file - * descriptor we can use. See the document fdsetsize.txt in - * this directory for a description of the setting of FD_SETSIZE - * for the OS'es we care about. - */ -#ifndef NSLDAPI_HAVE_POLL -/* XXX value for BSDI? */ -/* XXX value for macintosh (if applicable)? */ -#endif - -#include "ldap-int.h" -#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED -#include -#endif - -#ifdef NSLDAPI_HAVE_POLL -#include -#endif - - -#ifdef _WINDOWS -#define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) == INVALID_SOCKET) -#else -#define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) < 0 ) -#endif - - -#define NSLDAPI_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ - - -/* - * Structures and union for tracking status of network sockets - */ -#ifdef NSLDAPI_HAVE_POLL -struct nsldapi_os_statusinfo { /* used with native OS poll() */ - struct pollfd *ossi_pollfds; - int ossi_pollfds_size; -}; -#else /* NSLDAPI_HAVE_POLL */ -struct nsldapi_os_statusinfo { /* used with native OS select() */ - fd_set ossi_readfds; - fd_set ossi_writefds; - fd_set ossi_use_readfds; - fd_set ossi_use_writefds; -}; -#endif /* else NSLDAPI_HAVE_POLL */ - -struct nsldapi_cb_statusinfo { /* used with ext. I/O poll() callback */ - LDAP_X_PollFD *cbsi_pollfds; - int cbsi_pollfds_size; -}; - -/* - * NSLDAPI_CB_POLL_MATCH() evaluates to non-zero (true) if the Sockbuf *sdp - * matches the LDAP_X_PollFD pollfd. - */ -#ifdef _WINDOWS -#define NSLDAPI_CB_POLL_SD_CAST (unsigned int) -#else -#define NSLDAPI_CB_POLL_SD_CAST -#endif -#define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \ - ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd) && \ - (sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) - - -struct nsldapi_iostatus_info { - int ios_type; -#define NSLDAPI_IOSTATUS_TYPE_OSNATIVE 1 /* poll() or select() */ -#define NSLDAPI_IOSTATUS_TYPE_CALLBACK 2 /* poll()-like */ - int ios_read_count; - int ios_write_count; - union { - struct nsldapi_os_statusinfo ios_osinfo; - struct nsldapi_cb_statusinfo ios_cbinfo; - } ios_status; -}; - -#ifndef NSLDAPI_AVOID_OS_SOCKETS -#ifdef NSLDAPI_HAVE_POLL -static int nsldapi_add_to_os_pollfds( int fd, - struct nsldapi_os_statusinfo *pip, short events ); -static int nsldapi_clear_from_os_pollfds( int fd, - struct nsldapi_os_statusinfo *pip, short events ); -static int nsldapi_find_in_os_pollfds( int fd, - struct nsldapi_os_statusinfo *pip, short revents ); -#endif /* NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - -static int nsldapi_iostatus_init_nolock( LDAP *ld ); -static int nsldapi_add_to_cb_pollfds( Sockbuf *sb, - struct nsldapi_cb_statusinfo *pip, short events ); -static int nsldapi_clear_from_cb_pollfds( Sockbuf *sb, - struct nsldapi_cb_statusinfo *pip, short events ); -static int nsldapi_find_in_cb_pollfds( Sockbuf *sb, - struct nsldapi_cb_statusinfo *pip, short revents ); - - -#ifdef irix -#ifndef _PR_THREADS -/* - * XXXmcs: on IRIX NSPR's poll() and select() wrappers will crash if NSPR - * has not been initialized. We work around the problem by bypassing - * the NSPR wrapper functions and going directly to the OS' functions. - */ -#define NSLDAPI_POLL _poll -#define NSLDAPI_SELECT _select -extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); -extern int _select(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout); -#else /* _PR_THREADS */ -#define NSLDAPI_POLL poll -#define NSLDAPI_SELECT select -#endif /* else _PR_THREADS */ -#else /* irix */ -#define NSLDAPI_POLL poll -#define NSLDAPI_SELECT select -#endif /* else irix */ - - -static LBER_SOCKET nsldapi_os_socket( LDAP *ld, int secure, int domain, - int type, int protocol ); -static int nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp ); -static int nsldapi_os_connect_with_to( LBER_SOCKET s, struct sockaddr *name, - int namelen, int msec_timeout ); -#if defined(KERBEROS) -char * nsldapi_host_connected_to( LDAP *ld, Sockbuf *sb ); -#endif - -/* - * Function typedefs used by nsldapi_try_each_host() - */ -typedef LBER_SOCKET (NSLDAPI_SOCKET_FN)( LDAP *ld, int secure, int domain, - int type, int protocol ); -typedef int (NSLDAPI_IOCTL_FN)( LBER_SOCKET s, int option, int *statusp ); -typedef int (NSLDAPI_CONNECT_WITH_TO_FN )( LBER_SOCKET s, struct sockaddr *name, - int namelen, int msec_timeout ); -typedef int (NSLDAPI_CONNECT_FN )( LBER_SOCKET s, struct sockaddr *name, - int namelen ); -typedef int (NSLDAPI_CLOSE_FN )( LBER_SOCKET s ); - -static int nsldapi_try_each_host( LDAP *ld, const char *hostlist, int defport, - int secure, NSLDAPI_SOCKET_FN *socketfn, NSLDAPI_IOCTL_FN *ioctlfn, - NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn, - NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn ); - - -static int -nsldapi_os_closesocket( LBER_SOCKET s ) -{ - int rc; - -#ifdef NSLDAPI_AVOID_OS_SOCKETS - rc = -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef _WINDOWS - rc = closesocket( s ); -#else /* _WINDOWS */ - rc = close( s ); -#endif /* _WINDOWS */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - return( rc ); -} - - -static LBER_SOCKET -nsldapi_os_socket( LDAP *ld, int secure, int domain, int type, int protocol ) -{ -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ - int s, invalid_socket; - char *errmsg = NULL; - - if ( secure ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, - nsldapi_strdup( "secure mode not supported" )); - return( -1 ); - } - - s = socket( domain, type, protocol ); - - /* - * if the socket() call failed or it returned a socket larger - * than we can deal with, return a "local error." - */ - if ( NSLDAPI_INVALID_OS_SOCKET( s )) { - errmsg = "unable to create a socket"; - invalid_socket = 1; - } else { /* valid socket -- check for overflow */ - invalid_socket = 0; -#if !defined(NSLDAPI_HAVE_POLL) && !defined(_WINDOWS) - /* not on Windows and do not have poll() */ - if ( s >= FD_SETSIZE ) { - errmsg = "can't use socket >= FD_SETSIZE"; - } -#endif - } - - if ( errmsg != NULL ) { /* local socket error */ - if ( !invalid_socket ) { - nsldapi_os_closesocket( s ); - } - errmsg = nsldapi_strdup( errmsg ); - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, errmsg ); - return( -1 ); - } - - return( s ); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ -} - - - -/* - * Non-blocking connect call function - */ -static int -nsldapi_os_connect_with_to(LBER_SOCKET sockfd, struct sockaddr *saptr, - int salen, int msec) -{ -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ - int n, error; - int len; -#if defined(_WINDOWS) || defined(XP_OS2) - int nonblock = 1; - int block = 0; -#else - int flags; -#endif /* _WINDOWS */ -#ifdef NSLDAPI_HAVE_POLL - struct pollfd pfd; -#else - struct timeval tval; - fd_set rset, wset; -#ifdef _WINDOWS - fd_set eset; -#endif -#endif /* NSLDAPI_HAVE_POLL */ - - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_nonblock timeout: %d (msec)\n", - msec, 0, 0); - -#ifdef _WINDOWS - ioctlsocket(sockfd, FIONBIO, &nonblock); -#elif defined(XP_OS2) - ioctl( sockfd, FIONBIO, &nonblock, sizeof(nonblock) ); -#else - flags = fcntl(sockfd, F_GETFL, 0); - fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); -#endif /* _WINDOWS */ - - error = 0; - if ((n = connect(sockfd, saptr, salen)) < 0) -#ifdef _WINDOWS - if ((n != SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) { -#else - if (errno != EINPROGRESS) { -#endif /* _WINDOWS */ -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - perror("connect"); - } -#endif - return (-1); - } - - /* success */ - if (n == 0) - goto done; - -#ifdef NSLDAPI_HAVE_POLL - pfd.fd = sockfd; - pfd.events = POLLOUT; -#else - FD_ZERO(&rset); - FD_SET(sockfd, &rset); - wset = rset; - -#ifdef _WINDOWS - eset = rset; -#endif /* _WINDOWS */ -#endif /* NSLDAPI_HAVE_POLL */ - - if (msec < 0 && msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) { - LDAPDebug( LDAP_DEBUG_TRACE, "Invalid timeout value detected.." - "resetting connect timeout to default value " - "(LDAP_X_IO_TIMEOUT_NO_TIMEOUT\n", 0, 0, 0); - msec = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; -#ifndef NSLDAPI_HAVE_POLL - } else { - if (msec != 0) { - tval.tv_sec = msec / 1000; - tval.tv_usec = 1000 * ( msec % 1000 ); - } else { - tval.tv_sec = 0; - tval.tv_usec = 0; - } -#endif /* NSLDAPI_HAVE_POLL */ - } - -#ifdef NSLDAPI_HAVE_POLL - if ((n = poll(&pfd, 1, - (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? msec : -1)) == 0) { - errno = ETIMEDOUT; - return (-1); - } - if (pfd.revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { - len = sizeof(error); - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) - < 0) - return (-1); -#ifdef LDAP_DEBUG - } else if ( ldap_debug & LDAP_DEBUG_TRACE ) { - perror("poll error: sockfd not set"); -#endif - } - -#else /* NSLDAPI_HAVE_POLL */ - /* if timeval structure == NULL, select will block indefinitely */ - /* != NULL, and value == 0, select will */ - /* not block */ - /* Windows is a bit quirky on how it behaves w.r.t nonblocking */ - /* connects. If the connect fails, the exception fd, eset, is */ - /* set to show the failure. The first argument in select is */ - /* ignored */ - -#ifdef _WINDOWS - if ((n = select(sockfd +1, &rset, &wset, &eset, - (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) { - errno = WSAETIMEDOUT; - return (-1); - } - /* if wset is set, the connect worked */ - if (FD_ISSET(sockfd, &wset) || FD_ISSET(sockfd, &rset)) { - len = sizeof(error); - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) - < 0) - return (-1); - goto done; - } - - /* if eset is set, the connect failed */ - if (FD_ISSET(sockfd, &eset)) { - return (-1); - } - - /* failure on select call */ - if (n == SOCKET_ERROR) { - perror("select error: SOCKET_ERROR returned"); - return (-1); - } -#else - if ((n = select(sockfd +1, &rset, &wset, NULL, - (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) { - errno = ETIMEDOUT; - return (-1); - } - if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { - len = sizeof(error); - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) - < 0) - return (-1); -#ifdef LDAP_DEBUG - } else if ( ldap_debug & LDAP_DEBUG_TRACE ) { - perror("select error: sockfd not set"); -#endif - } -#endif /* _WINDOWS */ -#endif /* NSLDAPI_HAVE_POLL */ - -done: -#ifdef _WINDOWS - ioctlsocket(sockfd, FIONBIO, &block); -#elif defined(XP_OS2) - ioctl( sockfd, FIONBIO, &nonblock, sizeof(block) ); -#else - fcntl(sockfd, F_SETFL, flags); -#endif /* _WINDOWS */ - - if (error) { - errno = error; - return (-1); - } - - return (0); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ -} - - -static int -nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp ) -{ -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ - int err; -#if defined(_WINDOWS) || defined(XP_OS2) - u_long iostatus; -#endif - - if ( FIONBIO != option ) { - return( -1 ); - } - -#ifdef _WINDOWS - iostatus = *(u_long *)statusp; - err = ioctlsocket( s, FIONBIO, &iostatus ); -#else -#ifdef XP_OS2 - err = ioctl( s, FIONBIO, (caddr_t)&iostatus, sizeof(iostatus) ); -#else - err = ioctl( s, FIONBIO, (caddr_t)statusp ); -#endif -#endif - - return( err ); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ -} - - -int -nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *hostlist, - int defport, int secure, char **krbinstancep ) -/* - * "defport" must be in host byte order - * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS - * if -1 is returned, ld_errno is set - */ -{ - int s; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_to_host: %s, port: %d\n", - NULL == hostlist ? "NULL" : hostlist, defport, 0 ); - - /* - * If an extended I/O connect callback has been defined, just use it. - */ - if ( NULL != ld->ld_extconnect_fn ) { - unsigned long connect_opts = 0; - - if ( ld->ld_options & LDAP_BITOPT_ASYNC) { - connect_opts |= LDAP_X_EXTIOF_OPT_NONBLOCKING; - } - if ( secure ) { - connect_opts |= LDAP_X_EXTIOF_OPT_SECURE; - } - s = ld->ld_extconnect_fn( hostlist, defport, - ld->ld_connect_timeout, connect_opts, - ld->ld_ext_session_arg, - &sb->sb_ext_io_fns.lbextiofn_socket_arg ); - - } else { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return( -1 ); -#else /* NSLDAPI_AVOID_OS_SOCKETS */ - s = nsldapi_try_each_host( ld, hostlist, - defport, secure, nsldapi_os_socket, - nsldapi_os_ioctl, nsldapi_os_connect_with_to, - NULL, nsldapi_os_closesocket ); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - } - - if ( s < 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL ); - return( -1 ); - } - - sb->sb_sd = s; - - /* - * Set krbinstancep (canonical name of host for use by Kerberos). - */ -#ifdef KERBEROS - char *p; - - if (( *krbinstancep = nsldapi_host_connected_to( sb )) != NULL - && ( p = strchr( *krbinstancep, '.' )) != NULL ) { - *p = '\0'; - } -#else /* KERBEROS */ - *krbinstancep = NULL; -#endif /* KERBEROS */ - - return( 0 ); -} - - -/* - * Returns a socket number if successful and -1 if an error occurs. - */ -static int -nsldapi_try_each_host( LDAP *ld, const char *hostlist, - int defport, int secure, NSLDAPI_SOCKET_FN *socketfn, - NSLDAPI_IOCTL_FN *ioctlfn, NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn, - NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn ) -{ -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ - int rc = -1; - int s = 0; - int i, err, connected, use_hp; - int parse_err, port; - struct sockaddr_in sin; - nsldapi_in_addr_t address; - char **addrlist, *ldhpbuf, *ldhpbuf_allocd = NULL; - char *host; - LDAPHostEnt ldhent, *ldhp; - struct hostent *hp; - struct ldap_x_hostlist_status *status; -#ifdef GETHOSTBYNAME_BUF_T - GETHOSTBYNAME_BUF_T hbuf; - struct hostent hent; -#endif /* GETHOSTBYNAME_BUF_T */ - - connected = 0; - parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, - &status ); - while ( !connected && LDAP_SUCCESS == parse_err && host != NULL ) { - ldhpbuf_allocd = NULL; - ldhp = NULL; - hp = NULL; - s = 0; - use_hp = 0; - addrlist = NULL; - - - if (( address = inet_addr( host )) == -1 ) { - if ( ld->ld_dns_gethostbyname_fn == NULL ) { -#ifdef GETHOSTBYNAME_R_RETURNS_INT - (void)GETHOSTBYNAME( host, &hent, hbuf, - sizeof(hbuf), &hp, &err ); -#else - hp = GETHOSTBYNAME( host, &hent, hbuf, - sizeof(hbuf), &err ); -#endif - if ( hp != NULL ) { - addrlist = hp->h_addr_list; - } - } else { - /* - * DNS callback installed... use it. - */ -#ifdef GETHOSTBYNAME_buf_t - /* avoid allocation by using hbuf if large enough */ - if ( sizeof( hbuf ) < ld->ld_dns_bufsize ) { - ldhpbuf = ldhpbuf_allocd - = NSLDAPI_MALLOC( ld->ld_dns_bufsize ); - } else { - ldhpbuf = (char *)hbuf; - } -#else /* GETHOSTBYNAME_buf_t */ - ldhpbuf = ldhpbuf_allocd = NSLDAPI_MALLOC( - ld->ld_dns_bufsize ); -#endif /* else GETHOSTBYNAME_buf_t */ - - if ( ldhpbuf == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, - NULL, NULL ); - ldap_memfree( host ); - ldap_x_hostlist_statusfree( status ); - return( -1 ); - } - - if (( ldhp = ld->ld_dns_gethostbyname_fn( host, - &ldhent, ldhpbuf, ld->ld_dns_bufsize, &err, - ld->ld_dns_extradata )) != NULL ) { - addrlist = ldhp->ldaphe_addr_list; - } - } - - if ( addrlist == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL ); - LDAP_SET_ERRNO( ld, EHOSTUNREACH ); /* close enough */ - if ( ldhpbuf_allocd != NULL ) { - NSLDAPI_FREE( ldhpbuf_allocd ); - } - ldap_memfree( host ); - ldap_x_hostlist_statusfree( status ); - return( -1 ); - } - use_hp = 1; - } - - rc = -1; - for ( i = 0; !use_hp || ( addrlist[ i ] != 0 ); i++ ) { - if ( -1 == ( s = (*socketfn)( ld, secure, AF_INET, - SOCK_STREAM, 0 ))) { - if ( ldhpbuf_allocd != NULL ) { - NSLDAPI_FREE( ldhpbuf_allocd ); - } - ldap_memfree( host ); - ldap_x_hostlist_statusfree( status ); - return( -1 ); - } - - if ( ld->ld_options & LDAP_BITOPT_ASYNC ) { - int iostatus = 1; - - err = (*ioctlfn)( s, FIONBIO, &iostatus ); - if ( err == -1 ) { - LDAPDebug( LDAP_DEBUG_ANY, - "FIONBIO ioctl failed on %d\n", - s, 0, 0 ); - } - } - - (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); - sin.sin_family = AF_INET; - sin.sin_port = htons( (unsigned short)port ); - - SAFEMEMCPY( (char *) &sin.sin_addr.s_addr, - ( use_hp ? (char *) addrlist[ i ] : - (char *) &address ), sizeof( sin.sin_addr.s_addr) ); - - { -#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED -/* - * Block all of the signals that might interrupt connect() since - * there is an OS bug that causes connect() to fail if it is restarted. - * Look in ../../include/portable.h for the definition of - * NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED. - */ - sigset_t ints_off, oldset; - - sigemptyset( &ints_off ); - sigaddset( &ints_off, SIGALRM ); - sigaddset( &ints_off, SIGIO ); - sigaddset( &ints_off, SIGCLD ); - - NSLDAPI_MT_SAFE_SIGPROCMASK( SIG_BLOCK, &ints_off, &oldset ); -#endif /* NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED */ - - if ( NULL != connectwithtofn ) { - err = (*connectwithtofn)(s, - (struct sockaddr *)&sin, - sizeof(struct sockaddr_in), - ld->ld_connect_timeout); - } else { - err = (*connectfn)(s, - (struct sockaddr *)&sin, - sizeof(struct sockaddr_in)); - } -#ifdef NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED -/* - * restore original signal mask - */ - NSLDAPI_MT_SAFE_SIGPROCMASK( SIG_SETMASK, &oldset, 0 ); -#endif /* NSLDAPI_CONNECT_MUST_NOT_BE_INTERRUPTED */ - - } - if ( err >= 0 ) { - connected = 1; - rc = 0; - break; - } else { - if ( ld->ld_options & LDAP_BITOPT_ASYNC) { -#ifdef _WINDOWS - if (err == -1 && WSAGetLastError() == WSAEWOULDBLOCK) - LDAP_SET_ERRNO( ld, EWOULDBLOCK ); -#endif /* _WINDOWS */ - err = LDAP_GET_ERRNO( ld ); - if ( NSLDAPI_ERRNO_IO_INPROGRESS( err )) { - LDAPDebug( LDAP_DEBUG_TRACE, "connect would block...\n", - 0, 0, 0 ); - rc = -2; - break; - } - } - -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - perror( (char *)inet_ntoa( sin.sin_addr )); - } -#endif - (*closefn)( s ); - if ( !use_hp ) { - break; - } - } - } - - ldap_memfree( host ); - parse_err = ldap_x_hostlist_next( &host, &port, status ); - } - - if ( ldhpbuf_allocd != NULL ) { - NSLDAPI_FREE( ldhpbuf_allocd ); - } - ldap_memfree( host ); - ldap_x_hostlist_statusfree( status ); - - if ( connected ) { - LDAPDebug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n", - s, inet_ntoa( sin.sin_addr ), 0 ); - } - - return( rc == 0 ? s : -1 ); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ -} - -void -nsldapi_close_connection( LDAP *ld, Sockbuf *sb ) -{ - if ( ld->ld_extclose_fn == NULL ) { -#ifndef NSLDAPI_AVOID_OS_SOCKETS - nsldapi_os_closesocket( sb->sb_sd ); -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - } else { - ld->ld_extclose_fn( sb->sb_sd, - sb->sb_ext_io_fns.lbextiofn_socket_arg ); - } -} - - -#ifdef KERBEROS -char * -nsldapi_host_connected_to( LDAP *ld, Sockbuf *sb ) -{ - struct hostent *hp; - char *p; - int len; - struct sockaddr_in sin; - - (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); - len = sizeof( sin ); - if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) { - return( NULL ); - } - - /* - * do a reverse lookup on the addr to get the official hostname. - * this is necessary for kerberos to work right, since the official - * hostname is used as the kerberos instance. - */ -#error XXXmcs: need to use DNS callbacks here - if (( hp = (struct hostent *)gethostbyaddr( (char *) &sin.sin_addr, - sizeof( sin.sin_addr ), AF_INET )) != NULL ) { - if ( hp->h_name != NULL ) { - return( nsldapi_strdup( hp->h_name )); - } - } - - return( NULL ); -} -#endif /* KERBEROS */ - - -/* - * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) - * Also allocates initializes ld->ld_iostatus if needed.. - */ -int -nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb ) -{ - int rc = 0; - NSLDAPIIOStatus *iosp; - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - - if ( ld->ld_iostatus == NULL - && nsldapi_iostatus_init_nolock( ld ) < 0 ) { - rc = -1; - goto unlock_and_return; - } - - iosp = ld->ld_iostatus; - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - rc = -1; - goto unlock_and_return; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef NSLDAPI_HAVE_POLL - if ( nsldapi_add_to_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, POLLOUT )) { - ++iosp->ios_write_count; - } -#else /* NSLDAPI_HAVE_POLL */ - if ( !FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_writefds )) { - FD_SET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_writefds ); - ++iosp->ios_write_count; - } -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - if ( nsldapi_add_to_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) { - ++iosp->ios_write_count; - } - - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_interest_write: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - } - -unlock_and_return: - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - - -/* - * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) - * Also allocates initializes ld->ld_iostatus if needed.. - */ -int -nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb ) -{ - int rc = 0; - NSLDAPIIOStatus *iosp; - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - - if ( ld->ld_iostatus == NULL - && nsldapi_iostatus_init_nolock( ld ) < 0 ) { - rc = -1; - goto unlock_and_return; - } - - iosp = ld->ld_iostatus; - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - rc = -1; - goto unlock_and_return; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef NSLDAPI_HAVE_POLL - if ( nsldapi_add_to_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, POLLIN )) { - ++iosp->ios_read_count; - } -#else /* NSLDAPI_HAVE_POLL */ - if ( !FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_readfds )) { - FD_SET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_readfds ); - ++iosp->ios_read_count; - } -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - if ( nsldapi_add_to_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) { - ++iosp->ios_read_count; - } - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_interest_read: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - } - -unlock_and_return: - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - - -/* - * Returns 0 if all goes well and -1 if an error occurs (error code set in ld) - * Also allocates initializes ld->ld_iostatus if needed.. - */ -int -nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb ) -{ - int rc = 0; - NSLDAPIIOStatus *iosp; - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - - if ( ld->ld_iostatus == NULL - && nsldapi_iostatus_init_nolock( ld ) < 0 ) { - rc = -1; - goto unlock_and_return; - } - - iosp = ld->ld_iostatus; - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - rc = -1; - goto unlock_and_return; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef NSLDAPI_HAVE_POLL - if ( nsldapi_clear_from_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, POLLOUT )) { - --iosp->ios_write_count; - } - if ( nsldapi_clear_from_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, POLLIN )) { - --iosp->ios_read_count; - } -#else /* NSLDAPI_HAVE_POLL */ - if ( FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_writefds )) { - FD_CLR( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_writefds ); - --iosp->ios_write_count; - } - if ( FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_readfds )) { - FD_CLR( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_readfds ); - --iosp->ios_read_count; - } -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - if ( nsldapi_clear_from_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) { - --iosp->ios_write_count; - } - if ( nsldapi_clear_from_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) { - --iosp->ios_read_count; - } - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_interest_clear: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - } - -unlock_and_return: - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - - -/* - * Return a non-zero value if sb is ready for write. - */ -int -nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb ) -{ - int rc = 0; - NSLDAPIIOStatus *iosp; - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - iosp = ld->ld_iostatus; - if ( iosp == NULL ) { - goto unlock_and_return; - } - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - goto unlock_and_return; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef NSLDAPI_HAVE_POLL - /* - * if we are using poll() we do something a little tricky: if - * any bits in the socket's returned events field other than - * POLLIN (ready for read) are set, we return true. This - * is done so we notice when a server closes a connection - * or when another error occurs. The actual error will be - * noticed later when we call write() or send(). - */ - rc = nsldapi_find_in_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, ~POLLIN ); - -#else /* NSLDAPI_HAVE_POLL */ - rc = FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_use_writefds ); -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - rc = nsldapi_find_in_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLIN ); - - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_is_write_ready: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - rc = 0; - } - -unlock_and_return: - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - - -/* - * Return a non-zero value if sb is ready for read. - */ -int -nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb ) -{ - int rc = 0; - NSLDAPIIOStatus *iosp; - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - iosp = ld->ld_iostatus; - if ( iosp == NULL ) { - goto unlock_and_return; - } - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_AVOID_OS_SOCKETS - goto unlock_and_return; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef NSLDAPI_HAVE_POLL - /* - * if we are using poll() we do something a little tricky: if - * any bits in the socket's returned events field other than - * POLLOUT (ready for write) are set, we return true. This - * is done so we notice when a server closes a connection - * or when another error occurs. The actual error will be - * noticed later when we call read() or recv(). - */ - rc = nsldapi_find_in_os_pollfds( sb->sb_sd, - &iosp->ios_status.ios_osinfo, ~POLLOUT ); - -#else /* NSLDAPI_HAVE_POLL */ - rc = FD_ISSET( sb->sb_sd, - &iosp->ios_status.ios_osinfo.ossi_use_readfds ); -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - rc = nsldapi_find_in_cb_pollfds( sb, - &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLOUT ); - - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_is_read_ready: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - rc = 0; - } - -unlock_and_return: - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - - -/* - * Allocate and initialize ld->ld_iostatus if not already done. - * Should be called with LDAP_IOSTATUS_LOCK locked. - * Returns 0 if all goes well and -1 if not (sets error in ld) - */ -static int -nsldapi_iostatus_init_nolock( LDAP *ld ) -{ - NSLDAPIIOStatus *iosp; - - if ( ld->ld_iostatus != NULL ) { - return( 0 ); - } - - if (( iosp = (NSLDAPIIOStatus *)NSLDAPI_CALLOC( 1, - sizeof( NSLDAPIIOStatus ))) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - - if ( ld->ld_extpoll_fn == NULL ) { - iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_OSNATIVE; -#ifdef NSLDAPI_AVOID_OS_SOCKETS - return( -1 ); -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifndef NSLDAPI_HAVE_POLL - FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_readfds ); - FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_writefds ); -#endif /* !NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else { - iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_CALLBACK; - } - - ld->ld_iostatus = iosp; - return( 0 ); -} - - -void -nsldapi_iostatus_free( LDAP *ld ) -{ - if ( ld == NULL ) { - return; - } - - - /* clean up classic I/O compatibility glue */ - if ( ld->ld_io_fns_ptr != NULL ) { - if ( ld->ld_ext_session_arg != NULL ) { - NSLDAPI_FREE( ld->ld_ext_session_arg ); - } - NSLDAPI_FREE( ld->ld_io_fns_ptr ); - } - - /* clean up I/O status tracking info. */ - if ( ld->ld_iostatus != NULL ) { - NSLDAPIIOStatus *iosp = ld->ld_iostatus; - - if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifdef NSLDAPI_HAVE_POLL - if ( iosp->ios_status.ios_osinfo.ossi_pollfds - != NULL ) { - NSLDAPI_FREE( - iosp->ios_status.ios_osinfo.ossi_pollfds ); - } -#endif /* NSLDAPI_HAVE_POLL */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - if ( iosp->ios_status.ios_cbinfo.cbsi_pollfds - != NULL ) { - NSLDAPI_FREE( - iosp->ios_status.ios_cbinfo.cbsi_pollfds ); - } - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_free: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - } - - NSLDAPI_FREE( iosp ); - } -} - - - -#if !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) -static int -nsldapi_get_select_table_size( void ) -{ - static int tblsize = 0; /* static */ - - if ( tblsize == 0 ) { -#if defined(_WINDOWS) || defined(XP_OS2) - tblsize = FOPEN_MAX; /* ANSI spec. */ -#else -#ifdef USE_SYSCONF - tblsize = sysconf( _SC_OPEN_MAX ); -#else /* USE_SYSCONF */ - tblsize = getdtablesize(); -#endif /* else USE_SYSCONF */ -#endif /* else _WINDOWS */ - - if ( tblsize >= FD_SETSIZE ) { - /* - * clamp value so we don't overrun the fd_set structure - */ - tblsize = FD_SETSIZE - 1; - } - } - - return( tblsize ); -} -#endif /* !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) */ - - -static int -nsldapi_tv2ms( struct timeval *tv ) -{ - if ( tv == NULL ) { - return( -1 ); /* infinite timout for poll() */ - } - - return( tv->tv_sec * 1000 + tv->tv_usec / 1000 ); -} - - -int -nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout ) -{ - int rc; - NSLDAPIIOStatus *iosp; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_iostatus_poll\n", 0, 0, 0 ); - - LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK ); - iosp = ld->ld_iostatus; - - if ( iosp == NULL || - ( iosp->ios_read_count <= 0 && iosp->ios_write_count <= 0 )) { - rc = 0; /* simulate a timeout */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) { -#ifndef NSLDAPI_AVOID_OS_SOCKETS -#ifdef NSLDAPI_HAVE_POLL - - rc = NSLDAPI_POLL( iosp->ios_status.ios_osinfo.ossi_pollfds, - iosp->ios_status.ios_osinfo.ossi_pollfds_size, - nsldapi_tv2ms( timeout )); - -#else /* NSLDAPI_HAVE_POLL */ - - /* two (potentially large) struct copies */ - iosp->ios_status.ios_osinfo.ossi_use_readfds - = iosp->ios_status.ios_osinfo.ossi_readfds; - iosp->ios_status.ios_osinfo.ossi_use_writefds - = iosp->ios_status.ios_osinfo.ossi_writefds; - -#ifdef HPUX9 - rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(), - (int *)&iosp->ios_status.ios_osinfo.ossi_use_readfds - (int *)&iosp->ios_status.ios_osinfo.ossi_use_writefds, - NULL, timeout ); -#else - rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(), - &iosp->ios_status.ios_osinfo.ossi_use_readfds, - &iosp->ios_status.ios_osinfo.ossi_use_writefds, - NULL, timeout ); -#endif /* else HPUX9 */ -#endif /* else NSLDAPI_HAVE_POLL */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - - } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) { - /* - * We always pass the session extended I/O argument to - * the extended poll() callback. - */ - rc = ld->ld_extpoll_fn( - iosp->ios_status.ios_cbinfo.cbsi_pollfds, - iosp->ios_status.ios_cbinfo.cbsi_pollfds_size, - nsldapi_tv2ms( timeout ), ld->ld_ext_session_arg ); - - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_poll: unknown I/O type %d\n", - iosp->ios_type, 0, 0 ); - rc = 0; /* simulate a timeout (what else to do?) */ - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK ); - return( rc ); -} - -#if defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) -/* - * returns 1 if "fd" was added to pollfds. - * returns 1 if some of the bits in "events" were added to pollfds. - * returns 0 if no changes were made. - */ -static int -nsldapi_add_to_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, - short events ) -{ - int i, openslot; - - /* first we check to see if "fd" is already in our pollfds */ - openslot = -1; - for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { - if ( pip->ossi_pollfds[ i ].fd == fd ) { - if (( pip->ossi_pollfds[ i ].events & events ) - != events ) { - pip->ossi_pollfds[ i ].events |= events; - return( 1 ); - } else { - return( 0 ); - } - } - if ( pip->ossi_pollfds[ i ].fd == -1 && openslot == -1 ) { - openslot = i; /* remember for later */ - } - } - - /* - * "fd" is not currently being poll'd on -- add to array. - * if we need to expand the pollfds array, we do it in increments of - * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file). - */ - if ( openslot == -1 ) { - struct pollfd *newpollfds; - - if ( pip->ossi_pollfds_size == 0 ) { - newpollfds = (struct pollfd *)NSLDAPI_MALLOC( - NSLDAPI_POLL_ARRAY_GROWTH - * sizeof( struct pollfd )); - } else { - newpollfds = (struct pollfd *)NSLDAPI_REALLOC( - pip->ossi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH - + pip->ossi_pollfds_size) - * sizeof( struct pollfd )); - } - if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */ - return( 0 ); - } - pip->ossi_pollfds = newpollfds; - openslot = pip->ossi_pollfds_size; - pip->ossi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH; - for ( i = openslot + 1; i < pip->ossi_pollfds_size; ++i ) { - pip->ossi_pollfds[ i ].fd = -1; - pip->ossi_pollfds[ i ].events = - pip->ossi_pollfds[ i ].revents = 0; - } - } - pip->ossi_pollfds[ openslot ].fd = fd; - pip->ossi_pollfds[ openslot ].events = events; - pip->ossi_pollfds[ openslot ].revents = 0; - return( 1 ); -} - - -/* - * returns 1 if any "events" from "fd" were removed from pollfds - * returns 0 of "fd" wasn't in pollfds or if events did not overlap. - */ -static int -nsldapi_clear_from_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, - short events ) -{ - int i; - - for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { - if ( pip->ossi_pollfds[i].fd == fd ) { - if (( pip->ossi_pollfds[ i ].events & events ) != 0 ) { - pip->ossi_pollfds[ i ].events &= ~events; - if ( pip->ossi_pollfds[ i ].events == 0 ) { - pip->ossi_pollfds[i].fd = -1; - } - return( 1 ); /* events overlap */ - } else { - return( 0 ); /* events do not overlap */ - } - } - } - - return( 0 ); /* "fd" was not found */ -} - - -/* - * returns 1 if any "revents" from "fd" were set in pollfds revents field. - * returns 0 if not. - */ -static int -nsldapi_find_in_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip, - short revents ) -{ - int i; - - for ( i = 0; i < pip->ossi_pollfds_size; ++i ) { - if ( pip->ossi_pollfds[i].fd == fd ) { - if (( pip->ossi_pollfds[ i ].revents & revents ) != 0 ) { - return( 1 ); /* revents overlap */ - } else { - return( 0 ); /* revents do not overlap */ - } - } - } - - return( 0 ); /* "fd" was not found */ -} -#endif /* !defined(NSLDAPI_HAVE_POLL) && !defined(NSLDAPI_AVOID_OS_SOCKETS) */ - -/* - * returns 1 if "sb" was added to pollfds. - * returns 1 if some of the bits in "events" were added to pollfds. - * returns 0 if no changes were made. - */ -static int -nsldapi_add_to_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip, - short events ) -{ - int i, openslot; - - /* first we check to see if "sb" is already in our pollfds */ - openslot = -1; - for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { - if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { - if (( pip->cbsi_pollfds[ i ].lpoll_events & events ) - != events ) { - pip->cbsi_pollfds[ i ].lpoll_events |= events; - return( 1 ); - } else { - return( 0 ); - } - } - if ( pip->cbsi_pollfds[ i ].lpoll_fd == -1 && openslot == -1 ) { - openslot = i; /* remember for later */ - } - } - - /* - * "sb" is not currently being poll'd on -- add to array. - * if we need to expand the pollfds array, we do it in increments of - * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file). - */ - if ( openslot == -1 ) { - LDAP_X_PollFD *newpollfds; - - if ( pip->cbsi_pollfds_size == 0 ) { - newpollfds = (LDAP_X_PollFD *)NSLDAPI_MALLOC( - NSLDAPI_POLL_ARRAY_GROWTH - * sizeof( LDAP_X_PollFD )); - } else { - newpollfds = (LDAP_X_PollFD *)NSLDAPI_REALLOC( - pip->cbsi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH - + pip->cbsi_pollfds_size) - * sizeof( LDAP_X_PollFD )); - } - if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */ - return( 0 ); - } - pip->cbsi_pollfds = newpollfds; - openslot = pip->cbsi_pollfds_size; - pip->cbsi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH; - for ( i = openslot + 1; i < pip->cbsi_pollfds_size; ++i ) { - pip->cbsi_pollfds[ i ].lpoll_fd = -1; - pip->cbsi_pollfds[ i ].lpoll_socketarg = NULL; - pip->cbsi_pollfds[ i ].lpoll_events = - pip->cbsi_pollfds[ i ].lpoll_revents = 0; - } - } - pip->cbsi_pollfds[ openslot ].lpoll_fd = sb->sb_sd; - pip->cbsi_pollfds[ openslot ].lpoll_socketarg = - sb->sb_ext_io_fns.lbextiofn_socket_arg; - pip->cbsi_pollfds[ openslot ].lpoll_events = events; - pip->cbsi_pollfds[ openslot ].lpoll_revents = 0; - return( 1 ); -} - - -/* - * returns 1 if any "events" from "sb" were removed from pollfds - * returns 0 of "sb" wasn't in pollfds or if events did not overlap. - */ -static int -nsldapi_clear_from_cb_pollfds( Sockbuf *sb, - struct nsldapi_cb_statusinfo *pip, short events ) -{ - int i; - - for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { - if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { - if (( pip->cbsi_pollfds[ i ].lpoll_events - & events ) != 0 ) { - pip->cbsi_pollfds[ i ].lpoll_events &= ~events; - if ( pip->cbsi_pollfds[ i ].lpoll_events - == 0 ) { - pip->cbsi_pollfds[i].lpoll_fd = -1; - } - return( 1 ); /* events overlap */ - } else { - return( 0 ); /* events do not overlap */ - } - } - } - - return( 0 ); /* "sb" was not found */ -} - - -/* - * returns 1 if any "revents" from "sb" were set in pollfds revents field. - * returns 0 if not. - */ -static int -nsldapi_find_in_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip, - short revents ) -{ - int i; - - for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) { - if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) { - if (( pip->cbsi_pollfds[ i ].lpoll_revents - & revents ) != 0 ) { - return( 1 ); /* revents overlap */ - } else { - return( 0 ); /* revents do not overlap */ - } - } - } - - return( 0 ); /* "sb" was not found */ -} - - -/* - * Install read and write functions into lber layer / sb - */ -int -nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb ) -{ - struct lber_x_ext_io_fns lberiofns; - - if ( NULL != sb ) { - lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - lberiofns.lbextiofn_read = ld->ld_extread_fn; - lberiofns.lbextiofn_write = ld->ld_extwrite_fn; - lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; - lberiofns.lbextiofn_socket_arg = ld->ld_ext_session_arg; - - if ( ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, - &lberiofns ) != 0 ) { - return( LDAP_LOCAL_ERROR ); - } - } - - return( LDAP_SUCCESS ); -} - - -/* - ****************************************************************************** - * One struct and several functions to bridge the gap between new extended - * I/O functions that are installed using ldap_set_option( ..., - * LDAP_OPT_EXTIO_FN_PTRS, ... ) and the original "classic" I/O functions - * (installed using LDAP_OPT_IO_FN_PTRS) follow. - * - * Our basic strategy is to use the new extended arg to hold a pointer to a - * structure that contains a pointer to the LDAP * (which contains pointers - * to the old functions so we can call them) as well as a pointer to an - * LBER_SOCKET to hold the socket used by the classic functions (the new - * functions use a simple int for the socket). - */ -typedef struct nsldapi_compat_socket_info { - LBER_SOCKET csi_socket; - LDAP *csi_ld; -} NSLDAPICompatSocketInfo; - -static int LDAP_CALLBACK -nsldapi_ext_compat_read( int s, void *buf, int len, - struct lextiof_socket_private *arg ) -{ - NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; - struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; - - return( iofns->liof_read( csip->csi_socket, buf, len )); -} - - -static int LDAP_CALLBACK -nsldapi_ext_compat_write( int s, const void *buf, int len, - struct lextiof_socket_private *arg ) -{ - NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; - struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; - - return( iofns->liof_write( csip->csi_socket, buf, len )); -} - - -static int LDAP_CALLBACK -nsldapi_ext_compat_poll( LDAP_X_PollFD fds[], int nfds, int timeout, - struct lextiof_session_private *arg ) -{ - NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; - struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; - fd_set readfds, writefds; - int i, rc, maxfd = 0; - struct timeval tv, *tvp; - - /* - * Prepare fd_sets for select() - */ - FD_ZERO( &readfds ); - FD_ZERO( &writefds ); - for ( i = 0; i < nfds; ++i ) { - if ( fds[ i ].lpoll_fd < 0 ) { - continue; - } - - if ( fds[ i ].lpoll_fd >= FD_SETSIZE ) { - LDAP_SET_ERRNO( csip->csi_ld, EINVAL ); - return( -1 ); - } - - if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )) { - FD_SET( fds[i].lpoll_fd, &readfds ); - } - - if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )) { - FD_SET( fds[i].lpoll_fd, &writefds ); - } - - fds[i].lpoll_revents = 0; /* clear revents */ - - if ( fds[i].lpoll_fd >= maxfd ) { - maxfd = fds[i].lpoll_fd; - } - } - - /* - * select() using callback. - */ - ++maxfd; - if ( timeout == -1 ) { - tvp = NULL; - } else { - tv.tv_sec = timeout / 1000; - tv.tv_usec = 1000 * ( timeout - tv.tv_sec * 1000 ); - tvp = &tv; - } - rc = iofns->liof_select( maxfd, &readfds, &writefds, NULL, tvp ); - if ( rc <= 0 ) { /* timeout or fatal error */ - return( rc ); - } - - /* - * Use info. in fd_sets to populate poll() revents. - */ - for ( i = 0; i < nfds; ++i ) { - if ( fds[ i ].lpoll_fd < 0 ) { - continue; - } - - if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN ) - && FD_ISSET( fds[i].lpoll_fd, &readfds )) { - fds[i].lpoll_revents |= LDAP_X_POLLIN; - } - - if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT ) - && FD_ISSET( fds[i].lpoll_fd, &writefds )) { - fds[i].lpoll_revents |= LDAP_X_POLLOUT; - } - - /* XXXmcs: any other cases to deal with? LDAP_X_POLLERR? */ - } - - return( rc ); -} - - -static LBER_SOCKET -nsldapi_compat_socket( LDAP *ld, int secure, int domain, int type, - int protocol ) -{ - int s; - - s = ld->ld_io_fns_ptr->liof_socket( domain, type, protocol ); - - if ( s >= 0 ) { - char *errmsg = NULL; - -#ifdef NSLDAPI_HAVE_POLL - if ( ld->ld_io_fns_ptr->liof_select != NULL - && s >= FD_SETSIZE ) { - errmsg = "can't use socket >= FD_SETSIZE"; - } -#elif !defined(_WINDOWS) /* not on Windows and do not have poll() */ - if ( s >= FD_SETSIZE ) { - errmsg = "can't use socket >= FD_SETSIZE"; - } -#endif - - if ( NULL == errmsg && secure && - ld->ld_io_fns_ptr->liof_ssl_enable( s ) < 0 ) { - errmsg = "failed to enable secure mode"; - } - - if ( NULL != errmsg ) { - if ( NULL == ld->ld_io_fns_ptr->liof_close ) { - nsldapi_os_closesocket( s ); - } else { - ld->ld_io_fns_ptr->liof_close( s ); - } - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, - nsldapi_strdup( errmsg )); - return( -1 ); - } - } - - return( s ); -} - - -/* - * Note: timeout is ignored because we have no way to pass it via - * the old I/O callback interface. - */ -static int LDAP_CALLBACK -nsldapi_ext_compat_connect( const char *hostlist, int defport, int timeout, - unsigned long options, struct lextiof_session_private *sessionarg, - struct lextiof_socket_private **socketargp ) -{ - NSLDAPICompatSocketInfo *defcsip; - struct ldap_io_fns *iofns; - int s, secure; - NSLDAPI_SOCKET_FN *socketfn; - NSLDAPI_IOCTL_FN *ioctlfn; - NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn; - NSLDAPI_CONNECT_FN *connectfn; - NSLDAPI_CLOSE_FN *closefn; - - defcsip = (NSLDAPICompatSocketInfo *)sessionarg; - iofns = defcsip->csi_ld->ld_io_fns_ptr; - - if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { - if ( NULL == iofns->liof_ssl_enable ) { - LDAP_SET_ERRNO( defcsip->csi_ld, EINVAL ); - return( -1 ); - } - secure = 1; - } else { - secure = 0; - } - - socketfn = ( iofns->liof_socket == NULL ) ? - nsldapi_os_socket : nsldapi_compat_socket; - ioctlfn = ( iofns->liof_ioctl == NULL ) ? - nsldapi_os_ioctl : (NSLDAPI_IOCTL_FN *)(iofns->liof_ioctl); - if ( NULL == iofns->liof_connect ) { - connectwithtofn = nsldapi_os_connect_with_to; - connectfn = NULL; - } else { - connectwithtofn = NULL; - connectfn = iofns->liof_connect; - } - closefn = ( iofns->liof_close == NULL ) ? - nsldapi_os_closesocket : iofns->liof_close; - - s = nsldapi_try_each_host( defcsip->csi_ld, hostlist, defport, - secure, socketfn, ioctlfn, connectwithtofn, - connectfn, closefn ); - - if ( s >= 0 ) { - NSLDAPICompatSocketInfo *csip; - - if (( csip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1, - sizeof( NSLDAPICompatSocketInfo ))) == NULL ) { - (*closefn)( s ); - LDAP_SET_LDERRNO( defcsip->csi_ld, LDAP_NO_MEMORY, - NULL, NULL ); - return( -1 ); - } - - csip->csi_socket = s; - csip->csi_ld = defcsip->csi_ld; - *socketargp = (void *)csip; - - /* - * We always return 1, which is a valid but not unique socket - * (file descriptor) number. The extended I/O functions only - * require that the combination of the void *arg and the int - * socket be unique. Since we allocate the - * NSLDAPICompatSocketInfo that we assign to arg, we meet - * that requirement. - */ - s = 1; - } - - return( s ); -} - - -static int LDAP_CALLBACK -nsldapi_ext_compat_close( int s, struct lextiof_socket_private *arg ) -{ - NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg; - struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr; - int rc; - - rc = iofns->liof_close( csip->csi_socket ); - - NSLDAPI_FREE( csip ); - - return( rc ); -} - -/* - * Install the I/O functions. - * Return an LDAP error code (LDAP_SUCCESS if all goes well). - */ -int -nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns ) -{ - NSLDAPICompatSocketInfo *defcsip; - - if (( defcsip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1, - sizeof( NSLDAPICompatSocketInfo ))) == NULL ) { - return( LDAP_NO_MEMORY ); - } - - defcsip->csi_socket = -1; - defcsip->csi_ld = ld; - - if ( ld->ld_io_fns_ptr != NULL ) { - (void)memset( (char *)ld->ld_io_fns_ptr, 0, - sizeof( struct ldap_io_fns )); - } else if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_CALLOC( - 1, sizeof( struct ldap_io_fns ))) == NULL ) { - NSLDAPI_FREE( defcsip ); - return( LDAP_NO_MEMORY ); - } - - /* struct copy */ - *(ld->ld_io_fns_ptr) = *iofns; - - ld->ld_extio_size = LBER_X_EXTIO_FNS_SIZE; - ld->ld_ext_session_arg = defcsip; - ld->ld_extread_fn = nsldapi_ext_compat_read; - ld->ld_extwrite_fn = nsldapi_ext_compat_write; - ld->ld_extpoll_fn = nsldapi_ext_compat_poll; - ld->ld_extconnect_fn = nsldapi_ext_compat_connect; - ld->ld_extclose_fn = nsldapi_ext_compat_close; - - return( nsldapi_install_lber_extiofns( ld, ld->ld_sbp )); -} -/* - * end of compat I/O functions - ****************************************************************************** - */ diff --git a/ldap/c-sdk/libraries/libldap/proxyauthctrl.c b/ldap/c-sdk/libraries/libldap/proxyauthctrl.c deleted file mode 100644 index e8e80cb144..0000000000 --- a/ldap/c-sdk/libraries/libldap/proxyauthctrl.c +++ /dev/null @@ -1,164 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -/* ldap_create_proxyauth_control - - Create a "version 1" proxied authorization control. - - Parameters are - - ld LDAP pointer to the desired connection - - dn The dn used in the proxy auth - - ctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client - - ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_proxyauth_control ( - LDAP *ld, - const char *dn, - const char ctl_iscritical, - LDAPControl **ctrlp -) -{ - BerElement *ber; - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - if (NULL == dn) - { - dn = ""; - } - - /* create a ber package to hold the controlValue */ - if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - - - if ( LBER_ERROR == ber_printf( ber, - "{s}", - dn ) ) - { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_PROXYAUTH, ber, 1, - ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - -} - - -/* ldap_create_proxiedauth_control - - Create a "version 2" proxied authorization control. - - Parameters are - - ld LDAP pointer to the desired connection - - authzid The authorization identity used in the proxy auth, - e.g., dn:uid=bjensen,dc=example,dc=com - - ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_proxiedauth_control ( - LDAP *ld, - const char *authzid, - LDAPControl **ctrlp -) -{ - BerElement *ber; - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL || authzid == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - /* create a ber package to hold the controlValue */ - if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - - - if ( LBER_ERROR == ber_printf( ber, - "s", - authzid ) ) - { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_PROXIEDAUTH, ber, 1, 1, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - -} diff --git a/ldap/c-sdk/libraries/libldap/psearch.c b/ldap/c-sdk/libraries/libldap/psearch.c deleted file mode 100644 index 71b9da90dd..0000000000 --- a/ldap/c-sdk/libraries/libldap/psearch.c +++ /dev/null @@ -1,190 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * psearch.c - Persistent search and "Entry Change Notification" support. - */ -#include "ldap-int.h" - - -int -LDAP_CALL -ldap_create_persistentsearch_control( LDAP *ld, int changetypes, - int changesonly, int return_echg_ctls, char ctl_iscritical, - LDAPControl **ctrlp ) -{ - BerElement *ber; - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL || ( changetypes & ~LDAP_CHANGETYPE_ANY ) != 0 ) { - rc = LDAP_PARAM_ERROR; - goto report_error_and_return; - } - - /* - * create a Persistent Search control. The control value looks like this: - * - * PersistentSearch ::= SEQUENCE { - * changeTypes INTEGER, - * -- the changeTypes field is the logical OR of - * -- one or more of these values: add (1), delete (2), - * -- modify (4), modDN (8). It specifies which types of - * -- changes will cause an entry to be returned. - * changesOnly BOOLEAN, -- skip initial search? - * returnECs BOOLEAN, -- return "Entry Change" controls? - * } - */ - if (( nsldapi_alloc_ber_with_options( ld, &ber )) != LDAP_SUCCESS ) { - rc = LDAP_NO_MEMORY; - goto report_error_and_return; - } - - if ( ber_printf( ber, "{ibb}", changetypes, changesonly, - return_echg_ctls ) == -1 ) { - ber_free( ber, 1 ); - rc = LDAP_ENCODING_ERROR; - goto report_error_and_return; - } - - rc = nsldapi_build_control( LDAP_CONTROL_PERSISTENTSEARCH, ber, 1, - ctl_iscritical, ctrlp ); - -report_error_and_return: - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - - -int -LDAP_CALL -ldap_parse_entrychange_control( LDAP *ld, LDAPControl **ctrls, ber_int_t *chgtypep, - char **prevdnp, int *chgnumpresentp, ber_int_t *chgnump ) -{ - BerElement *ber; - int rc, i; - ber_int_t changetype; - ber_len_t len; - ber_int_t along; - char *previousdn; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - /* - * find the entry change notification in the list of controls - */ - for ( i = 0; ctrls != NULL && ctrls[i] != NULL; ++i ) { - if ( strcmp( ctrls[i]->ldctl_oid, LDAP_CONTROL_ENTRYCHANGE ) == 0 ) { - break; - } - } - - if ( ctrls == NULL || ctrls[i] == NULL ) { - rc = LDAP_CONTROL_NOT_FOUND; - goto report_error_and_return; - } - - /* - * allocate a BER element from the control value and parse it. The control - * value should look like this: - * - * EntryChangeNotification ::= SEQUENCE { - * changeType ENUMERATED { - * add (1), -- these values match the - * delete (2), -- values used for changeTypes - * modify (4), -- in the PersistentSearch control. - * modDN (8), - * }, - * previousDN LDAPDN OPTIONAL, -- modDN ops. only - * changeNumber INTEGER OPTIONAL, -- if supported - * } - */ - if (( ber = ber_init( &(ctrls[i]->ldctl_value))) == NULL ) { - rc = LDAP_NO_MEMORY; - goto report_error_and_return; - } - - if ( ber_scanf( ber, "{e", &along ) == LBER_ERROR ) { - ber_free( ber, 1 ); - rc = LDAP_DECODING_ERROR; - goto report_error_and_return; - } - changetype = along; - - if ( changetype == LDAP_CHANGETYPE_MODDN ) { - if ( ber_scanf( ber, "a", &previousdn ) == LBER_ERROR ) { - ber_free( ber, 1 ); - rc = LDAP_DECODING_ERROR; - goto report_error_and_return; - } - } else { - previousdn = NULL; - } - - if ( chgtypep != NULL ) { - *chgtypep = changetype; - } - if ( prevdnp != NULL ) { - *prevdnp = previousdn; - } else if ( previousdn != NULL ) { - NSLDAPI_FREE( previousdn ); - } - - if ( chgnump != NULL ) { /* check for optional changenumber */ - if ( ber_peek_tag( ber, &len ) == LBER_INTEGER - && ber_get_int( ber, chgnump ) != LBER_ERROR ) { - if ( chgnumpresentp != NULL ) { - *chgnumpresentp = 1; - } - } else { - if ( chgnumpresentp != NULL ) { - *chgnumpresentp = 0; - } - } - } - - ber_free( ber, 1 ); - rc = LDAP_SUCCESS; - -report_error_and_return: - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libldap/pthreadtest.c b/ldap/c-sdk/libraries/libldap/pthreadtest.c deleted file mode 100644 index fa913f6919..0000000000 --- a/ldap/c-sdk/libraries/libldap/pthreadtest.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Authentication and search information. */ -#define NAME "cn=Directory Manager" -#define PASSWORD "rtfm11111" -#define BASE "dc=example,dc=com" -#define SCOPE LDAP_SCOPE_SUBTREE - -static void *modify_thread(); -static void *add_thread(); -static void *delete_thread(); -static void *bind_thread(); -static void *compare_thread(); -static void *search_thread(); -static void *my_mutex_alloc(); -static void my_mutex_free(); -void *my_sema_alloc( void ); -void my_sema_free( void * ); -int my_sema_wait( void * ); -int my_sema_post( void * ); -static void set_ld_error(); -static int get_ld_error(); -static void set_errno(); -static int get_errno(); -static void tsd_setup(); -static void tsd_cleanup(); -static int get_random_id( void ); -static char *get_id_str( int id ); - -/* Linked list of LDAPMessage structs for search results. */ -typedef struct ldapmsgwrapper { - LDAPMessage *lmw_messagep; - struct ldapmsgwrapper *lmw_next; -} ldapmsgwrapper; - -LDAP *ld; -pthread_key_t key; -int maxid = MAXINT; -int maxops = 0; /* zero means no limit */ -int range_filters = 0; /* if non-zero use >= and >= filters */ - -main( int argc, char **argv ) - -{ - pthread_attr_t attr; - pthread_t *threadids; - void *status; - struct ldap_thread_fns tfns; - struct ldap_extra_thread_fns extrafns; - int rc, c, errflg, i, inited_attr; - int doadd, dodelete, domodify, docompare, dosearch, dobind; - int option_extthreads, option_restart; - int each_thread_count, thread_count; - extern int optind; - extern char *optarg; - - doadd = dodelete = domodify = docompare = dobind = dosearch = 0; - option_extthreads = option_restart = 0; - inited_attr = 0; - errflg = 0; - each_thread_count = 1; /* how many of each type of thread? */ - rc = LDAP_SUCCESS; /* optimistic */ - - while (( c = getopt( argc, argv, "abcdmrsERi:n:o:S:" )) != EOF ) { - switch( c ) { - case 'a': /* perform add operations */ - ++doadd; - break; - case 'b': /* perform bind operations */ - ++dobind; - break; - case 'c': /* perform compare operations */ - ++docompare; - break; - case 'd': /* perform delete operations */ - ++dodelete; - break; - case 'm': /* perform modify operations */ - ++domodify; - break; - case 'r': /* use range filters in searches */ - ++range_filters; - break; - case 's': /* perform search operations */ - ++dosearch; - break; - case 'E': /* use extended thread functions */ - ++option_extthreads; - break; - case 'R': /* turn on LDAP_OPT_RESTART */ - ++option_restart; - break; - case 'i': /* highest # used for entry names */ - maxid = atoi( optarg ); - break; - case 'n': /* # threads for each operation */ - if (( each_thread_count = atoi( optarg )) < 1 ) { - fprintf( stderr, "thread count must be > 0\n" ); - ++errflg; - } - break; - case 'o': /* operations to perform per thread */ - if (( maxops = atoi( optarg )) < 0 ) { - fprintf( stderr, - "operation limit must be >= 0\n" ); - ++errflg; - } - break; - case 'S': /* random number seed */ - if ( *optarg == 'r' ) { - int seed = (int)time( (time_t *)0 ); - srandom( seed ); - printf( "Random seed: %d\n", seed ); - } else { - srandom( atoi( optarg )); - } - break; - default: - ++errflg; - break; - } - } - - /* Check command-line syntax. */ - thread_count = each_thread_count * ( doadd + dodelete + domodify - + dobind + docompare + dosearch ); - if ( thread_count < 1 ) { - fprintf( stderr, - "Specify at least one of -a, -b, -c, -d, -m, or -s\n" ); - ++errflg; - } - - if ( errflg || argc - optind != 2 ) { - fprintf( stderr, "usage: %s [-abcdmrsER] [-i id] [-n thr]" - " [-o oplim] [-S sd] host port\n", argv[0] ); - fputs( "\nWhere:\n" - "\t\"id\" is the highest entry id (name) to use" - " (default is MAXINT)\n" - "\t\"thr\" is the number of threads for each operation" - " (default is 1)\n" - "\t\"oplim\" is the number of ops done by each thread" - " (default is infinite)\n" - "\t\"sd\" is a random() number seed (default is 1). Use" - " the letter r for\n" - "\t\tsd to seed random() using time of day.\n" - "\t\"host\" is the hostname of an LDAP directory server\n" - "\t\"port\" is the TCP port of the LDAP directory server\n" - , stderr ); - fputs( "\nAnd the single character options are:\n" - "\t-a\tstart thread(s) to perform add operations\n" - "\t-b\tstart thread(s) to perform bind operations\n" - "\t-c\tstart thread(s) to perform compare operations\n" - "\t-d\tstart thread(s) to perform delete operations\n" - "\t-m\tstart thread(s) to perform modify operations\n" - "\t-s\tstart thread(s) to perform search operations\n" - "\t-r\tuse range filters in searches\n" - "\t-E\tinstall LDAP_OPT_EXTRA_THREAD_FN_PTRS\n" - "\t-R\tturn on LDAP_OPT_RESTART\n", stderr ); - - return( LDAP_PARAM_ERROR ); - } - - /* Create a key. */ - if ( pthread_key_create( &key, free ) != 0 ) { - perror( "pthread_key_create" ); - } - tsd_setup(); - - /* Allocate space for thread ids */ - if (( threadids = (pthread_t *)calloc( thread_count, - sizeof( pthread_t ))) == NULL ) { - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - - - /* Initialize the LDAP session. */ - if (( ld = ldap_init( argv[optind], atoi( argv[optind+1] ))) == NULL ) { - perror( "ldap_init" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - - /* Set the function pointers for dealing with mutexes - and error information. */ - memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); - tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc; - tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free; - tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock; - tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock; - tfns.ltf_get_errno = get_errno; - tfns.ltf_set_errno = set_errno; - tfns.ltf_get_lderrno = get_ld_error; - tfns.ltf_set_lderrno = set_ld_error; - tfns.ltf_lderrno_arg = NULL; - - /* Set up this session to use those function pointers. */ - - rc = ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns ); - if ( rc < 0 ) { - rc = ldap_get_lderrno( ld, NULL, NULL ); - fprintf( stderr, - "ldap_set_option (LDAP_OPT_THREAD_FN_PTRS): %s\n", - ldap_err2string( rc ) ); - goto clean_up_and_return; - } - - if ( option_extthreads ) { - /* Set the function pointers for working with semaphores. */ - - memset( &extrafns, '\0', sizeof(struct ldap_extra_thread_fns) ); - extrafns.ltf_mutex_trylock = - (int (*)(void *)) pthread_mutex_trylock; - extrafns.ltf_sema_alloc = (void *(*)(void)) my_sema_alloc; - extrafns.ltf_sema_free = (void (*)(void *)) my_sema_free; - extrafns.ltf_sema_wait = (int (*)(void *)) my_sema_wait; - extrafns.ltf_sema_post = (int (*)(void *)) my_sema_post; - - /* Set up this session to use those function pointers. */ - - if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, - (void *) &extrafns ) != 0 ) { - rc = ldap_get_lderrno( ld, NULL, NULL ); - ldap_perror( ld, "ldap_set_option" - " (LDAP_OPT_EXTRA_THREAD_FN_PTRS)" ); - goto clean_up_and_return; - } - } - - - if ( option_restart && ldap_set_option( ld, LDAP_OPT_RESTART, - LDAP_OPT_ON ) != 0 ) { - rc = ldap_get_lderrno( ld, NULL, NULL ); - ldap_perror( ld, "ldap_set_option(LDAP_OPT_RESTART)" ); - goto clean_up_and_return; - } - - /* Attempt to bind to the server. */ - rc = ldap_simple_bind_s( ld, NAME, PASSWORD ); - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_simple_bind_s: %s\n", - ldap_err2string( rc ) ); - goto clean_up_and_return; - } - - /* Initialize the attribute. */ - if ( pthread_attr_init( &attr ) != 0 ) { - perror( "pthread_attr_init" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++inited_attr; - - /* Specify that the threads are joinable. */ - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); - - /* Create all the requested threads */ - thread_count = 0; - if ( domodify ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - modify_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create modify_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - if ( doadd ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - add_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create add_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - if ( dodelete ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - delete_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create delete_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - if ( dobind ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - bind_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create bind_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - if ( docompare ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - compare_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create compare_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - if ( dosearch ) { - for ( i = 0; i < each_thread_count; ++i ) { - if ( pthread_create( &threadids[thread_count], &attr, - search_thread, get_id_str(thread_count) ) != 0 ) { - perror( "pthread_create search_thread" ); - rc = LDAP_LOCAL_ERROR; - goto clean_up_and_return; - } - ++thread_count; - } - } - - /* Wait until these threads exit. */ - for ( i = 0; i < thread_count; ++i ) { - pthread_join( threadids[i], &status ); - } - -clean_up_and_return: - if ( ld != NULL ) { - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - ldap_unbind( ld ); - } - if ( threadids != NULL ) { - free( threadids ); - } - if ( inited_attr ) { - pthread_attr_destroy( &attr ); - } - tsd_cleanup(); - - return( rc ); -} - - -static void * -modify_thread( char *id ) -{ - LDAPMessage *res; - LDAPMessage *e; - int i, modentry, num_entries, msgid, parse_rc, finished; - int rc, opcount; - LDAPMod mod; - LDAPMod *mods[2]; - char *vals[2]; - char *dn; - ldapmsgwrapper *list, *lmwp, *lastlmwp; - struct timeval zerotime; - void *voidrc = (void *)0; - - zerotime.tv_sec = zerotime.tv_usec = 0L; - - printf( "Starting modify_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", - NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: Modify thread: " - "ldap_search_ext: %s\n", id, ldap_err2string( rc ) ); - exit( 1 ); - } - list = lastlmwp = NULL; - finished = 0; - num_entries = 0; - while ( !finished ) { - rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); - switch ( rc ) { - case -1: - rc = ldap_get_lderrno( ld, NULL, NULL ); - fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); - exit( 1 ); - break; - case 0: - break; - /* Keep track of the number of entries found. */ - case LDAP_RES_SEARCH_ENTRY: - num_entries++; - if (( lmwp = (ldapmsgwrapper *) - malloc( sizeof( ldapmsgwrapper ))) == NULL ) { - fprintf( stderr, "Thread %s: Modify thread: Cannot malloc\n", id ); - exit( 1 ); - } - lmwp->lmw_messagep = res; - lmwp->lmw_next = NULL; - if ( lastlmwp == NULL ) { - list = lastlmwp = lmwp; - } else { - lastlmwp->lmw_next = lmwp; - } - lastlmwp = lmwp; - break; - case LDAP_RES_SEARCH_REFERENCE: - break; - case LDAP_RES_SEARCH_RESULT: - finished = 1; - parse_rc = ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, NULL, 1 ); - if ( parse_rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: can't parse result code.\n", id ); - exit( 1 ); - } else { - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: ldap_search: %s\n", id, ldap_err2string( rc ) ); - } else { - printf( "Thread %s: Got %d results.\n", id, num_entries ); - } - } - break; - default: - break; - } - } - - mods[0] = &mod; - mods[1] = NULL; - vals[0] = "bar"; - vals[1] = NULL; - - for ( ;; ) { - modentry = random() % num_entries; - for ( i = 0, lmwp = list; lmwp != NULL && i < modentry; - i++, lmwp = lmwp->lmw_next ) { - /* NULL */ - } - - if ( lmwp == NULL ) { - fprintf( stderr, - "Thread %s: Modify thread could not find entry %d of %d\n", - id, modentry, num_entries ); - continue; - } - - e = lmwp->lmw_messagep; - printf( "Thread %s: Modify thread picked entry %d of %d\n", id, i, num_entries ); - dn = ldap_get_dn( ld, e ); - - mod.mod_op = LDAP_MOD_REPLACE; - mod.mod_type = "description"; - mod.mod_values = vals; - printf( "Thread %s: Modifying (%s)\n", id, dn ); - - rc = ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_modify_ext_s: %s\n", - ldap_err2string( rc ) ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_modify_ext_s" ); - voidrc = (void *)1; - goto modify_cleanup_and_return; - } - } - free( dn ); - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -modify_cleanup_and_return: - printf( "Thread %s: attempted %d modify operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -add_thread( char *id ) -{ - LDAPMod mod[4]; - LDAPMod *mods[5]; - char dn[BUFSIZ], name[40]; - char *cnvals[2], *snvals[2], *pwdvals[2], *ocvals[3]; - int i, rc, opcount; - void *voidrc = (void *)0; - - printf( "Starting add_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - for ( i = 0; i < 4; i++ ) { - mods[i] = &mod[i]; - } - - mods[4] = NULL; - - mod[0].mod_op = 0; - mod[0].mod_type = "cn"; - mod[0].mod_values = cnvals; - cnvals[1] = NULL; - mod[1].mod_op = 0; - mod[1].mod_type = "sn"; - mod[1].mod_values = snvals; - snvals[1] = NULL; - mod[2].mod_op = 0; - mod[2].mod_type = "objectclass"; - mod[2].mod_values = ocvals; - ocvals[0] = "top"; - ocvals[1] = "person"; - ocvals[2] = NULL; - mod[3].mod_op = 0; - mod[3].mod_type = "userPassword"; - mod[3].mod_values = pwdvals; - pwdvals[1] = NULL; - mods[4] = NULL; - - for ( ;; ) { - sprintf( name, "%d", get_random_id() ); - sprintf( dn, "cn=%s, " BASE, name ); - cnvals[0] = name; - snvals[0] = name; - pwdvals[0] = name; - - printf( "Thread %s: Adding entry (%s)\n", id, dn ); - rc = ldap_add_ext_s( ld, dn, mods, NULL, NULL ); - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_add_ext_s: %s\n", - ldap_err2string( rc ) ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_add_ext_s" ); - voidrc = (void *)1; - goto add_cleanup_and_return; - } - } - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -add_cleanup_and_return: - printf( "Thread %s: attempted %d add operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -delete_thread( char *id ) -{ - LDAPMessage *res; - char dn[BUFSIZ], name[40]; - int num_entries, msgid, rc, parse_rc, finished, opcount; - struct timeval zerotime; - void *voidrc = (void *)0; - - zerotime.tv_sec = zerotime.tv_usec = 0L; - - printf( "Starting delete_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", - NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: Delete thread: " - "ldap_search_ext: %s\n", id, ldap_err2string( rc ) ); - exit( 1 ); - } - - finished = 0; - num_entries = 0; - while ( !finished ) { - rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); - switch ( rc ) { - case -1: - rc = ldap_get_lderrno( ld, NULL, NULL ); - fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); - exit( 1 ); - break; - case 0: - break; - /* Keep track of the number of entries found. */ - case LDAP_RES_SEARCH_ENTRY: - num_entries++; - break; - case LDAP_RES_SEARCH_REFERENCE: - break; - case LDAP_RES_SEARCH_RESULT: - finished = 1; - parse_rc = ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, NULL, 1 ); - if ( parse_rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: can't parse result code.\n", id ); - exit( 1 ); - } else { - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "Thread %s error: ldap_search: %s\n", id, ldap_err2string( rc ) ); - } else { - printf( "Thread %s: Got %d results.\n", id, num_entries ); - } - } - break; - default: - break; - } - } - - for ( ;; ) { - sprintf( name, "%d", get_random_id() ); - sprintf( dn, "cn=%s, " BASE, name ); - printf( "Thread %s: Deleting entry (%s)\n", id, dn ); - - if (( rc = ldap_delete_ext_s( ld, dn, NULL, NULL )) - != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_delete_ext_s" ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_delete_ext_s" ); - voidrc = (void *)1; - goto delete_cleanup_and_return; - } - } - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -delete_cleanup_and_return: - printf( "Thread %s: attempted %d delete operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -bind_thread( char *id ) -{ - char dn[BUFSIZ], name[40]; - int rc, opcount; - void *voidrc = (void *)0; - - printf( "Starting bind_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - for ( ;; ) { - sprintf( name, "%d", get_random_id() ); - sprintf( dn, "cn=%s, " BASE, name ); - printf( "Thread %s: Binding as entry (%s)\n", id, dn ); - - if (( rc = ldap_simple_bind_s( ld, dn, name )) - != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_simple_bind_s" ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_simple_bind_s" ); - voidrc = (void *)1; - goto bind_cleanup_and_return; - } - } else { - printf( "Thread %s: bound as entry (%s)\n", id, dn ); - } - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -bind_cleanup_and_return: - printf( "Thread %s: attempted %d bind operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -compare_thread( char *id ) -{ - char dn[BUFSIZ], name[40], cmpval[40]; - int rc, randval, opcount; - struct berval bv; - void *voidrc = (void *)0; - - printf( "Starting compare_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - for ( ;; ) { - randval = get_random_id(); - sprintf( name, "%d", randval ); - sprintf( dn, "cn=%s, " BASE, name ); - sprintf( cmpval, "%d", randval + random() % 3 ); - bv.bv_val = cmpval; - bv.bv_len = strlen( cmpval ); - - printf( "Thread %s: Comparing cn in entry (%s) with %s\n", - id, dn, cmpval ); - - rc = ldap_compare_ext_s( ld, dn, "cn", &bv, NULL, NULL ); - switch ( rc ) { - case LDAP_COMPARE_TRUE: - printf( "Thread %s: entry (%s) contains cn %s\n", - id, dn, cmpval ); - break; - case LDAP_COMPARE_FALSE: - printf( "Thread %s: entry (%s) doesn't contain cn %s\n", - id, dn, cmpval ); - break; - default: - ldap_perror( ld, "ldap_compare_ext_s" ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_compare_ext_s" ); - voidrc = (void *)1; - goto compare_cleanup_and_return; - } - } - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -compare_cleanup_and_return: - printf( "Thread %s: attempted %d compare operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -search_thread( char *id ) -{ - LDAPMessage *res, *entry; - char *dn, filter[40]; - int rc, opcount; - void *voidrc = (void *)0; - - printf( "Starting search_thread %s.\n", id ); - opcount = 0; - tsd_setup(); - - for ( ;; ) { - if ( range_filters ) { - switch( get_random_id() % 3 ) { - case 0: - sprintf( filter, "(cn>=%d)", get_random_id()); - break; - case 1: - sprintf( filter, "(cn<=%d)", get_random_id()); - break; - case 2: - sprintf( filter, "(&(cn>=%d)(cn<=%d))", - get_random_id(), get_random_id() ); - break; - } - } else { - sprintf( filter, "cn=%d", get_random_id() ); - } - - printf( "Thread %s: Searching for entry (%s)\n", id, filter ); - - res = NULL; - if (( rc = ldap_search_ext_s( ld, BASE, SCOPE, filter, NULL, 0, - NULL, NULL, NULL, 0, &res )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_search_ext_s" ); - if ( rc == LDAP_SERVER_DOWN ) { - perror( "ldap_search_ext_s" ); - voidrc = (void *)1; - goto search_cleanup_and_return; - } - } - if ( res != NULL ) { - entry = ldap_first_entry( ld, res ); - if ( entry == NULL ) { - printf( "Thread %s: found no entries\n", id ); - } else { - dn = ldap_get_dn( ld, entry ); - printf( - "Thread %s: found entry (%s); %d total\n", - id, dn == NULL ? "(Null)" : dn, - ldap_count_entries( ld, res )); - ldap_memfree( dn ); - } - ldap_msgfree( res ); - } - - ++opcount; - if ( maxops != 0 && opcount >= maxops ) { - break; - } - } - -search_cleanup_and_return: - printf( "Thread %s: attempted %d search operations\n", id, opcount ); - set_ld_error( 0, NULL, NULL, NULL ); /* disposes of memory */ - tsd_cleanup(); - free( id ); - return voidrc; -} - - -static void * -my_mutex_alloc( void ) -{ - pthread_mutex_t *mutexp; - - if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { - pthread_mutex_init( mutexp, NULL ); - } - return( mutexp ); -} - - -void * -my_sema_alloc( void ) -{ - sema_t *semptr; - - if( (semptr = malloc( sizeof(sema_t) ) ) != NULL ) { - sema_init( semptr, 0, USYNC_THREAD, NULL ); - } - return ( semptr ); -} - - -static void -my_mutex_free( void *mutexp ) -{ - pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); - free( mutexp ); -} - - -void -my_sema_free( void *semptr ) -{ - sema_destroy( (sema_t *) semptr ); - free( semptr ); -} - - -int -my_sema_wait( void *semptr ) -{ - if( semptr != NULL ) - return( sema_wait( (sema_t *) semptr ) ); - else - return( -1 ); -} - - -int -my_sema_post( void *semptr ) -{ - if( semptr != NULL ) - return( sema_post( (sema_t *) semptr ) ); - else - return( -1 ); -} - - -struct ldap_error { - int le_errno; - char *le_matched; - char *le_errmsg; -}; - - -static void -tsd_setup() -{ - void *tsd; - tsd = pthread_getspecific( key ); - if ( tsd != NULL ) { - fprintf( stderr, "tsd non-null!\n" ); - pthread_exit( NULL ); - } - - tsd = (void *) calloc( 1, sizeof(struct ldap_error) ); - pthread_setspecific( key, tsd ); -} - - -static void -tsd_cleanup() -{ - void *tsd; - - if (( tsd = pthread_getspecific( key )) != NULL ) { - pthread_setspecific( key, NULL ); - free( tsd ); - } -} - - -static void -set_ld_error( int err, char *matched, char *errmsg, void *dummy ) -{ - struct ldap_error *le; - - le = pthread_getspecific( key ); - - le->le_errno = err; - - if ( le->le_matched != NULL ) { - ldap_memfree( le->le_matched ); - } - le->le_matched = matched; - - if ( le->le_errmsg != NULL ) { - ldap_memfree( le->le_errmsg ); - } - le->le_errmsg = errmsg; -} - - -static int -get_ld_error( char **matchedp, char **errmsgp, void *dummy ) -{ - struct ldap_error *le; - - le = pthread_getspecific( key ); - if ( matchedp != NULL ) { - *matchedp = le->le_matched; - } - if ( errmsgp != NULL ) { - *errmsgp = le->le_errmsg; - } - return( le->le_errno ); -} - - -static void -set_errno( int err ) -{ - errno = err; -} - - -static int -get_errno( void ) -{ - return( errno ); -} - - -static int -get_random_id() -{ - return( random() % maxid ); -} - - -static char * -get_id_str( int id ) -{ - char idstr[ 10 ]; - - sprintf( idstr, "%d", id ); - return( strdup( idstr )); -} diff --git a/ldap/c-sdk/libraries/libldap/pwmodext.c b/ldap/c-sdk/libraries/libldap/pwmodext.c deleted file mode 100644 index fd737c4a3f..0000000000 --- a/ldap/c-sdk/libraries/libldap/pwmodext.c +++ /dev/null @@ -1,265 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): abobrov - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_passwd */ -int -LDAP_CALL -ldap_passwd ( - LDAP *ld, - struct berval *userid, - struct berval *oldpasswd, - struct berval *newpasswd, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ) -{ - int rc; - BerElement *ber = NULL; - struct berval *requestdata = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - requestdata = NSLDAPI_MALLOC( sizeof( struct berval ) ); - if ( requestdata == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* If the requestValue field is provided, it SHALL contain a - * PasswdModifyRequestValue with one or more fields present. - */ - if ( userid || oldpasswd || newpasswd ) { - if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) - != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* - * PasswdModifyRequestValue ::= SEQUENCE { - * userIdentity [0] OCTET STRING OPTIONAL - * oldPasswd [1] OCTET STRING OPTIONAL - * newPasswd [2] OCTET STRING OPTIONAL } - */ - if ( LBER_ERROR == ( ber_printf( ber, "{" ) ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if ( userid && userid->bv_val && userid->bv_len ) { - if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_ID, - userid->bv_val, userid->bv_len ) ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - - if ( oldpasswd && oldpasswd->bv_val && oldpasswd->bv_len ) { - if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_OLD, - oldpasswd->bv_val, oldpasswd->bv_len ) ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - - if ( newpasswd && newpasswd->bv_val && newpasswd->bv_len ) { - if ( LBER_ERROR == ( ber_printf( ber, "to", LDAP_TAG_PWDMOD_REQ_NEW, - newpasswd->bv_val, newpasswd->bv_len ) ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - - if ( LBER_ERROR == ( ber_printf( ber, "}" ) ) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - /* allocate struct berval with contents of the BER encoding */ - rc = ber_flatten( ber, &requestdata ); - if ( rc == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_NO_MEMORY ); - } - } else { - requestdata = NULL; - } - - rc = ldap_extended_operation( ld, LDAP_EXOP_MODIFY_PASSWD, requestdata, - serverctrls, clientctrls, msgidp ); - - /* the ber encoding is no longer needed */ - if ( requestdata ) { - ber_bvfree( requestdata ); - } - - if ( ber ) { - ber_free( ber, 1 ); - } - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - -/* ldap_parse_passwd */ -int -LDAP_CALL -ldap_parse_passwd ( - LDAP *ld, - LDAPMessage *result, - struct berval *genpasswd - ) -{ - int rc; - char *retoidp = NULL; - struct berval *retdatap = NULL; - BerElement *ber = NULL; - ber_len_t len; - ber_tag_t tag; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( !result ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( !genpasswd ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - rc = ldap_parse_extended_result( ld, result, &retoidp, &retdatap, 0 ); - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - rc = ldap_get_lderrno( ld, NULL, NULL ); - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - if ( retdatap ) { - /* allocate a Ber element with the contents of the - * berval from the response. - */ - if ( ( ber = ber_init( retdatap ) ) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - if ( ( tag = ber_skip_tag( ber, &len ) ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - ldap_memfree( retoidp ); - return( LDAP_DECODING_ERROR ); - } - - if ( ( ( tag = ber_peek_tag( ber, &len ) ) == LBER_ERROR ) || - tag != LDAP_TAG_PWDMOD_RES_GEN ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - ldap_memfree( retoidp ); - return( LDAP_DECODING_ERROR ); - } - - if ( ber_scanf( ber, "o}", genpasswd ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - ldap_memfree( retoidp ); - return( LDAP_DECODING_ERROR ); - } - - /* the ber encoding is no longer needed */ - ber_free( ber,1 ); - } - - ldap_memfree( retoidp ); - return( LDAP_SUCCESS ); -} - -/* ldap_passwd_s */ -int -LDAP_CALL -ldap_passwd_s ( - LDAP *ld, - struct berval *userid, - struct berval *oldpasswd, - struct berval *newpasswd, - struct berval *genpasswd, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ) -{ - int rc, msgid; - LDAPMessage *result = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - rc = ldap_passwd( ld, userid, oldpasswd, newpasswd, serverctrls, - clientctrls, &msgid ); - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); - if ( rc == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - rc = ldap_parse_passwd( ld, result, genpasswd ); - - ldap_msgfree( result ); - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libldap/pwpctrl.c b/ldap/c-sdk/libraries/libldap/pwpctrl.c deleted file mode 100644 index 26a3f1b2f6..0000000000 --- a/ldap/c-sdk/libraries/libldap/pwpctrl.c +++ /dev/null @@ -1,315 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): abobrov@sun.com - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_create_passwordpolicy_control: - -Parameters are - -ld LDAP pointer to the desired connection - -ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_passwordpolicy_control ( - LDAP *ld, - LDAPControl **ctrlp - ) -{ - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY, - NULL, 0, 0, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - -/* ldap_create_passwordpolicy_control_ext: - -Parameters are - -ld LDAP pointer to the desired connection - -ctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client - -ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_passwordpolicy_control_ext ( - LDAP *ld, - const char ctl_iscritical, - LDAPControl **ctrlp - ) -{ - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY, - NULL, 0, ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - -/* ldap_parse_passwordpolicy_control: - -Parameters are - -ld LDAP pointer to the desired connection - -ctrlp pointer to LDAPControl structure, obtained from - calling ldap_find_control() or by other means. - -exptimep result parameter is filled in with the number of seconds before - the password will expire. - -gracep result parameter is filled in with the number of grace logins - after the password has expired. - -errorcodep result parameter is filled in with the error code of the - password operation. -*/ - -int -LDAP_CALL -ldap_parse_passwordpolicy_control ( - LDAP *ld, - LDAPControl *ctrlp, - ber_int_t *expirep, - ber_int_t *gracep, - LDAPPasswordPolicyError *errorp - ) -{ - ber_len_t len; - ber_tag_t tag; - ber_int_t pp_exp = -1; - ber_int_t pp_grace = -1; - ber_int_t pp_warning = -1; - ber_int_t pp_err = PP_noError; - BerElement *ber = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - - /* allocate a Ber element with the contents of the control's struct berval */ - if ( ( ber = ber_init( &ctrlp->ldctl_value ) ) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* - * The control value should look like this: - * - * PasswordPolicyResponseValue ::= SEQUENCE { - * warning [0] CHOICE { - * timeBeforeExpiration [0] INTEGER (0 .. maxInt), - * graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL - * error [1] ENUMERATED { - * passwordExpired (0), - * accountLocked (1), - * changeAfterReset (2), - * passwordModNotAllowed (3), - * mustSupplyOldPassword (4), - * insufficientPasswordQuality (5), - * passwordTooShort (6), - * passwordTooYoung (7), - * passwordInHistory (8) } OPTIONAL } - */ - - if ( ber_scanf( ber, "{" ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - - tag = ber_peek_tag( ber, &len ); - - while ( (tag != LBER_ERROR) && (tag != LBER_END_OF_SEQORSET) ) { - if ( tag == ( LBER_CONSTRUCTED | LBER_CLASS_CONTEXT ) ) { - ber_skip_tag( ber, &len ); - if ( ber_scanf( ber, "ti", &tag, &pp_warning ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - if ( tag == LBER_CLASS_CONTEXT ) { - pp_exp = pp_warning; - } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) { - pp_grace = pp_warning; - } - } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) { - if ( ber_scanf( ber, "ti", &tag, &pp_err ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - } - if ( tag == LBER_DEFAULT ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - tag = ber_skip_tag( ber, &len ); - } - - if (expirep) *expirep = pp_exp; - if (gracep) *gracep = pp_grace; - if (errorp) *errorp = pp_err; - - /* the ber encoding is no longer needed */ - ber_free( ber, 1 ); - return( LDAP_SUCCESS ); -} - -/* ldap_parse_passwordpolicy_control_ext: - -Parameters are - -ld LDAP pointer to the desired connection - -ctrlp An array of controls obtained from calling - ldap_parse_result on the set of results - returned by the server - -exptimep result parameter is filled in with the number of seconds before - the password will expire. - -gracep result parameter is filled in with the number of grace logins - after the password has expired. - -errorcodep result parameter is filled in with the error code of the - password operation. -*/ - -int -LDAP_CALL -ldap_parse_passwordpolicy_control_ext ( - LDAP *ld, - LDAPControl **ctrlp, - ber_int_t *expirep, - ber_int_t *gracep, - LDAPPasswordPolicyError *errorp - ) -{ - int i, foundPPControl; - LDAPControl *PPCtrlp = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) { - return( LDAP_PARAM_ERROR ); - } - - /* find the control in the list of controls if it exists */ - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - foundPPControl = 0; - for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundPPControl )); i++ ) { - foundPPControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_PASSWD_POLICY ); - } - if ( !foundPPControl ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } else { - /* let local var point to the control */ - PPCtrlp = ctrlp[i-1]; - } - - return ( - ldap_parse_passwordpolicy_control( ld, PPCtrlp, expirep, gracep, errorp )); -} - -const char * -LDAP_CALL -ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err ) -{ - switch(err) { - case PP_passwordExpired: - return "Password expired"; - case PP_accountLocked: - return "Account locked"; - case PP_changeAfterReset: - return "Password must be changed"; - case PP_passwordModNotAllowed: - return "Policy prevents password modification"; - case PP_mustSupplyOldPassword: - return "Policy requires old password in order to change password"; - case PP_insufficientPasswordQuality: - return "Password fails quality checks"; - case PP_passwordTooShort: - return "Password is too short for policy"; - case PP_passwordTooYoung: - return "Password has been changed too recently"; - case PP_passwordInHistory: - return "New password is in list of old passwords"; - case PP_noError: - return "No error"; - default: - return "Unknown error code"; - } -} diff --git a/ldap/c-sdk/libraries/libldap/referral.c b/ldap/c-sdk/libraries/libldap/referral.c deleted file mode 100644 index 742d3d9861..0000000000 --- a/ldap/c-sdk/libraries/libldap/referral.c +++ /dev/null @@ -1,177 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * referral.c - routines for handling LDAPv3 referrals and references. - */ - -#include "ldap-int.h" - - -LDAPMessage * -LDAP_CALL -ldap_first_reference( LDAP *ld, LDAPMessage *res ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || res == NULLMSG ) { - return( NULLMSG ); - } - - if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { - return( res ); - } - - return( ldap_next_reference( ld, res )); -} - - -LDAPMessage * -LDAP_CALL -ldap_next_reference( LDAP *ld, LDAPMessage *ref ) -{ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || ref == NULLMSG ) { - return( NULLMSG ); /* punt */ - } - - for ( ref = ref->lm_chain; ref != NULLMSG; ref = ref->lm_chain ) { - if ( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { - return( ref ); - } - } - - return( NULLMSG ); -} - - -int -LDAP_CALL -ldap_count_references( LDAP *ld, LDAPMessage *res ) -{ - int i; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); - } - - for ( i = 0; res != NULL; res = res->lm_chain ) { - if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { - ++i; - } - } - - return( i ); -} - - -/* - * returns an LDAP error code. - */ -int -LDAP_CALL -ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp, - LDAPControl ***serverctrlsp, int freeit ) -{ - int err; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || - !NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( ref )) { - return( LDAP_PARAM_ERROR ); - } - - err = nsldapi_parse_reference( ld, ref->lm_ber, referralsp, - serverctrlsp ); - - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - - if ( freeit ) { - ldap_msgfree( ref ); - } - - return( err ); -} - - -/* - * returns an LDAP error code indicating success or failure of parsing - * does NOT set any error information inside "ld" - */ -int -nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp, - LDAPControl ***serverctrlsp ) -{ - int err; - BerElement ber; - char **refs; - - /* - * Parse a searchResultReference message. These are used in LDAPv3 - * and beyond and look like this: - * - * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL - * - * all wrapped up in an LDAPMessage sequence which looks like this: - * - * LDAPMessage ::= SEQUENCE { - * messageID MessageID, - * SearchResultReference - * controls [0] Controls OPTIONAL - * } - * - * ldap_result() pulls out the message id, so by the time a result - * message gets here we are conveniently sitting at the start of the - * SearchResultReference itself. - */ - err = LDAP_SUCCESS; /* optimistic */ - ber = *rber; /* struct copy */ - - if ( ber_scanf( &ber, "{v", &refs ) == LBER_ERROR ) { - err = LDAP_DECODING_ERROR; - } else if ( serverctrlsp != NULL ) { - /* pull out controls (if requested and any are present) */ - if ( ber_scanf( &ber, "}" ) == LBER_ERROR ) { - err = LDAP_DECODING_ERROR; - } else { - err = nsldapi_get_controls( &ber, serverctrlsp ); - } - } - - if ( referralsp == NULL ) { - ldap_value_free( refs ); - } else { - *referralsp = refs; - } - - return( err ); -} diff --git a/ldap/c-sdk/libraries/libldap/regex.c b/ldap/c-sdk/libraries/libldap/regex.c deleted file mode 100644 index 4ba4ee08a1..0000000000 --- a/ldap/c-sdk/libraries/libldap/regex.c +++ /dev/null @@ -1,920 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" -#if defined( macintosh ) || defined( DOS ) || defined( _WINDOWS ) || defined( NEED_BSDREGEX ) || defined( XP_OS2) -#include "regex.h" - -/* - * regex - Regular expression pattern matching and replacement - * - * By: Ozan S. Yigit (oz) - * Dept. of Computer Science - * York University - * - * These routines are the PUBLIC DOMAIN equivalents of regex - * routines as found in 4.nBSD UN*X, with minor extensions. - * - * These routines are derived from various implementations found - * in software tools books, and Conroy's grep. They are NOT derived - * from licensed/restricted software. - * For more interesting/academic/complicated implementations, - * see Henry Spencer's regexp routines, or GNU Emacs pattern - * matching module. - * - * Use the actual CCL code in the CLO - * section of pmatch. No need for a recursive - * pmatch call. - * - * Use a bitmap table to set char bits in an - * 8-bit chunk. - * - * Interfaces: - * re_comp: compile a regular expression into a NFA. - * - * char *re_comp(s) - * char *s; - * - * re_exec: execute the NFA to match a pattern. - * - * int re_exec(s) - * char *s; - * - * re_modw change re_exec's understanding of what a "word" - * looks like (for \< and \>) by adding into the - * hidden word-syntax table. - * - * void re_modw(s) - * char *s; - * - * re_subs: substitute the matched portions in a new string. - * - * int re_subs(src, dst) - * char *src; - * char *dst; - * - * re_fail: failure routine for re_exec. - * - * void re_fail(msg, op) - * char *msg; - * char op; - * - * Regular Expressions: - * - * [1] char matches itself, unless it is a special - * character (metachar): . \ [ ] * + ^ $ - * - * [2] . matches any character. - * - * [3] \ matches the character following it, except - * when followed by a left or right round bracket, - * a digit 1 to 9 or a left or right angle bracket. - * (see [7], [8] and [9]) - * It is used as an escape character for all - * other meta-characters, and itself. When used - * in a set ([4]), it is treated as an ordinary - * character. - * - * [4] [set] matches one of the characters in the set. - * If the first character in the set is "^", - * it matches a character NOT in the set, i.e. - * complements the set. A shorthand S-E is - * used to specify a set of characters S upto - * E, inclusive. The special characters "]" and - * "-" have no special meaning if they appear - * as the first chars in the set. - * examples: match: - * - * [a-z] any lowercase alpha - * - * [^]-] any char except ] and - - * - * [^A-Z] any char except uppercase - * alpha - * - * [a-zA-Z] any alpha - * - * [5] * any regular expression form [1] to [4], followed by - * closure char (*) matches zero or more matches of - * that form. - * - * [6] + same as [5], except it matches one or more. - * - * [7] a regular expression in the form [1] to [10], enclosed - * as \(form\) matches what form matches. The enclosure - * creates a set of tags, used for [8] and for - * pattern substution. The tagged forms are numbered - * starting from 1. - * - * [8] a \ followed by a digit 1 to 9 matches whatever a - * previously tagged regular expression ([7]) matched. - * - * [9] \< a regular expression starting with a \< construct - * \> and/or ending with a \> construct, restricts the - * pattern matching to the beginning of a word, and/or - * the end of a word. A word is defined to be a character - * string beginning and/or ending with the characters - * A-Z a-z 0-9 and _. It must also be preceded and/or - * followed by any character outside those mentioned. - * - * [10] a composite regular expression xy where x and y - * are in the form [1] to [10] matches the longest - * match of x followed by a match for y. - * - * [11] ^ a regular expression starting with a ^ character - * $ and/or ending with a $ character, restricts the - * pattern matching to the beginning of the line, - * or the end of line. [anchors] Elsewhere in the - * pattern, ^ and $ are treated as ordinary characters. - * - * - * Acknowledgements: - * - * HCR's Hugh Redelmeier has been most helpful in various - * stages of development. He convinced me to include BOW - * and EOW constructs, originally invented by Rob Pike at - * the University of Toronto. - * - * References: - * Software tools Kernighan & Plauger - * Software tools in Pascal Kernighan & Plauger - * Grep [rsx-11 C dist] David Conroy - * ed - text editor Un*x Programmer's Manual - * Advanced editing on Un*x B. W. Kernighan - * RegExp routines Henry Spencer - * - * Notes: - * - * This implementation uses a bit-set representation for character - * classes for speed and compactness. Each character is represented - * by one bit in a 128-bit block. Thus, CCL always takes a - * constant 16 bytes in the internal nfa, and re_exec does a single - * bit comparison to locate the character in the set. - * - * Examples: - * - * pattern: foo*.* - * compile: CHR f CHR o CLO CHR o END CLO ANY END END - * matches: fo foo fooo foobar fobar foxx ... - * - * pattern: fo[ob]a[rz] - * compile: CHR f CHR o CCL bitset CHR a CCL bitset END - * matches: fobar fooar fobaz fooaz - * - * pattern: foo\\+ - * compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END - * matches: foo\ foo\\ foo\\\ ... - * - * pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo) - * compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END - * matches: foo1foo foo2foo foo3foo - * - * pattern: \(fo.*\)-\1 - * compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END - * matches: foo-foo fo-fo fob-fob foobar-foobar ... - */ - -#define MAXNFA 1024 -#define MAXTAG 10 - -#define OKP 1 -#define NOP 0 - -#define CHR 1 -#define ANY 2 -#define CCL 3 -#define BOL 4 -#define EOL 5 -#define BOT 6 -#define EOT 7 -#define BOW 8 -#define EOW 9 -#define REF 10 -#define CLO 11 - -#define END 0 - -/* - * The following defines are not meant to be changeable. - * They are for readability only. - */ -#define MAXCHR 128 -#define CHRBIT 8 -#define BITBLK MAXCHR/CHRBIT -#define BLKIND 0170 -#define BITIND 07 - -#define ASCIIB 0177 - -/* Plain char, on the other hand, may be signed or unsigned; it depends on - * the platform and perhaps a compiler option. A hard fact of life, in C. - * - * 6-April-1999 mcs@netscape.com: replaced CHAR with REGEXCHAR to avoid - * conflicts with system types on Win32. Changed typedef - * for REGEXCHAR to always be unsigned, which seems right. - */ -typedef unsigned char REGEXCHAR; - -static int tagstk[MAXTAG]; /* subpat tag stack..*/ -static REGEXCHAR nfa[MAXNFA]; /* automaton.. */ -static int sta = NOP; /* status of lastpat */ - -static REGEXCHAR bittab[BITBLK]; /* bit table for CCL */ - /* pre-set bits... */ -static REGEXCHAR bitarr[] = {1,2,4,8,16,32,64,128}; - -static void -chset(REGEXCHAR c) -{ - bittab[((c) & (unsigned)BLKIND) >> 3] |= bitarr[(c) & BITIND]; -} - -#define badpat(x) (*nfa = END, x) -#define store(x) *mp++ = x - -char * -LDAP_CALL -re_comp( const char *pat ) -{ - register REGEXCHAR *p; /* pattern pointer */ - register REGEXCHAR *mp=nfa; /* nfa pointer */ - register REGEXCHAR *lp; /* saved pointer.. */ - register REGEXCHAR *sp=nfa; /* another one.. */ - - register int tagi = 0; /* tag stack index */ - register int tagc = 1; /* actual tag count */ - - register int n; - register REGEXCHAR mask; /* xor mask -CCL/NCL */ - int c1, c2; - - if (!pat || !*pat) { - if (sta) { - return 0; - } else { - return badpat("No previous regular expression"); - } - } - sta = NOP; - - for (p = (REGEXCHAR*)pat; *p; p++) { - lp = mp; - switch(*p) { - - case '.': /* match any char.. */ - store(ANY); - break; - - case '^': /* match beginning.. */ - if (p == (REGEXCHAR*)pat) - store(BOL); - else { - store(CHR); - store(*p); - } - break; - - case '$': /* match endofline.. */ - if (!*(p+1)) - store(EOL); - else { - store(CHR); - store(*p); - } - break; - - case '[': /* match char class..*/ - store(CCL); - - if (*++p == '^') { - mask = 0377; - p++; - } - else - mask = 0; - - if (*p == '-') /* real dash */ - chset(*p++); - if (*p == ']') /* real brac */ - chset(*p++); - while (*p && *p != ']') { - if (*p == '-' && *(p+1) && *(p+1) != ']') { - p++; - c1 = *(p-2) + 1; - c2 = *p++; - while (c1 <= c2) - chset((REGEXCHAR)c1++); - } -#ifdef EXTEND - else if (*p == '\\' && *(p+1)) { - p++; - chset(*p++); - } -#endif - else - chset(*p++); - } - if (!*p) - return badpat("Missing ]"); - - for (n = 0; n < BITBLK; bittab[n++] = (REGEXCHAR) 0) - store(mask ^ bittab[n]); - - break; - - case '*': /* match 0 or more.. */ - case '+': /* match 1 or more.. */ - if (p == (REGEXCHAR*)pat) - return badpat("Empty closure"); - lp = sp; /* previous opcode */ - if (*lp == CLO) /* equivalence.. */ - break; - switch(*lp) { - - case BOL: - case BOT: - case EOT: - case BOW: - case EOW: - case REF: - return badpat("Illegal closure"); - default: - break; - } - - if (*p == '+') - for (sp = mp; lp < sp; lp++) - store(*lp); - - store(END); - store(END); - sp = mp; - while (--mp > lp) - *mp = mp[-1]; - store(CLO); - mp = sp; - break; - - case '\\': /* tags, backrefs .. */ - switch(*++p) { - - case '(': - if (tagc < MAXTAG) { - tagstk[++tagi] = tagc; - store(BOT); - store(tagc++); - } - else - return badpat("Too many \\(\\) pairs"); - break; - case ')': - if (*sp == BOT) - return badpat("Null pattern inside \\(\\)"); - if (tagi > 0) { - store(EOT); - store(tagstk[tagi--]); - } - else - return badpat("Unmatched \\)"); - break; - case '<': - store(BOW); - break; - case '>': - if (*sp == BOW) - return badpat("Null pattern inside \\<\\>"); - store(EOW); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - n = *p-'0'; - if (tagi > 0 && tagstk[tagi] == n) - return badpat("Cyclical reference"); - if (tagc > n) { - store(REF); - store(n); - } - else - return badpat("Undetermined reference"); - break; -#ifdef EXTEND - case 'b': - store(CHR); - store('\b'); - break; - case 'n': - store(CHR); - store('\n'); - break; - case 'f': - store(CHR); - store('\f'); - break; - case 'r': - store(CHR); - store('\r'); - break; - case 't': - store(CHR); - store('\t'); - break; -#endif - default: - store(CHR); - store(*p); - } - break; - - default : /* an ordinary char */ - store(CHR); - store(*p); - break; - } - sp = lp; - } - if (tagi > 0) - return badpat("Unmatched \\("); - store(END); - sta = OKP; - return 0; -} - - -static REGEXCHAR *bol; -static REGEXCHAR *bopat[MAXTAG]; -static REGEXCHAR *eopat[MAXTAG]; -#ifdef NEEDPROTOS -static REGEXCHAR *pmatch( REGEXCHAR *lp, REGEXCHAR *ap ); -#else /* NEEDPROTOS */ -static REGEXCHAR *pmatch(); -#endif /* NEEDPROTOS */ - -/* - * re_exec: - * execute nfa to find a match. - * - * special cases: (nfa[0]) - * BOL - * Match only once, starting from the - * beginning. - * CHR - * First locate the character without - * calling pmatch, and if found, call - * pmatch for the remaining string. - * END - * re_comp failed, poor luser did not - * check for it. Fail fast. - * - * If a match is found, bopat[0] and eopat[0] are set - * to the beginning and the end of the matched fragment, - * respectively. - * - */ - -int -LDAP_CALL -re_exec( const char *lp ) -{ - register REGEXCHAR c; - register REGEXCHAR *ep = 0; - register REGEXCHAR *ap = nfa; - - bol = (REGEXCHAR*)lp; - - bopat[0] = 0; - bopat[1] = 0; - bopat[2] = 0; - bopat[3] = 0; - bopat[4] = 0; - bopat[5] = 0; - bopat[6] = 0; - bopat[7] = 0; - bopat[8] = 0; - bopat[9] = 0; - - switch(*ap) { - - case BOL: /* anchored: match from BOL only */ - ep = pmatch((REGEXCHAR*)lp,ap); - break; - case CHR: /* ordinary char: locate it fast */ - c = *(ap+1); - while (*lp && *(REGEXCHAR*)lp != c) - lp++; - if (!*lp) /* if EOS, fail, else fall thru. */ - return 0; - default: /* regular matching all the way. */ - do { - if ((ep = pmatch((REGEXCHAR*)lp,ap))) - break; - lp++; - } while (*lp); - - break; - case END: /* munged automaton. fail always */ - return 0; - } - if (!ep) - return 0; - - bopat[0] = (REGEXCHAR*)lp; - eopat[0] = ep; - return 1; -} - -/* - * pmatch: internal routine for the hard part - * - * This code is partly snarfed from an early grep written by - * David Conroy. The backref and tag stuff, and various other - * innovations are by oz. - * - * special case optimizations: (nfa[n], nfa[n+1]) - * CLO ANY - * We KNOW .* will match everything upto the - * end of line. Thus, directly go to the end of - * line, without recursive pmatch calls. As in - * the other closure cases, the remaining pattern - * must be matched by moving backwards on the - * string recursively, to find a match for xy - * (x is ".*" and y is the remaining pattern) - * where the match satisfies the LONGEST match for - * x followed by a match for y. - * CLO CHR - * We can again scan the string forward for the - * single char and at the point of failure, we - * execute the remaining nfa recursively, same as - * above. - * - * At the end of a successful match, bopat[n] and eopat[n] - * are set to the beginning and end of subpatterns matched - * by tagged expressions (n = 1 to 9). - * - */ - -#ifndef re_fail -extern void re_fail(); -#endif /* re_fail */ - -/* - * character classification table for word boundary operators BOW - * and EOW. the reason for not using ctype macros is that we can - * let the user add into our own table. see re_modw. This table - * is not in the bitset form, since we may wish to extend it in the - * future for other character classifications. - * - * TRUE for 0-9 A-Z a-z _ - */ -static char chrtyp[MAXCHR] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 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, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0 - }; - -#define HIBIT 0200 -#define inascii(x) (0177&(x)) -#define iswordc(x) chrtyp[inascii(x)] -#define isinset(x,y) (((y)&HIBIT)?0:((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])) - -/* - * skip values for CLO XXX to skip past the closure - */ - -#define ANYSKIP 2 /* [CLO] ANY END ... */ -#define CHRSKIP 3 /* [CLO] CHR chr END ... */ -#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */ - -static REGEXCHAR * -pmatch( REGEXCHAR *lp, REGEXCHAR *ap) -{ - register int op, c, n; - register REGEXCHAR *e; /* extra pointer for CLO */ - register REGEXCHAR *bp; /* beginning of subpat.. */ - register REGEXCHAR *ep; /* ending of subpat.. */ - REGEXCHAR *are; /* to save the line ptr. */ - - while ((op = *ap++) != END) - switch(op) { - - case CHR: - if (*lp++ != *ap++) - return 0; - break; - case ANY: - if (!*lp++) - return 0; - break; - case CCL: - c = *lp++; - if (!isinset(ap,c)) - return 0; - ap += BITBLK; - break; - case BOL: - if (lp != bol) - return 0; - break; - case EOL: - if (*lp) - return 0; - break; - case BOT: - bopat[*ap++] = lp; - break; - case EOT: - eopat[*ap++] = lp; - break; - case BOW: - if ((lp!=bol && iswordc(lp[-1])) || !iswordc(*lp)) - return 0; - break; - case EOW: - if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp)) - return 0; - break; - case REF: - n = *ap++; - bp = bopat[n]; - ep = eopat[n]; - while (bp < ep) - if (*bp++ != *lp++) - return 0; - break; - case CLO: - are = lp; - switch(*ap) { - - case ANY: - while (*lp) - lp++; - n = ANYSKIP; - break; - case CHR: - c = *(ap+1); - while (*lp && c == *lp) - lp++; - n = CHRSKIP; - break; - case CCL: - while ((c = *lp) && isinset(ap+1,c)) - lp++; - n = CCLSKIP; - break; - default: - re_fail("closure: bad nfa.", *ap); - return 0; - } - - ap += n; - - while (lp >= are) { - if ((e = pmatch(lp, ap))) - return e; - --lp; - } - return 0; - default: - re_fail("re_exec: bad nfa.", op); - return 0; - } - return lp; -} - -/* - * re_modw: - * add new characters into the word table to change re_exec's - * understanding of what a word should look like. Note that we - * only accept additions into the word definition. - * - * If the string parameter is 0 or null string, the table is - * reset back to the default containing A-Z a-z 0-9 _. [We use - * the compact bitset representation for the default table] - */ - -static REGEXCHAR deftab[16] = { - 0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207, - 0376, 0377, 0377, 007 -}; - -void -LDAP_CALL -re_modw( char *s ) -{ - register int i; - - if (!s || !*s) { - for (i = 0; i < MAXCHR; i++) - if (!isinset(deftab,i)) - iswordc(i) = 0; - } - else - while(*s) - iswordc(*s++) = 1; -} - -/* - * re_subs: - * substitute the matched portions of the src in dst. - * - * & substitute the entire matched pattern. - * - * \digit substitute a subpattern, with the given tag number. - * Tags are numbered from 1 to 9. If the particular - * tagged subpattern does not exist, null is substituted. - */ -int -LDAP_CALL -re_subs( char *src, char *dst) -{ - register char c; - register int pin; - register REGEXCHAR *bp; - register REGEXCHAR *ep; - - if (!*src || !bopat[0]) - return 0; - - while ((c = *src++)) { - switch(c) { - - case '&': - pin = 0; - break; - - case '\\': - c = *src++; - if (c >= '0' && c <= '9') { - pin = c - '0'; - break; - } - - default: - *dst++ = c; - continue; - } - - if ((bp = bopat[pin]) && (ep = eopat[pin])) { - while (*bp && bp < ep) - *dst++ = *(char*)bp++; - if (bp < ep) - return 0; - } - } - *dst = (char) 0; - return 1; -} - -#ifdef DEBUG - -/* No printf or exit in 16-bit Windows */ -#if defined( _WINDOWS ) && !defined( _WIN32 ) -static int LDAP_C printf( const char* pszFormat, ...) -{ - char buf[1024]; - va_list arglist; - va_start(arglist, pszFormat); - vsprintf(buf, pszFormat, arglist); - va_end(arglist); - OutputDebugString(buf); - return 0; -} -#define exit(v) return -#endif /* 16-bit Windows */ - - -#ifdef REGEX_DEBUG - -static void nfadump( REGEXCHAR *ap); - -/* - * symbolic - produce a symbolic dump of the nfa - */ -void -symbolic( char *s ) -{ - printf("pattern: %s\n", s); - printf("nfacode:\n"); - nfadump(nfa); -} - -static void -nfadump( REGEXCHAR *ap) -{ - register int n; - - while (*ap != END) - switch(*ap++) { - case CLO: - printf("CLOSURE"); - nfadump(ap); - switch(*ap) { - case CHR: - n = CHRSKIP; - break; - case ANY: - n = ANYSKIP; - break; - case CCL: - n = CCLSKIP; - break; - } - ap += n; - break; - case CHR: - printf("\tCHR %c\n",*ap++); - break; - case ANY: - printf("\tANY .\n"); - break; - case BOL: - printf("\tBOL -\n"); - break; - case EOL: - printf("\tEOL -\n"); - break; - case BOT: - printf("BOT: %d\n",*ap++); - break; - case EOT: - printf("EOT: %d\n",*ap++); - break; - case BOW: - printf("BOW\n"); - break; - case EOW: - printf("EOW\n"); - break; - case REF: - printf("REF: %d\n",*ap++); - break; - case CCL: - printf("\tCCL ["); - for (n = 0; n < MAXCHR; n++) - if (isinset(ap,(REGEXCHAR)n)) { - if (n < ' ') - printf("^%c", n ^ 0x040); - else - printf("%c", n); - } - printf("]\n"); - ap += BITBLK; - break; - default: - printf("bad nfa. opcode %o\n", ap[-1]); - exit(1); - break; - } -} -#endif /* REGEX_DEBUG */ -#endif /* DEBUG */ -#endif /* macintosh or DOS or _WINDOWS or NEED_BSDREGEX */ diff --git a/ldap/c-sdk/libraries/libldap/rename.c b/ldap/c-sdk/libraries/libldap/rename.c deleted file mode 100644 index ac3ec7c737..0000000000 --- a/ldap/c-sdk/libraries/libldap/rename.c +++ /dev/null @@ -1,265 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * rename.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * ldap_rename - initiate an ldap modifyDN operation. Parameters: - * - * ld LDAP descriptor - * dn DN of the object to modify - * newrdn RDN that will form leftmost component of entry's new name - * newparent if present, this is the Distinguished Name of the entry - * which becomes the immediate parent of the existing entry - * deleteoldrdn nonzero means to delete old rdn values from the entry - * while zero means to retain them as attributes of the entry - * 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_rename() call succeeds - * - * Example: - * int rc; - * rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid ); - */ -int -LDAP_CALL -ldap_rename( - LDAP *ld, - const char *dn, - const char *newrdn, - const char *newparent, - int deleteoldrdn, - LDAPControl **serverctrls, - LDAPControl **clientctrls, /* not used for anything yet */ - int *msgidp -) -{ - BerElement *ber; - int rc, err; - - /* - * A modify dn request looks like this: - * ModifyDNRequest ::= SEQUENCE { - * entry LDAPDN, - * newrdn RelativeLDAPDN, - * newparent [0] LDAPDN OPTIONAL, - * deleteoldrdn BOOLEAN - * } - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - if ( NULL == newrdn) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - /* only ldapv3 or higher can do a proper rename - * (i.e. with non-NULL newparent and/or controls) - */ - - if (( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) - && ((newparent != NULL) || (serverctrls != NULL) - || (clientctrls != NULL))) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( msgidp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* see if modRDN or modDN is handled by the cache */ - if ( ld->ld_cache_on ) { - if ( newparent == NULL && ld->ld_cache_modrdn != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_modrdn)( ld, *msgidp, - LDAP_REQ_MODRDN, dn, newrdn, deleteoldrdn )) - != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); -#if 0 - } else if ( ld->ld_cache_rename != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_rename)( ld, *msgidp, - LDAP_REQ_MODDN, dn, newrdn, newparent, - deleteoldrdn )) != 0 ) { - *msgidp = rc; - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); -#endif - } - } - - /* create a message to send */ - if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( err ); - } - - /* fill it in */ - if ( ber_printf( ber, "{it{ssb", *msgidp, LDAP_REQ_MODDN, dn, - newrdn, deleteoldrdn ) == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if ( newparent == NULL ) { - if ( ber_printf( ber, "}" ) == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } else { - if ( ber_printf( ber, "ts}", LDAP_TAG_NEWSUPERIOR, newparent ) - == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - - if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( rc ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODDN, - (char *) dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -int -LDAP_CALL -ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn ) -{ - int msgid; - - if ( ldap_rename( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL, &msgid ) == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - -int -LDAP_CALL -ldap_modrdn( LDAP *ld, const char *dn, const char *newrdn ) -{ - return( ldap_modrdn2( ld, dn, newrdn, 1 ) ); -} - -int -LDAP_CALL -ldap_rename_s( - LDAP *ld, - const char *dn, - const char *newrdn, - const char *newparent, - int deleteoldrdn, - LDAPControl **serverctrls, - LDAPControl **clientctrls /* not used for anything yet */ -) -{ - int msgid; - LDAPMessage *res; - - if ( ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid ) != LDAP_SUCCESS ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( msgid == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - return( ldap_result2error( ld, res, 1 ) ); -} - -int -LDAP_CALL -ldap_modrdn2_s( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn ) -{ - int msgid; - LDAPMessage *res; - - if ( (msgid = ldap_modrdn2( ld, dn, newrdn, deleteoldrdn )) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - return( ldap_result2error( ld, res, 1 ) ); -} - -int -LDAP_CALL -ldap_modrdn_s( LDAP *ld, const char *dn, const char *newrdn ) -{ - return( ldap_modrdn2_s( ld, dn, newrdn, 1 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/request.c b/ldap/c-sdk/libraries/libldap/request.c deleted file mode 100644 index d379917b2b..0000000000 --- a/ldap/c-sdk/libraries/libldap/request.c +++ /dev/null @@ -1,1659 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * request.c - sending of ldap requests; handling of referrals - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any ); -static void free_servers( LDAPServer *srvlist ); -static int chase_one_referral( LDAP *ld, LDAPRequest *lr, LDAPRequest *origreq, - char *refurl, char *desc, int *unknownp, int is_reference ); -static int re_encode_request( LDAP *ld, BerElement *origber, - int msgid, LDAPURLDesc *ludp, BerElement **berp, int is_reference ); - -#ifdef LDAP_DNS -static LDAPServer *dn2servers( LDAP *ld, char *dn ); -#endif /* LDAP_DNS */ - - -/* returns an LDAP error code and also sets error inside LDAP * */ -int -nsldapi_alloc_ber_with_options( LDAP *ld, BerElement **berp ) -{ - int err; - - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - if (( *berp = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - } else { - err = LDAP_SUCCESS; -#ifdef STR_TRANSLATION - nsldapi_set_ber_options( ld, *berp ); -#endif /* STR_TRANSLATION */ - } - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - - return( err ); -} - - -void -nsldapi_set_ber_options( LDAP *ld, BerElement *ber ) -{ - ber->ber_options = ld->ld_lberoptions; -#ifdef STR_TRANSLATION - if (( ld->ld_lberoptions & LBER_OPT_TRANSLATE_STRINGS ) != 0 ) { - ber_set_string_translators( ber, - ld->ld_lber_encode_translate_proc, - ld->ld_lber_decode_translate_proc ); - } -#endif /* STR_TRANSLATION */ -} - - -/* returns the message id of the request or -1 if an error occurs */ -int -nsldapi_send_initial_request( LDAP *ld, int msgid, unsigned long msgtype, - char *dn, BerElement *ber ) -{ - LDAPServer *servers; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_initial_request\n", 0,0,0 ); - -#ifdef LDAP_DNS - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - if (( ld->ld_options & LDAP_BITOPT_DNS ) != 0 && ldap_is_dns_dn( dn )) { - if (( servers = dn2servers( ld, dn )) == NULL ) { - ber_free( ber, 1 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - return( -1 ); - } - -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - LDAPServer *srv; - char msg[256]; - - for ( srv = servers; srv != NULL; - srv = srv->lsrv_next ) { - sprintf( msg, - "LDAP server %s: dn %s, port %d\n", - srv->lsrv_host, ( srv->lsrv_dn == NULL ) ? - "(default)" : srv->lsrv_dn, - srv->lsrv_port ); - ber_err_print( msg ); - } - } -#endif /* LDAP_DEBUG */ - } else { -#endif /* LDAP_DNS */ - /* - * use of DNS is turned off or this is an LDAP DN... - * use our default connection - */ - servers = NULL; -#ifdef LDAP_DNS - } - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); -#endif /* LDAP_DNS */ - - return( nsldapi_send_server_request( ld, ber, msgid, NULL, - servers, NULL, ( msgtype == LDAP_REQ_BIND ) ? dn : NULL, 0 )); -} - - -/* returns the message id of the request or -1 if an error occurs */ -int -nsldapi_send_server_request( - LDAP *ld, /* session handle */ - BerElement *ber, /* message to send */ - int msgid, /* ID of message to send */ - LDAPRequest *parentreq, /* non-NULL for referred requests */ - LDAPServer *srvlist, /* servers to connect to (NULL for default) */ - LDAPConn *lc, /* connection to use (NULL for default) */ - char *bindreqdn, /* non-NULL for bind requests */ - int bind /* perform a bind after opening new conn.? */ -) -{ - LDAPRequest *lr; - int err; - int incparent; /* did we bump parent's ref count? */ - /* EPIPE and Unsolicited Response handling variables */ - int res_rc = 0; - int epipe_err = 0; - int ext_res_rc = 0; - char *ext_oid = NULL; - struct berval *ext_data = NULL; - LDAPMessage *ext_res = NULL; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_server_request\n", 0, 0, 0 ); - - incparent = 0; - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - if ( lc == NULL ) { - if ( srvlist == NULL ) { - if ( ld->ld_defconn == NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - if ( bindreqdn == NULL && ( ld->ld_options - & LDAP_BITOPT_RECONNECT ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, - NULL, NULL ); - ber_free( ber, 1 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - - if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { - ber_free( ber, 1 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - } - lc = ld->ld_defconn; - } else { - if (( lc = find_connection( ld, srvlist, 1 )) == - NULL ) { - if ( bind && (parentreq != NULL) ) { - /* Remember the bind in the parent */ - incparent = 1; - ++parentreq->lr_outrefcnt; - } - - lc = nsldapi_new_connection( ld, &srvlist, 0, - 1, bind ); - } - free_servers( srvlist ); - } - } - - - /* - * return a fatal error if: - * 1. no connections exists - * or - * 2. the connection is dead - * or - * 3. it is not in the connected state with normal (non async) I/O - */ - if ( lc == NULL - || ( lc->lconn_status == LDAP_CONNST_DEAD ) - || ( 0 == (ld->ld_options & LDAP_BITOPT_ASYNC) && - lc->lconn_status != LDAP_CONNST_CONNECTED) ) { - - ber_free( ber, 1 ); - if ( lc != NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); - } - if ( incparent ) { - /* Forget about the bind */ - --parentreq->lr_outrefcnt; - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - - if (( lr = nsldapi_new_request( lc, ber, msgid, - 1 /* expect a response */)) == NULL - || ( bindreqdn != NULL && ( bindreqdn = - nsldapi_strdup( bindreqdn )) == NULL )) { - if ( lr != NULL ) { - NSLDAPI_FREE( lr ); - } - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); - ber_free( ber, 1 ); - if ( incparent ) { - /* Forget about the bind */ - --parentreq->lr_outrefcnt; - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - lr->lr_binddn = bindreqdn; - - if ( parentreq != NULL ) { /* sub-request */ - if ( !incparent ) { - /* Increment if we didn't do it before the bind */ - ++parentreq->lr_outrefcnt; - } - lr->lr_origid = parentreq->lr_origid; - lr->lr_parentcnt = parentreq->lr_parentcnt + 1; - lr->lr_parent = parentreq; - if ( parentreq->lr_child != NULL ) { - lr->lr_sibling = parentreq->lr_child; - } - parentreq->lr_child = lr; - } else { /* original request */ - lr->lr_origid = lr->lr_msgid; - } - - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - /* add new request to the end of the list of outstanding requests */ - nsldapi_queue_request_nolock( ld, lr ); - - /* - * Issue a non-blocking poll() if we need to check this - * connection's status. - */ - if ( lc->lconn_status == LDAP_CONNST_CONNECTING || - lc->lconn_pending_requests > 0 ) { - struct timeval tv; - - tv.tv_sec = tv.tv_usec = 0; - (void)nsldapi_iostatus_poll( ld, &tv ); - } - - /* - * If the connect is pending, check to see if it has now completed. - */ - if ( lc->lconn_status == LDAP_CONNST_CONNECTING && - nsldapi_iostatus_is_write_ready( ld, lc->lconn_sb )) { - lc->lconn_status = LDAP_CONNST_CONNECTED; - - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: connection 0x%p -" - " LDAP_CONNST_CONNECTING -> LDAP_CONNST_CONNECTED\n", - lc, 0, 0 ); - } - - if ( lc->lconn_status == LDAP_CONNST_CONNECTING || - lc->lconn_pending_requests > 0 ) { - /* - * The connect is not yet complete, or there are existing - * requests that have not yet been sent to the server. - * Delay sending this request. - */ - lr->lr_status = LDAP_REQST_WRITING; - ++lc->lconn_pending_requests; - nsldapi_iostatus_interest_write( ld, lc->lconn_sb ); - - /* - * If the connection is now connected, and it is ready - * to accept some more outbound data, send as many - * pending requests as possible. - */ - if ( lc->lconn_status != LDAP_CONNST_CONNECTING - && nsldapi_iostatus_is_write_ready( ld, lc->lconn_sb )) { - if ( nsldapi_send_pending_requests_nolock( ld, lc ) - == -1 ) { /* error */ - /* - * Since nsldapi_send_pending_requests_nolock() - * sets LDAP errno, there is no need to do so - * here. - */ - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - } - - } else { - if (( err = nsldapi_send_ber_message( ld, lc->lconn_sb, - ber, 0 /* do not free ber */, - 1 /* will handle EPIPE */ )) != 0 ) { - - epipe_err = LDAP_GET_ERRNO( ld ); - if ( epipe_err == EPIPE ) { - res_rc = nsldapi_result_nolock(ld, LDAP_RES_UNSOLICITED, 1, - 1, (struct timeval *) NULL, &ext_res); - if ( ( res_rc == LDAP_RES_EXTENDED ) && ext_res ) { - ext_res_rc = ldap_parse_extended_result( ld, ext_res, - &ext_oid, &ext_data, 0 ); - if ( ext_res_rc != LDAP_SUCCESS ) { - if ( ext_res ) { - ldap_msgfree( ext_res ); - } - nsldapi_connection_lost_nolock( ld, lc->lconn_sb ); - } else { -#ifdef LDAP_DEBUG - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: Unsolicited response\n", 0, 0, 0 ); - if ( ext_oid ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: Unsolicited response oid: %s\n", - ext_oid, 0, 0 ); - } - if ( ext_data && ext_data->bv_len && ext_data->bv_val ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: Unsolicited response len: %d\n", - ext_data->bv_len, 0, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: Unsolicited response val: %s\n", - ext_data->bv_val, 0, 0 ); - } - if ( !ext_oid && !ext_data ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_send_server_request: Unsolicited response is empty\n", - 0, 0, 0 ); - } -#endif /* LDAP_DEBUG */ - if ( ext_oid ) { - if ( strcmp ( ext_oid, - LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) { - if ( ext_data ) { - ber_bvfree( ext_data ); - } - if ( ext_oid ) { - ldap_memfree( ext_oid ); - } - if ( ext_res ) { - ldap_msgfree( ext_res ); - } - nsldapi_connection_lost_nolock( ld, - lc->lconn_sb ); - nsldapi_free_request( ld, lr, 0 ); - nsldapi_free_connection( ld, lc, - NULL, NULL, 0, 0 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - } - } - } else { - if ( ext_res ) { - ldap_msgfree( ext_res ); - } - nsldapi_connection_lost_nolock( ld, lc->lconn_sb ); - } - } - - /* need to continue write later */ - if (err == -2 ) { - lr->lr_status = LDAP_REQST_WRITING; - ++lc->lconn_pending_requests; - nsldapi_iostatus_interest_write( ld, lc->lconn_sb ); - } else { - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); - nsldapi_free_request( ld, lr, 0 ); - nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - return( -1 ); - } - - } else { - if ( parentreq == NULL ) { - ber->ber_end = ber->ber_ptr; - ber->ber_ptr = ber->ber_buf; - } - - /* sent -- waiting for a response */ - if (ld->ld_options & LDAP_BITOPT_ASYNC) { - lc->lconn_status = LDAP_CONNST_CONNECTED; - } - - nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); - return( msgid ); -} - - -/* - * nsldapi_send_ber_message(): Attempt to send a BER-encoded message. - * If freeit is non-zero, ber is freed when the send succeeds. - * If errno is EPIPE and epipe_handler is set we let the caller - * deal with EPIPE and dont call lost_nolock here but the caller - * should call lost_nolock itself when done with handling EPIPE. - * - * Return values: - * 0: message sent successfully. - * -1: a fatal error occurred while trying to send. - * -2: async. I/O is enabled and the send would block. - */ -int -nsldapi_send_ber_message( LDAP *ld, Sockbuf *sb, BerElement *ber, int freeit, - int epipe_handler ) -{ - int rc = 0; /* optimistic */ - int async = ( 0 != (ld->ld_options & LDAP_BITOPT_ASYNC)); - int more_to_send = 1; - - while ( more_to_send) { - /* - * ber_flush() doesn't set errno on EOF, so we pre-set it to - * zero to avoid getting tricked by leftover "EAGAIN" errors - */ - LDAP_SET_ERRNO( ld, 0 ); - - if ( ber_flush( sb, ber, freeit ) == 0 ) { - more_to_send = 0; /* success */ - } else { - int terrno = LDAP_GET_ERRNO( ld ); - if ( NSLDAPI_ERRNO_IO_INPROGRESS( terrno )) { - if ( async ) { - rc = -2; - break; - } - } else { - if ( !(epipe_handler && ( terrno == EPIPE )) ) { - nsldapi_connection_lost_nolock( ld, sb ); - } - rc = -1; /* fatal error */ - break; - } - } - } - - return( rc ); -} - - -/* - * nsldapi_send_pending_requests_nolock(): Send one or more pending requests - * that are associated with connection 'lc'. - * - * Return values: 0 -- success. - * -1 -- fatal error; connection closed. - * - * Must be called with these two mutexes locked, in this order: - * LDAP_CONN_LOCK - * LDAP_REQ_LOCK - */ -int -nsldapi_send_pending_requests_nolock( LDAP *ld, LDAPConn *lc ) -{ - int err; - int waiting_for_a_response = 0; - int rc = 0; - LDAPRequest *lr; - char *logname = "nsldapi_send_pending_requests_nolock"; - - LDAPDebug( LDAP_DEBUG_TRACE, "%s\n", logname, 0, 0 ); - - for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { - /* - * This code relies on the fact that the ld_requests list - * is in order from oldest to newest request (the oldest - * requests that have not yet been sent to the server are - * sent first). - */ - if ( lr->lr_status == LDAP_REQST_WRITING - && lr->lr_conn == lc ) { - err = nsldapi_send_ber_message( ld, lc->lconn_sb, - lr->lr_ber, 0 /* do not free ber */, - 0 /* will not handle EPIPE */ ); - if ( err == 0 ) { /* send succeeded */ - LDAPDebug( LDAP_DEBUG_TRACE, - "%s: 0x%p SENT\n", logname, lr, 0 ); - lr->lr_ber->ber_end = lr->lr_ber->ber_ptr; - lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf; - lr->lr_status = LDAP_REQST_INPROGRESS; - --lc->lconn_pending_requests; - } else if ( err == -2 ) { /* would block */ - rc = 0; /* not an error */ - LDAPDebug( LDAP_DEBUG_TRACE, - "%s: 0x%p WOULD BLOCK\n", logname, lr, 0 ); - break; - } else { /* fatal error */ - LDAPDebug( LDAP_DEBUG_TRACE, - "%s: 0x%p FATAL ERROR\n", logname, lr, 0 ); - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, - NULL, NULL ); - nsldapi_free_request( ld, lr, 0 ); - lr = NULL; - nsldapi_free_connection( ld, lc, NULL, NULL, - 0, 0 ); - lc = NULL; - rc = -1; - break; - } - } - - if (lr->lr_status == LDAP_REQST_INPROGRESS ) { - if (lr->lr_expect_resp) { - ++waiting_for_a_response; - } else { - LDAPDebug( LDAP_DEBUG_TRACE, - "%s: 0x%p NO RESPONSE EXPECTED;" - " freeing request \n", logname, lr, 0 ); - nsldapi_free_request( ld, lr, 0 ); - lr = NULL; - } - } - } - - if ( lc != NULL ) { - if ( lc->lconn_pending_requests < 1 ) { - /* no need to poll for "write ready" any longer */ - nsldapi_iostatus_interest_clear( ld, lc->lconn_sb ); - } - - if ( waiting_for_a_response ) { - /* need to poll for "read ready" */ - nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); - } - } - - LDAPDebug( LDAP_DEBUG_TRACE, "%s <- %d\n", logname, rc, 0 ); - return( rc ); -} - - -LDAPConn * -nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, - int connect, int bind ) -{ - int rc = -1; - LDAPConn *lc; - LDAPServer *prevsrv, *srv; - Sockbuf *sb = NULL; - - /* - * make a new LDAP server connection - */ - if (( lc = (LDAPConn *)NSLDAPI_CALLOC( 1, sizeof( LDAPConn ))) == NULL - || ( !use_ldsb && ( sb = ber_sockbuf_alloc()) == NULL )) { - if ( lc != NULL ) { - NSLDAPI_FREE( (char *)lc ); - } - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( NULL ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - if ( !use_ldsb ) { - /* - * we have allocated a new sockbuf - * set I/O routines to match those in default LDAP sockbuf - */ - IFP sb_fn; - struct lber_x_ext_io_fns extiofns; - - extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - - if ( ber_sockbuf_get_option( ld->ld_sbp, - LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ) == 0 ) { - ber_sockbuf_set_option( sb, - LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ); - } - if ( ber_sockbuf_get_option( ld->ld_sbp, - LBER_SOCKBUF_OPT_READ_FN, (void *)&sb_fn ) == 0 - && sb_fn != NULL ) { - ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_READ_FN, - (void *)sb_fn ); - } - if ( ber_sockbuf_get_option( ld->ld_sbp, - LBER_SOCKBUF_OPT_WRITE_FN, (void *)&sb_fn ) == 0 - && sb_fn != NULL ) { - ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_WRITE_FN, - (void *)sb_fn ); - } - } - - lc->lconn_sb = ( use_ldsb ) ? ld->ld_sbp : sb; - lc->lconn_version = ld->ld_version; /* inherited */ - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - - if ( connect ) { - prevsrv = NULL; - /* - * save the return code for later - */ - for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) { - rc = nsldapi_connect_to_host( ld, lc->lconn_sb, - srv->lsrv_host, srv->lsrv_port, - ( srv->lsrv_options & LDAP_SRV_OPT_SECURE ) != 0, - &lc->lconn_krbinstance ); - if (rc != -1) { - break; - } - prevsrv = srv; - } - - if ( srv == NULL ) { - if ( !use_ldsb ) { - NSLDAPI_FREE( (char *)lc->lconn_sb ); - } - NSLDAPI_FREE( (char *)lc ); - /* nsldapi_open_ldap_connection has already set ld_errno */ - return( NULL ); - } - - if ( prevsrv == NULL ) { - *srvlistp = srv->lsrv_next; - } else { - prevsrv->lsrv_next = srv->lsrv_next; - } - lc->lconn_server = srv; - } - - if ( 0 != (ld->ld_options & LDAP_BITOPT_ASYNC)) { - /* - * Technically, the socket may already be connected but we are - * not sure. By setting the state to LDAP_CONNST_CONNECTING, we - * ensure that we will check the socket status to make sure it - * is connected before we try to send any LDAP messages. - */ - lc->lconn_status = LDAP_CONNST_CONNECTING; - } else { - lc->lconn_status = LDAP_CONNST_CONNECTED; - } - - lc->lconn_next = ld->ld_conns; - ld->ld_conns = lc; - - /* - * XXX for now, we always do a synchronous bind. This will have - * to change in the long run... - */ - if ( bind ) { - int err, lderr, freepasswd, authmethod; - char *binddn, *passwd; - LDAPConn *savedefconn; - - freepasswd = err = 0; - - if ( ld->ld_rebind_fn == NULL ) { - binddn = passwd = ""; - authmethod = LDAP_AUTH_SIMPLE; - } else { - if (( lderr = (*ld->ld_rebind_fn)( ld, &binddn, &passwd, - &authmethod, 0, ld->ld_rebind_arg )) - == LDAP_SUCCESS ) { - freepasswd = 1; - } else { - LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); - err = -1; - } - } - - - if ( err == 0 ) { - savedefconn = ld->ld_defconn; - ld->ld_defconn = lc; - ++lc->lconn_refcnt; /* avoid premature free */ - - /* - * when binding, we will back down as low as LDAPv2 - * if we get back "protocol error" from bind attempts - */ - for ( ;; ) { - /* LDAP_MUTEX_UNLOCK(ld, LDAP_CONN_LOCK); */ - if (( lderr = ldap_bind_s( ld, binddn, passwd, - authmethod )) == LDAP_SUCCESS ) { - /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ - break; - } - /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ - if ( lc->lconn_version <= LDAP_VERSION2 - || lderr != LDAP_PROTOCOL_ERROR ) { - err = -1; - break; - } - --lc->lconn_version; /* try lower version */ - } - --lc->lconn_refcnt; - ld->ld_defconn = savedefconn; - } - - if ( freepasswd ) { - (*ld->ld_rebind_fn)( ld, &binddn, &passwd, - &authmethod, 1, ld->ld_rebind_arg ); - } - - if ( err != 0 ) { - nsldapi_free_connection( ld, lc, NULL, NULL, 1, 0 ); - lc = NULL; - } - } - - return( lc ); -} - - -#define LDAP_CONN_SAMEHOST( h1, h2 ) \ - (( (h1) == NULL && (h2) == NULL ) || \ - ( (h1) != NULL && (h2) != NULL && strcasecmp( (h1), (h2) ) == 0 )) - -static LDAPConn * -find_connection( LDAP *ld, LDAPServer *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; - - for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) { - if ( LDAP_CONN_SAMEHOST( ls->lsrv_host, - lc->lconn_server->lsrv_host ) - && ls->lsrv_port == lc->lconn_server->lsrv_port - && ls->lsrv_options == - lc->lconn_server->lsrv_options ) { - return( lc ); - } - if ( !any ) { - break; - } - } - } - - return( NULL ); -} - - -void -nsldapi_free_connection( LDAP *ld, LDAPConn *lc, LDAPControl **serverctrls, - LDAPControl **clientctrls, int force, int unbind ) -{ - LDAPConn *tmplc, *prevlc; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection\n", 0, 0, 0 ); - - if ( force || --lc->lconn_refcnt <= 0 ) { - nsldapi_iostatus_interest_clear( ld, lc->lconn_sb ); - if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { - if ( unbind ) { - nsldapi_send_unbind( ld, lc->lconn_sb, - serverctrls, clientctrls ); - } - } - nsldapi_close_connection( ld, lc->lconn_sb ); - prevlc = NULL; - for ( tmplc = ld->ld_conns; tmplc != NULL; - tmplc = tmplc->lconn_next ) { - if ( tmplc == lc ) { - if ( prevlc == NULL ) { - ld->ld_conns = tmplc->lconn_next; - } else { - prevlc->lconn_next = tmplc->lconn_next; - } - break; - } - prevlc = tmplc; - } - free_servers( lc->lconn_server ); - if ( lc->lconn_krbinstance != NULL ) { - NSLDAPI_FREE( lc->lconn_krbinstance ); - } - /* - * if this is the default connection (lc->lconn_sb==ld->ld_sbp) - * we do not free the Sockbuf here since it will be freed - * later inside ldap_unbind(). - */ - if ( lc->lconn_sb != ld->ld_sbp ) { - ber_sockbuf_free( lc->lconn_sb ); - lc->lconn_sb = NULL; - } - if ( lc->lconn_ber != NULLBER ) { - ber_free( lc->lconn_ber, 1 ); - } - if ( lc->lconn_binddn != NULL ) { - NSLDAPI_FREE( lc->lconn_binddn ); - } -#ifdef LDAP_SASLIO_HOOKS - if ( lc->lconn_sasl_ctx ) { /* the sasl connection context */ - sasl_dispose(&lc->lconn_sasl_ctx); - lc->lconn_sasl_ctx = NULL; - } -#endif /* LDAP_SASLIO_HOOKS */ - NSLDAPI_FREE( lc ); - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: actually freed\n", - 0, 0, 0 ); - } else { - lc->lconn_lastused = time( 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: refcnt %d\n", - lc->lconn_refcnt, 0, 0 ); - } -} - - -#ifdef LDAP_DEBUG -void -nsldapi_dump_connection( LDAP *ld, LDAPConn *lconns, int all ) -{ - LDAPConn *lc; - char msg[256]; -/* CTIME for this platform doesn't use this. */ -#if !defined(SUNOS4) && !defined(_WIN32) && !defined(LINUX) && !defined(macintosh) - char buf[26]; -#endif - - sprintf( msg, "** Connection%s:\n", all ? "s" : "" ); - ber_err_print( msg ); - for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) { - if ( lc->lconn_server != NULL ) { - sprintf( msg, "* 0x%p - host: %s port: %d secure: %s%s\n", - lc, ( lc->lconn_server->lsrv_host == NULL ) ? "(null)" - : lc->lconn_server->lsrv_host, - lc->lconn_server->lsrv_port, - ( lc->lconn_server->lsrv_options & - LDAP_SRV_OPT_SECURE ) ? "Yes" : - "No", ( lc->lconn_sb == ld->ld_sbp ) ? - " (default)" : "" ); - ber_err_print( msg ); - } - sprintf( msg, " refcnt: %d pending: %d status: %s\n", - lc->lconn_refcnt, lc->lconn_pending_requests, - ( lc->lconn_status == LDAP_CONNST_CONNECTING ) - ? "Connecting" : - ( lc->lconn_status == LDAP_CONNST_DEAD ) ? "Dead" : - "Connected" ); - ber_err_print( msg ); - sprintf( msg, " last used: %s", - NSLDAPI_CTIME( (time_t *) &lc->lconn_lastused, buf, - sizeof(buf) )); - ber_err_print( msg ); - if ( lc->lconn_ber != NULLBER ) { - ber_err_print( " partial response has been received:\n" ); - ber_dump( lc->lconn_ber, 1 ); - } - ber_err_print( "\n" ); - - if ( !all ) { - break; - } - } -} - - -void -nsldapi_dump_requests_and_responses( LDAP *ld ) -{ - LDAPRequest *lr; - LDAPMessage *lm, *l; - char msg[256]; - - ber_err_print( "** Outstanding Requests:\n" ); - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - if (( lr = ld->ld_requests ) == NULL ) { - ber_err_print( " Empty\n" ); - } - for ( ; lr != NULL; lr = lr->lr_next ) { - sprintf( msg, " * 0x%p - msgid %d, origid %d, status %s\n", - lr, 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_CONNDEAD ) ? "Dead" : - "Writing" ); - ber_err_print( msg ); - sprintf( msg, " outstanding referrals %d, parent count %d\n", - lr->lr_outrefcnt, lr->lr_parentcnt ); - ber_err_print( msg ); - if ( lr->lr_binddn != NULL ) { - sprintf( msg, " pending bind DN: <%s>\n", lr->lr_binddn ); - ber_err_print( msg ); - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - - ber_err_print( "** Response Queue:\n" ); - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - if (( lm = ld->ld_responses ) == NULLMSG ) { - ber_err_print( " Empty\n" ); - } - for ( ; lm != NULLMSG; lm = lm->lm_next ) { - sprintf( msg, " * 0x%p - msgid %d, type %d\n", - lm, lm->lm_msgid, lm->lm_msgtype ); - ber_err_print( msg ); - if (( l = lm->lm_chain ) != NULL ) { - ber_err_print( " chained responses:\n" ); - for ( ; l != NULLMSG; l = l->lm_chain ) { - sprintf( msg, - " * 0x%p - msgid %d, type %d\n", - l, l->lm_msgid, l->lm_msgtype ); - ber_err_print( msg ); - } - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); -} -#endif /* LDAP_DEBUG */ - - -LDAPRequest * -nsldapi_new_request( LDAPConn *lc, BerElement *ber, int msgid, int expect_resp ) -{ - LDAPRequest *lr; - - lr = (LDAPRequest *)NSLDAPI_CALLOC( 1, sizeof( LDAPRequest )); - - if ( lr != NULL ) { - lr->lr_conn = lc; - lr->lr_ber = ber; - lr->lr_msgid = lr->lr_origid = msgid; - lr->lr_expect_resp = expect_resp; - lr->lr_status = LDAP_REQST_INPROGRESS; - lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */ - - if ( lc != NULL ) { /* mark connection as in use */ - ++lc->lconn_refcnt; - lc->lconn_lastused = time( 0 ); - } - } - - return( lr ); -} - - -void -nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn ) -{ - LDAPRequest *tmplr, *nextlr; - - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_free_request 0x%p (origid %d, msgid %d)\n", - lr, lr->lr_origid, lr->lr_msgid ); - - if ( lr->lr_parent != NULL ) { - /* unlink child from parent */ - lr->lr_parent->lr_child = NULL; - --lr->lr_parent->lr_outrefcnt; - } - - if ( lr->lr_status == LDAP_REQST_WRITING ) { - --lr->lr_conn->lconn_pending_requests; - } - - /* free all of our spawned referrals (child requests) */ - for ( tmplr = lr->lr_child; tmplr != NULL; tmplr = nextlr ) { - nextlr = tmplr->lr_sibling; - nsldapi_free_request( ld, tmplr, free_conn ); - } - - if ( free_conn ) { - nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL, 0, 1 ); - } - - if ( lr->lr_prev == NULL ) { - ld->ld_requests = lr->lr_next; - } else { - lr->lr_prev->lr_next = lr->lr_next; - } - - if ( lr->lr_next != NULL ) { - lr->lr_next->lr_prev = lr->lr_prev; - } - - if ( lr->lr_ber != NULL ) { - ber_free( lr->lr_ber, 1 ); - } - - if ( lr->lr_res_error != NULL ) { - NSLDAPI_FREE( lr->lr_res_error ); - } - - if ( lr->lr_res_matched != NULL ) { - NSLDAPI_FREE( lr->lr_res_matched ); - } - - if ( lr->lr_binddn != NULL ) { - NSLDAPI_FREE( lr->lr_binddn ); - } - - if ( lr->lr_res_ctrls != NULL ) { - ldap_controls_free( lr->lr_res_ctrls ); - } - NSLDAPI_FREE( lr ); -} - - -/* - * Add a request to the end of the list of outstanding requests. - * This function must be called with these two locks in hand, acquired in - * this order: - * LDAP_CONN_LOCK - * LDAP_REQ_LOCK - */ -void -nsldapi_queue_request_nolock( LDAP *ld, LDAPRequest *lr ) -{ - if ( NULL == ld->ld_requests ) { - ld->ld_requests = lr; - } else { - LDAPRequest *tmplr; - - for ( tmplr = ld->ld_requests; tmplr->lr_next != NULL; - tmplr = tmplr->lr_next ) { - ; - } - tmplr->lr_next = lr; - lr->lr_prev = tmplr; - } -} - - -static void -free_servers( LDAPServer *srvlist ) -{ - LDAPServer *nextsrv; - - while ( srvlist != NULL ) { - nextsrv = srvlist->lsrv_next; - if ( srvlist->lsrv_dn != NULL ) { - NSLDAPI_FREE( srvlist->lsrv_dn ); - } - if ( srvlist->lsrv_host != NULL ) { - NSLDAPI_FREE( srvlist->lsrv_host ); - } - NSLDAPI_FREE( srvlist ); - srvlist = nextsrv; - } -} - - -/* - * Initiate chasing of LDAPv2+ (Umich extension) referrals. - * - * Returns an LDAP error code. - * - * Note that *hadrefp will be set to 1 if one or more referrals were found in - * "*errstrp" (even if we can't chase them) and zero if none were found. - * - * XXX merging of errors in this routine needs to be improved. - */ -int -nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, - int *totalcountp, int *chasingcountp ) -{ - char *p, *ref, *unfollowed; - LDAPRequest *origreq; - int rc, tmprc, len, unknown; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_chase_v2_referrals\n", 0, 0, 0 ); - - *totalcountp = *chasingcountp = 0; - - if ( *errstrp == NULL ) { - return( LDAP_SUCCESS ); - } - - len = strlen( *errstrp ); - for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { - if (( *p == 'R' || *p == 'r' ) && strncasecmp( p, - LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) { - *p = '\0'; - p += LDAP_REF_STR_LEN; - break; - } - } - - if ( len < LDAP_REF_STR_LEN ) { - return( LDAP_SUCCESS ); - } - - if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "more than %d referral hops (dropping)\n", - ld->ld_refhoplimit, 0, 0 ); - return( LDAP_REFERRAL_LIMIT_EXCEEDED ); - } - - /* find original request */ - for ( origreq = lr; origreq->lr_parent != NULL; - origreq = origreq->lr_parent ) { - ; - } - - unfollowed = NULL; - rc = LDAP_SUCCESS; - - /* parse out & follow referrals */ - for ( ref = p; rc == LDAP_SUCCESS && ref != NULL; ref = p ) { - if (( p = strchr( ref, '\n' )) != NULL ) { - *p++ = '\0'; - } else { - p = NULL; - } - - ++*totalcountp; - - rc = chase_one_referral( ld, lr, origreq, ref, "v2 referral", - &unknown, 0 /* not a reference */ ); - - if ( rc != LDAP_SUCCESS || unknown ) { - if (( tmprc = nsldapi_append_referral( ld, &unfollowed, - ref )) != LDAP_SUCCESS ) { - rc = tmprc; - } - } else { - ++*chasingcountp; - } - } - - NSLDAPI_FREE( *errstrp ); - *errstrp = unfollowed; - - return( rc ); -} - - -/* returns an LDAP error code */ -int -nsldapi_chase_v3_refs( LDAP *ld, LDAPRequest *lr, char **v3refs, - int is_reference, int *totalcountp, int *chasingcountp ) -{ - int rc = LDAP_SUCCESS; - int i, unknown; - LDAPRequest *origreq; - - *totalcountp = *chasingcountp = 0; - - if ( v3refs == NULL || v3refs[0] == NULL ) { - return( LDAP_SUCCESS ); - } - - *totalcountp = 1; - - if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "more than %d referral hops (dropping)\n", - ld->ld_refhoplimit, 0, 0 ); - return( LDAP_REFERRAL_LIMIT_EXCEEDED ); - } - - /* find original request */ - for ( origreq = lr; origreq->lr_parent != NULL; - origreq = origreq->lr_parent ) { - ; - } - - /* - * in LDAPv3, we just need to follow one referral in the set. - * we dp this by stopping as soon as we succeed in initiating a - * chase on any referral (basically this means we were able to connect - * to the server and bind). - */ - for ( i = 0; v3refs[i] != NULL; ++i ) { - rc = chase_one_referral( ld, lr, origreq, v3refs[i], - is_reference ? "v3 reference" : "v3 referral", &unknown, - is_reference ); - if ( rc == LDAP_SUCCESS && !unknown ) { - *chasingcountp = 1; - break; - } - } - - /* XXXmcs: should we save unfollowed referrals somewhere? */ - - return( rc ); /* last error is as good as any other I guess... */ -} - - -/* - * returns an LDAP error code - * - * XXXmcs: this function used to have #ifdef LDAP_DNS code in it but I - * removed it when I improved the parsing (we don't define LDAP_DNS - * here at Netscape). - */ -static int -chase_one_referral( LDAP *ld, LDAPRequest *lr, LDAPRequest *origreq, - char *refurl, char *desc, int *unknownp, int is_reference ) -{ - int rc, tmprc, secure, msgid; - LDAPServer *srv; - BerElement *ber; - LDAPURLDesc *ludp; - - *unknownp = 0; - ludp = NULLLDAPURLDESC; - - if ( nsldapi_url_parse( refurl, &ludp, 0 ) != 0 ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "ignoring unknown %s <%s>\n", desc, refurl, 0 ); - *unknownp = 1; - rc = LDAP_SUCCESS; - goto cleanup_and_return; - } - - secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ); - -/* XXXmcs: can't tell if secure is supported by connect callback */ - if ( secure && ld->ld_extconnect_fn == NULL ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "ignoring LDAPS %s <%s>\n", desc, refurl, 0 ); - *unknownp = 1; - rc = LDAP_SUCCESS; - goto cleanup_and_return; - } - - LDAPDebug( LDAP_DEBUG_TRACE, "chasing LDAP%s %s: <%s>\n", - secure ? "S" : "", desc, refurl ); - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if (( tmprc = re_encode_request( ld, origreq->lr_ber, msgid, - ludp, &ber, is_reference )) != LDAP_SUCCESS ) { - rc = tmprc; - goto cleanup_and_return; - } - - if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) - == NULL ) { - ber_free( ber, 1 ); - rc = LDAP_NO_MEMORY; - goto cleanup_and_return; - } - - if ( ludp->lud_host == NULL && ld->ld_defhost == NULL ) { - srv->lsrv_host = NULL; - } else { - if ( ludp->lud_host == NULL ) { - srv->lsrv_host = - nsldapi_strdup( origreq->lr_conn->lconn_server->lsrv_host ); - LDAPDebug( LDAP_DEBUG_TRACE, - "chase_one_referral: using hostname '%s' from original " - "request on new request\n", - srv->lsrv_host, 0, 0); - } else { - srv->lsrv_host = nsldapi_strdup( ludp->lud_host ); - LDAPDebug( LDAP_DEBUG_TRACE, - "chase_one_referral: using hostname '%s' as specified " - "on new request\n", - srv->lsrv_host, 0, 0); - } - - if ( srv->lsrv_host == NULL ) { - NSLDAPI_FREE( (char *)srv ); - ber_free( ber, 1 ); - rc = LDAP_NO_MEMORY; - goto cleanup_and_return; - } - } - - if ( ludp->lud_port == 0 && ludp->lud_host == NULL ) { - srv->lsrv_port = origreq->lr_conn->lconn_server->lsrv_port; - LDAPDebug( LDAP_DEBUG_TRACE, - "chase_one_referral: using port (%d) from original " - "request on new request\n", - srv->lsrv_port, 0, 0); - } else if ( ludp->lud_port != 0 ) { - srv->lsrv_port = ludp->lud_port; - LDAPDebug( LDAP_DEBUG_TRACE, - "chase_one_referral: using port (%d) as specified on " - "new request\n", - srv->lsrv_port, 0, 0); - } else { - srv->lsrv_port = secure ? LDAPS_PORT : LDAP_PORT; - LDAPDebug( LDAP_DEBUG_TRACE, - "chase_one_referral: using default port (%d)\n", - srv->lsrv_port, 0, 0 ); - } - - if ( secure ) { - srv->lsrv_options |= LDAP_SRV_OPT_SECURE; - } - - if ( nsldapi_send_server_request( ld, ber, msgid, - lr, srv, NULL, NULL, 1 ) < 0 ) { - rc = LDAP_GET_LDERRNO( ld, NULL, NULL ); - LDAPDebug( LDAP_DEBUG_ANY, "Unable to chase %s %s (%s)\n", - desc, refurl, ldap_err2string( rc )); - } else { - rc = LDAP_SUCCESS; - } - -cleanup_and_return: - if ( ludp != NULLLDAPURLDESC ) { - ldap_free_urldesc( ludp ); - } - - return( rc ); -} - - -/* returns an LDAP error code */ -int -nsldapi_append_referral( LDAP *ld, char **referralsp, char *s ) -{ - int first; - - if ( *referralsp == NULL ) { - first = 1; - *referralsp = (char *)NSLDAPI_MALLOC( strlen( s ) + - LDAP_REF_STR_LEN + 1 ); - } else { - first = 0; - *referralsp = (char *)NSLDAPI_REALLOC( *referralsp, - strlen( *referralsp ) + strlen( s ) + 2 ); - } - - if ( *referralsp == NULL ) { - return( LDAP_NO_MEMORY ); - } - - if ( first ) { - strcpy( *referralsp, LDAP_REF_STR ); - } else { - strcat( *referralsp, "\n" ); - } - strcat( *referralsp, s ); - - return( LDAP_SUCCESS ); -} - - - -/* returns an LDAP error code */ -static int -re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *ludp, - BerElement **berp, int is_reference ) -{ -/* - * XXX this routine knows way too much about how the lber library works! - */ - ber_int_t origmsgid; - ber_tag_t tag; - ber_int_t ver; - int rc; - BerElement *ber; - struct berelement tmpber; - char *dn, *orig_dn; - /* extra stuff for search request */ - ber_int_t scope = -1; - - LDAPDebug( LDAP_DEBUG_TRACE, - "re_encode_request: new msgid %d, new dn <%s>\n", - msgid, ( ludp->lud_dn == NULL ) ? "NONE" : ludp->lud_dn, 0 ); - - tmpber = *origber; - - /* - * All LDAP requests are sequences that start with a message id. For - * everything except delete requests, this is followed by a sequence - * that is tagged with the operation code. For deletes, there is just - * a DN that is tagged with the operation code. - */ - - /* skip past msgid and get operation tag */ - if ( ber_scanf( &tmpber, "{it", &origmsgid, &tag ) == LBER_ERROR ) { - return( LDAP_DECODING_ERROR ); - } - - /* - * XXXmcs: we don't support filters in search referrals yet, - * so if present we return an error which is probably - * better than just ignoring the extra info. - * XXXrichm: we now support scopes. Supporting filters would require - * a lot more additional work to be able to read the filter from - * the ber original search request, convert to string, etc. It might - * be better and easier to change nsldapi_build_search_req to have - * some special mode by which you could tell it to skip filter and - * attrlist encoding if no filter was given - then we could just - * create a new ber search request with our new filter if present. - */ - if ( ( tag == LDAP_REQ_SEARCH ) && ( ludp->lud_filter != NULL )) { - return( LDAP_LOCAL_ERROR ); - } - - if ( tag == LDAP_REQ_BIND ) { - /* bind requests have a version number before the DN */ - rc = ber_scanf( &tmpber, "{ia", &ver, &orig_dn ); - } else if ( tag == LDAP_REQ_DELETE ) { - /* delete requests DNs are not within a sequence */ - rc = ber_scanf( &tmpber, "a", &orig_dn ); - } else if ( tag == LDAP_REQ_SEARCH ) { - /* need scope */ - rc = ber_scanf( &tmpber, "{ae", &orig_dn, &scope ); - } else { - rc = ber_scanf( &tmpber, "{a", &orig_dn ); - } - - if ( rc == LBER_ERROR ) { - return( LDAP_DECODING_ERROR ); - } - - if ( ludp->lud_dn == NULL ) { - dn = orig_dn; - } else { - dn = ludp->lud_dn; - NSLDAPI_FREE( orig_dn ); - orig_dn = NULL; - } - - if ( ludp->lud_scope != -1 ) { - scope = ludp->lud_scope; /* scope provided by ref - use it */ - } else if (is_reference) { - /* - * RFC 4511 says that the we should use scope BASE in the - * search reference if the client's original request was for scope - * ONELEVEL - since the server did not include the scope in the - * search reference returned, we must provide the correct behavior - * in the client (i.e. the correct behavior is implied) - * see RFC 4511 section 4.5.3 for more information - */ - if (scope == LDAP_SCOPE_ONELEVEL) { - scope = LDAP_SCOPE_BASE; - } - } - - /* allocate and build the new request */ - if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - if ( orig_dn != NULL ) { - NSLDAPI_FREE( orig_dn ); - } - return( rc ); - } - - if ( tag == LDAP_REQ_BIND ) { - rc = ber_printf( ber, "{it{is", msgid, tag, ver , dn ); - } else if ( tag == LDAP_REQ_DELETE ) { - rc = ber_printf( ber, "{its}", msgid, tag, dn ); - } else if ( tag == LDAP_REQ_SEARCH ) { - rc = ber_printf( ber, "{it{se", msgid, tag, dn, scope ); - } else { - rc = ber_printf( ber, "{it{s", msgid, tag, dn ); - } - - if ( orig_dn != NULL ) { - NSLDAPI_FREE( orig_dn ); - } -/* - * can't use "dn" or "orig_dn" from this point on (they've been freed) - */ - - if ( rc == -1 ) { - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - 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 )) { - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { - LDAPDebug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n", - 0, 0, 0 ); - ber_dump( ber, 0 ); - } -#endif /* LDAP_DEBUG */ - - *berp = ber; - return( LDAP_SUCCESS ); -} - - -LDAPRequest * -nsldapi_find_request_by_msgid( LDAP *ld, int msgid ) -{ - LDAPRequest *lr; - - for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { - if ( msgid == lr->lr_msgid ) { - break; - } - } - - return( lr ); -} - - -/* - * nsldapi_connection_lost_nolock() resets "ld" to a non-connected, known - * state. It should be called whenever a fatal error occurs on the - * Sockbuf "sb." sb == NULL means we don't know specifically where - * the problem was so we assume all connections are bad. - */ -void -nsldapi_connection_lost_nolock( LDAP *ld, Sockbuf *sb ) -{ - LDAPRequest *lr; - - /* - * change status of all pending requests that are associated with "sb - * to "connection dead." - * also change the connection status to "dead" and remove it from - * the list of sockets we are interested in. - */ - for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { - if ( sb == NULL || - ( lr->lr_conn != NULL && lr->lr_conn->lconn_sb == sb )) { - lr->lr_status = LDAP_REQST_CONNDEAD; - if ( lr->lr_conn != NULL ) { - lr->lr_conn->lconn_status = LDAP_CONNST_DEAD; - nsldapi_iostatus_interest_clear( ld, - lr->lr_conn->lconn_sb ); - } - } - } -} - - -#ifdef LDAP_DNS -static LDAPServer * -dn2servers( LDAP *ld, char *dn ) /* dn can also be a domain.... */ -{ - char *p, *domain, *host, *server_dn, **dxs; - int i, port; - LDAPServer *srvlist, *prevsrv, *srv; - - if (( domain = strrchr( dn, '@' )) != NULL ) { - ++domain; - } else { - domain = dn; - } - - if (( dxs = nsldapi_getdxbyname( domain )) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( NULL ); - } - - srvlist = NULL; - - for ( i = 0; dxs[ i ] != NULL; ++i ) { - port = LDAP_PORT; - 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 *)NSLDAPI_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 = nsldapi_strdup( host )) == NULL - || ( server_dn != NULL && ( srv->lsrv_dn = - nsldapi_strdup( server_dn )) == NULL )) { - free_servers( srvlist ); - srvlist = NULL; - break; /* exit loop & return */ - } - srv->lsrv_port = port; - } - } - - ldap_value_free( dxs ); - - if ( srvlist == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); - } - - return( srvlist ); -} -#endif /* LDAP_DNS */ diff --git a/ldap/c-sdk/libraries/libldap/reslist.c b/ldap/c-sdk/libraries/libldap/reslist.c deleted file mode 100644 index a382941eba..0000000000 --- a/ldap/c-sdk/libraries/libldap/reslist.c +++ /dev/null @@ -1,86 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * reslist.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -LDAPMessage * -LDAP_CALL -ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e ) -{ - LDAPMessage *tmp, *prev = NULL; - - if ( list == NULL || e == NULL ) { - return( NULL ); - } - - for ( tmp = *list; tmp != NULL && tmp != e; tmp = tmp->lm_chain ) - prev = tmp; - - if ( tmp == NULL ) - return( NULL ); - - if ( prev == NULL ) - *list = tmp->lm_chain; - else - prev->lm_chain = tmp->lm_chain; - tmp->lm_chain = NULL; - - return( tmp ); -} - -void -LDAP_CALL -ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e ) -{ - if ( list != NULL && e != NULL ) { - e->lm_chain = *list; - *list = e; - } -} diff --git a/ldap/c-sdk/libraries/libldap/result.c b/ldap/c-sdk/libraries/libldap/result.c deleted file mode 100644 index 59c15f8115..0000000000 --- a/ldap/c-sdk/libraries/libldap/result.c +++ /dev/null @@ -1,1473 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * result.c - wait for an ldap result - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -/* - * Special return values used by some functions (wait4msg() and read1msg()). - */ -#define NSLDAPI_RESULT_TIMEOUT 0 -#define NSLDAPI_RESULT_ERROR (-1) -#define NSLDAPI_RESULT_NOT_FOUND (-2) - -static int check_response_queue( LDAP *ld, int msgid, int all, - int do_abandon_check, LDAPMessage **result ); -static int ldap_abandoned( LDAP *ld, int msgid ); -static int ldap_mark_abandoned( LDAP *ld, int msgid ); -static int wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, - struct timeval *timeout, LDAPMessage **result ); -static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp, - LDAPMessage **result ); -static void check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, - int ldapversion, int *totalcountp, int *chasingcountp ); -static int build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ); -static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ); -#if defined( CLDAP ) -static int cldap_select1( LDAP *ld, struct timeval *timeout ); -#endif -static void link_pend( LDAP *ld, LDAPPend *lp ); - -/* - * ldap_result - wait for an ldap result response to a message from the - * ldap server. If msgid is -1, any message will be accepted, otherwise - * ldap_result will wait for a response with msgid. If all is 0 the - * first message with id msgid will be accepted, otherwise, ldap_result - * will wait for all responses with id msgid and then return a pointer to - * the entire list of messages. This is only useful for search responses, - * which can be of two message types (zero or more entries, followed by an - * ldap result). The type of the first message received is returned. - * When waiting, any messages that have been abandoned are discarded. - * - * Example: - * ldap_result( s, msgid, all, timeout, result ) - */ -int -LDAP_CALL -ldap_result( - LDAP *ld, - int msgid, - int all, - struct timeval *timeout, - LDAPMessage **result -) -{ - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); /* punt */ - } - - LDAP_MUTEX_LOCK( ld, LDAP_RESULT_LOCK ); - - rc = nsldapi_result_nolock(ld, msgid, all, 1, timeout, result); - - LDAP_MUTEX_UNLOCK( ld, LDAP_RESULT_LOCK ); - - return( rc ); -} - - -int -nsldapi_result_nolock( LDAP *ld, int msgid, int all, int unlock_permitted, - struct timeval *timeout, LDAPMessage **result ) -{ - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_result_nolock (msgid=%d, all=%d)\n", msgid, all, 0 ); - - /* - * First, look through the list of responses we have received on - * this association and see if the response we're interested in - * is there. If it is, return it. If not, call wait4msg() to - * wait until it arrives or timeout occurs. - */ - - if ( result == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( -1 ); - } - - if ( check_response_queue( ld, msgid, all, 1, result ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); - rc = (*result)->lm_msgtype; - } else { - rc = wait4msg( ld, msgid, all, unlock_permitted, timeout, - result ); - } - - /* - * XXXmcs should use cache function pointers to hook in memcache - */ - if ( ld->ld_memcache != NULL && NSLDAPI_SEARCH_RELATED_RESULT( rc ) && - !((*result)->lm_fromcache )) { - ldap_memcache_append( ld, (*result)->lm_msgid, - (all || NSLDAPI_IS_SEARCH_RESULT( rc )), *result ); - } - - return( rc ); -} - - -/* - * Look through the list of queued responses for a message that matches the - * criteria in the msgid and all parameters. msgid == LDAP_RES_ANY matches - * all ids. - * - * If an appropriate message is found, a non-zero value is returned and the - * message is dequeued and assigned to *result. - * - * If not, *result is set to NULL and this function returns 0. - */ -static int -check_response_queue( LDAP *ld, int msgid, int all, int do_abandon_check, - LDAPMessage **result ) -{ - LDAPMessage *lm, *lastlm, *nextlm; - LDAPRequest *lr; - - LDAPDebug( LDAP_DEBUG_TRACE, - "=> check_response_queue (msgid=%d, all=%d)\n", msgid, all, 0 ); - - *result = NULL; - lastlm = NULL; - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { - nextlm = lm->lm_next; - - if ( do_abandon_check && ldap_abandoned( ld, lm->lm_msgid ) ) { - ldap_mark_abandoned( ld, lm->lm_msgid ); - - if ( lastlm == NULL ) { - ld->ld_responses = lm->lm_next; - } else { - lastlm->lm_next = nextlm; - } - - ldap_msgfree( lm ); - - continue; - } - - if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { - LDAPMessage *tmp; - - if ( all == 0 - || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT - && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE - && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) - break; - - for ( tmp = lm; tmp != NULL; tmp = tmp->lm_chain ) { - if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) - break; - } - - if ( tmp == NULL ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - LDAPDebug( LDAP_DEBUG_TRACE, - "<= check_response_queue NOT FOUND\n", - 0, 0, 0 ); - return( 0 ); /* no message to return */ - } - - break; - } - lastlm = lm; - } - - /* - * if we did not find a message OR if the one we found is a result for - * a request that is still pending, return failure. - */ - if ( lm == NULL - || (( lr = nsldapi_find_request_by_msgid( ld, lm->lm_msgid )) - != NULL && lr->lr_outrefcnt > 0 )) { - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - LDAPDebug( LDAP_DEBUG_TRACE, - "<= check_response_queue NOT FOUND\n", - 0, 0, 0 ); - return( 0 ); /* no message to return */ - } - - if ( all == 0 ) { - if ( lm->lm_chain == NULL ) { - if ( lastlm == NULL ) { - ld->ld_responses = lm->lm_next; - } else { - lastlm->lm_next = lm->lm_next; - } - } else { - if ( lastlm == NULL ) { - ld->ld_responses = lm->lm_chain; - ld->ld_responses->lm_next = lm->lm_next; - } else { - lastlm->lm_next = lm->lm_chain; - lastlm->lm_next->lm_next = lm->lm_next; - } - } - } else { - if ( lastlm == NULL ) { - ld->ld_responses = lm->lm_next; - } else { - lastlm->lm_next = lm->lm_next; - } - } - - if ( all == 0 ) { - lm->lm_chain = NULL; - } - lm->lm_next = NULL; - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - - *result = lm; - LDAPDebug( LDAP_DEBUG_TRACE, - "<= check_response_queue returning msgid %d type %d\n", - lm->lm_msgid, lm->lm_msgtype, 0 ); - return( 1 ); /* a message was found and returned in *result */ -} - - -/* - * wait4msg(): Poll for incoming LDAP messages, respecting the timeout. - * - * Return values: - * > 0: message received; value is the tag of the message. - * NSLDAPI_RESULT_TIMEOUT timeout exceeded. - * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed. - */ -static int -wait4msg( LDAP *ld, int msgid, int all, int unlock_permitted, - struct timeval *timeout, LDAPMessage **result ) -{ - int err, rc = NSLDAPI_RESULT_NOT_FOUND, msgfound; - struct timeval tv, *tvp; - long start_time = 0, tmp_time; - LDAPConn *lc, *nextlc; - /* lr points to the specific request we are waiting for, if any */ - LDAPRequest *lr = NULL; - -#ifdef LDAP_DEBUG - if ( timeout == NULL ) { - LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n", - 0, 0, 0 ); - } else { - LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg (timeout %ld sec, %ld usec)\n", - timeout->tv_sec, (long) timeout->tv_usec, 0 ); - } -#endif /* LDAP_DEBUG */ - - /* check the cache */ - if ( ld->ld_cache_on && ld->ld_cache_result != NULL ) { - /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */ - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - rc = (ld->ld_cache_result)( ld, msgid, all, timeout, result ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */ - if ( rc != NSLDAPI_RESULT_TIMEOUT ) { - return( rc ); - } - if ( ld->ld_cache_strategy == LDAP_CACHE_LOCALDB ) { - LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL ); - return( NSLDAPI_RESULT_TIMEOUT ); - } - } - - /* - * if we are looking for a specific msgid, check to see if it is - * associated with a dead connection and return an error if so. - */ - if ( msgid != LDAP_RES_ANY && msgid != LDAP_RES_UNSOLICITED ) { - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - if (( lr = nsldapi_find_request_by_msgid( ld, msgid )) - == NULL ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, - nsldapi_strdup( "unknown message id" )); - return( NSLDAPI_RESULT_ERROR ); /* could not find request for msgid */ - } - if ( lr->lr_conn != NULL && - lr->lr_conn->lconn_status == LDAP_CONNST_DEAD ) { - nsldapi_free_request( ld, lr, 1 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); - return( NSLDAPI_RESULT_ERROR ); /* connection dead */ - } - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - } - - if ( timeout == NULL ) { - tvp = NULL; - } else { - tv = *timeout; - tvp = &tv; - start_time = (long)time( NULL ); - } - - rc = NSLDAPI_RESULT_NOT_FOUND; - while ( rc == NSLDAPI_RESULT_NOT_FOUND ) { - msgfound = 0; -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - nsldapi_dump_connection( ld, ld->ld_conns, 1 ); - nsldapi_dump_requests_and_responses( ld ); - } -#endif /* LDAP_DEBUG */ - - /* - * Check if we have some data in a connection's BER buffer. - * If so, use it. - */ - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - if ( lc->lconn_sb->sb_ber.ber_ptr < - lc->lconn_sb->sb_ber.ber_end ) { - /* read1msg() might free the connection. */ - rc = read1msg( ld, msgid, all, lc->lconn_sb, - &lc, result ); - /* Indicate to next segment that we've processed a message - (or several, via chased refs) this time around. */ - msgfound = 1; - break; - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - - if ( !msgfound ) { - /* - * There was no buffered data. Poll to check connection - * status (read/write readiness). - */ - err = nsldapi_iostatus_poll( ld, tvp ); - -#if defined( LDAP_DEBUG ) && !defined( macintosh ) && !defined( DOS ) - if ( err == -1 ) { - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_iostatus_poll returned -1: errno %d\n", - LDAP_GET_ERRNO( ld ), 0, 0 ); - } -#endif - -#if !defined( macintosh ) && !defined( DOS ) - /* - * If the restart option is enabled and the error - * was EINTR, try again. - */ - if ( err == -1 - && 0 != ( ld->ld_options & LDAP_BITOPT_RESTART ) - && LDAP_GET_ERRNO( ld ) == EINTR ) { - continue; - } -#endif - - /* - * Handle timeouts (no activity) and fatal errors. - */ - if ( err == -1 || err == 0 ) { - LDAP_SET_LDERRNO( ld, (err == -1 ? - LDAP_SERVER_DOWN : LDAP_TIMEOUT), NULL, - NULL ); - if ( err == -1 ) { - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - nsldapi_connection_lost_nolock( ld, - NULL ); - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - rc = NSLDAPI_RESULT_ERROR; - } else { - rc = NSLDAPI_RESULT_TIMEOUT; - } - return( rc ); - } - - /* - * Check each connection for interesting activity. - */ - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - for ( lc = ld->ld_conns; - rc == NSLDAPI_RESULT_NOT_FOUND && lc != NULL; - lc = nextlc ) { - nextlc = lc->lconn_next; - - /* - * For connections that are in the CONNECTING - * state, check for write ready (which - * indicates that the connection completed) and - * transition to the CONNECTED state. - */ - if ( lc->lconn_status == LDAP_CONNST_CONNECTING - && nsldapi_iostatus_is_write_ready( ld, - lc->lconn_sb ) ) { - lc->lconn_status = LDAP_CONNST_CONNECTED; - LDAPDebug( LDAP_DEBUG_TRACE, - "wait4msg: connection 0x%p -" - " LDAP_CONNST_CONNECTING ->" - " LDAP_CONNST_CONNECTED\n", - lc, 0, 0 ); - } - - if ( lc->lconn_status - != LDAP_CONNST_CONNECTED ) { - continue; - } - - /* - * For connections that are CONNECTED, check - * for read ready (which indicates that data - * from server is available), and, for - * connections with associated requests that - * have not yet been sent, write ready (okay - * to send some data to the server). - */ - if ( nsldapi_iostatus_is_read_ready( ld, - lc->lconn_sb )) { - /* read1msg() might free the connection. */ - rc = read1msg( ld, msgid, all, - lc->lconn_sb, &lc, result ); - } - - /* - * Send pending requests if possible. If there is no lc then - * it was a child connection closed by read1msg(). - */ - if ( lc && lc->lconn_pending_requests > 0 - && nsldapi_iostatus_is_write_ready( ld, - lc->lconn_sb )) { - err = nsldapi_send_pending_requests_nolock( - ld, lc ); - if ( err == -1 && - rc == NSLDAPI_RESULT_NOT_FOUND ) { - rc = NSLDAPI_RESULT_ERROR; - } - } - - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - } - - /* - * It is possible that recursion occurred while chasing - * referrals and as a result the message we are looking - * for may have been placed on the response queue. Look - * for it there before continuing so we don't end up - * waiting on the network for a message that we already - * received! - */ - if ( rc == NSLDAPI_RESULT_NOT_FOUND && - check_response_queue( ld, msgid, all, 0, result ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); - rc = (*result)->lm_msgtype; - } - - /* - * honor the timeout if specified - */ - if ( rc == NSLDAPI_RESULT_NOT_FOUND && tvp != NULL ) { - tmp_time = (long)time( NULL ); - if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) { - rc = NSLDAPI_RESULT_TIMEOUT; - LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, - NULL ); - break; - } - - LDAPDebug( LDAP_DEBUG_TRACE, "wait4msg: %ld secs to go\n", - tv.tv_sec, 0, 0 ); - start_time = tmp_time; - } - } - - return( rc ); -} - - -#define NSLDAPI_REQUEST_COMPLETE( lr ) \ - ( (lr)->lr_outrefcnt <= 0 && \ - (lr)->lr_res_msgtype != LDAP_RES_SEARCH_ENTRY && \ - (lr)->lr_res_msgtype != LDAP_RES_SEARCH_REFERENCE ) - -/* - * read1msg() should be called with LDAP_CONN_LOCK and LDAP_REQ_LOCK locked. - * - * Return values: - * > 0: message received; value is the tag of the message. - * NSLDAPI_RESULT_TIMEOUT timeout exceeded. - * NSLDAPI_RESULT_ERROR fatal error occurred such as connection closed. - * NSLDAPI_RESULT_NOT_FOUND message not yet complete; keep waiting. - * - * The LDAPConn passed in my be freed by read1msg() if the reference count - * shows that it's no longer needed. - */ -static int -read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn **lcp, - LDAPMessage **result ) -{ - BerElement *ber; - LDAPMessage *new, *l, *prev, *chainprev, *tmp; - ber_int_t id; - ber_tag_t tag; - ber_len_t len; - int terrno, lderr, foundit = 0; - LDAPRequest *lr; - int rc, has_parent, message_can_be_returned; - int manufactured_result = 0; - LDAPConn *lc = *lcp; - - LDAPDebug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 ); - - message_can_be_returned = 1; /* the usual case... */ - - /* - * if we are not already in the midst of reading a message, allocate - * a ber that is associated with this connection - */ - if ( lc->lconn_ber == NULLBER && nsldapi_alloc_ber_with_options( ld, - &lc->lconn_ber ) != LDAP_SUCCESS ) { - return( NSLDAPI_RESULT_ERROR ); - } - - /* - * ber_get_next() doesn't set errno on EOF, so we pre-set it to - * zero to avoid getting tricked by leftover "EAGAIN" errors - */ - LDAP_SET_ERRNO( ld, 0 ); - - /* get the next message */ - if ( (tag = ber_get_next( sb, &len, lc->lconn_ber )) - != LDAP_TAG_MESSAGE ) { - terrno = LDAP_GET_ERRNO( ld ); - if ( terrno == EWOULDBLOCK || terrno == EAGAIN ) { - return( NSLDAPI_RESULT_NOT_FOUND ); /* try again */ - } - LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : - LDAP_LOCAL_ERROR), NULL, NULL ); - if ( tag == LBER_DEFAULT ) { - nsldapi_connection_lost_nolock( ld, sb ); - } - return( NSLDAPI_RESULT_ERROR ); - } - - /* - * Since we have received a complete message now, we pull this ber - * out of the connection structure and never read into it again. - */ - ber = lc->lconn_ber; - lc->lconn_ber = NULLBER; - - /* message id */ - if ( ber_get_int( ber, &id ) == LBER_ERROR ) { - ber_free( ber, 1 ); - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( NSLDAPI_RESULT_ERROR ); - } - - /* if it's been abandoned, toss it */ - if ( ldap_abandoned( ld, (int)id ) ) { - ber_free( ber, 1 ); - return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ - } - - if ( id == LDAP_RES_UNSOLICITED ) { - lr = NULL; - } else if (( lr = nsldapi_find_request_by_msgid( ld, id )) == NULL ) { - LDAPDebug( LDAP_DEBUG_ANY, - "no request for response with msgid %d (tossing)\n", - id, 0, 0 ); - ber_free( ber, 1 ); - return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ - } - - /* the message type */ - if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { - ber_free( ber, 1 ); - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( NSLDAPI_RESULT_ERROR ); - } - LDAPDebug( LDAP_DEBUG_TRACE, "got %s msgid %d, original id %d\n", - ( tag == LDAP_RES_SEARCH_ENTRY ) ? "ENTRY" : - ( tag == LDAP_RES_SEARCH_REFERENCE ) ? "REFERENCE" : "RESULT", id, - ( lr == NULL ) ? id : lr->lr_origid ); - - if ( lr != NULL ) { - id = lr->lr_origid; - lr->lr_res_msgtype = tag; - } - rc = NSLDAPI_RESULT_NOT_FOUND; /* default is to keep looking (no response found) */ - - if ( id != LDAP_RES_UNSOLICITED && ( tag == LDAP_RES_SEARCH_REFERENCE || - tag != LDAP_RES_SEARCH_ENTRY )) { - int refchasing, reftotal, simple_request = 0; - LDAPControl **ctrls = NULL; - - check_for_refs( ld, lr, ber, lc->lconn_version, &reftotal, - &refchasing ); - - if ( refchasing > 0 || lr->lr_outrefcnt > 0 ) { - /* - * we're chasing one or more new refs... - */ - ber_free( ber, 1 ); - ber = NULLBER; - lr->lr_status = LDAP_REQST_CHASINGREFS; - message_can_be_returned = 0; - - } else if ( tag != LDAP_RES_SEARCH_REFERENCE ) { - /* - * this request is complete... - */ - has_parent = ( lr->lr_parent != NULL ); - - if ( lr->lr_outrefcnt <= 0 && !has_parent ) { - /* request without any refs */ - simple_request = ( reftotal == 0 ); - } - - /* - * If this is not a child request and it is a bind - * request, reset the connection's bind DN and - * status based on the result of the operation. - */ - if ( !has_parent && - LDAP_RES_BIND == lr->lr_res_msgtype && - lr->lr_conn != NULL ) { - if ( lr->lr_conn->lconn_binddn != NULL ) { - NSLDAPI_FREE( - lr->lr_conn->lconn_binddn ); - } - if ( LDAP_SUCCESS == nsldapi_parse_result( ld, - lr->lr_res_msgtype, ber, &lderr, NULL, - NULL, NULL, NULL ) - && LDAP_SUCCESS == lderr ) { - lr->lr_conn->lconn_bound = 1; - lr->lr_conn->lconn_binddn = - lr->lr_binddn; - lr->lr_binddn = NULL; - } else { - lr->lr_conn->lconn_bound = 0; - lr->lr_conn->lconn_binddn = NULL; - } - } - - /* - * if this response is to a child request, we toss - * the message contents and just merge error info. - * into the parent. - */ - if ( has_parent ) { - /* Extract any response controls from ber before ditching it */ - if( nsldapi_find_controls( ber, &ctrls ) != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - return( NSLDAPI_RESULT_ERROR ); - } - - ber_free( ber, 1 ); - ber = NULLBER; - } - while ( lr->lr_parent != NULL ) { - merge_error_info( ld, lr->lr_parent, lr ); - - lr = lr->lr_parent; - --lr->lr_outrefcnt; - if ( !NSLDAPI_REQUEST_COMPLETE(lr)) { - break; - } - } - /* Stash response controls in original request so they can be baked - into the manufactured result message later */ - if( ctrls != NULL ) { - if( lr->lr_res_ctrls != NULL ) { - /* There are controls saved in original request already, - replace them with the new ones because we only save - the final controls received. - May want to arrange for merging intermediate response - controls into the array in the future */ - ldap_controls_free( lr->lr_res_ctrls ); - } - lr->lr_res_ctrls = ctrls; - } - - /* - * we recognize a request as fully complete when: - * 1) it is not a child request (NULL parent) - * 2) it has no outstanding referrals - * 3) we have received a result for the request (i.e., - * something other than an entry or a reference). - */ - if ( lr->lr_parent == NULL - && NSLDAPI_REQUEST_COMPLETE(lr)) { - id = lr->lr_msgid; - tag = lr->lr_res_msgtype; - LDAPDebug( LDAP_DEBUG_TRACE, - "request %d done\n", id, 0, 0 ); -LDAPDebug( LDAP_DEBUG_TRACE, -"res_errno: %d, res_error: <%s>, res_matched: <%s>\n", -lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", -lr->lr_res_matched ? lr->lr_res_matched : "" ); - if ( !simple_request ) { - if ( ber != NULLBER ) { - ber_free( ber, 1 ); - ber = NULLBER; - } - if ( build_result_ber( ld, &ber, lr ) - != LDAP_SUCCESS ) { - rc = NSLDAPI_RESULT_ERROR; - } else { - manufactured_result = 1; - } - } - - nsldapi_free_request( ld, lr, 1 ); - /* Since we asked nsldapi_free_request() to free the - connection, lets make sure our callers know it's gone. */ - *lcp = NULL; - } else { - message_can_be_returned = 0; - } - } - } - - if ( ber == NULLBER ) { - return( rc ); - } - - /* make a new ldap message */ - if ( (new = (LDAPMessage*)NSLDAPI_CALLOC( 1, sizeof(struct ldapmsg) )) - == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( NSLDAPI_RESULT_ERROR ); - } - new->lm_msgid = (int)id; - new->lm_msgtype = tag; - new->lm_ber = ber; - - /* - * if this is a search entry or if this request is complete (i.e., - * there are no outstanding referrals) then add to cache and check - * to see if we should return this to the caller right away or not. - */ - if ( message_can_be_returned ) { - if ( ld->ld_cache_on ) { - nsldapi_add_result_to_cache( ld, new ); - } - - if ( msgid == LDAP_RES_ANY || id == msgid ) { - if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { - /* - * return the first response we have for this - * search request later (possibly an entire - * chain of messages). - */ - foundit = 1; - } else if ( all == 0 - || (new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE - && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) { - *result = new; - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, - NULL ); - return( tag ); - } - } - } - - /* - * if not, we must add it to the list of responses. if - * the msgid is already there, it must be part of an existing - * search response. - */ - - prev = NULL; - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) { - if ( l->lm_msgid == new->lm_msgid ) - break; - prev = l; - } - - /* not part of an existing search response */ - if ( l == NULL ) { - if ( foundit ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - *result = new; - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); - return( tag ); - } - - new->lm_next = ld->ld_responses; - ld->ld_responses = new; - LDAPDebug( LDAP_DEBUG_TRACE, - "adding new response id %d type %d (looking for id %d)\n", - new->lm_msgid, new->lm_msgtype, msgid ); - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - if( message_can_be_returned ) - POST( ld, new->lm_msgid, new ); - return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ - } - - LDAPDebug( LDAP_DEBUG_TRACE, - "adding response 0x%p - id %d type %d", - new, new->lm_msgid, new->lm_msgtype ); - LDAPDebug( LDAP_DEBUG_TRACE, " (looking for id %d)\n", msgid, 0, 0 ); - - /* - * part of a search response - add to end of list of entries - * - * the first step is to find the end of the list of entries and - * references. after the following loop is executed, tmp points to - * the last entry or reference in the chain. If there are none, - * tmp points to the search result. - */ - chainprev = NULL; - 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 ) { - chainprev = tmp; - } - - /* - * If this is a manufactured result message and a result is already - * queued we throw away the one that is queued and replace it with - * our new result. This is necessary so we don't end up returning - * more than one result. - */ - if ( manufactured_result && - tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { - /* - * the result is the only thing in the chain... replace it. - */ - new->lm_chain = tmp->lm_chain; - new->lm_next = tmp->lm_next; - if ( chainprev == NULL ) { - if ( prev == NULL ) { - ld->ld_responses = new; - } else { - prev->lm_next = new; - } - } else { - chainprev->lm_chain = new; - } - if ( l == tmp ) { - l = new; - } - ldap_msgfree( tmp ); - - } else if ( manufactured_result && tmp->lm_chain != NULL - && tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { - /* - * entries or references are also present, so the result - * is the next entry after tmp. replace it. - */ - new->lm_chain = tmp->lm_chain->lm_chain; - new->lm_next = tmp->lm_chain->lm_next; - ldap_msgfree( tmp->lm_chain ); - tmp->lm_chain = new; - - } else if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) { - /* - * the result is the only thing in the chain... add before it. - */ - new->lm_chain = tmp; - if ( chainprev == NULL ) { - if ( prev == NULL ) { - ld->ld_responses = new; - } else { - prev->lm_next = new; - } - } else { - chainprev->lm_chain = new; - } - if ( l == tmp ) { - l = new; - } - - } else { - /* - * entries and/or references are present... add to the end - * of the entry/reference part of the chain. - */ - new->lm_chain = tmp->lm_chain; - tmp->lm_chain = new; - } - - /* - * return the first response or the whole chain if that's what - * we were looking for.... - */ - if ( foundit ) { - if ( all == 0 && l->lm_chain != NULL ) { - /* - * only return the first response in the chain - */ - if ( prev == NULL ) { - ld->ld_responses = l->lm_chain; - } else { - prev->lm_next = l->lm_chain; - } - l->lm_chain = NULL; - tag = l->lm_msgtype; - } else { - /* - * return all of the responses (may be a chain) - */ - if ( prev == NULL ) { - ld->ld_responses = l->lm_next; - } else { - prev->lm_next = l->lm_next; - } - } - *result = l; - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); - return( tag ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - return( NSLDAPI_RESULT_NOT_FOUND ); /* continue looking */ -} - - -/* - * check for LDAPv2+ (UMich extension) or LDAPv3 referrals or references - * errors are merged in "lr". - */ -static void -check_for_refs( LDAP *ld, LDAPRequest *lr, BerElement *ber, - int ldapversion, int *totalcountp, int *chasingcountp ) -{ - int err, origerr; - char *errstr, *matcheddn, **v3refs; - - LDAPDebug( LDAP_DEBUG_TRACE, "check_for_refs\n", 0, 0, 0 ); - - *chasingcountp = *totalcountp = 0; - - if ( ldapversion < LDAP_VERSION2 || ( lr->lr_parent == NULL - && ( ld->ld_options & LDAP_BITOPT_REFERRALS ) == 0 )) { - /* referrals are not supported or are disabled */ - return; - } - - if ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ) { - err = nsldapi_parse_reference( ld, ber, &v3refs, NULL ); - origerr = LDAP_REFERRAL; /* a small lie... */ - matcheddn = errstr = NULL; - } else { - err = nsldapi_parse_result( ld, lr->lr_res_msgtype, ber, - &origerr, &matcheddn, &errstr, &v3refs, NULL ); - } - - if ( err != LDAP_SUCCESS ) { - /* parse failed */ - return; - } - - if ( origerr == LDAP_REFERRAL ) { /* ldapv3 */ - if ( v3refs != NULL ) { - err = nsldapi_chase_v3_refs( ld, lr, v3refs, - ( lr->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ), - totalcountp, chasingcountp ); - ldap_value_free( v3refs ); - } - } else if ( ldapversion == LDAP_VERSION2 - && origerr != LDAP_SUCCESS ) { - /* referrals may be present in the error string */ - err = nsldapi_chase_v2_referrals( ld, lr, &errstr, - totalcountp, chasingcountp ); - } - - /* set LDAP errno, message, and matched string appropriately */ - if ( lr->lr_res_error != NULL ) { - NSLDAPI_FREE( lr->lr_res_error ); - } - lr->lr_res_error = errstr; - - if ( lr->lr_res_matched != NULL ) { - NSLDAPI_FREE( lr->lr_res_matched ); - } - lr->lr_res_matched = matcheddn; - - if ( err == LDAP_SUCCESS && ( *chasingcountp == *totalcountp )) { - if ( *totalcountp > 0 && ( origerr == LDAP_PARTIAL_RESULTS - || origerr == LDAP_REFERRAL )) { - /* substitute success for referral error codes */ - lr->lr_res_errno = LDAP_SUCCESS; - } else { - /* preserve existing non-referral error code */ - lr->lr_res_errno = origerr; - } - } else if ( err != LDAP_SUCCESS ) { - /* error occurred while trying to chase referrals */ - lr->lr_res_errno = err; - } else { - /* some referrals were not recognized */ - lr->lr_res_errno = ( ldapversion == LDAP_VERSION2 ) - ? LDAP_PARTIAL_RESULTS : LDAP_REFERRAL; - } - - LDAPDebug( LDAP_DEBUG_TRACE, - "check_for_refs: new result: msgid %d, res_errno %d, ", - lr->lr_msgid, lr->lr_res_errno, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, " res_error <%s>, res_matched <%s>\n", - lr->lr_res_error ? lr->lr_res_error : "", - lr->lr_res_matched ? lr->lr_res_matched : "", 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, - "check_for_refs: %d new refs(s); chasing %d of them\n", - *totalcountp, *chasingcountp, 0 ); -} - - -/* returns an LDAP error code and also sets it in LDAP * */ -static int -build_result_ber( LDAP *ld, BerElement **berp, LDAPRequest *lr ) -{ - ber_len_t len; - ber_int_t along; - BerElement *ber; - int err; - - if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( err ); - } - *berp = ber; - if ( ber_printf( ber, lr->lr_res_ctrls ? "{it{ess}" : "{it{ess}}", - lr->lr_msgid, (long)lr->lr_res_msgtype, lr->lr_res_errno, - lr->lr_res_matched ? lr->lr_res_matched : "", - lr->lr_res_error ? lr->lr_res_error : "" ) == -1 ) { - return( LDAP_ENCODING_ERROR ); - } - - if ( NULL != lr->lr_res_ctrls && nsldapi_put_controls( ld, - lr->lr_res_ctrls, 1 /* close seq */, ber ) != LDAP_SUCCESS ) { - return( LDAP_ENCODING_ERROR ); - } - - ber_reset( ber, 1 ); - if ( ber_skip_tag( ber, &len ) == LBER_ERROR || - ber_get_int( ber, &along ) == LBER_ERROR || - ber_peek_tag( ber, &len ) == LBER_ERROR ) { - return( LDAP_DECODING_ERROR ); - } - - return( LDAP_SUCCESS ); -} - - -static void -merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) -{ -/* - * Merge error information in "lr" with "parentr" error code and string. - */ - if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { - parentr->lr_res_errno = lr->lr_res_errno; - if ( lr->lr_res_error != NULL ) { - (void)nsldapi_append_referral( ld, &parentr->lr_res_error, - lr->lr_res_error ); - } - } else if ( lr->lr_res_errno != LDAP_SUCCESS && - parentr->lr_res_errno == LDAP_SUCCESS ) { - parentr->lr_res_errno = lr->lr_res_errno; - if ( parentr->lr_res_error != NULL ) { - NSLDAPI_FREE( parentr->lr_res_error ); - } - parentr->lr_res_error = lr->lr_res_error; - lr->lr_res_error = NULL; - if ( NAME_ERROR( lr->lr_res_errno )) { - if ( parentr->lr_res_matched != NULL ) { - NSLDAPI_FREE( parentr->lr_res_matched ); - } - parentr->lr_res_matched = lr->lr_res_matched; - lr->lr_res_matched = NULL; - } - } - - LDAPDebug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ", - parentr->lr_msgid, 0, 0 ); - LDAPDebug( LDAP_DEBUG_TRACE, "result lderrno %d, error <%s>, matched <%s>\n", - parentr->lr_res_errno, parentr->lr_res_error ? - parentr->lr_res_error : "", parentr->lr_res_matched ? - parentr->lr_res_matched : "" ); -} - -#if defined( CLDAP ) -#if !defined( macintosh ) && !defined( DOS ) && !defined( _WINDOWS ) && !defined(XP_OS2) -/* XXXmcs: was revised to support extended I/O callbacks but never compiled! */ -static int -cldap_select1( LDAP *ld, struct timeval *timeout ) -{ - int rc; - static int tblsize = 0; - NSLDAPIIOStatus *iosp = ld->ld_iostatus; - - if ( tblsize == 0 ) { -#ifdef USE_SYSCONF - tblsize = sysconf( _SC_OPEN_MAX ); -#else /* USE_SYSCONF */ - tblsize = getdtablesize(); -#endif /* USE_SYSCONF */ - } - - if ( tblsize >= FD_SETSIZE ) { - /* - * clamp value so we don't overrun the fd_set structure - */ - tblsize = FD_SETSIZE - 1; - } - - if ( NSLDAPI_IOSTATUS_TYPE_OSNATIVE == iosp->ios_type ) { - fd_set readfds; - - FD_ZERO( &readfds ); - FD_SET( ld->ld_sbp->sb_sd, &readfds ); - - /* XXXmcs: UNIX platforms should use poll() */ - rc = select( tblsize, &readfds, 0, 0, timeout ) ); - - } else if ( NSLDAPI_IOSTATUS_TYPE_CALLBACK == iosp->ios_type ) { - LDAP_X_PollFD pollfds[ 1 ]; - - pollfds[0].lpoll_fd = ld->ld_sbp->sb_sd; - pollfds[0].lpoll_arg = ld->ld_sbp->sb_arg; - pollfds[0].lpoll_events = LDAP_X_POLLIN; - pollfds[0].lpoll_revents = 0; - rc = ld->ld_extpoll_fn( pollfds, 1, nsldapi_tv2ms( timeout ), - ld->ld_ext_session_arg ); - } else { - LDAPDebug( LDAP_DEBUG_ANY, - "nsldapi_iostatus_poll: unknown I/O type %d\n", - rc = 0; /* simulate a timeout (what else to do?) */ - } - - return( rc ); -} -#endif /* !macintosh */ - - -#ifdef macintosh -static int -cldap_select1( LDAP *ld, struct timeval *timeout ) -{ - /* XXXmcs: needs to be revised to support I/O callbacks */ - return( tcpselect( ld->ld_sbp->sb_sd, timeout )); -} -#endif /* macintosh */ - - -#if (defined( DOS ) && defined( WINSOCK )) || defined( _WINDOWS ) || defined(XP_OS2) -/* XXXmcs: needs to be revised to support extended I/O callbacks */ -static int -cldap_select1( LDAP *ld, struct timeval *timeout ) -{ - fd_set readfds; - int rc; - - FD_ZERO( &readfds ); - FD_SET( ld->ld_sbp->sb_sd, &readfds ); - - if ( NSLDAPI_IO_TYPE_STANDARD == ld->ldiou_type && - NULL != ld->ld_select_fn ) { - rc = ld->ld_select_fn( 1, &readfds, 0, 0, timeout ); - } else if ( NSLDAPI_IO_TYPE_EXTENDED == ld->ldiou_type && - NULL != ld->ld_extselect_fn ) { - rc = ld->ld_extselect_fn( ld->ld_ext_session_arg, 1, &readfds, 0, - 0, timeout ) ); - } else { - /* XXXmcs: UNIX platforms should use poll() */ - rc = select( 1, &readfds, 0, 0, timeout ) ); - } - - return( rc == SOCKET_ERROR ? -1 : rc ); -} -#endif /* WINSOCK || _WINDOWS */ -#endif /* CLDAP */ - -int -LDAP_CALL -ldap_msgfree( LDAPMessage *lm ) -{ - LDAPMessage *next; - int type = 0; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 ); - - for ( ; lm != NULL; lm = next ) { - next = lm->lm_chain; - type = lm->lm_msgtype; - ber_free( lm->lm_ber, 1 ); - NSLDAPI_FREE( (char *) lm ); - } - - return( type ); -} - -/* - * ldap_msgdelete - delete a message. It returns: - * 0 if the entire message was deleted - * -1 if the message was not found, or only part of it was found - */ -int -ldap_msgdelete( LDAP *ld, int msgid ) -{ - LDAPMessage *lm, *prev; - int msgtype; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); /* punt */ - } - - prev = NULL; - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { - if ( lm->lm_msgid == msgid ) - break; - prev = lm; - } - - if ( lm == NULL ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - return( -1 ); - } - - if ( prev == NULL ) - ld->ld_responses = lm->lm_next; - else - prev->lm_next = lm->lm_next; - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - - msgtype = ldap_msgfree( lm ); - if ( msgtype == LDAP_RES_SEARCH_ENTRY - || msgtype == LDAP_RES_SEARCH_REFERENCE ) { - return( -1 ); - } - - return( 0 ); -} - - -/* - * return 1 if message msgid is waiting to be abandoned, 0 otherwise - */ -static int -ldap_abandoned( LDAP *ld, int msgid ) -{ - int i; - - LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); - if ( ld->ld_abandoned == NULL ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( 0 ); - } - - for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) - if ( ld->ld_abandoned[i] == msgid ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( 1 ); - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( 0 ); -} - - -static int -ldap_mark_abandoned( LDAP *ld, int msgid ) -{ - int i; - - LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK ); - if ( ld->ld_abandoned == NULL ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( -1 ); - } - - for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) - if ( ld->ld_abandoned[i] == msgid ) - break; - - if ( ld->ld_abandoned[i] == -1 ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( -1 ); - } - - for ( ; ld->ld_abandoned[i] != -1; i++ ) { - ld->ld_abandoned[i] = ld->ld_abandoned[i + 1]; - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK ); - return( 0 ); -} - - -#ifdef CLDAP -int -cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement **ber ) -{ - int rc; - ber_tag_t tag; - ber_len_t len; - - if ( ld->ld_sbp->sb_ber.ber_ptr >= ld->ld_sbp->sb_ber.ber_end ) { - rc = cldap_select1( ld, timeout ); - if ( rc == -1 || rc == 0 ) { - LDAP_SET_LDERRNO( ld, (rc == -1 ? LDAP_SERVER_DOWN : - LDAP_TIMEOUT), NULL, NULL ); - return( rc ); - } - } - - /* get the next message */ - if ( (tag = ber_get_next( ld->ld_sbp, &len, ber )) - != LDAP_TAG_MESSAGE ) { - LDAP_SET_LDERRNO( ld, (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : - LDAP_LOCAL_ERROR), NULL, NULL ); - return( -1 ); - } - - return( tag ); -} -#endif /* CLDAP */ - -int -nsldapi_post_result( LDAP *ld, int msgid, LDAPMessage *result ) -{ - LDAPPend *lp; - - LDAPDebug( LDAP_DEBUG_TRACE, - "nsldapi_post_result(ld=0x%p, msgid=%d, result=0x%p)\n", - ld, msgid, result ); - LDAP_MUTEX_LOCK( ld, LDAP_PEND_LOCK ); - if( msgid == LDAP_RES_ANY ) { - /* - * Look for any pending request for which someone is waiting. - */ - for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) - { - if ( lp->lp_sema != NULL ) { - break; - } - } - /* - * If we did't find a pending request, lp is NULL at this - * point, and we will leave this function without doing - * anything more -- which is exactly what we want to do. - */ - } - else - { - /* - * Look for a pending request specific to this message id - */ - for( lp = ld->ld_pend; lp != NULL; lp = lp->lp_next ) - { - if( lp->lp_msgid == msgid ) - break; - } - - if( lp == NULL ) - { - /* - * No pending requests for this response... append to - * our pending result list. - */ - LDAPPend *newlp; - newlp = (LDAPPend *)NSLDAPI_CALLOC( 1, - sizeof( LDAPPend )); - if( newlp == NULL ) - { - LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, - NULL ); - return (-1); - } - newlp->lp_msgid = msgid; - newlp->lp_result = result; - link_pend( ld, newlp ); - } - } - - - if( lp != NULL ) - { - /* - * Wake up a thread that is waiting for this result. - */ - lp->lp_msgid = msgid; - lp->lp_result = result; - LDAP_SEMA_POST( ld, lp ); - } - - LDAP_MUTEX_UNLOCK( ld, LDAP_PEND_LOCK ); - return (0); -} - -static void -link_pend( LDAP *ld, LDAPPend *lp ) -{ - if (( lp->lp_next = ld->ld_pend ) != NULL ) - { - lp->lp_next->lp_prev = lp; - } - ld->ld_pend = lp; - lp->lp_prev = NULL; -} diff --git a/ldap/c-sdk/libraries/libldap/saslbind.c b/ldap/c-sdk/libraries/libldap/saslbind.c deleted file mode 100644 index 5cbe73bbff..0000000000 --- a/ldap/c-sdk/libraries/libldap/saslbind.c +++ /dev/null @@ -1,877 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -#ifdef LDAP_SASLIO_HOOKS -/* - * Global SASL Init data - */ - -static int -nsldapi_sasl_fail() -{ - return( SASL_FAIL ); -} - -sasl_callback_t client_callbacks[] = { - { SASL_CB_GETOPT, nsldapi_sasl_fail, NULL }, - { SASL_CB_GETREALM, NULL, NULL }, - { SASL_CB_USER, NULL, NULL }, - { SASL_CB_CANON_USER, NULL, NULL }, - { SASL_CB_AUTHNAME, NULL, NULL }, - { SASL_CB_PASS, NULL, NULL }, - { SASL_CB_ECHOPROMPT, NULL, NULL }, - { SASL_CB_NOECHOPROMPT, NULL, NULL }, - { SASL_CB_LIST_END, NULL, NULL } -}; - -int -nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg ) -{ - int rc = LDAP_LOCAL_ERROR; - - switch (err) { - case SASL_OK: - rc = LDAP_SUCCESS; - break; - case SASL_NOMECH: - rc = LDAP_AUTH_UNKNOWN; - break; - case SASL_BADSERV: - rc = LDAP_CONNECT_ERROR; - break; - case SASL_DISABLED: - case SASL_ENCRYPT: - case SASL_EXPIRED: - case SASL_NOUSERPASS: - case SASL_NOVERIFY: - case SASL_PWLOCK: - case SASL_TOOWEAK: - case SASL_UNAVAIL: - case SASL_WEAKPASS: - rc = LDAP_INAPPROPRIATE_AUTH; - break; - case SASL_BADAUTH: - case SASL_NOAUTHZ: - rc = LDAP_INVALID_CREDENTIALS; - break; - case SASL_NOMEM: - rc = LDAP_NO_MEMORY; - break; - case SASL_NOUSER: - rc = LDAP_NO_SUCH_OBJECT; - break; - case SASL_CONTINUE: - case SASL_FAIL: - case SASL_INTERACT: - default: - rc = LDAP_LOCAL_ERROR; - break; - } - - LDAP_SET_LDERRNO( ld, rc, NULL, msg ); - return( rc ); -} - -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER -/* - * Get available SASL Mechanisms supported by the server - */ - -static int -nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech ) -{ - char *attr[] = { "supportedSASLMechanisms", NULL }; - char **values, **v, *mech, *m; - LDAPMessage *res, *e; - struct timeval timeout; - int slen, rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - timeout.tv_sec = SEARCH_TIMEOUT_SECS; - timeout.tv_usec = 0; - - rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE, - "objectclass=*", attr, 0, &timeout, &res ); - - if ( rc != LDAP_SUCCESS ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - e = ldap_first_entry( ld, res ); - if ( e == NULL ) { - ldap_msgfree( res ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL ); - } - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); - if ( values == NULL ) { - ldap_msgfree( res ); - LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL ); - return( LDAP_NO_SUCH_ATTRIBUTE ); - } - - slen = 0; - for(v = values; *v != NULL; v++ ) { - slen += strlen(*v) + 1; - } - if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) { - ldap_value_free( values ); - ldap_msgfree( res ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - m = mech; - for(v = values; *v; v++) { - if (v != values) { - *m++ = ' '; - } - slen = strlen(*v); - strncpy(m, *v, slen); - m += slen; - } - *m = '\0'; - - ldap_value_free( values ); - ldap_msgfree( res ); - - *pmech = mech; - - return( LDAP_SUCCESS ); -} -#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ - -int -nsldapi_sasl_secprops( - const char *in, - sasl_security_properties_t *secprops ) -{ - int i; - char **props = NULL; - char *inp; - unsigned sflags = 0; - sasl_ssf_t max_ssf = 0; - sasl_ssf_t min_ssf = 0; - unsigned maxbufsize = 0; - int got_sflags = 0; - int got_max_ssf = 0; - int got_min_ssf = 0; - int got_maxbufsize = 0; - - if (in == NULL) { - return LDAP_PARAM_ERROR; - } - inp = nsldapi_strdup(in); - if (inp == NULL) { - return LDAP_PARAM_ERROR; - } - props = ldap_str2charray( inp, "," ); - NSLDAPI_FREE( inp ); - - if( props == NULL || secprops == NULL ) { - return LDAP_PARAM_ERROR; - } - - for( i=0; props[i]; i++ ) { - if( strcasecmp(props[i], "none") == 0 ) { - got_sflags++; - - } else if( strcasecmp(props[i], "noactive") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOACTIVE; - - } else if( strcasecmp(props[i], "noanonymous") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOANONYMOUS; - - } else if( strcasecmp(props[i], "nodict") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NODICTIONARY; - - } else if( strcasecmp(props[i], "noplain") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOPLAINTEXT; - - } else if( strcasecmp(props[i], "forwardsec") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_FORWARD_SECRECY; - - } else if( strcasecmp(props[i], "passcred") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_PASS_CREDENTIALS; - - } else if( strncasecmp(props[i], - "minssf=", sizeof("minssf")) == 0 ) { - if( isdigit( props[i][sizeof("minssf")] ) ) { - got_min_ssf++; - min_ssf = atoi( &props[i][sizeof("minssf")] ); - } else { - return LDAP_NOT_SUPPORTED; - } - - } else if( strncasecmp(props[i], - "maxssf=", sizeof("maxssf")) == 0 ) { - if( isdigit( props[i][sizeof("maxssf")] ) ) { - got_max_ssf++; - max_ssf = atoi( &props[i][sizeof("maxssf")] ); - } else { - return LDAP_NOT_SUPPORTED; - } - - } else if( strncasecmp(props[i], - "maxbufsize=", sizeof("maxbufsize")) == 0 ) { - if( isdigit( props[i][sizeof("maxbufsize")] ) ) { - got_maxbufsize++; - maxbufsize = atoi( &props[i][sizeof("maxbufsize")] ); - if( maxbufsize && - (( maxbufsize < SASL_MIN_BUFF_SIZE ) - || (maxbufsize > SASL_MAX_BUFF_SIZE ))) { - return( LDAP_PARAM_ERROR ); - } - } else { - return( LDAP_NOT_SUPPORTED ); - } - } else { - return( LDAP_NOT_SUPPORTED ); - } - } - - if(got_sflags) { - secprops->security_flags = sflags; - } - if(got_min_ssf) { - secprops->min_ssf = min_ssf; - } - if(got_max_ssf) { - secprops->max_ssf = max_ssf; - } - if(got_maxbufsize) { - secprops->maxbufsize = maxbufsize; - } - - ldap_charray_free( props ); - return( LDAP_SUCCESS ); -} -#endif /* LDAP_SASLIO_HOOKS */ - -static int -nsldapi_sasl_bind_s( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct berval **servercredp, - LDAPControl ***responsectrls -) -{ - int err, msgid; - LDAPMessage *result; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_sasl_bind_s\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( ( err = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls, - clientctrls, &msgid )) != LDAP_SUCCESS ) - return( err ); - - if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - /* Get the controls sent by the server if requested */ - if ( responsectrls ) { - if ( ( err = ldap_parse_result( ld, result, &err, NULL, NULL, - NULL, responsectrls, 0 )) != LDAP_SUCCESS ) - return( err ); - } - - err = ldap_parse_sasl_bind_result( ld, result, servercredp, 0 ); - if (err != LDAP_SUCCESS && err != LDAP_SASL_BIND_IN_PROGRESS) { - ldap_msgfree( result ); - return( err ); - } - - return( ldap_result2error( ld, result, 1 ) ); -} - -#ifdef LDAP_SASLIO_HOOKS -static int -nsldapi_sasl_do_bind( LDAP *ld, const char *dn, - const char *mechs, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, - LDAPControl **sctrl, LDAPControl **cctrl, LDAPControl ***rctrl ) -{ - sasl_interact_t *prompts = NULL; - sasl_conn_t *ctx = NULL; - sasl_ssf_t *ssf = NULL; - const char *mech = NULL; - int saslrc, rc; - struct berval ccred; - unsigned credlen; - int stepnum = 1; - char *sasl_username = NULL; - - if (rctrl) { - /* init to NULL so we can call ldap_controls_free below */ - *rctrl = NULL; - } - - if (NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - /* shouldn't happen */ - if (callback == NULL) { - return( LDAP_LOCAL_ERROR ); - } - - if ( (rc = nsldapi_sasl_open(ld, NULL, &ctx, 0)) != LDAP_SUCCESS ) { - return( rc ); - } - - ccred.bv_val = NULL; - ccred.bv_len = 0; - - LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n", - (mechs ? mechs : ""), 0, 0 ); - - do { - saslrc = sasl_client_start( ctx, - mechs, - &prompts, - (const char **)&ccred.bv_val, - &credlen, - &mech ); - - LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n", - stepnum, (mech ? mech : ""), 0 ); - stepnum++; - - if( saslrc == SASL_INTERACT && - (callback)(ld, flags, defaults, prompts) != LDAP_SUCCESS ) { - break; - } - } while ( saslrc == SASL_INTERACT ); - - ccred.bv_len = credlen; - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - - stepnum = 1; - - do { - struct berval *scred; - int clientstepnum = 1; - - scred = NULL; - - if (rctrl) { - /* if we're looping again, we need to free any controls set - during the previous loop */ - /* NOTE that this assumes we only care about the controls - returned by the last call to nsldapi_sasl_bind_s - if - we care about _all_ controls, we will have to figure out - some way to append them each loop go round */ - ldap_controls_free(*rctrl); - *rctrl = NULL; - } - - LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n", - stepnum, (mech ? mech : ""), 0 ); - stepnum++; - - /* notify server of a sasl bind step */ - rc = nsldapi_sasl_bind_s(ld, dn, mech, &ccred, - sctrl, cctrl, &scred, rctrl); - - if ( ccred.bv_val != NULL ) { - ccred.bv_val = NULL; - } - - if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { - ber_bvfree( scred ); - return( rc ); - } - - if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) { - /* we're done, no need to step */ - if( scred ) { - if ( scred->bv_len == 0 ) { /* MS AD sends back empty screds */ - LDAPDebug(LDAP_DEBUG_ANY, - "SASL BIND complete - ignoring empty credential response\n", - 0, 0, 0); - ber_bvfree( scred ); - } else { - /* but server provided us with data! */ - LDAPDebug(LDAP_DEBUG_TRACE, - "SASL BIND complete but invalid because server responded with credentials - length [%u]\n", - scred->bv_len, 0, 0); - ber_bvfree( scred ); - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, - NULL, "Error during SASL handshake - invalid server credential response" ); - return( LDAP_LOCAL_ERROR ); - } - } - break; - } - - /* perform the next step of the sasl bind */ - do { - LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n", - clientstepnum, stepnum, (mech ? mech : "") ); - clientstepnum++; - saslrc = sasl_client_step( ctx, - (scred == NULL) ? NULL : scred->bv_val, - (scred == NULL) ? 0 : scred->bv_len, - &prompts, - (const char **)&ccred.bv_val, - &credlen ); - - if( saslrc == SASL_INTERACT && - (callback)(ld, flags, defaults, prompts) - != LDAP_SUCCESS ) { - break; - } - } while ( saslrc == SASL_INTERACT ); - - ccred.bv_len = credlen; - ber_bvfree( scred ); - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); - - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - if ( saslrc != SASL_OK ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - - saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username ); - if ( (saslrc == SASL_OK) && sasl_username ) { - LDAPDebug(LDAP_DEBUG_TRACE, "SASL identity: %s\n", sasl_username, 0, 0); - } - - saslrc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); - if( saslrc == SASL_OK ) { - if( ssf && *ssf ) { - LDAPDebug(LDAP_DEBUG_TRACE, - "SASL install encryption, for SSF: %lu\n", - (unsigned long) *ssf, 0, 0 ); - nsldapi_sasl_install( ld, NULL ); - } - } - - return( rc ); -} -#endif /* LDAP_SASLIO_HOOKS */ - - -/* - * ldap_sasl_bind - authenticate to the ldap server. The dn, mechanism, - * and credentials of the entry to which to bind are supplied. An LDAP - * error code is returned and if LDAP_SUCCESS is returned *msgidp is set - * to the id of the request initiated. - * - * Example: - * struct berval creds; - * LDAPControl **ctrls; - * int err, msgid; - * ... fill in creds with credentials ... - * ... fill in ctrls with server controls ... - * err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", - * "mechanismname", &creds, ctrls, NULL, &msgid ); - */ -int -LDAP_CALL -ldap_sasl_bind( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp -) -{ - BerElement *ber; - int rc, simple, msgid, ldapversion; - - /* - * The ldapv3 bind request looks like this: - * BindRequest ::= SEQUENCE { - * version INTEGER, - * name DistinguishedName, -- who - * authentication CHOICE { - * simple [0] OCTET STRING, -- passwd - * sasl [3] SaslCredentials -- v3 only - * } - * } - * SaslCredentials ::= SEQUENCE { - * mechanism LDAPString, - * credentials OCTET STRING - * } - * all wrapped up in an LDAPMessage sequence. - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( msgidp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { - nsldapi_handle_reconnect( ld ); - } - - simple = ( mechanism == LDAP_SASL_SIMPLE ); - ldapversion = NSLDAPI_LDAP_VERSION( ld ); - - /* only ldapv3 or higher can do sasl binds */ - if ( !simple && ldapversion < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if ( dn == NULL ) - dn = ""; - - if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, - cred, LDAP_AUTH_SASL )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( rc ); - } - - /* fill it in */ - if ( simple ) { /* simple bind; works in LDAPv2 or v3 */ - struct berval tmpcred; - - if ( cred == NULL ) { - tmpcred.bv_val = ""; - tmpcred.bv_len = 0; - cred = &tmpcred; - } - rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND, - ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val, - cred->bv_len ); - - } else { /* SASL bind; requires LDAPv3 or better */ - if ( cred == NULL || cred->bv_val == NULL || cred->bv_len == 0) { - rc = ber_printf( ber, "{it{ist{s}}", msgid, - LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, - mechanism ); - } else { - rc = ber_printf( ber, "{it{ist{so}}", msgid, - LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, - mechanism, cred->bv_val, - cred->bv_len ); - } - } - - if ( rc == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( rc ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, - (char *)dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -/* - * ldap_sasl_bind_s - bind to the ldap server using sasl authentication - * The dn, mechanism, and credentials of the entry to which to bind are - * supplied. LDAP_SUCCESS is returned upon success, the ldap error code - * otherwise. - * - * Example: - * struct berval creds; - * ... fill in creds with credentials ... - * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * "mechanismname", &creds ) - */ -int -LDAP_CALL -ldap_sasl_bind_s( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct berval **servercredp -) -{ - return ( nsldapi_sasl_bind_s( ld, dn, mechanism, cred, - serverctrls, clientctrls, servercredp, NULL ) ); -} - -#ifdef LDAP_SASLIO_HOOKS -/* - * SASL Authentication Interface: ldap_sasl_interactive_bind_s - * - * This routine takes a DN, SASL mech list, and a SASL callback - * and performs the necessary sequencing to complete a SASL bind - * to the LDAP connection ld. The user provided callback can - * use an optionally provided set of default values to complete - * any necessary interactions. - * - * Currently imposes the following restrictions: - * A mech list must be provided - * LDAP_SASL_INTERACTIVE mode requires a callback - */ -int -LDAP_CALL -ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults ) -{ - return ldap_sasl_interactive_bind_ext_s( ld, dn, - saslMechanism, sctrl, cctrl, flags, callback, - defaults, NULL ); -} - -/* - * ldap_sasl_interactive_bind_ext_s - * - * This function extends ldap_sasl_interactive_bind_s by allowing - * controls received from the server to be returned as rctrl. The - * caller must pass in a valid LDAPControl** pointer and free the - * array of controls when finished with them e.g. - * LDAPControl **retctrls = NULL; - * ... - * ldap_sasl_interactive_bind_ext_s(ld, ...., &retctrls); - * ... - * ldap_controls_free(retctrls); - * Only the controls from the server during the last bind step are returned - - * intermediate controls (if any, usually not) are discarded. - */ -int -LDAP_CALL -ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) -{ -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER - char *smechs; -#endif - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind_s\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ((flags == LDAP_SASL_INTERACTIVE) && (callback == NULL)) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK(ld, LDAP_SASL_LOCK ); - - if( saslMechanism == NULL || *saslMechanism == '\0' ) { -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER - rc = nsldapi_get_sasl_mechs( ld, &smechs ); - if( rc != LDAP_SUCCESS ) { - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( rc ); - } - saslMechanism = smechs; -#else - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( LDAP_PARAM_ERROR ); -#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ - } - - rc = nsldapi_sasl_do_bind( ld, dn, saslMechanism, - flags, callback, defaults, sctrl, cctrl, rctrl); - - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( rc ); -} -#else /* LDAP_SASLIO_HOOKS */ -/* stubs for platforms that do not support SASL */ -int -LDAP_CALL -ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults ) -{ - return LDAP_SUCCESS; -} - -int -LDAP_CALL -ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) -{ - return LDAP_SUCCESS; -} -#endif /* LDAP_SASLIO_HOOKS */ - - -/* returns an LDAP error code that indicates if parse succeeded or not */ -int -LDAP_CALL -ldap_parse_sasl_bind_result( - LDAP *ld, - LDAPMessage *res, - struct berval **servercredp, - int freeit -) -{ - BerElement ber; - int rc, err; - ber_int_t along; - ber_len_t len; - char *m, *e; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); - - /* - * the ldapv3 SASL bind response looks like this: - * - * BindResponse ::= [APPLICATION 1] SEQUENCE { - * COMPONENTS OF LDAPResult, - * serverSaslCreds [7] OCTET STRING OPTIONAL - * } - * - * all wrapped up in an LDAPMessage sequence. - */ - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || - !NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( res )) { - return( LDAP_PARAM_ERROR ); - } - - /* only ldapv3 or higher can do sasl binds */ - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( servercredp != NULL ) { - *servercredp = NULL; - } - - ber = *(res->lm_ber); /* struct copy */ - - /* skip past message id, matched dn, error message ... */ - rc = ber_scanf( &ber, "{iaa}", &along, &m, &e ); - - if ( rc != LBER_ERROR && - ber_peek_tag( &ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { - rc = ber_get_stringal( &ber, servercredp ); - } - - if ( freeit ) { - ldap_msgfree( res ); - } - - if ( rc == LBER_ERROR ) { - err = LDAP_DECODING_ERROR; - } else { - err = (int) along; - } - - LDAP_SET_LDERRNO( ld, err, m, e ); - /* this is a little kludge for the 3.0 Barracuda/hammerhead relese */ - /* the docs state that the return is either LDAP_DECODING_ERROR */ - /* or LDAP_SUCCESS. Here we match the docs... it's cleaner in 3.1 */ - - if ( LDAP_DECODING_ERROR == err ) { - return (LDAP_DECODING_ERROR); - } else { - return( LDAP_SUCCESS ); - } -} - diff --git a/ldap/c-sdk/libraries/libldap/saslio.c b/ldap/c-sdk/libraries/libldap/saslio.c deleted file mode 100644 index 6ab6303d0c..0000000000 --- a/ldap/c-sdk/libraries/libldap/saslio.c +++ /dev/null @@ -1,635 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifdef LDAP_SASLIO_HOOKS -#include -#include "ldap-int.h" -#include "../liblber/lber-int.h" -#include -/* Should be pulled in from lber-int.h */ -#define READBUFSIZ 8192 - -#define SEARCH_TIMEOUT_SECS 120 -#define NSLDAPI_SM_BUF 128 - -/* - * Data structures: - */ - -/* data structure that populates the I/O callback socket-specific arg. */ -typedef struct lextiof_socket_private { - struct ldap_x_ext_io_fns sess_io_fns; /* the saved layered ld fns from the layer we are "pushing" */ - struct lber_x_ext_io_fns sock_io_fns; /* the saved layered ber fns from the layer we are "pushing" */ - sasl_conn_t *sasl_ctx; /* the sasl context - pointer to the one from the connection */ - char *sb_sasl_ibuf; /* sasl decrypted input buffer */ - char *sb_sasl_iptr; /* current location in buffer */ - int sb_sasl_bfsz; /* Alloc'd size of input buffer */ - int sb_sasl_ilen; /* remaining length to process */ - LDAP *ld; /* used to set errno */ - Sockbuf *sb; /* pointer to our associated sockbuf */ -} SASLIOSocketArg; - -static void -destroy_SASLIOSocketArg(SASLIOSocketArg** sockarg) -{ - if (sockarg && *sockarg) { - NSLDAPI_FREE((*sockarg)->sb_sasl_ibuf); - NSLDAPI_FREE((*sockarg)); - *sockarg = NULL; - } -} - -static SASLIOSocketArg* -new_SASLIOSocketArg(sasl_conn_t *ctx, int bufsiz, LDAP *ld, Sockbuf *sb) -{ - SASLIOSocketArg *sockarg = NULL; - - if (bufsiz <= 0) { - return sockarg; - } - - sockarg = (SASLIOSocketArg*)NSLDAPI_CALLOC(1, sizeof(SASLIOSocketArg)); - if (sockarg) { - sockarg->sasl_ctx = ctx; - sockarg->sb_sasl_ibuf = NSLDAPI_MALLOC(bufsiz); - if (!sockarg->sb_sasl_ibuf) { - destroy_SASLIOSocketArg(&sockarg); - return sockarg; - } - sockarg->sb_sasl_iptr = NULL; - sockarg->sb_sasl_bfsz = bufsiz; - sockarg->sb_sasl_ilen = 0; - sockarg->ld = ld; - sockarg->sb = sb; - } - - return sockarg; -} - -/* - * SASL Dependent routines - * - * SASL security and integrity options are supported through the - * use of the extended I/O functionality. Because the extended - * I/O functions may already be in use prior to enabling encryption, - * when SASL encryption si enabled, these routine interpose themselves - * over the exitng extended I/O routines and add an additional level - * of indirection. - * IE: Before SASL: client->libldap->lber->extio - * After SASL: client->libldap->lber->saslio->extio - * Any extio function are stilled used for the raw i/O [IE prldap] - * but SASL will decrypt before passing to lber. - * SASL cannot decrypt a stream so full packaets must be read - * before proceeding. - */ - -/* - * Get the 4 octet header [size] for a sasl encrypted buffer. - * See RFC222 [section 3]. - */ -static int -nsldapi_sasl_pktlen( char *buf, int maxbufsize ) -{ - int size; - -#if defined( _WINDOWS ) || defined( _WIN32 ) - size = ntohl(*(u_long *)buf); -#else - size = ntohl(*(uint32_t *)buf); -#endif - if ( size < 0 || size > maxbufsize ) { - return (-1 ); - } - - return( size + 4 ); /* include the first 4 bytes */ -} - -/* - * SASL encryption routines - */ - -static int -nsldapi_sasl_read( int s, void *buf, int len, - struct lextiof_socket_private *arg) -{ - LDAP *ld; - const char *dbuf; - char *cp; - int ret; - unsigned dlen, blen; - - ld = (LDAP *)arg->ld; - - /* Is there anything left in the existing buffer? */ - if ((ret = arg->sb_sasl_ilen) > 0) { - ret = (ret > len ? len : ret); - SAFEMEMCPY( buf, arg->sb_sasl_iptr, ret ); - if (ret == arg->sb_sasl_ilen) { - arg->sb_sasl_ilen = 0; - arg->sb_sasl_iptr = NULL; - } else { - arg->sb_sasl_ilen -= ret; - arg->sb_sasl_iptr += ret; - } - return( ret ); - } - - /* buffer is empty - fill it */ - cp = arg->sb_sasl_ibuf; - dlen = 0; - - /* Read the length of the packet */ - while ( dlen < 4 ) { - if (arg->sock_io_fns.lbextiofn_read != NULL) { - ret = arg->sock_io_fns.lbextiofn_read( - s, cp, 4 - dlen, - arg->sock_io_fns.lbextiofn_socket_arg); - } else { - ret = read( s, cp, 4 - dlen ); - } -#ifdef EINTR - if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) ) - continue; -#endif - if ( ret <= 0 ) - return( ret ); - - cp += ret; - dlen += ret; - } - - blen = 4; - - ret = nsldapi_sasl_pktlen( arg->sb_sasl_ibuf, arg->sb_sasl_bfsz ); - if (ret < 0) { - LDAP_SET_ERRNO(ld, EIO); - return( -1 ); - } - dlen = ret - dlen; - - /* read the rest of the encrypted packet */ - while ( dlen > 0 ) { - if (arg->sock_io_fns.lbextiofn_read != NULL) { - ret = arg->sock_io_fns.lbextiofn_read( - s, cp, dlen, - arg->sock_io_fns.lbextiofn_socket_arg); - } else { - ret = read( s, cp, dlen ); - } - -#ifdef EINTR - if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) ) - continue; -#endif - if ( ret <= 0 ) - return( ret ); - - cp += ret; - blen += ret; - dlen -= ret; - } - - /* Decode the packet */ - ret = sasl_decode( arg->sasl_ctx, - arg->sb_sasl_ibuf, blen, - &dbuf, &dlen); - if ( ret != SASL_OK ) { - /* sb_sasl_read: failed to decode packet, drop it, error */ - arg->sb_sasl_iptr = NULL; - arg->sb_sasl_ilen = 0; - LDAP_SET_ERRNO(ld, EIO); - return( -1 ); - } - - /* copy decrypted packet to the input buffer */ - SAFEMEMCPY( arg->sb_sasl_ibuf, dbuf, dlen ); - arg->sb_sasl_iptr = arg->sb_sasl_ibuf; - arg->sb_sasl_ilen = dlen; - - ret = (dlen > (unsigned) len ? len : dlen); - SAFEMEMCPY( buf, arg->sb_sasl_iptr, ret ); - if (ret == arg->sb_sasl_ilen) { - arg->sb_sasl_ilen = 0; - arg->sb_sasl_iptr = NULL; - } else { - arg->sb_sasl_ilen -= ret; - arg->sb_sasl_iptr += ret; - } - return( ret ); -} - -static int -nsldapi_sasl_write( int s, const void *buf, int len, - struct lextiof_socket_private *arg) -{ - int ret = 0; - const char *obuf, *optr, *cbuf = (const char *)buf; - unsigned olen, clen, tlen = 0; - unsigned *maxbuf; - - ret = sasl_getprop(arg->sasl_ctx, SASL_MAXOUTBUF, - (const void **)&maxbuf); - if ( ret != SASL_OK ) { - /* just a sanity check, should never happen */ - return( -1 ); - } - - while (len > 0) { - clen = (len > *maxbuf) ? *maxbuf : len; - /* encode the next packet. */ - ret = sasl_encode( arg->sasl_ctx, cbuf, clen, &obuf, &olen); - if ( ret != SASL_OK ) { - /* XXX Log error? "sb_sasl_write: failed to encode packet..." */ - return( -1 ); - } - /* Write everything now, buffer is only good until next sasl_encode */ - optr = obuf; - while (olen > 0) { - if (arg->sock_io_fns.lbextiofn_write != NULL) { - ret = arg->sock_io_fns.lbextiofn_write( - s, optr, olen, - arg->sock_io_fns.lbextiofn_socket_arg); - } else { - ret = write( s, optr, olen); - } - if ( ret < 0 ) - return( ret ); - optr += ret; - olen -= ret; - } - len -= clen; - cbuf += clen; - tlen += clen; - } - return( tlen ); -} - -/* - * What's all this then? - * First, take a look at os-ip.c:nsldapi_add_to_cb_pollfds(). When a new descriptor is - * added to the pollfds array, the lpoll_socketarg field is initialized to the value from - * the socketarg field - sb->sb_ext_io_fns.lbextiofn_socket_arg. In our case, since we - * override this with our sasl data (see below nsldapi_sasl_install), we need to restore - * the previous value so that the layer below us (i.e. prldap) can use the lpoll_socketarg - * which it sets. - * So how do which know which fds[i] is a "sasl" fd? - * We initialize the lextiof_session_private *arg (see nsldapi_sasl_install) to point to - * the socket_private data in sb->sb_ext_io_fns.lbextiofn_socket_arg for "sasl" sockets, - * which is then used to initialize lpoll_socketarg (see above). - * So, if the arg which gets passed into nsldapi_sasl_poll is the same as the - * fds[i].lpoll_socketarg, we know it is a "sasl" socket and we need to "pop" the sasl - * layer. We do this by replacing lpoll_socketarg with the one we saved when we "pushed" - * the sasl layer. - * So why the loop to restore the sasl lpoll_socketarg? - * The lower layer only uses lpoll_socketarg during poll(). See ldappr-io.c:prldap_poll() - * for more information about how that works. However, after the polling is done, there - * is some special magic in os-ip.c in the functions nsldapi_add_to_cb_pollfds(), - * nsldapi_clear_from_cb_pollfds(), and nsldapi_find_in_cb_pollfds() to find the correct - * Sockbuf to operate on. This is the macro NSLDAPI_CB_POLL_MATCH(). For the extended - * io function callbacks to work correctly, it is not sufficient to say that the file - * descriptor in the Sockbuf matches the one that poll says has activity - we also need - * to match the lpoll_socketarg with the sb->sb_ext_io_fns.lbextiofn_socket_arg to make - * sure this really is the Sockbuf we want to use. So we have to restore the - * lpoll_socketarg with the original one. - * Why have origarg and staticorigarg? - * To avoid malloc. The sizeof staticorigarg should be large enough to accomodate almost - * all clients without incurring too much additional overhead. However, if we need more - * room, origarg will grow to nfds. If this proves to be inadequate, the size of the - * staticorigarg is a good candidate for a #define set by configure. - */ -static int -nsldapi_sasl_poll( - LDAP_X_PollFD fds[], int nfds, int timeout, - struct lextiof_session_private *arg ) -{ - LDAP_X_EXTIOF_POLL_CALLBACK *origpoll; /* poll fn from the pushed layer */ - struct lextiof_session_private *origsess = NULL; /* session arg from the pushed layer */ - SASLIOSocketArg **origarg = NULL; /* list of saved original socket args */ - SASLIOSocketArg *staticorigarg[1024]; /* default list to avoid malloc */ - int origargsize = sizeof(staticorigarg)/sizeof(staticorigarg[0]); - int rc = -1; /* the return code - -1 means failure */ - - if (arg == NULL) { /* should not happen */ - return( rc ); - } - - origarg = staticorigarg; - /* if the static array is not large enough, alloc a dynamic one */ - if (origargsize < nfds) { - origarg = (SASLIOSocketArg **)NSLDAPI_MALLOC(nfds*sizeof(SASLIOSocketArg *)); - } - - if (fds && nfds > 0) { - int i; - for(i = 0; i < nfds; i++) { - /* save the original socket arg */ - origarg[i] = fds[i].lpoll_socketarg; - if (arg == (struct lextiof_session_private *)fds[i].lpoll_socketarg) { - /* lpoll_socketarg is a sasl socket arg - we need to replace it - with the one from the layer we pushed (i.e. prldap) */ - SASLIOSocketArg *sockarg = (SASLIOSocketArg *)fds[i].lpoll_socketarg; - /* reset to pushed layer's socket arg */ - fds[i].lpoll_socketarg = sockarg->sock_io_fns.lbextiofn_socket_arg; - /* grab the pushed layers' poll fn and its session arg */ - if (!origsess) { - origpoll = sockarg->sess_io_fns.lextiof_poll; - origsess = sockarg->sess_io_fns.lextiof_session_arg; - } - } - } - } - - if (origsess == NULL) { /* should not happen */ - goto done; - } - - /* call the "real" poll function */ - rc = origpoll( fds, nfds, timeout, origsess ); - - /* reset the lpoll_socketarg values to their original values because - they must match what's in sb->iofns->lbextiofn_socket_arg in order - for NSLDAPI_CB_POLL_MATCH to work - see os-ip.c */ - if (fds && nfds > 0) { - int i; - for(i = 0; i < nfds; i++) { - if ((SASLIOSocketArg *)arg == origarg[i]) { - fds[i].lpoll_socketarg = origarg[i]; - } - } - } - -done: - /* if we had to use a dynamic array, free it */ - if (origarg != staticorigarg) { - NSLDAPI_FREE(origarg); - } - - return rc; -} - -int -nsldapi_sasl_open( LDAP *ld, LDAPConn *lconn, sasl_conn_t **ctx, sasl_ssf_t ssf ) -{ - int saslrc; - char *host = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - if ( lconn == NULL ) { - if ( ld->ld_defconn == NULL || - ld->ld_defconn->lconn_status != LDAP_CONNST_CONNECTED) { - int rc = nsldapi_open_ldap_defconn( ld ); - if( rc < 0 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - } - lconn = ld->ld_defconn; - } - - /* need to clear out the old context for this connection, if any */ - /* client may have re-bind-ed this connection without closing first */ - if (lconn->lconn_sasl_ctx) { - sasl_dispose(&lconn->lconn_sasl_ctx); - lconn->lconn_sasl_ctx = NULL; - } - - if ( 0 != ldap_get_option( ld, LDAP_OPT_HOST_NAME, &host ) ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - saslrc = sasl_client_new( "ldap", host, - NULL, NULL, /* iplocalport, ipremoteport - use defaults */ - NULL, 0, ctx ); - ldap_memfree(host); - - if ( (saslrc != SASL_OK) || (!*ctx) ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, NULL ) ); - } - - if( ssf ) { - sasl_ssf_t extprops; - memset(&extprops, 0L, sizeof(extprops)); - extprops = ssf; - - (void) sasl_setprop( *ctx, SASL_SSF_EXTERNAL, - (void *) &extprops ); - } - - /* (re)set security properties */ - sasl_setprop( *ctx, SASL_SEC_PROPS, &ld->ld_sasl_secprops ); - - /* set the connection context */ - lconn->lconn_sasl_ctx = *ctx; - - return( LDAP_SUCCESS ); -} - -static int -nsldapi_sasl_close( struct lextiof_socket_private *arg ) -{ - /* undo function pointer interposing */ - ldap_set_option( arg->ld, LDAP_X_OPT_EXTIO_FN_PTRS, &arg->sess_io_fns ); - /* have to do this separately to make sure the socketarg is set correctly */ - ber_sockbuf_set_option( arg->sb, - LBER_SOCKBUF_OPT_EXT_IO_FNS, - (void *)&arg->sock_io_fns ); - - destroy_SASLIOSocketArg(&arg); - return( LDAP_SUCCESS ); -} - -static int -nsldapi_sasl_close_socket(int s, struct lextiof_socket_private *arg ) -{ - LDAP_X_EXTIOF_CLOSE_CALLBACK *origclose; - struct lextiof_socket_private *origsock; - - if (arg == NULL) { - return( -1 ); - } - - origclose = arg->sess_io_fns.lextiof_close; - origsock = arg->sock_io_fns.lbextiofn_socket_arg; - - /* undo SASL */ - nsldapi_sasl_close( arg ); - arg = NULL; - /* arg is destroyed at this point - do not use it */ - - if (origclose ) - return ( origclose( s, origsock ) ); - else { - /* This is a copy of nsldapi_os_closesocket() - * from os-ip.c. It is declared static there, - * hence the copy of it. - */ - int rc; - -#ifdef NSLDAPI_AVOID_OS_SOCKETS - rc = -1; -#else /* NSLDAPI_AVOID_OS_SOCKETS */ -#ifdef _WINDOWS - rc = closesocket( s ); -#else /* _WINDOWS */ - rc = close( s ); -#endif /* _WINDOWS */ -#endif /* NSLDAPI_AVOID_OS_SOCKETS */ - return( rc ); - } - -} - -/* - * install encryption routines if security has been negotiated - */ -int -nsldapi_sasl_install( LDAP *ld, LDAPConn *lconn ) -{ - struct lber_x_ext_io_fns fns; - struct ldap_x_ext_io_fns iofns; - sasl_security_properties_t *secprops; - int rc, value; - int bufsiz; - Sockbuf *sb = NULL; - sasl_conn_t *ctx = NULL; - SASLIOSocketArg *sockarg = NULL; - - if ( lconn == NULL ) { - lconn = ld->ld_defconn; - if ( lconn == NULL ) { - return( LDAP_LOCAL_ERROR ); - } - } - if ( (sb = lconn->lconn_sb) == NULL ) { - return( LDAP_LOCAL_ERROR ); - } - rc = ber_sockbuf_get_option( sb, - LBER_SOCKBUF_OPT_TO_FILE_ONLY, - (void *) &value); - if (rc != 0 || value != 0) { - return( LDAP_LOCAL_ERROR ); - } - - /* the sasl context in the lconn must have been set prior to this */ - ctx = lconn->lconn_sasl_ctx; - rc = sasl_getprop( ctx, SASL_SEC_PROPS, - (const void **)&secprops ); - if (rc != SASL_OK) - return( LDAP_LOCAL_ERROR ); - bufsiz = secprops->maxbufsize; - if (bufsiz <= 0) { - return( LDAP_LOCAL_ERROR ); - } - - /* create our socket specific context */ - sockarg = new_SASLIOSocketArg(ctx, bufsiz, ld, sb); - if (!sockarg) { - return( LDAP_LOCAL_ERROR ); - } - - /* save a copy of the existing io fns and the session arg */ - memset( &sockarg->sess_io_fns, 0, LDAP_X_EXTIO_FNS_SIZE ); - sockarg->sess_io_fns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; - rc = ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, - &sockarg->sess_io_fns ); - if (rc != 0) { - destroy_SASLIOSocketArg(&sockarg); - return( LDAP_LOCAL_ERROR ); - } - - /* save a copy of the existing ber io fns and the socket arg */ - memset( &sockarg->sock_io_fns, 0, LBER_X_EXTIO_FNS_SIZE ); - sockarg->sock_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - rc = ber_sockbuf_get_option( sb, - LBER_SOCKBUF_OPT_EXT_IO_FNS, - (void *)&sockarg->sock_io_fns); - if (rc != 0) { - destroy_SASLIOSocketArg(&sockarg); - return( LDAP_LOCAL_ERROR ); - } - - /* Always set the ext io close fn pointer to ensure we - * clean up our sockarg context */ - memset( &iofns, 0, sizeof(iofns)); - /* first, copy struct - sets defaults */ - iofns = sockarg->sess_io_fns; - iofns.lextiof_close = nsldapi_sasl_close_socket; - iofns.lextiof_session_arg = sockarg; /* needed for close and poll */ - - /* Set new values for the other ext io funcs if there are any - - when using the native io fns (as opposed to prldap) there - won't be any */ - if ( sockarg->sess_io_fns.lextiof_read != NULL || - sockarg->sess_io_fns.lextiof_write != NULL || - sockarg->sess_io_fns.lextiof_poll != NULL || - sockarg->sess_io_fns.lextiof_connect != NULL ) { - /* next, just reset those functions we want to override */ - iofns.lextiof_read = nsldapi_sasl_read; - iofns.lextiof_write = nsldapi_sasl_write; - iofns.lextiof_poll = nsldapi_sasl_poll; - } - - /* set the ext io funcs */ - rc = ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ); - if (rc != 0) { - /* frees everything and resets fns above */ - nsldapi_sasl_close(sockarg); - return( LDAP_LOCAL_ERROR ); - } - - /* set the new ber io funcs and socket arg */ - (void) memset( &fns, 0, LBER_X_EXTIO_FNS_SIZE); - fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - fns.lbextiofn_read = nsldapi_sasl_read; - fns.lbextiofn_write = nsldapi_sasl_write; - fns.lbextiofn_socket_arg = sockarg; - rc = ber_sockbuf_set_option( sb, - LBER_SOCKBUF_OPT_EXT_IO_FNS, - (void *)&fns); - if (rc != 0) { - /* frees everything and resets fns above */ - nsldapi_sasl_close(sockarg); - return( LDAP_LOCAL_ERROR ); - } - - return( LDAP_SUCCESS ); -} - -#endif diff --git a/ldap/c-sdk/libraries/libldap/sbind.c b/ldap/c-sdk/libraries/libldap/sbind.c deleted file mode 100644 index d9bfc71fd4..0000000000 --- a/ldap/c-sdk/libraries/libldap/sbind.c +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * sbind.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -static int simple_bind_nolock( LDAP *ld, const char *dn, const char *passwd, - int unlock_permitted ); - -/* - * ldap_simple_bind - bind to the ldap server. The dn and - * password of the entry to which to bind are supplied. The message id - * of the request initiated is returned. - * - * Example: - * ldap_simple_bind( ld, "cn=manager, o=university of michigan, c=us", - * "secret" ) - */ - -int -LDAP_CALL -ldap_simple_bind( LDAP *ld, const char *dn, const char *passwd ) -{ - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { - nsldapi_handle_reconnect( ld ); - } - - rc = simple_bind_nolock( ld, dn, passwd, 1 ); - - return( rc ); -} - - -static int -simple_bind_nolock( LDAP *ld, const char *dn, const char *passwd, - int unlock_permitted ) -{ - BerElement *ber; - int rc, msgid; - - /* - * The bind request looks like this: - * BindRequest ::= SEQUENCE { - * version INTEGER, - * name DistinguishedName, -- who - * authentication CHOICE { - * simple [0] OCTET STRING -- passwd - * } - * } - * all wrapped up in an LDAPMessage sequence. - */ - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if ( dn == NULL ) - dn = ""; - if ( passwd == NULL ) - passwd = ""; - - if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { - struct berval bv; - - bv.bv_val = (char *)passwd; - bv.bv_len = strlen( passwd ); - /* if ( unlock_permitted ) LDAP_MUTEX_UNLOCK( ld ); */ - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, &bv, - LDAP_AUTH_SIMPLE ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - /* if ( unlock_permitted ) LDAP_MUTEX_LOCK( ld ); */ - if ( rc != 0 ) { - return( rc ); - } - } - - /* create a message to send */ - if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( -1 ); - } - - /* fill it in */ - if ( ber_printf( ber, "{it{ists}", msgid, LDAP_REQ_BIND, - NSLDAPI_LDAP_VERSION( ld ), dn, LDAP_AUTH_SIMPLE, passwd ) == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( -1 ); - } - - if ( nsldapi_put_controls( ld, NULL, 1, ber ) != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( -1 ); - } - - /* send the message */ - return( nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, - (char *)dn, ber )); -} - - -/* - * ldap_simple_bind - bind to the ldap server 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_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * "secret" ) - */ -int -LDAP_CALL -ldap_simple_bind_s( LDAP *ld, const char *dn, const char *passwd ) -{ - int msgid; - LDAPMessage *result; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - return( ldap_result2error( ld, result, 1 ) ); -} - -void nsldapi_handle_reconnect( LDAP *ld ) -{ - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_handle_reconnect\n", 0, 0, 0 ); - - /* - * if the default connection has been lost and is now marked dead, - * dispose of the default connection so it will get re-established. - * - * if not, clear the bind DN and status to ensure that we don't - * report the wrong bind DN to a different thread while waiting - * for our bind result to return from the server. - */ - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - if ( NULL != ld->ld_defconn ) { - if ( LDAP_CONNST_DEAD == ld->ld_defconn->lconn_status ) { - nsldapi_free_connection( ld, ld->ld_defconn, NULL, NULL, 1, 0 ); - ld->ld_defconn = NULL; - } else if ( ld->ld_defconn->lconn_binddn != NULL ) { - NSLDAPI_FREE( ld->ld_defconn->lconn_binddn ); - ld->ld_defconn->lconn_binddn = NULL; - ld->ld_defconn->lconn_bound = 0; - } - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); -} diff --git a/ldap/c-sdk/libraries/libldap/search.c b/ldap/c-sdk/libraries/libldap/search.c deleted file mode 100644 index 648d739e6a..0000000000 --- a/ldap/c-sdk/libraries/libldap/search.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * search.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -static int nsldapi_timeval2ldaplimit( struct timeval *timeoutp, - int defaultvalue ); -static int nsldapi_search( LDAP *ld, const char *base, int scope, - const char *filter, char **attrs, int attrsonly, - LDAPControl **serverctrls, LDAPControl **clientctrls, - int timelimit, int sizelimit, int *msgidp ); -static char *find_right_paren( char *s ); -static char *put_complex_filter( BerElement *ber, char *str, - unsigned long tag, int not ); -static int put_filter( BerElement *ber, char *str ); -static int unescape_filterval( char *str ); -static int hexchar2int( char c ); -static int is_valid_attr( char *a ); -static int put_simple_filter( BerElement *ber, char *str ); -static int put_substring_filter( BerElement *ber, char *type, - char *str ); -static int put_filter_list( BerElement *ber, char *str ); -static int nsldapi_search_s( LDAP *ld, const char *base, int scope, - const char *filter, char **attrs, int attrsonly, - LDAPControl **serverctrls, LDAPControl **clientctrls, - struct timeval *localtimeoutp, int timelimit, int sizelimit, - LDAPMessage **res ); - -/* - * ldap_search - initiate an ldap search operation. Parameters: - * - * ld LDAP descriptor - * base DN of the base object - * scope the search scope - one of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE - * filter a string containing the search filter - * (e.g., "(|(cn=bob)(sn=bob))") - * attrs list of attribute types to return for matches - * attrsonly 1 => attributes only 0 => attributes and values - * - * Example: - * char *attrs[] = { "mail", "title", 0 }; - * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", - * attrs, attrsonly ); - */ -int -LDAP_CALL -ldap_search( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly -) -{ - int msgid; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); - - if ( ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, NULL, - NULL, NULL, -1, &msgid ) == LDAP_SUCCESS ) { - return( msgid ); - } else { - return( -1 ); /* error is in ld handle */ - } -} - - -/* - * LDAPv3 extended search. - * Returns an LDAP error code. - */ -int -LDAP_CALL -ldap_search_ext( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct timeval *timeoutp, /* NULL means use ld->ld_timelimit */ - int sizelimit, - int *msgidp -) -{ - /* - * It is an error to pass in a zero'd timeval. - */ - if ( timeoutp != NULL && timeoutp->tv_sec == 0 && - timeoutp->tv_usec == 0 ) { - if ( ld != NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - } - return( LDAP_PARAM_ERROR ); - } - - return( nsldapi_search( ld, base, scope, filter, attrs, attrsonly, - serverctrls, clientctrls, - nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, msgidp )); -} - - -/* - * Like ldap_search_ext() except an integer timelimit is passed instead of - * using the overloaded struct timeval *timeoutp. - */ -static int -nsldapi_search( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int timelimit, /* -1 means use ld->ld_timelimit */ - int sizelimit, /* -1 means use ld->ld_sizelimit */ - int *msgidp -) -{ - BerElement *ber; - int rc, rc_key; - unsigned long key; /* XXXmcs: memcache */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( base == NULL ) { - base = ""; - } - - if ( filter == NULL ) { - filter = "(objectclass=*)"; - } - - if ( msgidp == NULL || ( scope != LDAP_SCOPE_BASE - && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE ) - || ( sizelimit < -1 )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - *msgidp = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - /* - * XXXmcs: should use cache function pointers to hook in memcache - */ - if ( ld->ld_memcache == NULL ) { - rc_key = LDAP_NOT_SUPPORTED; - } else if (( rc_key = ldap_memcache_createkey( ld, base, scope, filter, - attrs, attrsonly, serverctrls, clientctrls, &key)) == LDAP_SUCCESS - && ldap_memcache_result( ld, *msgidp, key ) == LDAP_SUCCESS ) { - return LDAP_SUCCESS; - } - - /* check the cache */ - if ( ld->ld_cache_on && ld->ld_cache_search != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_search)( ld, *msgidp, LDAP_REQ_SEARCH, - base, scope, filter, attrs, attrsonly )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* caching off or did not find it in the cache - check the net */ - if (( rc = nsldapi_build_search_req( ld, base, scope, filter, attrs, - attrsonly, serverctrls, clientctrls, timelimit, sizelimit, - *msgidp, &ber )) != LDAP_SUCCESS ) { - return( rc ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_SEARCH, - (char *) base, ber ); - - /* - * XXXmcs: should use cache function pointers to hook in memcache - */ - if ( (rc_key == LDAP_SUCCESS) && (rc >= 0) ) { - ldap_memcache_new( ld, rc, key, base ); - } - - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - - -/* - * Convert a non-NULL timeoutp to a value in seconds that is appropriate to - * send in an LDAP search request. If timeoutp is NULL, return defaultvalue. - */ -static int -nsldapi_timeval2ldaplimit( struct timeval *timeoutp, int defaultvalue ) -{ - int timelimit; - - if ( NULL == timeoutp ) { - timelimit = defaultvalue; - } else if ( timeoutp->tv_sec > 0 ) { - timelimit = timeoutp->tv_sec; - } else if ( timeoutp->tv_usec > 0 ) { - timelimit = 1; /* minimum we can express in LDAP */ - } else { - /* - * both tv_sec and tv_usec are less than one (zero?) so - * to maintain compatiblity with our "zero means no limit" - * convention we pass no limit to the server. - */ - timelimit = 0; /* no limit */ - } - - return( timelimit ); -} - - -/* returns an LDAP error code and also sets it in ld */ -int -nsldapi_build_search_req( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, /* not used for anything yet */ - int timelimit, /* if -1, ld->ld_timelimit is used */ - int sizelimit, /* if -1, ld->ld_sizelimit is used */ - int msgid, - BerElement **berp -) -{ - BerElement *ber; - int err; - char *fdup; - - /* - * Create the search request. It looks like this: - * SearchRequest := [APPLICATION 3] SEQUENCE { - * baseObject DistinguishedName, - * scope ENUMERATED { - * baseObject (0), - * singleLevel (1), - * wholeSubtree (2) - * }, - * derefAliases ENUMERATED { - * neverDerefaliases (0), - * derefInSearching (1), - * derefFindingBaseObj (2), - * alwaysDerefAliases (3) - * }, - * sizelimit INTEGER (0 .. 65535), - * timelimit INTEGER (0 .. 65535), - * attrsOnly BOOLEAN, - * filter Filter, - * attributes SEQUENCE OF AttributeType - * } - * wrapped in an ldap message. - */ - - /* create a message to send */ - if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( err ); - } - - if ( base == NULL ) { - base = ""; - } - - if ( sizelimit == -1 ) { - sizelimit = ld->ld_sizelimit; - } - - if ( timelimit == -1 ) { - timelimit = ld->ld_timelimit; - } - -#ifdef CLDAP - if ( ld->ld_sbp->sb_naddr > 0 ) { - err = ber_printf( ber, "{ist{seeiib", msgid, - ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, - sizelimit, timelimit, attrsonly ); - } else { -#endif /* CLDAP */ - err = ber_printf( ber, "{it{seeiib", msgid, - LDAP_REQ_SEARCH, base, scope, ld->ld_deref, - sizelimit, timelimit, attrsonly ); -#ifdef CLDAP - } -#endif /* CLDAP */ - - if ( err == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - fdup = nsldapi_strdup( filter ); - err = put_filter( ber, fdup ); - NSLDAPI_FREE( fdup ); - - if ( err == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_FILTER_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_FILTER_ERROR ); - } - - if ( ber_printf( ber, "{v}}", attrs ) == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if ( (err = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( err ); - } - - *berp = ber; - return( LDAP_SUCCESS ); -} - -static char * -find_right_paren( char *s ) -{ - int balance, escape; - - balance = 1; - escape = 0; - while ( *s && balance ) { - if ( escape == 0 ) { - if ( *s == '(' ) - balance++; - else if ( *s == ')' ) - balance--; - } - if ( *s == '\\' && ! escape ) - escape = 1; - else - escape = 0; - if ( balance ) - s++; - } - - return( *s ? s : NULL ); -} - -static char * -put_complex_filter( - BerElement *ber, - char *str, - unsigned long tag, - int not -) -{ - char *next; - - /* - * We have (x(filter)...) with str sitting on - * the x. We have to find the paren matching - * the one before the x and put the intervening - * filters by calling put_filter_list(). - */ - - /* put explicit tag */ - if ( ber_printf( ber, "t{", tag ) == -1 ) - return( NULL ); - - str++; - if ( (next = find_right_paren( str )) == NULL ) - return( NULL ); - - *next = '\0'; - if ( put_filter_list( ber, str ) == -1 ) - return( NULL ); - *next++ = ')'; - - /* flush explicit tagged thang */ - if ( ber_printf( ber, "}" ) == -1 ) - return( NULL ); - - return( next ); -} - -static int -put_filter( BerElement *ber, char *str ) -{ - char *next; - int parens, balance, escape; - - /* - * A Filter looks like this: - * 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] IA5String, - * any [1] IA5String, - * final [2] IA5String - * } - * } - * Note: tags in a choice are always explicit - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 ); - - parens = 0; - while ( *str ) { - switch ( *str ) { - case '(': - str++; - parens++; - switch ( *str ) { - case '&': - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: AND\n", - 0, 0, 0 ); - - if ( (str = put_complex_filter( ber, str, - LDAP_FILTER_AND, 0 )) == NULL ) - return( -1 ); - - parens--; - break; - - case '|': - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: OR\n", - 0, 0, 0 ); - - if ( (str = put_complex_filter( ber, str, - LDAP_FILTER_OR, 0 )) == NULL ) - return( -1 ); - - parens--; - break; - - case '!': - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: NOT\n", - 0, 0, 0 ); - - if ( (str = put_complex_filter( ber, str, - LDAP_FILTER_NOT, 1 )) == NULL ) - return( -1 ); - - parens--; - break; - - default: - LDAPDebug( LDAP_DEBUG_TRACE, - "put_filter: simple\n", 0, 0, 0 ); - - balance = 1; - escape = 0; - next = str; - while ( *next && balance ) { - if ( escape == 0 ) { - if ( *next == '(' ) - balance++; - else if ( *next == ')' ) - balance--; - } - if ( *next == '\\' && ! escape ) - escape = 1; - else - escape = 0; - if ( balance ) - next++; - } - if ( balance != 0 ) - return( -1 ); - - *next = '\0'; - if ( put_simple_filter( ber, str ) == -1 ) { - return( -1 ); - } - *next++ = ')'; - str = next; - parens--; - break; - } - break; - - case ')': - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0, - 0 ); - if ( ber_printf( ber, "]" ) == -1 ) - return( -1 ); - str++; - parens--; - break; - - case ' ': - str++; - break; - - default: /* assume it's a simple type=value filter */ - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, - 0 ); - next = strchr( str, '\0' ); - if ( put_simple_filter( ber, str ) == -1 ) { - return( -1 ); - } - str = next; - break; - } - } - - return( parens ? -1 : 0 ); -} - - -/* - * Put a list of filters like this "(filter1)(filter2)..." - */ - -static int -put_filter_list( BerElement *ber, char *str ) -{ - char *next; - char save; - - LDAPDebug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 ); - - while ( *str ) { - while ( *str && isspace( *str ) ) - str++; - if ( *str == '\0' ) - break; - - if ( (next = find_right_paren( str + 1 )) == NULL ) - return( -1 ); - save = *++next; - - /* now we have "(filter)" with str pointing to it */ - *next = '\0'; - if ( put_filter( ber, str ) == -1 ) - return( -1 ); - *next = save; - - str = next; - } - - return( 0 ); -} - - -/* - * is_valid_attr - returns 1 if a is a syntactically valid left-hand side - * of a filter expression, 0 otherwise. A valid string may contain only - * letters, numbers, hyphens, semi-colons, colons and periods. examples: - * cn - * cn;lang-fr - * 1.2.3.4;binary;dynamic - * mail;dynamic - * cn:dn:1.2.3.4 - * - * For compatibility with older servers, we also allow underscores in - * attribute types, even through they are not allowed by the LDAPv3 RFCs. - */ -static int -is_valid_attr( char *a ) -{ - for ( ; *a; a++ ) { - if ( !isascii( *a ) ) { - return( 0 ); - } else if ( !isalnum( *a ) ) { - switch ( *a ) { - case '-': - case '.': - case ';': - case ':': - case '_': - break; /* valid */ - default: - return( 0 ); - } - } - } - - return( 1 ); -} - -static char * -find_star( char *s ) -{ - for ( ; *s; ++s ) { - switch ( *s ) { - case '*': return s; - case '\\': - ++s; - if ( hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0 ) ++s; - default: break; - } - } - return NULL; -} - -static int -put_simple_filter( BerElement *ber, char *str ) -{ - char *s, *s2, *s3, filterop; - char *value; - unsigned long ftype; - int rc, len; - char *oid; /* for v3 extended filter */ - int dnattr; /* for v3 extended filter */ - - LDAPDebug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 ); - - rc = -1; /* pessimistic */ - - if (( str = nsldapi_strdup( str )) == NULL ) { - return( rc ); - } - - if ( (s = strchr( str, '=' )) == NULL ) { - goto free_and_return; - } - value = s + 1; - *s-- = '\0'; - filterop = *s; - if ( filterop == '<' || filterop == '>' || filterop == '~' || - filterop == ':' ) { - *s = '\0'; - } - - if ( ! is_valid_attr( str ) ) { - goto free_and_return; - } - - switch ( filterop ) { - case '<': - ftype = LDAP_FILTER_LE; - break; - case '>': - ftype = LDAP_FILTER_GE; - break; - case '~': - ftype = LDAP_FILTER_APPROX; - break; - case ':': /* extended filter - v3 only */ - /* - * extended filter looks like this: - * - * [type][':dn'][':'oid]':='value - * - * where one of type or :oid is required. - * - */ - ftype = LDAP_FILTER_EXTENDED; - s2 = s3 = NULL; - if ( (s2 = strrchr( str, ':' )) == NULL ) { - goto free_and_return; - } - if ( strcasecmp( s2, ":dn" ) == 0 ) { - oid = NULL; - dnattr = 1; - *s2 = '\0'; - } else { - oid = s2 + 1; - dnattr = 0; - *s2 = '\0'; - if ( (s3 = strrchr( str, ':' )) != NULL ) { - if ( strcasecmp( s3, ":dn" ) == 0 ) { - dnattr = 1; - } else { - goto free_and_return; - } - *s3 = '\0'; - } - } - if ( (rc = ber_printf( ber, "t{", ftype )) == -1 ) { - goto free_and_return; - } - if ( oid != NULL ) { - if ( (rc = ber_printf( ber, "ts", LDAP_TAG_MRA_OID, - oid )) == -1 ) { - goto free_and_return; - } - } - if ( *str != '\0' ) { - if ( (rc = ber_printf( ber, "ts", - LDAP_TAG_MRA_TYPE, str )) == -1 ) { - goto free_and_return; - } - } - if (( len = unescape_filterval( value )) < 0 || - ( rc = ber_printf( ber, "totb}", LDAP_TAG_MRA_VALUE, - value, len, LDAP_TAG_MRA_DNATTRS, dnattr )) == -1 ) { - goto free_and_return; - } - rc = 0; - goto free_and_return; - break; - default: - if ( find_star( value ) == NULL ) { - ftype = LDAP_FILTER_EQUALITY; - } else if ( strcmp( value, "*" ) == 0 ) { - ftype = LDAP_FILTER_PRESENT; - } else { - rc = put_substring_filter( ber, str, value ); - goto free_and_return; - } - break; - } - - if ( ftype == LDAP_FILTER_PRESENT ) { - rc = ber_printf( ber, "ts", ftype, str ); - } else if (( len = unescape_filterval( value )) >= 0 ) { - rc = ber_printf( ber, "t{so}", ftype, str, value, len ); - } - if ( rc != -1 ) { - rc = 0; - } - -free_and_return: - NSLDAPI_FREE( str ); - return( rc ); -} - - -/* - * Undo in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape - * sequences within the null-terminated string 'val'. The resulting value - * may contain null characters. - * - * If 'val' contains invalid escape sequences we return -1. - * Otherwise the length of the unescaped value is returned. - */ -static int -unescape_filterval( char *val ) -{ - int escape, firstdigit, ival; - char *s, *d; - - escape = firstdigit = 0; - for ( s = d = val; *s; s++ ) { - if ( escape ) { - /* - * first try LDAPv3 escape (hexadecimal) sequence - */ - if (( ival = hexchar2int( *s )) < 0 ) { - if ( firstdigit ) { - /* - * LDAPv2 (RFC1960) escape sequence - */ - *d++ = *s; - escape = 0; - } else { - return(-1); - } - } - if ( firstdigit ) { - *d = ( ival<<4 ); - firstdigit = 0; - } else { - *d++ |= ival; - escape = 0; - } - - } else if ( *s != '\\' ) { - *d++ = *s; - escape = 0; - - } else { - escape = 1; - firstdigit = 1; - } - } - - return( d - val ); -} - - -/* - * convert character 'c' that represents a hexadecimal digit to an integer. - * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned. - * otherwise the converted value is returned. - */ -static int -hexchar2int( char c ) -{ - if ( c >= '0' && c <= '9' ) { - return( c - '0' ); - } - if ( c >= 'A' && c <= 'F' ) { - return( c - 'A' + 10 ); - } - if ( c >= 'a' && c <= 'f' ) { - return( c - 'a' + 10 ); - } - return( -1 ); -} - -static int -put_substring_filter( BerElement *ber, char *type, char *val ) -{ - char *nextstar, gotstar = 0; - unsigned long ftype; - int len; - - LDAPDebug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type, - val, 0 ); - - if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 ) { - return( -1 ); - } - - for ( ; val != NULL; val = nextstar ) { - if ( (nextstar = find_star( val )) != NULL ) { - *nextstar++ = '\0'; - } - - if ( gotstar == 0 ) { - ftype = LDAP_SUBSTRING_INITIAL; - } else if ( nextstar == NULL ) { - ftype = LDAP_SUBSTRING_FINAL; - } else { - ftype = LDAP_SUBSTRING_ANY; - } - if ( *val != '\0' ) { - if (( len = unescape_filterval( val )) < 0 || - ber_printf( ber, "to", ftype, val, len ) == -1 ) { - return( -1 ); - } - } - - gotstar = 1; - } - - if ( ber_printf( ber, "}}" ) == -1 ) { - return( -1 ); - } - - return( 0 ); -} - -int -LDAP_CALL -ldap_search_st( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - struct timeval *timeout, - LDAPMessage **res -) -{ - return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, - NULL, NULL, timeout, -1, -1, res )); -} - -int -LDAP_CALL -ldap_search_s( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPMessage **res -) -{ - return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, - NULL, NULL, NULL, -1, -1, res )); -} - -int LDAP_CALL -ldap_search_ext_s( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct timeval *timeoutp, - int sizelimit, - LDAPMessage **res -) -{ - return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly, - serverctrls, clientctrls, timeoutp, - nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, res )); -} - - -static int -nsldapi_search_s( - LDAP *ld, - const char *base, - int scope, - const char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct timeval *localtimeoutp, - int timelimit, /* -1 means use ld->ld_timelimit */ - int sizelimit, /* -1 means use ld->ld_sizelimit */ - LDAPMessage **res -) -{ - int err, msgid; - - /* - * It is an error to pass in a zero'd timeval. - */ - if ( localtimeoutp != NULL && localtimeoutp->tv_sec == 0 && - localtimeoutp->tv_usec == 0 ) { - if ( ld != NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - } - if ( res != NULL ) { - *res = NULL; - } - return( LDAP_PARAM_ERROR ); - } - - if (( err = nsldapi_search( ld, base, scope, filter, attrs, attrsonly, - serverctrls, clientctrls, timelimit, sizelimit, &msgid )) - != LDAP_SUCCESS ) { - if ( res != NULL ) { - *res = NULL; - } - return( err ); - } - - if ( ldap_result( ld, msgid, 1, localtimeoutp, res ) == -1 ) { - /* - * Error. ldap_result() sets *res to NULL for us. - */ - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { - (void) ldap_abandon( ld, msgid ); - err = LDAP_TIMEOUT; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - if ( res != NULL ) { - *res = NULL; - } - return( err ); - } - - return( ldap_result2error( ld, *res, 0 ) ); -} diff --git a/ldap/c-sdk/libraries/libldap/setoption.c b/ldap/c-sdk/libraries/libldap/setoption.c deleted file mode 100644 index 5c4d753f5a..0000000000 --- a/ldap/c-sdk/libraries/libldap/setoption.c +++ /dev/null @@ -1,411 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * setoption.c - ldap_set_option implementation - */ - -#include "ldap-int.h" - -#define LDAP_SETCLR_BITOPT( ld, bit, optdata ) \ - if ( optdata != NULL ) { \ - (ld)->ld_options |= bit; \ - } else { \ - (ld)->ld_options &= ~bit; \ - } - - -int -LDAP_CALL -ldap_set_option( LDAP *ld, int option, const void *optdata ) -{ - int rc, i; - char *matched, *errstr; - - /* - * if ld is NULL, arrange to modify our default settings - */ - if ( ld == NULL ) { - if ( !nsldapi_initialized ) { - nsldapi_initialize_defaults(); - } - ld = &nsldapi_ld_defaults; - } - - /* - * process global options (not associated with an LDAP session handle) - */ - if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) { - struct lber_memalloc_fns memalloc_fns; - - /* set libldap ones via a struct copy */ - nsldapi_memalloc_fns = *((struct ldap_memalloc_fns *)optdata); - - /* also set liblber memory allocation callbacks */ - memalloc_fns.lbermem_malloc = - nsldapi_memalloc_fns.ldapmem_malloc; - memalloc_fns.lbermem_calloc = - nsldapi_memalloc_fns.ldapmem_calloc; - memalloc_fns.lbermem_realloc = - nsldapi_memalloc_fns.ldapmem_realloc; - memalloc_fns.lbermem_free = - nsldapi_memalloc_fns.ldapmem_free; - if ( ber_set_option( NULL, LBER_OPT_MEMALLOC_FN_PTRS, - &memalloc_fns ) != 0 ) { - return( -1 ); - } - - return( 0 ); - } - /* - * LDAP_OPT_DEBUG_LEVEL is global - */ - if (LDAP_OPT_DEBUG_LEVEL == option) - { -#ifdef LDAP_DEBUG - ldap_debug = *((int *) optdata); -#endif - return 0; - } - - /* - * process options that are associated with an LDAP session handle - */ - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); /* punt */ - } - - rc = 0; - if ( ld != &nsldapi_ld_defaults - && option != LDAP_OPT_EXTRA_THREAD_FN_PTRS - && option != LDAP_OPT_THREAD_FN_PTRS ) { - LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); - } - switch( option ) { - /* options that can be turned on and off */ -#ifdef LDAP_DNS - case LDAP_OPT_DNS: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_DNS, optdata ); - break; -#endif - - case LDAP_OPT_REFERRALS: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_REFERRALS, optdata ); - break; - - case LDAP_OPT_SSL: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_SSL, optdata ); - break; - - case LDAP_OPT_RESTART: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_RESTART, optdata ); - break; - - case LDAP_OPT_RECONNECT: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_RECONNECT, optdata ); - break; - - case LDAP_OPT_NOREBIND: - LDAP_SETCLR_BITOPT( ld, LDAP_BITOPT_NOREBIND, optdata ); - break; - -#ifdef LDAP_ASYNC_IO - case LDAP_OPT_ASYNC_CONNECT: - LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_ASYNC, optdata ); - break; -#endif /* LDAP_ASYNC_IO */ - - /* fields in the LDAP structure */ - case LDAP_OPT_DEREF: - ld->ld_deref = *((int *) optdata); - break; - case LDAP_OPT_SIZELIMIT: - ld->ld_sizelimit = *((int *) optdata); - break; - case LDAP_OPT_TIMELIMIT: - ld->ld_timelimit = *((int *) optdata); - break; - case LDAP_OPT_REFERRAL_HOP_LIMIT: - ld->ld_refhoplimit = *((int *) optdata); - break; - case LDAP_OPT_PROTOCOL_VERSION: - ld->ld_version = *((int *) optdata); - if ( ld->ld_defconn != NULL ) { /* also set in default conn. */ - ld->ld_defconn->lconn_version = ld->ld_version; - } - break; - case LDAP_OPT_SERVER_CONTROLS: - /* nsldapi_dup_controls returns -1 and sets lderrno on error */ - rc = nsldapi_dup_controls( ld, &ld->ld_servercontrols, - (LDAPControl **)optdata ); - break; - case LDAP_OPT_CLIENT_CONTROLS: - /* nsldapi_dup_controls returns -1 and sets lderrno on error */ - rc = nsldapi_dup_controls( ld, &ld->ld_clientcontrols, - (LDAPControl **)optdata ); - break; - - /* rebind proc */ - case LDAP_OPT_REBIND_FN: - ld->ld_rebind_fn = (LDAP_REBINDPROC_CALLBACK *) optdata; - break; - case LDAP_OPT_REBIND_ARG: - ld->ld_rebind_arg = (void *) optdata; - break; - - /* i/o function pointers */ - case LDAP_OPT_IO_FN_PTRS: - if (( rc = nsldapi_install_compat_io_fns( ld, - (struct ldap_io_fns *)optdata )) != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - rc = -1; - } - break; - - /* extended i/o function pointers */ - case LDAP_X_OPT_EXTIO_FN_PTRS: - /* denotes use of old iofns struct (no writev) */ - if (((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) { - ld->ld_extio_size = LDAP_X_EXTIO_FNS_SIZE; - ld->ld_extclose_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close; - ld->ld_extconnect_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect; - ld->ld_extread_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read; - ld->ld_extwrite_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write; - ld->ld_extpoll_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll; - ld->ld_extnewhandle_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle; - ld->ld_extdisposehandle_fn = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle; - ld->ld_ext_session_arg = ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg; - ld->ld_extwritev_fn = NULL; - if ( ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, - &(ld->ld_ext_io_fns) ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - rc = -1; - break; - } - } - else { - /* struct copy */ - ld->ld_ext_io_fns = *((struct ldap_x_ext_io_fns *) optdata); - } - if (( rc = nsldapi_install_lber_extiofns( ld, ld->ld_sbp )) - != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - rc = -1; - } - break; - - /* set Socket Arg in extended socket i/o functions*/ - case LDAP_X_OPT_SOCKETARG: - if ( ber_sockbuf_set_option( ld->ld_sbp, - LBER_SOCKBUF_OPT_SOCK_ARG, (void *)optdata ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - rc = -1; - } - - break; - - /* thread function pointers */ - case LDAP_OPT_THREAD_FN_PTRS: - /* - * It is only safe to set the thread function pointers - * when one thread is using the LDAP session handle. - */ - /* free existing mutexes (some are allocated by ldap_init()) */ - nsldapi_mutex_free_all( ld ); - - /* struct copy */ - ld->ld_thread = *((struct ldap_thread_fns *) optdata); - - /* allocate new mutexes */ - nsldapi_mutex_alloc_all( ld ); - - /* LDAP_OPTION_LOCK was never locked... so just return */ - return (rc); - - /* extra thread function pointers */ - case LDAP_OPT_EXTRA_THREAD_FN_PTRS: - /* The extra thread funcs will only pick up the threadid */ - ld->ld_thread2 = *((struct ldap_extra_thread_fns *) optdata); - - /* Reset the rest of the structure preserving the threadid fn */ - ld->ld_mutex_trylock_fn = (LDAP_TF_MUTEX_TRYLOCK_CALLBACK *)NULL; - ld->ld_sema_alloc_fn = (LDAP_TF_SEMA_ALLOC_CALLBACK *) NULL; - ld->ld_sema_free_fn = (LDAP_TF_SEMA_FREE_CALLBACK *) NULL; - ld->ld_sema_wait_fn = (LDAP_TF_SEMA_WAIT_CALLBACK *) NULL; - ld->ld_sema_post_fn = (LDAP_TF_SEMA_POST_CALLBACK *) NULL; - - /* We assume that only one thread is active when replacing */ - /* the threadid function. We will now proceed and reset all */ - /* of the threadid/refcounts */ - for( i=0; ild_mutex_threadid[i] = (void *) -1; - ld->ld_mutex_refcnt[i] = 0; - } - - /* LDAP_OPTION_LOCK was never locked... so just return */ - return (rc); - - /* DNS function pointers */ - case LDAP_OPT_DNS_FN_PTRS: - /* struct copy */ - ld->ld_dnsfn = *((struct ldap_dns_fns *) optdata); - break; - - /* cache function pointers */ - case LDAP_OPT_CACHE_FN_PTRS: - /* struct copy */ - ld->ld_cache = *((struct ldap_cache_fns *) optdata); - break; - case LDAP_OPT_CACHE_STRATEGY: - ld->ld_cache_strategy = *((int *) optdata); - break; - case LDAP_OPT_CACHE_ENABLE: - ld->ld_cache_on = *((int *) optdata); - break; - - case LDAP_OPT_ERROR_NUMBER: - LDAP_GET_LDERRNO( ld, &matched, &errstr ); - matched = nsldapi_strdup( matched ); - errstr = nsldapi_strdup( errstr ); - LDAP_SET_LDERRNO( ld, *((int *) optdata), matched, errstr ); - break; - - case LDAP_OPT_ERROR_STRING: - rc = LDAP_GET_LDERRNO( ld, &matched, NULL ); - matched = nsldapi_strdup( matched ); - LDAP_SET_LDERRNO( ld, rc, matched, - nsldapi_strdup((char *) optdata)); - rc = LDAP_SUCCESS; - break; - - case LDAP_OPT_MATCHED_DN: - rc = LDAP_GET_LDERRNO( ld, NULL, &errstr ); - errstr = nsldapi_strdup( errstr ); - LDAP_SET_LDERRNO( ld, rc, - nsldapi_strdup((char *) optdata), errstr ); - rc = LDAP_SUCCESS; - break; - - case LDAP_OPT_PREFERRED_LANGUAGE: - if ( NULL != ld->ld_preferred_language ) { - NSLDAPI_FREE(ld->ld_preferred_language); - } - ld->ld_preferred_language = nsldapi_strdup((char *) optdata); - break; - - case LDAP_OPT_HOST_NAME: - if ( NULL != ld->ld_defhost ) { - NSLDAPI_FREE(ld->ld_defhost); - } - ld->ld_defhost = nsldapi_strdup((char *) optdata); - break; - - case LDAP_X_OPT_CONNECT_TIMEOUT: - ld->ld_connect_timeout = *((int *) optdata); - break; - -#ifdef LDAP_SASLIO_HOOKS - /* SASL options */ - case LDAP_OPT_X_SASL_MECH: - NSLDAPI_FREE(ld->ld_def_sasl_mech); - ld->ld_def_sasl_mech = nsldapi_strdup((char *) optdata); - break; - case LDAP_OPT_X_SASL_REALM: - NSLDAPI_FREE(ld->ld_def_sasl_realm); - ld->ld_def_sasl_realm = nsldapi_strdup((char *) optdata); - break; - case LDAP_OPT_X_SASL_AUTHCID: - NSLDAPI_FREE(ld->ld_def_sasl_authcid); - ld->ld_def_sasl_authcid = nsldapi_strdup((char *) optdata); - break; - case LDAP_OPT_X_SASL_AUTHZID: - NSLDAPI_FREE(ld->ld_def_sasl_authzid); - ld->ld_def_sasl_authzid = nsldapi_strdup((char *) optdata); - break; - case LDAP_OPT_X_SASL_SSF_EXTERNAL: - { - int sc; - sasl_ssf_t extprops; - sasl_conn_t *ctx; - if( ld->ld_defconn == NULL ) { - return -1; - } - ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sasl_ctx); - if ( ctx == NULL ) { - return -1; - } - memset(&extprops, 0L, sizeof(extprops)); - extprops = * ((sasl_ssf_t *) optdata); - sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, - (void *) &extprops ); - if ( sc != SASL_OK ) { - return -1; - } - } - break; - case LDAP_OPT_X_SASL_SECPROPS: - { - int sc; - sc = nsldapi_sasl_secprops( (char *) optdata, - &ld->ld_sasl_secprops ); - return sc == LDAP_SUCCESS ? 0 : -1; - } - break; - case LDAP_OPT_X_SASL_SSF_MIN: - ld->ld_sasl_secprops.min_ssf = *((sasl_ssf_t *) optdata); - break; - case LDAP_OPT_X_SASL_SSF_MAX: - ld->ld_sasl_secprops.max_ssf = *((sasl_ssf_t *) optdata); - break; - case LDAP_OPT_X_SASL_MAXBUFSIZE: - ld->ld_sasl_secprops.maxbufsize = *((sasl_ssf_t *) optdata); - break; - case LDAP_OPT_X_SASL_SSF: /* read only */ - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - rc = -1; - break; -#endif - - default: - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - rc = -1; - } - - if ( ld != &nsldapi_ld_defaults ) { - LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); - } - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libldap/sort.c b/ldap/c-sdk/libraries/libldap/sort.c deleted file mode 100644 index 8a716c818b..0000000000 --- a/ldap/c-sdk/libraries/libldap/sort.c +++ /dev/null @@ -1,355 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1994 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. - */ -/* - * sort.c: LDAP library entry and value sort routines - */ - -#include "ldap-int.h" - -/* This xp_qsort fixes a memory problem (ABR) on Solaris for the client. - * Server is welcome to use it too, but I wasn't sure if it - * would be ok to use XP code here. -slamm - * - * We don't want to require use of libxp when linking with libldap, so - * I'll leave use of xp_qsort as a MOZILLA_CLIENT-only thing for now. --mcs - */ -#if defined(MOZILLA_CLIENT) && defined(SOLARIS) -#include "xp_qsort.h" -#else -#define XP_QSORT qsort -#endif - -typedef struct keycmp { - void *kc_arg; - LDAP_KEYCMP_CALLBACK *kc_cmp; -} keycmp_t; - -typedef struct keything { - keycmp_t *kt_cmp; - const struct berval *kt_key; - LDAPMessage *kt_msg; -} keything_t; - -static int LDAP_C LDAP_CALLBACK -ldapi_keycmp( const void *Lv, const void *Rv ) -{ - auto keything_t **L = (keything_t**)Lv; - auto keything_t **R = (keything_t**)Rv; - auto keycmp_t *cmp = (*L)->kt_cmp; - return cmp->kc_cmp( cmp->kc_arg, (*L)->kt_key, (*R)->kt_key ); -} - -int -LDAP_CALL -ldap_keysort_entries( - LDAP *ld, - LDAPMessage **chain, - void *arg, - LDAP_KEYGEN_CALLBACK *gen, - LDAP_KEYCMP_CALLBACK *cmp, - LDAP_KEYFREE_CALLBACK *fre) -{ - size_t count, i; - keycmp_t kc = {0}; - keything_t **kt; - LDAPMessage *e, *last; - LDAPMessage **ep; - int scount; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) - || chain == NULL || cmp == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - scount = ldap_count_entries( ld, *chain ); - - if (scount < 0) { /* error */ - return( LDAP_PARAM_ERROR ); - } - - count = scount; - - if (count < 2) { /* nothing to sort */ - return( 0 ); - } - - kt = (keything_t**)NSLDAPI_MALLOC( count * (sizeof(keything_t*) + sizeof(keything_t)) ); - if ( kt == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - for ( i = 0; i < count; i++ ) { - kt[i] = i + (keything_t*)(kt + count); - } - kc.kc_arg = arg; - kc.kc_cmp = cmp; - - for ( e = *chain, i = 0; i < count; i++, e = e->lm_chain ) { - kt[i]->kt_msg = e; - kt[i]->kt_cmp = &kc; - kt[i]->kt_key = gen( arg, ld, e ); - if ( kt[i]->kt_key == NULL ) { - if ( fre ) while ( i-- > 0 ) fre( arg, kt[i]->kt_key ); - NSLDAPI_FREE( (char*)kt ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - } - last = e; - - XP_QSORT( (void*)kt, count, (size_t)sizeof(keything_t*), ldapi_keycmp ); - - ep = chain; - for ( i = 0; i < count; i++ ) { - *ep = kt[i]->kt_msg; - ep = &(*ep)->lm_chain; - if ( fre ) fre( arg, kt[i]->kt_key ); - } - *ep = last; - NSLDAPI_FREE( (char*)kt ); - return( 0 ); -} - - -struct entrything { - char **et_vals; - LDAPMessage *et_msg; -}; - -typedef int (LDAP_C LDAP_CALLBACK LDAP_CHARCMP_CALLBACK)(char*, char*); -typedef int (LDAP_C LDAP_CALLBACK LDAP_VOIDCMP_CALLBACK)(const void*, - const void*); - -static LDAP_CHARCMP_CALLBACK *et_cmp_fn; -static LDAP_VOIDCMP_CALLBACK et_cmp; - -int -LDAP_C -LDAP_CALLBACK -ldap_sort_strcasecmp( - const char **a, - const char **b -) -{ - /* XXXceb - * I am not 100% sure this is the way this should be handled. - * For now we will return a 0 on invalid. - */ - if (NULL == a || NULL == b) - return (0); - return( strcasecmp( (char *)*a, (char *)*b ) ); -} - -static int -LDAP_C -LDAP_CALLBACK -et_cmp( - const void *aa, - const void *bb -) -{ - int i, rc; - struct entrything *a = (struct entrything *)aa; - struct entrything *b = (struct entrything *)bb; - - if ( a->et_vals == NULL && b->et_vals == NULL ) - return( 0 ); - if ( a->et_vals == NULL ) - return( -1 ); - if ( b->et_vals == NULL ) - return( 1 ); - - for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) { - if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] )) - != 0 ) { - return( rc ); - } - } - - if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL ) - return( 0 ); - if ( a->et_vals[i] == NULL ) - return( -1 ); - return( 1 ); -} - -int -LDAP_CALL -ldap_multisort_entries( - LDAP *ld, - LDAPMessage **chain, - char **attr, /* NULL => sort by DN */ - LDAP_CMP_CALLBACK *cmp -) -{ - int i, count; - struct entrything *et; - LDAPMessage *e, *last; - LDAPMessage **ep; - int scount; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) - || chain == NULL || cmp == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - scount = ldap_count_entries( ld, *chain ); - - if (scount < 0) { /* error, usually with bad ld or malloc */ - return( LDAP_PARAM_ERROR ); - } - - count = scount; - - if (count < 2) { /* nothing to sort */ - return( 0 ); - } - - if ( (et = (struct entrything *)NSLDAPI_MALLOC( count * - sizeof(struct entrything) )) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - - e = *chain; - for ( i = 0; i < count; i++ ) { - et[i].et_msg = e; - et[i].et_vals = NULL; - if ( attr == NULL ) { - char *dn; - - dn = ldap_get_dn( ld, e ); - et[i].et_vals = ldap_explode_dn( dn, 1 ); - NSLDAPI_FREE( dn ); - } else { - int attrcnt; - char **vals; - - for ( attrcnt = 0; attr[attrcnt] != NULL; attrcnt++ ) { - vals = ldap_get_values( ld, e, attr[attrcnt] ); - if ( ldap_charray_merge( &(et[i].et_vals), vals ) - != 0 ) { - int j; - - /* XXX risky: ldap_value_free( vals ); */ - for ( j = 0; j <= i; j++ ) - ldap_value_free( et[j].et_vals ); - NSLDAPI_FREE( (char *) et ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, - NULL ); - return( -1 ); - } - if ( vals != NULL ) { - NSLDAPI_FREE( (char *)vals ); - } - } - } - - e = e->lm_chain; - } - last = e; - - et_cmp_fn = (LDAP_CHARCMP_CALLBACK *)cmp; - XP_QSORT( (void *) et, (size_t) count, - (size_t) sizeof(struct entrything), et_cmp ); - - ep = chain; - for ( i = 0; i < count; i++ ) { - *ep = et[i].et_msg; - ep = &(*ep)->lm_chain; - - ldap_value_free( et[i].et_vals ); - } - *ep = last; - NSLDAPI_FREE( (char *) et ); - - return( 0 ); -} - -int -LDAP_CALL -ldap_sort_entries( - LDAP *ld, - LDAPMessage **chain, - char *attr, /* NULL => sort by DN */ - LDAP_CMP_CALLBACK *cmp -) -{ - char *attrs[2]; - - attrs[0] = attr; - attrs[1] = NULL; - return( ldap_multisort_entries( ld, chain, attr ? attrs : NULL, cmp ) ); -} - -int -LDAP_CALL -ldap_sort_values( - LDAP *ld, - char **vals, - LDAP_VALCMP_CALLBACK *cmp -) -{ - int nel; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || cmp == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - if ( NULL == vals) - { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - for ( nel = 0; vals[nel] != NULL; nel++ ) - ; /* NULL */ - - XP_QSORT( vals, nel, sizeof(char *), (LDAP_VOIDCMP_CALLBACK *)cmp ); - - return( LDAP_SUCCESS ); -} diff --git a/ldap/c-sdk/libraries/libldap/sortctrl.c b/ldap/c-sdk/libraries/libldap/sortctrl.c deleted file mode 100644 index 585e2fd3fa..0000000000 --- a/ldap/c-sdk/libraries/libldap/sortctrl.c +++ /dev/null @@ -1,438 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -/* ldap_create_sort_control: - - Parameters are - - ld LDAP pointer to the desired connection - - sortKeyList an array of sortkeys - - ctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client - - ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_sort_control ( - LDAP *ld, - LDAPsortkey **sortKeyList, - const char ctl_iscritical, - LDAPControl **ctrlp -) -{ - BerElement *ber; - int i, rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( sortKeyList == NULL || ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - /* create a ber package to hold the controlValue */ - if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* encode the start of the sequence of sequences into the ber */ - if ( ber_printf( ber, "{" ) == -1 ) { - goto encoding_error_exit; - } - - /* the sort control value will be encoded as a sequence of sequences - which are each encoded as one of the following: {s} or {sts} or {stb} or {ststb} - since the orderingRule and reverseOrder flag are both optional */ - for ( i = 0; sortKeyList[i] != NULL; i++ ) { - - /* encode the attributeType into the ber */ - if ( ber_printf( ber, "{s", (sortKeyList[i])->sk_attrtype ) - == -1 ) { - goto encoding_error_exit; - } - - /* encode the optional orderingRule into the ber */ - if ( (sortKeyList[i])->sk_matchruleoid != NULL ) { - if ( ber_printf( ber, "ts", LDAP_TAG_SK_MATCHRULE, - (sortKeyList[i])->sk_matchruleoid ) - == -1 ) { - goto encoding_error_exit; - } - } - - /* Encode the optional reverseOrder flag into the ber. */ - /* If the flag is false, it should be absent. */ - if ( (sortKeyList[i])->sk_reverseorder ) { - if ( ber_printf( ber, "tb}", LDAP_TAG_SK_REVERSE, - (sortKeyList[i])->sk_reverseorder ) == -1 ) { - goto encoding_error_exit; - } - } else { - if ( ber_printf( ber, "}" ) == -1 ) { - goto encoding_error_exit; - } - } - } - - /* encode the end of the sequence of sequences into the ber */ - if ( ber_printf( ber, "}" ) == -1 ) { - goto encoding_error_exit; - } - - rc = nsldapi_build_control( LDAP_CONTROL_SORTREQUEST, ber, 1, - ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - -encoding_error_exit: - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); -} - -/* ldap_parse_sort_control: - - Parameters are - - ld LDAP pointer to the desired connection - - ctrlp An array of controls obtained from calling - ldap_parse_result on the set of results returned by - the server - - result the address of a place to put the result code - - attribute the address of a place to put the name of the - attribute which cause the operation to fail, optionally - returned by the server */ - -int -LDAP_CALL -ldap_parse_sort_control ( - LDAP *ld, - LDAPControl **ctrlp, - ber_int_t *result, - char **attribute -) -{ - BerElement *ber; - int i, foundSortControl; - LDAPControl *sortCtrlp; - ber_len_t len; - ber_tag_t tag; - char *attr; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || result == NULL || - attribute == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - - /* find the sortControl in the list of controls if it exists */ - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - foundSortControl = 0; - for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundSortControl )); i++ ) { - foundSortControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_SORTRESPONSE ); - } - if ( !foundSortControl ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } else { - /* let local var point to the sortControl */ - sortCtrlp = ctrlp[i-1]; - } - - /* allocate a Ber element with the contents of the sort_control's struct berval */ - if ( ( ber = ber_init( &sortCtrlp->ldctl_value ) ) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* decode the result from the Berelement */ - if ( ber_scanf( ber, "{i", result ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - - /* if the server returned one, decode the attribute from the Ber element */ - if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SR_ATTRTYPE ) { - if ( ber_scanf( ber, "ta", &tag, &attr ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - *attribute = attr; - } else { - *attribute = NULL; - } - - if ( ber_scanf( ber, "}" ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - - /* the ber encoding is no longer needed */ - ber_free(ber,1); - - return( LDAP_SUCCESS ); -} - -/* Routines for the manipulation of string-representations of sort control keylists */ - -static int count_tokens(const char *s) -{ - int count = 0; - const char *p = s; - int whitespace = 1; - /* Loop along the string counting the number of times we see the - * beginning of non-whitespace. This tells us - * the number of tokens in the string - */ - while (*p != '\0') { - if (whitespace) { - if (!isspace(*p)) { - whitespace = 0; - count++; - } - } else { - if (isspace(*p)) { - whitespace = 1; - } - } - p++; - } - return count; -} - - -static int read_next_token(const char **s,LDAPsortkey **key) -{ - char c = 0; - const char *pos = *s; - int retval = 0; - LDAPsortkey *new_key = NULL; - - const char *matchrule_source = NULL; - int matchrule_size = 0; - const char *attrdesc_source = NULL; - int attrdesc_size = 0; - int reverse = 0; - - int state = 0; - - while ( ((c = *pos++) != '\0') && (state != 4) ) { - switch (state) { - case 0: - /* case where we've not seen the beginning of the attr yet */ - /* If we still see whitespace, nothing to do */ - if (!isspace(c)) { - /* Otherwise, something to look at */ - /* Is it a minus sign ? */ - if ('-' == c) { - reverse = 1; - } else { - attrdesc_source = pos - 1; - state = 1; - } - } - break; - case 1: - /* case where we've seen the beginning of the attr, but not the end */ - /* Is this char either whitespace or a ';' ? */ - if ( isspace(c) || (':' == c)) { - attrdesc_size = (pos - attrdesc_source) - 1; - if (':' == c) { - state = 2; - } else { - state = 4; - } - } - break; - case 2: - /* case where we've seen the end of the attr and want the beginning of match rule */ - if (!isspace(c)) { - matchrule_source = pos - 1; - state = 3; - } else { - state = 4; - } - break; - case 3: - /* case where we've seen the beginning of match rule and want to find the end */ - if (isspace(c)) { - matchrule_size = (pos - matchrule_source) - 1; - state = 4; - } - break; - default: - break; - } - } - - if (3 == state) { - /* means we fell off the end of the string looking for the end of the marching rule */ - matchrule_size = (pos - matchrule_source) - 1; - } - - if (1 == state) { - /* means we fell of the end of the string looking for the end of the attribute */ - attrdesc_size = (pos - attrdesc_source) - 1; - } - - if (NULL == attrdesc_source) { - /* Didn't find anything */ - return -1; - } - - new_key = (LDAPsortkey*)NSLDAPI_MALLOC(sizeof(LDAPsortkey)); - if (0 == new_key) { - return LDAP_NO_MEMORY; - } - - /* Allocate the strings */ - new_key->sk_attrtype = (char *)NSLDAPI_MALLOC(attrdesc_size + 1); - if (NULL != matchrule_source) { - new_key->sk_matchruleoid = (char *)NSLDAPI_MALLOC( - matchrule_size + 1); - } else { - new_key->sk_matchruleoid = NULL; - } - /* Copy over the strings */ - memcpy(new_key->sk_attrtype,attrdesc_source,attrdesc_size); - *(new_key->sk_attrtype + attrdesc_size) = '\0'; - if (NULL != matchrule_source) { - memcpy(new_key->sk_matchruleoid,matchrule_source,matchrule_size); - *(new_key->sk_matchruleoid + matchrule_size) = '\0'; - } - - new_key->sk_reverseorder = reverse; - - *s = pos - 1; - *key = new_key; - return retval; -} - -int -LDAP_CALL -ldap_create_sort_keylist ( - LDAPsortkey ***sortKeyList, - const char *string_rep -) -{ - int count = 0; - LDAPsortkey **pointer_array = NULL; - const char *current_position = NULL; - int retval = 0; - int i = 0; - - /* Figure out how many there are */ - if (NULL == string_rep) { - return LDAP_PARAM_ERROR; - } - if (NULL == sortKeyList) { - return LDAP_PARAM_ERROR; - } - count = count_tokens(string_rep); - if (0 == count) { - *sortKeyList = NULL; - return LDAP_PARAM_ERROR; - } - /* Allocate enough memory for the pointers */ - pointer_array = (LDAPsortkey**)NSLDAPI_MALLOC(sizeof(LDAPsortkey*) - * (count + 1) ); - if (NULL == pointer_array) { - return LDAP_NO_MEMORY; - } - /* Now walk along the string, allocating and filling in the LDAPsearchkey structure */ - current_position = string_rep; - - for (i = 0; i < count; i++) { - if (0 != (retval = read_next_token(¤t_position,&(pointer_array[i])))) { - pointer_array[count] = NULL; - ldap_free_sort_keylist(pointer_array); - *sortKeyList = NULL; - return retval; - } - } - pointer_array[count] = NULL; - *sortKeyList = pointer_array; - return LDAP_SUCCESS; -} - -void -LDAP_CALL -ldap_free_sort_keylist ( - LDAPsortkey **sortKeyList -) -{ - LDAPsortkey *this_one = NULL; - int i = 0; - - if ( NULL == sortKeyList ) { - return; - } - - /* Walk down the list freeing the LDAPsortkey structures */ - for (this_one = sortKeyList[0]; this_one ; this_one = sortKeyList[++i]) { - /* Free the strings, if present */ - if (NULL != this_one->sk_attrtype) { - NSLDAPI_FREE(this_one->sk_attrtype); - } - if (NULL != this_one->sk_matchruleoid) { - NSLDAPI_FREE(this_one->sk_matchruleoid); - } - NSLDAPI_FREE(this_one); - } - /* Free the pointer list */ - NSLDAPI_FREE(sortKeyList); -} diff --git a/ldap/c-sdk/libraries/libldap/srchpref.c b/ldap/c-sdk/libraries/libldap/srchpref.c deleted file mode 100644 index a3025afd39..0000000000 --- a/ldap/c-sdk/libraries/libldap/srchpref.c +++ /dev/null @@ -1,434 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1993, 1994 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. - * - */ -/* - * searchpref.c: search preferences library routines for LDAP clients - */ - -#include "ldap-int.h" -#include "srchpref.h" - -static void free_searchobj( struct ldap_searchobj *so ); -static int read_next_searchobj( char **bufp, long *blenp, - struct ldap_searchobj **sop, int soversion ); - - -static char *sobjoptions[] = { - "internal", - NULL -}; - - -static unsigned long sobjoptvals[] = { - LDAP_SEARCHOBJ_OPT_INTERNAL, -}; - - -int -LDAP_CALL -ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp ) -{ - FILE *fp; - char *buf; - long rlen, len; - int rc, eof; - - if (( fp = NSLDAPI_FOPEN( file, "r" )) == NULL ) { - return( LDAP_SEARCHPREF_ERR_FILE ); - } - - if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ - fclose( fp ); - return( LDAP_SEARCHPREF_ERR_FILE ); - } - - len = ftell( fp ); - - if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ - fclose( fp ); - return( LDAP_SEARCHPREF_ERR_FILE ); - } - - if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { - fclose( fp ); - return( LDAP_SEARCHPREF_ERR_MEM ); - } - - rlen = fread( buf, 1, (size_t)len, fp ); - eof = feof( fp ); - fclose( fp ); - - if ( rlen != len && !eof ) { /* error: didn't get the whole file */ - NSLDAPI_FREE( buf ); - return( LDAP_SEARCHPREF_ERR_FILE ); - } - - rc = ldap_init_searchprefs_buf( buf, rlen, solistp ); - NSLDAPI_FREE( buf ); - - return( rc ); -} - - -int -LDAP_CALL -ldap_init_searchprefs_buf( char *buf, long buflen, - struct ldap_searchobj **solistp ) -{ - int rc = 0, version; - char **toks; - struct ldap_searchobj *prevso, *so; - - *solistp = prevso = NULLSEARCHOBJ; - - if ( nsldapi_next_line_tokens( &buf, &buflen, &toks ) != 2 || - strcasecmp( toks[ 0 ], "version" ) != 0 ) { - nsldapi_free_strarray( toks ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - version = atoi( toks[ 1 ] ); - nsldapi_free_strarray( toks ); - if ( version != LDAP_SEARCHPREF_VERSION && - version != LDAP_SEARCHPREF_VERSION_ZERO ) { - return( LDAP_SEARCHPREF_ERR_VERSION ); - } - - while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so, - version )) == 0 && so != NULLSEARCHOBJ ) { - if ( prevso == NULLSEARCHOBJ ) { - *solistp = so; - } else { - prevso->so_next = so; - } - prevso = so; - } - - if ( rc != 0 ) { - ldap_free_searchprefs( *solistp ); - } - - return( rc ); -} - - - -void -LDAP_CALL -ldap_free_searchprefs( struct ldap_searchobj *solist ) -{ - struct ldap_searchobj *so, *nextso; - - if ( solist != NULL ) { - for ( so = solist; so != NULL; so = nextso ) { - nextso = so->so_next; - free_searchobj( so ); - } - } - /* XXX XXX need to do some work here */ -} - - -static void -free_searchobj( struct ldap_searchobj *so ) -{ - if ( so != NULL ) { - if ( so->so_objtypeprompt != NULL ) { - NSLDAPI_FREE( so->so_objtypeprompt ); - } - if ( so->so_prompt != NULL ) { - NSLDAPI_FREE( so->so_prompt ); - } - if ( so->so_filterprefix != NULL ) { - NSLDAPI_FREE( so->so_filterprefix ); - } - if ( so->so_filtertag != NULL ) { - NSLDAPI_FREE( so->so_filtertag ); - } - if ( so->so_defaultselectattr != NULL ) { - NSLDAPI_FREE( so->so_defaultselectattr ); - } - if ( so->so_defaultselecttext != NULL ) { - NSLDAPI_FREE( so->so_defaultselecttext ); - } - if ( so->so_salist != NULL ) { - struct ldap_searchattr *sa, *nextsa; - for ( sa = so->so_salist; sa != NULL; sa = nextsa ) { - nextsa = sa->sa_next; - if ( sa->sa_attrlabel != NULL ) { - NSLDAPI_FREE( sa->sa_attrlabel ); - } - if ( sa->sa_attr != NULL ) { - NSLDAPI_FREE( sa->sa_attr ); - } - if ( sa->sa_selectattr != NULL ) { - NSLDAPI_FREE( sa->sa_selectattr ); - } - if ( sa->sa_selecttext != NULL ) { - NSLDAPI_FREE( sa->sa_selecttext ); - } - NSLDAPI_FREE( sa ); - } - } - if ( so->so_smlist != NULL ) { - struct ldap_searchmatch *sm, *nextsm; - for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) { - nextsm = sm->sm_next; - if ( sm->sm_matchprompt != NULL ) { - NSLDAPI_FREE( sm->sm_matchprompt ); - } - if ( sm->sm_filter != NULL ) { - NSLDAPI_FREE( sm->sm_filter ); - } - NSLDAPI_FREE( sm ); - } - } - NSLDAPI_FREE( so ); - } -} - - - -struct ldap_searchobj * -LDAP_CALL -ldap_first_searchobj( struct ldap_searchobj *solist ) -{ - return( solist ); -} - - -struct ldap_searchobj * -LDAP_CALL -ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so ) -{ - return( so == NULLSEARCHOBJ ? so : so->so_next ); -} - - - -static int -read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop, - int soversion ) -{ - int i, j, tokcnt; - char **toks; - struct ldap_searchobj *so; - struct ldap_searchattr **sa; - struct ldap_searchmatch **sm; - - *sop = NULL; - - /* - * Object type prompt comes first - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX ); - } - - if (( so = (struct ldap_searchobj *)NSLDAPI_CALLOC( 1, - sizeof( struct ldap_searchobj ))) == NULL ) { - nsldapi_free_strarray( toks ); - return( LDAP_SEARCHPREF_ERR_MEM ); - } - so->so_objtypeprompt = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * if this is post-version zero, options come next - */ - if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) { - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) < 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - for ( i = 0; toks[ i ] != NULL; ++i ) { - for ( j = 0; sobjoptions[ j ] != NULL; ++j ) { - if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) { - so->so_options |= sobjoptvals[ j ]; - } - } - } - nsldapi_free_strarray( toks ); - } - - /* - * "Fewer choices" prompt is next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - so->so_prompt = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * Filter prefix for "More Choices" searching is next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - so->so_filterprefix = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * "Fewer Choices" filter tag comes next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - so->so_filtertag = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * Selection (disambiguation) attribute comes next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - so->so_defaultselectattr = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * Label for selection (disambiguation) attribute - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - so->so_defaultselecttext = toks[ 0 ]; - NSLDAPI_FREE( (char *)toks ); - - /* - * Search scope is next - */ - if (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) != 1 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - if ( !strcasecmp(toks[ 0 ], "subtree" )) { - so->so_defaultscope = LDAP_SCOPE_SUBTREE; - } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) { - so->so_defaultscope = LDAP_SCOPE_ONELEVEL; - } else if ( !strcasecmp(toks[ 0 ], "base" )) { - so->so_defaultscope = LDAP_SCOPE_BASE; - } else { - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - nsldapi_free_strarray( toks ); - - - /* - * "More Choices" search option list comes next - */ - sa = &( so->so_salist ); - while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { - if ( tokcnt < 5 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - if (( *sa = ( struct ldap_searchattr * )NSLDAPI_CALLOC( 1, - sizeof( struct ldap_searchattr ))) == NULL ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_MEM ); - } - ( *sa )->sa_attrlabel = toks[ 0 ]; - ( *sa )->sa_attr = toks[ 1 ]; - ( *sa )->sa_selectattr = toks[ 3 ]; - ( *sa )->sa_selecttext = toks[ 4 ]; - /* Deal with bitmap */ - ( *sa )->sa_matchtypebitmap = 0; - for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) { - if ( toks[ 2 ][ i ] == '1' ) { - ( *sa )->sa_matchtypebitmap |= (1 << j); - } - } - NSLDAPI_FREE( toks[ 2 ] ); - NSLDAPI_FREE( ( char * ) toks ); - sa = &(( *sa )->sa_next); - } - *sa = NULL; - - /* - * Match types are last - */ - sm = &( so->so_smlist ); - while (( tokcnt = nsldapi_next_line_tokens( bufp, blenp, &toks )) > 0 ) { - if ( tokcnt < 2 ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_SYNTAX ); - } - if (( *sm = ( struct ldap_searchmatch * )NSLDAPI_CALLOC( 1, - sizeof( struct ldap_searchmatch ))) == NULL ) { - nsldapi_free_strarray( toks ); - ldap_free_searchprefs( so ); - return( LDAP_SEARCHPREF_ERR_MEM ); - } - ( *sm )->sm_matchprompt = toks[ 0 ]; - ( *sm )->sm_filter = toks[ 1 ]; - NSLDAPI_FREE( ( char * ) toks ); - sm = &(( *sm )->sm_next ); - } - *sm = NULL; - - *sop = so; - return( 0 ); -} diff --git a/ldap/c-sdk/libraries/libldap/test.c b/ldap/c-sdk/libraries/libldap/test.c deleted file mode 100644 index fa984f3430..0000000000 --- a/ldap/c-sdk/libraries/libldap/test.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* test.c - a simple test harness. */ -#include -#include -#include -#include -#ifdef MACOS -#ifdef THINK_C -#include -#include -#include -#endif /* THINK_C */ -#include "macos.h" -#else /* MACOS */ -#if defined( DOS ) -#include "msdos.h" -#if defined( WINSOCK ) -#include "console.h" -#endif /* WINSOCK */ -#else /* DOS */ -#ifdef _WINDOWS -#include -#include -#include -#include -//#include "console.h" -#else /* _WINDOWS */ -#include -#include -#include -#include -#include -#ifndef VMS -#include -#include -#endif /* VMS */ -#endif /* _WINDOWS */ -#endif /* DOS */ -#endif /* MACOS */ - -#include "ldap.h" -#include "disptmpl.h" -#include "ldaplog.h" -#include "portable.h" -#ifndef NO_LIBLCACHE -#include "lcache.h" -#endif /* !NO_LIBLCACHE */ - -#undef NET_SSL -#if defined(NET_SSL) -#include -#include -#endif - - -#if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS ) -#define MOD_USE_BVALS -#endif /* !PCNFS && !WINSOCK && !MACOS */ - -static void handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ); -static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ); -static void print_controls( LDAPControl **ctrls, int freeit ); -static void print_referrals( char **refs, int freeit ); -static void print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ); -static char *changetype_num2string( ber_int_t chgtype ); -static void print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ); -static void free_list( char **list ); -static int entry2textwrite( void *fp, char *buf, int len ); -static void bprint( char *data, int len ); -static char **string2words( char *str, char *delims ); -static const char * url_parse_err2string( int e ); - -char *dnsuffix; - -#ifndef WINSOCK -static char * -getline( char *line, int len, FILE *fp, char *prompt ) -{ - printf(prompt); - - if ( fgets( line, len, fp ) == NULL ) - return( NULL ); - - line[ strlen( line ) - 1 ] = '\0'; - - return( line ); -} -#endif /* WINSOCK */ - -static char ** -get_list( char *prompt ) -{ - static char buf[256]; - int num; - char **result; - - num = 0; - result = (char **) 0; - while ( 1 ) { - getline( buf, sizeof(buf), stdin, prompt ); - - if ( *buf == '\0' ) - break; - - if ( result == (char **) 0 ) - result = (char **) malloc( sizeof(char *) ); - else - result = (char **) realloc( result, - sizeof(char *) * (num + 1) ); - - result[num++] = (char *) strdup( buf ); - } - if ( result == (char **) 0 ) - return( NULL ); - result = (char **) realloc( result, sizeof(char *) * (num + 1) ); - result[num] = NULL; - - return( result ); -} - - -static void -free_list( char **list ) -{ - int i; - - if ( list != NULL ) { - for ( i = 0; list[ i ] != NULL; ++i ) { - free( list[ i ] ); - } - free( (char *)list ); - } -} - - -#ifdef MOD_USE_BVALS -static int -file_read( char *path, struct berval *bv ) -{ - FILE *fp; - long rlen; - int eof; - - if (( fp = NSLDAPI_FOPEN( path, "r" )) == NULL ) { - perror( path ); - return( -1 ); - } - - if ( fseek( fp, 0L, SEEK_END ) != 0 ) { - perror( path ); - fclose( fp ); - return( -1 ); - } - - bv->bv_len = ftell( fp ); - - if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) { - perror( "malloc" ); - fclose( fp ); - return( -1 ); - } - - if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { - perror( path ); - fclose( fp ); - return( -1 ); - } - - rlen = fread( bv->bv_val, 1, bv->bv_len, fp ); - eof = feof( fp ); - fclose( fp ); - - if ( (unsigned long)rlen != bv->bv_len ) { - perror( path ); - free( bv->bv_val ); - return( -1 ); - } - - return( bv->bv_len ); -} -#endif /* MOD_USE_BVALS */ - - -static LDAPMod ** -get_modlist( char *prompt1, char *prompt2, char *prompt3 ) -{ - static char buf[256]; - int num; - LDAPMod tmp; - LDAPMod **result; -#ifdef MOD_USE_BVALS - struct berval **bvals; -#endif /* MOD_USE_BVALS */ - - num = 0; - result = NULL; - while ( 1 ) { - if ( prompt1 ) { - getline( buf, sizeof(buf), stdin, prompt1 ); - tmp.mod_op = atoi( buf ); - - if ( tmp.mod_op == -1 || buf[0] == '\0' ) - break; - } else { - tmp.mod_op = 0; - } - - getline( buf, sizeof(buf), stdin, prompt2 ); - if ( buf[0] == '\0' ) - break; - tmp.mod_type = strdup( buf ); - - tmp.mod_values = get_list( prompt3 ); -#ifdef MOD_USE_BVALS - if ( tmp.mod_values != NULL ) { - int i; - - for ( i = 0; tmp.mod_values[i] != NULL; ++i ) - ; - bvals = (struct berval **)calloc( i + 1, - sizeof( struct berval *)); - for ( i = 0; tmp.mod_values[i] != NULL; ++i ) { - bvals[i] = (struct berval *)malloc( - sizeof( struct berval )); - if ( strncmp( tmp.mod_values[i], "{FILE}", - 6 ) == 0 ) { - if ( file_read( tmp.mod_values[i] + 6, - bvals[i] ) < 0 ) { - return( NULL ); - } - } else { - bvals[i]->bv_val = tmp.mod_values[i]; - bvals[i]->bv_len = - strlen( tmp.mod_values[i] ); - } - } - tmp.mod_bvalues = bvals; - tmp.mod_op |= LDAP_MOD_BVALUES; - } -#endif /* MOD_USE_BVALS */ - - if ( result == NULL ) - result = (LDAPMod **) malloc( sizeof(LDAPMod *) ); - else - result = (LDAPMod **) realloc( result, - sizeof(LDAPMod *) * (num + 1) ); - - result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) ); - *(result[num]) = tmp; /* struct copy */ - num++; - } - if ( result == NULL ) - return( NULL ); - result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); - result[num] = NULL; - - return( result ); -} - - -int LDAP_CALL LDAP_CALLBACK -bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp, - int freeit, void *dummy ) -{ - static char dn[256], passwd[256]; - - if ( !freeit ) { -#ifdef KERBEROS - 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; - } else { - *authmethodp |= 0x80; - } -#else /* KERBEROS */ - *authmethodp = LDAP_AUTH_SIMPLE; -#endif /* KERBEROS */ - - getline( dn, sizeof(dn), stdin, "re-bind dn? " ); - strcat( dn, dnsuffix ); - *dnp = dn; - - if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { - getline( passwd, sizeof(passwd), stdin, - "re-bind password? " ); - } else { - passwd[0] = '\0'; - } - *passwdp = passwd; - } - - return( LDAP_SUCCESS ); -} - - -#define HEX2BIN( h ) ( (h) >= '0' && (h) <='9' ? (h) - '0' : (h) - 'A' + 10 ) - -void -berval_from_hex( struct berval *bvp, char *hexstr ) -{ - char *src, *dst, c; - unsigned char abyte; - - dst = bvp->bv_val; - bvp->bv_len = 0; - src = hexstr; - while ( *src != '\0' ) { - c = *src; - if ( isupper( c )) { - c = tolower( c ); - } - abyte = HEX2BIN( c ) << 4; - - ++src; - c = *src; - if ( isupper( c )) { - c = tolower( c ); - } - abyte |= HEX2BIN( c ); - ++src; - - *dst++ = abyte; - ++bvp->bv_len; - } -} - - -static void -add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl ) -{ - int i; - - if ( *ctrlsp == NULL ) { - *ctrlsp = (LDAPControl **) calloc( 2, sizeof(LDAPControl *) ); - i = 0; - } else { - for ( i = 0; (*ctrlsp)[i] != NULL; i++ ) { - ; /* NULL */ - } - *ctrlsp = (LDAPControl **) realloc( *ctrlsp, - (i + 2) * sizeof(LDAPControl *) ); - } - (*ctrlsp)[i] = newctrl; - (*ctrlsp)[i+1] = NULL; -} - - -#ifdef TEST_CUSTOM_MALLOC - -typedef struct my_malloc_info { - long mmi_magic; - size_t mmi_actualsize; -} MyMallocInfo; -#define MY_MALLOC_MAGIC_NUMBER 0x19940618 - -#define MY_MALLOC_CHECK_MAGIC( p ) if ( ((MyMallocInfo *)( (p) - sizeof() - -void * -my_malloc( size_t size ) -{ - void *p; - MyMallocInfo *mmip; - - if (( p = malloc( size + sizeof( struct my_malloc_info ))) != NULL ) { - mmip = (MyMallocInfo *)p; - mmip->mmi_magic = MY_MALLOC_MAGIC_NUMBER; - mmip->mmi_actualsize = size; - } - - fprintf( stderr, "my_malloc: allocated ptr 0x%x, size %ld\n", - p, mmip->mmi_actualsize ); - - return( (char *)p + sizeof( MyMallocInfo )); -} - - -void * -my_calloc( size_t nelem, size_t elsize ) -{ - void *p; - - if (( p = my_malloc( nelem * elsize )) != NULL ) { - memset( p, 0, nelem * elsize ); - } - - return( p ); -} - - -void -my_free( void *ptr ) -{ - char *p; - MyMallocInfo *mmip; - - p = (char *)ptr; - p -= sizeof( MyMallocInfo ); - mmip = (MyMallocInfo *)p; - if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { - fprintf( stderr, - "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); - exit( 1 ); - } - - fprintf( stderr, "my_free: freeing ptr 0x%x, size %ld\n", - p, mmip->mmi_actualsize ); - - memset( p, 0, mmip->mmi_actualsize + sizeof( MyMallocInfo )); - free( p ); -} - - -void * -my_realloc( void *ptr, size_t size ) -{ - void *p; - MyMallocInfo *mmip; - - if ( ptr == NULL ) { - return( my_malloc( size )); - } - - mmip = (MyMallocInfo *)( (char *)ptr - sizeof( MyMallocInfo )); - if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { - fprintf( stderr, - "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); - exit( 1 ); - } - - if ( size <= mmip->mmi_actualsize ) { /* current block big enough? */ - return( ptr ); - } - - if (( p = my_malloc( size )) != NULL ) { - memcpy( p, ptr, mmip->mmi_actualsize ); - my_free( ptr ); - } - - return( p ); -} -#endif /* TEST_CUSTOM_MALLOC */ - -int -#ifdef WINSOCK -ldapmain( -#else /* WINSOCK */ -main( -#endif /* WINSOCK */ - int argc, char **argv ) -{ - LDAP *ld; - int rc, i, c, port, cldapflg, errflg, method, id, msgtype; - int version; - char line[256], command1, command2, command3; - char passwd[64], dn[256], rdn[64], attr[64], value[256]; - char filter[256], *host, **types; - char **exdn, *fnname; - int bound, all, scope, attrsonly, optval, ldapversion; - LDAPMessage *res; - LDAPMod **mods, **attrs; - struct timeval timeout, *tvp; - char *copyfname = NULL; - int copyoptions = 0; - LDAPURLDesc *ludp; - struct ldap_disptmpl *tmpllist = NULL; - int changetypes, changesonly, return_echg_ctls; - LDAPControl **tmpctrls, *newctrl, **controls = NULL; - char *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file] [-V protocolversion]\n"; - - extern char *optarg; - extern int optind; - -#ifdef MACOS - if (( argv = get_list( "cmd line arg?" )) == NULL ) { - exit( 1 ); - } - for ( argc = 0; argv[ argc ] != NULL; ++argc ) { - ; - } -#endif /* MACOS */ - -#ifdef TEST_CUSTOM_MALLOC - { - struct ldap_memalloc_fns memalloc_fns; - - memalloc_fns.ldapmem_malloc = my_malloc; - memalloc_fns.ldapmem_calloc = my_calloc; - memalloc_fns.ldapmem_realloc = my_realloc; - memalloc_fns.ldapmem_free = my_free; - - if ( ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, - &memalloc_fns ) != 0 ) { - fputs( "ldap_set_option failed\n", stderr ); - exit( 1 ); - } - } -#endif /* TEST_CUSTOM_MALLOC */ - - host = NULL; - port = LDAP_PORT; - dnsuffix = ""; - cldapflg = errflg = 0; - ldapversion = 0; /* use default */ -#ifndef _WIN32 -#ifdef LDAP_DEBUG - ldap_debug = LDAP_DEBUG_ANY; -#endif -#endif - - while (( c = getopt( argc, argv, "uh:d:s:p:t:T:V:" )) != -1 ) { - switch( c ) { - case 'u': -#ifdef CLDAP - cldapflg++; -#else /* CLDAP */ - printf( "Compile with -DCLDAP for UDP support\n" ); -#endif /* CLDAP */ - break; - - case 'd': -#ifndef _WIN32 -#ifdef LDAP_DEBUG - ldap_debug = atoi( optarg ) | LDAP_DEBUG_ANY; - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { - ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, - &ldap_debug ); - } -#else - printf( "Compile with -DLDAP_DEBUG for debugging\n" ); -#endif -#endif - break; - - case 'h': - host = optarg; - break; - - case 's': - dnsuffix = optarg; - break; - - case 'p': - port = atoi( optarg ); - break; - -#if !defined(MACOS) && !defined(DOS) - case 't': /* copy ber's to given file */ - copyfname = strdup( optarg ); - copyoptions = LBER_SOCKBUF_OPT_TO_FILE; - break; - - case 'T': /* only output ber's to given file */ - copyfname = strdup( optarg ); - copyoptions = (LBER_SOCKBUF_OPT_TO_FILE | - LBER_SOCKBUF_OPT_TO_FILE_ONLY); - break; -#endif - case 'V': /* LDAP protocol version */ - ldapversion = atoi( optarg ); - break; - - default: - ++errflg; - } - } - - if ( host == NULL && optind == argc - 1 ) { - host = argv[ optind ]; - ++optind; - } - - if ( errflg || optind < argc - 1 ) { - fprintf( stderr, usage, argv[ 0 ] ); - exit( 1 ); - } - - printf( "%sldap_init( %s, %d )\n", cldapflg ? "c" : "", - host == NULL ? "(null)" : host, port ); - - if ( cldapflg ) { -#ifdef CLDAP - ld = cldap_open( host, port ); -#endif /* CLDAP */ - } else { - ld = ldap_init( host, port ); - } - - if ( ld == NULL ) { - perror( "ldap_init" ); - exit(1); - } - - if ( ldapversion != 0 && ldap_set_option( ld, - LDAP_OPT_PROTOCOL_VERSION, (void *)&ldapversion ) != 0 ) { - ldap_perror( ld, "ldap_set_option (protocol version)" ); - exit(1); - } - -#ifdef notdef -#if !defined(MACOS) && !defined(DOS) - if ( copyfname != NULL ) { - int fd; - Sockbuf *sb; - - if ( (fd = open( copyfname, O_WRONLY | O_CREAT, 0600 )) - == -1 ) { - perror( copyfname ); - exit ( 1 ); - } - ldap_get_option( ld, LDAP_OPT_SOCKBUF, &sb ); - ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_COPYDESC, - (void *) &fd ); - ber_sockbuf_set_option( sb, copyoptions, LBER_OPT_ON ); - } -#endif -#endif - - bound = 0; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - tvp = &timeout; - - (void) memset( line, '\0', sizeof(line) ); - while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) { - command1 = line[0]; - command2 = line[1]; - command3 = line[2]; - - switch ( command1 ) { - case 'a': /* add or abandon */ - switch ( command2 ) { - case 'd': /* add */ - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - if ( (attrs = get_modlist( NULL, "attr? ", - "value? " )) == NULL ) - break; - if ( (id = ldap_add( ld, dn, attrs )) == -1 ) - ldap_perror( ld, "ldap_add" ); - else - printf( "Add initiated with id %d\n", - id ); - break; - - case 'b': /* abandon */ - getline( line, sizeof(line), stdin, "msgid? " ); - id = atoi( line ); - if ( ldap_abandon( ld, id ) != 0 ) - ldap_perror( ld, "ldap_abandon" ); - else - printf( "Abandon successful\n" ); - break; - default: - printf( "Possibilities: [ad]d, [ab]ort\n" ); - } - break; - - case 'v': /* ldap protocol version */ - getline( line, sizeof(line), stdin, - "ldap version? " ); - version = atoi( line ); - if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, - (void *) &version ) != 0 ) { - ldap_perror( ld, "ldap_set_option" ); - } - break; - - case 'b': /* asynch bind */ - getline( line, sizeof(line), stdin, - "method 0->simple 3->sasl? " ); - method = atoi( line ); - if ( method == 0 ) { - method = LDAP_AUTH_SIMPLE; - } else if ( method == 3 ) { - method = LDAP_AUTH_SASL; - } - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - - if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { - } else { - passwd[0] = '\0'; - } - - if ( method == LDAP_AUTH_SIMPLE ) { - if ( dn[0] != '\0' ) { - getline( passwd, sizeof(passwd), stdin, - "password? " ); - } else { - passwd[0] = '\0'; - } - rc = ldap_simple_bind( ld, dn, passwd ); - } else { - struct berval cred; - char mechanism[BUFSIZ]; - - getline( mechanism, sizeof(mechanism), stdin, - "mechanism? " ); - getline( passwd, sizeof(passwd), stdin, - "credentials? " ); - cred.bv_val = passwd; - cred.bv_len = strlen( passwd ); - if ( ldap_sasl_bind( ld, dn, mechanism, &cred, - NULL, NULL, &rc ) != LDAP_SUCCESS ) { - rc = -1; - } - } - if ( rc == -1 ) { - fprintf( stderr, "ldap_bind failed\n" ); - ldap_perror( ld, "ldap_bind" ); - } else { - printf( "Bind initiated\n" ); - bound = 1; - } - break; - - case 'B': /* synch bind */ - getline( line, sizeof(line), stdin, - "method 0->simple 3->sasl? " ); - method = atoi( line ); - if ( method == 0 ) { - method = LDAP_AUTH_SIMPLE; - } else if ( method == 3 ) { - method = LDAP_AUTH_SASL; - } - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - - if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { - } else { - passwd[0] = '\0'; - } - - if ( method == LDAP_AUTH_SIMPLE ) { - if ( dn[0] != '\0' ) { - getline( passwd, sizeof(passwd), stdin, - "password? " ); - } else { - passwd[0] = '\0'; - } - rc = ldap_simple_bind_s( ld, dn, passwd ); - fnname = "ldap_simple_bind_s"; - } else { - struct berval cred; - char mechanism[BUFSIZ]; - - getline( mechanism, sizeof(mechanism), stdin, - "mechanism? " ); - getline( passwd, sizeof(passwd), stdin, - "credentials? " ); - cred.bv_val = passwd; - cred.bv_len = strlen( passwd ); - rc = ldap_sasl_bind_s( ld, dn, mechanism, - &cred, NULL, NULL, NULL ); - fnname = "ldap_sasl_bind_s"; - } - if ( rc != LDAP_SUCCESS ) { - fprintf( stderr, "%s failed\n", fnname ); - ldap_perror( ld, fnname ); - } else { - printf( "Bind successful\n" ); - bound = 1; - } - break; - - case 'c': /* compare */ - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - getline( attr, sizeof(attr), stdin, "attr? " ); - getline( value, sizeof(value), stdin, "value? " ); - - if ( (id = ldap_compare( ld, dn, attr, value )) == -1 ) - ldap_perror( ld, "ldap_compare" ); - else - printf( "Compare initiated with id %d\n", id ); - break; - - case 'x': /* extended operation */ - { - char oid[100]; - struct berval val; - - getline( oid, sizeof(oid), stdin, "oid? " ); - getline( value, sizeof(value), stdin, "value? " ); - if ( strncmp( value, "0x", 2 ) == 0 ) { - val.bv_val = (char *)malloc( strlen( value ) / 2 ); - berval_from_hex( &val, value + 2 ); - } else { - val.bv_val = strdup( value ); - val.bv_len = strlen( value ); - } - if ( ldap_extended_operation( ld, oid, &val, NULL, - NULL, &id ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_extended_operation" ); - } else { - printf( "Extended op initiated with id %d\n", - id ); - } - free( val.bv_val ); - } - break; - - case 'C': /* set cache parameters */ -#ifdef NO_LIBLCACHE - getline( line, sizeof(line), stdin, - "cache init (memcache 0)? " ); -#else - getline( line, sizeof(line), stdin, - "cache init (memcache 0, lcache 1)? " ); -#endif - i = atoi( line ); - if ( i == 0 ) { /* memcache */ - unsigned long ttl, size; - char **basedns, *dnarray[2]; - LDAPMemCache *mc; - - getline( line, sizeof(line), stdin, - "memcache ttl? " ); - ttl = atoi( line ); - getline( line, sizeof(line), stdin, - "memcache size? " ); - size = atoi( line ); - getline( line, sizeof(line), stdin, - "memcache baseDN? " ); - if ( *line == '\0' ) { - basedns = NULL; - } else { - dnarray[0] = line; - dnarray[1] = NULL; - basedns = dnarray; - } - if (( rc = ldap_memcache_init( ttl, size, - basedns, NULL, &mc )) != LDAP_SUCCESS ) { - fprintf( stderr, - "ldap_memcache_init: %s\n", - ldap_err2string( rc )); - } else if (( rc = ldap_memcache_set( ld, mc )) - != LDAP_SUCCESS ) { - fprintf( stderr, - "ldap_memcache_set: %s\n", - ldap_err2string( rc )); - } - -#ifndef NO_LIBLCACHE - } else if ( i == 1 ) { - getline( line, sizeof(line), stdin, - "cache config file? " ); - if ( line[0] != '\0' ) { - if ( lcache_init( ld, line ) != 0 ) { - perror( "ldap_cache_init" ); - break; - } - } - getline( line, sizeof(line), stdin, - "cache on/off (on 1, off 0)? " ); - if ( line[0] != '\0' ) { - i = atoi( line ); - if ( ldap_set_option( ld, - LDAP_OPT_CACHE_ENABLE, &i ) != 0 ) { - ldap_perror( ld, "ldap_cache_enable" ); - break; - } - } - getline( line, sizeof(line), stdin, - "cache strategy (check 0, populate 1, localdb 2)? " ); - if ( line[0] != '\0' ) { - i = atoi( line ); - if ( ldap_set_option( ld, - LDAP_OPT_CACHE_STRATEGY, &i ) - != 0 ) { - ldap_perror(ld, "ldap_cache_strategy"); - break; - } - } -#endif /* !NO_LIBLCACHE */ - - } else { - fprintf( stderr, "unknown cachetype %d\n", i ); - } - break; - - case 'd': /* turn on debugging */ -#ifndef _WIN32 -#ifdef LDAP_DEBUG - getline( line, sizeof(line), stdin, "debug level? " ); - ldap_debug = atoi( line ) | LDAP_DEBUG_ANY; - if ( ldap_debug & LDAP_DEBUG_PACKETS ) { - ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, - &ldap_debug ); - } -#else - printf( "Compile with -DLDAP_DEBUG for debugging\n" ); -#endif -#endif - break; - - case 'E': /* explode a dn */ - getline( line, sizeof(line), stdin, "dn? " ); - exdn = ldap_explode_dn( line, 0 ); - for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { - printf( "\t\"%s\"\n", exdn[i] ); - } - break; - - case 'R': /* explode an rdn */ - getline( line, sizeof(line), stdin, "rdn? " ); - exdn = ldap_explode_rdn( line, 0 ); - for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { - printf( "\t\"%s\"\n", exdn[i] ); - } - break; - - case 'm': /* modify or modifyrdn */ - if ( strncmp( line, "modify", 4 ) == 0 ) { - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - if ( (mods = get_modlist( - "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ", - "attribute type? ", "attribute value? " )) - == NULL ) - break; - if ( (id = ldap_modify( ld, dn, mods )) == -1 ) - ldap_perror( ld, "ldap_modify" ); - else - printf( "Modify initiated with id %d\n", - id ); - } else if ( strncmp( line, "modrdn", 4 ) == 0 ) { - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - getline( rdn, sizeof(rdn), stdin, "newrdn? " ); - getline( line, sizeof(line), stdin, - "deleteoldrdn? " ); - if ( (id = ldap_modrdn2( ld, dn, rdn, - atoi(line) )) == -1 ) - ldap_perror( ld, "ldap_modrdn" ); - else - printf( "Modrdn initiated with id %d\n", - id ); - } else { - printf( "Possibilities: [modi]fy, [modr]dn\n" ); - } - break; - - case 'q': /* quit */ -#ifdef CLDAP - if ( cldapflg ) - cldap_close( ld ); -#endif /* CLDAP */ - if ( !cldapflg ) - ldap_unbind( ld ); - exit( 0 ); - break; - - case 'r': /* result or remove */ - switch ( command3 ) { - case 's': /* result */ - getline( line, sizeof(line), stdin, - "msgid (-1=>any)? " ); - if ( line[0] == '\0' ) - id = -1; - else - id = atoi( line ); - getline( line, sizeof(line), stdin, - "all (0=>any, 1=>all)? " ); - if ( line[0] == '\0' ) - all = 1; - else - all = atoi( line ); - if (( msgtype = ldap_result( ld, id, all, - tvp, &res )) < 1 ) { - ldap_perror( ld, "ldap_result" ); - break; - } - printf( "\nresult: msgtype %d msgid %d\n", - msgtype, ldap_msgid( res ) ); - handle_result( ld, res, 0 ); - res = NULL; - break; - - case 'm': /* remove */ - getline( dn, sizeof(dn), stdin, "dn? " ); - strcat( dn, dnsuffix ); - if ( (id = ldap_delete( ld, dn )) == -1 ) - ldap_perror( ld, "ldap_delete" ); - else - printf( "Remove initiated with id %d\n", - id ); - break; - - default: - printf( "Possibilities: [rem]ove, [res]ult\n" ); - break; - } - break; - - case 's': /* search */ - getline( dn, sizeof(dn), stdin, "searchbase? " ); - strcat( dn, dnsuffix ); - getline( line, sizeof(line), stdin, - "scope (0=Base, 1=One Level, 2=Subtree)? " ); - scope = atoi( line ); - getline( filter, sizeof(filter), stdin, - "search filter (e.g. sn=jones)? " ); - types = get_list( "attrs to return? " ); - getline( line, sizeof(line), stdin, - "attrsonly (0=attrs&values, 1=attrs only)? " ); - attrsonly = atoi( line ); - - if ( cldapflg ) { -#ifdef CLDAP - getline( line, sizeof(line), stdin, - "Requestor DN (for logging)? " ); - if ( cldap_search_s( ld, dn, scope, filter, types, - attrsonly, &res, line ) != 0 ) { - ldap_perror( ld, "cldap_search_s" ); - } else { - printf( "\nresult: msgid %d\n", - res->lm_msgid ); - handle_result( ld, res, 0 ); - res = NULL; - } -#endif /* CLDAP */ - } else { - if (( id = ldap_search( ld, dn, scope, filter, - types, attrsonly )) == -1 ) { - ldap_perror( ld, "ldap_search" ); - } else { - printf( "Search initiated with id %d\n", id ); - } - } - free_list( types ); - break; - - case 't': /* set timeout value */ - getline( line, sizeof(line), stdin, "timeout (-1=infinite)? " ); - timeout.tv_sec = atoi( line ); - if ( timeout.tv_sec < 0 ) { - tvp = NULL; - } else { - tvp = &timeout; - } - break; - - case 'U': /* set ufn search prefix */ - getline( line, sizeof(line), stdin, "ufn prefix? " ); - ldap_ufn_setprefix( ld, line ); - break; - - case 'u': /* user friendly search w/optional timeout */ - getline( dn, sizeof(dn), stdin, "ufn? " ); - strcat( dn, dnsuffix ); - types = get_list( "attrs to return? " ); - getline( line, sizeof(line), stdin, - "attrsonly (0=attrs&values, 1=attrs only)? " ); - attrsonly = atoi( line ); - - if ( command2 == 't' ) { - id = ldap_ufn_search_c( ld, dn, types, - attrsonly, &res, ldap_ufn_timeout, - &timeout ); - } else { - id = ldap_ufn_search_s( ld, dn, types, - attrsonly, &res ); - } - if ( res == NULL ) - ldap_perror( ld, "ldap_ufn_search" ); - else { - printf( "\nresult: err %d\n", id ); - handle_result( ld, res, 0 ); - res = NULL; - } - free_list( types ); - break; - - case 'l': /* URL search */ - getline( line, sizeof(line), stdin, - "attrsonly (0=attrs&values, 1=attrs only)? " ); - attrsonly = atoi( line ); - getline( line, sizeof(line), stdin, "LDAP URL? " ); - if (( id = ldap_url_search( ld, line, attrsonly )) - == -1 ) { - ldap_perror( ld, "ldap_url_search" ); - } else { - printf( "URL search initiated with id %d\n", id ); - } - break; - - case 'p': /* parse LDAP URL */ - getline( line, sizeof(line), stdin, "LDAP URL? " ); - if (( i = ldap_url_parse( line, &ludp )) != 0 ) { - fprintf( stderr, "ldap_url_parse: error %d (%s)\n", i, - url_parse_err2string( i )); - } else { - printf( "\t host: " ); - if ( ludp->lud_host == NULL ) { - printf( "DEFAULT\n" ); - } else { - printf( "<%s>\n", ludp->lud_host ); - } - printf( "\t port: " ); - if ( ludp->lud_port == 0 ) { - printf( "DEFAULT\n" ); - } else { - printf( "%d\n", ludp->lud_port ); - } - printf( "\tsecure: %s\n", ( ludp->lud_options & - LDAP_URL_OPT_SECURE ) != 0 ? "Yes" : "No" ); - printf( "\t dn: " ); - if ( ludp->lud_dn == NULL ) { - printf( "ROOT\n" ); - } else { - printf( "%s\n", ludp->lud_dn ); - } - printf( "\t attrs:" ); - if ( ludp->lud_attrs == NULL ) { - printf( " ALL" ); - } else { - for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) { - printf( " <%s>", ludp->lud_attrs[ i ] ); - } - } - printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? - "ONE" : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" : - ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" : "**invalid**" ); - printf( "\tfilter: <%s>\n", ludp->lud_filter ); - ldap_free_urldesc( ludp ); - } - break; - - case 'n': /* set dn suffix, for convenience */ - getline( line, sizeof(line), stdin, "DN suffix? " ); - strcpy( dnsuffix, line ); - break; - - case 'N': /* add an LDAPv3 control */ - getline( line, sizeof(line), stdin, - "Control oid (. to clear list)? " ); - if ( *line == '.' && *(line+1) == '\0' ) { - controls = NULL; - } else { - newctrl = (LDAPControl *) malloc( - sizeof(LDAPControl) ); - newctrl->ldctl_oid = strdup( line ); - getline( line, sizeof(line), stdin, - "Control value? " ); - if ( strncmp( line, "0x", 2 ) == 0 ) { - newctrl->ldctl_value.bv_val = - (char *)malloc( strlen( line ) / 2 ); - berval_from_hex( &(newctrl->ldctl_value), - line + 2 ); - } else { - newctrl->ldctl_value.bv_val - = strdup( line ); - } - newctrl->ldctl_value.bv_len = strlen( line ); - getline( line, sizeof(line), stdin, - "Critical (0=no, 1=yes)? " ); - newctrl->ldctl_iscritical = atoi( line ); - add_control( &controls, newctrl ); - } - ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, - controls ); - ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, - &tmpctrls ); - print_controls( tmpctrls, 0 ); - break; - - case 'P': /* add a persistent search control */ - getline( line, sizeof(line), stdin, "Changetypes to " - " return (additive - add (1), delete (2), " - "modify (4), modDN (8))? " ); - changetypes = atoi(line); - getline( line, sizeof(line), stdin, - "Return changes only (0=no, 1=yes)? " ); - changesonly = atoi(line); - getline( line, sizeof(line), stdin, "Return entry " - "change controls (0=no, 1=yes)? " ); - return_echg_ctls = atoi(line); - getline( line, sizeof(line), stdin, - "Critical (0=no, 1=yes)? " ); - if ( ldap_create_persistentsearch_control( ld, - changetypes, changesonly, return_echg_ctls, - (char)atoi(line), &newctrl ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_create_persistent" - "search_control" ); - } else { - add_control( &controls, newctrl ); - ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, - controls ); - ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, - &tmpctrls ); - print_controls( tmpctrls, 0 ); - } - break; - - case 'o': /* set ldap options */ - getline( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" ); - i = atoi( line ); - ldap_set_option( ld, LDAP_OPT_DEREF, &i ); - getline( line, sizeof(line), stdin, "timelimit?" ); - i = atoi( line ); - ldap_set_option( ld, LDAP_OPT_TIMELIMIT, &i ); - getline( line, sizeof(line), stdin, "sizelimit?" ); - i = atoi( line ); - ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &i ); - -#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_OPT_TRANSLATE_STRINGS; - } else { - ld->ld_lberoptions |= LBER_OPT_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_DNS - getline( line, sizeof(line), stdin, - "Use DN & DNS to determine where to send requests (0=no, 1=yes)?" ); - optval = ( atoi( line ) != 0 ); - ldap_set_option( ld, LDAP_OPT_DNS, (void *) optval ); -#endif /* LDAP_DNS */ - - getline( line, sizeof(line), stdin, - "Recognize and chase referrals (0=no, 1=yes)?" ); - optval = ( atoi( line ) != 0 ); - ldap_set_option( ld, LDAP_OPT_REFERRALS, - (void *) optval ); - if ( optval ) { - getline( line, sizeof(line), stdin, - "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" ); - if ( atoi( line ) != 0 ) { - ldap_set_rebind_proc( ld, bind_prompt, - NULL ); - } - } -#ifdef NET_SSL - getline( line, sizeof(line), stdin, - "Use Secure Sockets Layer - SSL (0=no, 1=yes)?" ); - optval = ( atoi( line ) != 0 ); - if ( optval ) { - getline( line, sizeof(line), stdin, - "security DB path?" ); - if ( ldapssl_client_init( (*line == '\0') ? - NULL : line, NULL ) < 0 ) { - perror( "ldapssl_client_init" ); - optval = 0; /* SSL not avail. */ - } else if ( ldapssl_install_routines( ld ) - < 0 ) { - ldap_perror( ld, - "ldapssl_install_routines" ); - optval = 0; /* SSL not avail. */ - } - } - - ldap_set_option( ld, LDAP_OPT_SSL, - optval ? LDAP_OPT_ON : LDAP_OPT_OFF ); - - getline( line, sizeof(line), stdin, - "Set SSL options (0=no, 1=yes)?" ); - optval = ( atoi( line ) != 0 ); - while ( 1 ) { - PRInt32 sslopt; - PRBool on; - - getline( line, sizeof(line), stdin, - "Option to set (0 if done)?" ); - sslopt = atoi(line); - if ( sslopt == 0 ) { - break; - } - getline( line, sizeof(line), stdin, - "On=1, Off=0?" ); - on = ( atoi( line ) != 0 ); - if ( ldapssl_set_option( ld, sslopt, on ) != 0 ) { - ldap_perror( ld, "ldapssl_set_option" ); - } - } -#endif - - getline( line, sizeof(line), stdin, "Reconnect?" ); - ldap_set_option( ld, LDAP_OPT_RECONNECT, - ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : - LDAP_OPT_ON ); - - getline( line, sizeof(line), stdin, "Async I/O?" ); - ldap_set_option( ld, LDAP_OPT_ASYNC_CONNECT, - ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : - LDAP_OPT_ON ); - break; - - case 'I': /* initialize display templates */ - getline( line, sizeof(line), stdin, - "Template file [ldaptemplates.conf]?" ); - if (( i = ldap_init_templates( *line == '\0' ? - "ldaptemplates.conf" : line, &tmpllist )) - != 0 ) { - fprintf( stderr, "ldap_init_templates: %s\n", - ldap_tmplerr2string( i )); - } - break; - - case 'T': /* read & display using template */ - getline( dn, sizeof(dn), stdin, "entry DN? " ); - strcat( dn, dnsuffix ); - if (( i = ldap_entry2text_search( ld, dn, NULL, NULL, - tmpllist, NULL, NULL, entry2textwrite, stdout, - "\n", 0, 0 )) != LDAP_SUCCESS ) { - fprintf( stderr, "ldap_entry2text_search: %s\n", - ldap_err2string( i )); - } - break; - - case 'L': /* set preferred language */ - getline( line, sizeof(line), stdin, - "Preferred language? " ); - if ( *line == '\0' ) { - ldap_set_option( ld, - LDAP_OPT_PREFERRED_LANGUAGE, NULL ); - } else { - ldap_set_option( ld, - LDAP_OPT_PREFERRED_LANGUAGE, line ); - } - break; - - case 'F': /* create filter */ - { - char filtbuf[ 512 ], pattern[ 512 ]; - char prefix[ 512 ], suffix[ 512 ]; - char attr[ 512 ], value[ 512 ]; - char *dupvalue, **words; - - getline( pattern, sizeof(pattern), stdin, - "pattern? " ); - getline( prefix, sizeof(prefix), stdin, - "prefix? " ); - getline( suffix, sizeof(suffix), stdin, - "suffix? " ); - getline( attr, sizeof(attr), stdin, - "attribute? " ); - getline( value, sizeof(value), stdin, - "value? " ); - - if (( dupvalue = strdup( value )) != NULL ) { - words = string2words( value, " " ); - } else { - words = NULL; - } - if ( ldap_create_filter( filtbuf, - sizeof(filtbuf), pattern, prefix, suffix, - attr, value, words) != 0 ) { - fprintf( stderr, - "ldap_create_filter failed\n" ); - } else { - printf( "filter is \"%s\"\n", filtbuf ); - } - if ( dupvalue != NULL ) free( dupvalue ); - if ( words != NULL ) free( words ); - } - break; - - case '?': /* help */ - case '\0': /* help */ - printf( "Commands: [ad]d [ab]andon [b]ind\n" ); - printf( " synch [B]ind [c]ompare [l]URL search\n" ); - printf( " [modi]fy [modr]dn [rem]ove\n" ); - printf( " [res]ult [s]earch [q]uit/unbind\n\n" ); - printf( " [u]fn search [ut]fn search with timeout\n" ); - printf( " [d]ebug [C]set cache parms[g]set msgid\n" ); - printf( " d[n]suffix [t]imeout [v]ersion\n" ); - printf( " [U]fn prefix [?]help [o]ptions\n" ); - printf( " [E]xplode dn [p]arse LDAP URL [R]explode RDN\n" ); - printf( " e[x]tended op [F]ilter create\n" ); - printf( " set co[N]trols set preferred [L]anguage\n" ); - printf( " add a [P]ersistent search control\n" ); - printf( " [I]nitialize display templates\n" ); - printf( " [T]read entry and display using template\n" ); - break; - - default: - printf( "Invalid command. Type ? for help.\n" ); - break; - } - - (void) memset( line, '\0', sizeof(line) ); - } - - return( 0 ); -} - -static void -handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ) -{ - int msgtype; - - switch ( (msgtype = ldap_msgtype( lm )) ) { - case LDAP_RES_COMPARE: - printf( "Compare result\n" ); - print_ldap_result( ld, lm, "compare" ); - break; - - case LDAP_RES_SEARCH_RESULT: - printf( "Search result\n" ); - print_ldap_result( ld, lm, "search" ); - break; - - case LDAP_RES_SEARCH_ENTRY: - printf( "Search entry\n" ); - print_search_entry( ld, lm, onlyone ); - break; - - case LDAP_RES_SEARCH_REFERENCE: - printf( "Search reference\n" ); - print_search_reference( ld, lm, onlyone ); - break; - - case LDAP_RES_ADD: - printf( "Add result\n" ); - print_ldap_result( ld, lm, "add" ); - break; - - case LDAP_RES_DELETE: - printf( "Delete result\n" ); - print_ldap_result( ld, lm, "delete" ); - break; - - case LDAP_RES_MODIFY: - printf( "Modify result\n" ); - print_ldap_result( ld, lm, "modify" ); - break; - - case LDAP_RES_MODRDN: - printf( "ModRDN result\n" ); - print_ldap_result( ld, lm, "modrdn" ); - break; - - case LDAP_RES_BIND: - printf( "Bind result\n" ); - print_ldap_result( ld, lm, "bind" ); - break; - case LDAP_RES_EXTENDED: - if ( ldap_msgid( lm ) == LDAP_RES_UNSOLICITED ) { - printf( "Unsolicited result\n" ); - print_ldap_result( ld, lm, "unsolicited" ); - } else { - printf( "ExtendedOp result\n" ); - print_ldap_result( ld, lm, "extendedop" ); - } - break; - - default: - printf( "Unknown result type 0x%x\n", msgtype ); - print_ldap_result( ld, lm, "unknown" ); - } - - if ( !onlyone ) { - ldap_msgfree( lm ); - } -} - -static void -print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ) -{ - int lderr; - char *matcheddn, *errmsg, *oid, **refs; - LDAPControl **ctrls; - struct berval *servercred, *data; - - if ( ldap_parse_result( ld, lm, &lderr, &matcheddn, &errmsg, &refs, - &ctrls, 0 ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_parse_result" ); - } else { - fprintf( stderr, "%s: %s", s, ldap_err2string( lderr )); - if ( lderr == LDAP_CONNECT_ERROR ) { - perror( " - " ); - } else { - fputc( '\n', stderr ); - } - if ( errmsg != NULL ) { - if ( *errmsg != '\0' ) { - fprintf( stderr, "Additional info: %s\n", - errmsg ); - } - ldap_memfree( errmsg ); - } - if ( matcheddn != NULL ) { - if ( NAME_ERROR( lderr )) { - fprintf( stderr, "Matched DN: %s\n", - matcheddn ); - } - ldap_memfree( matcheddn ); - } - print_referrals( refs, 1 ); - print_controls( ctrls, 1 ); - } - - /* if SASL bind response, get and show server credentials */ - if ( ldap_msgtype( lm ) == LDAP_RES_BIND && - ldap_parse_sasl_bind_result( ld, lm, &servercred, 0 ) == - LDAP_SUCCESS && servercred != NULL ) { - fputs( "\tSASL server credentials:\n", stderr ); - bprint( servercred->bv_val, servercred->bv_len ); - ber_bvfree( servercred ); - } - - /* if ExtendedOp response, get and show oid plus data */ - if ( ldap_msgtype( lm ) == LDAP_RES_EXTENDED && - ldap_parse_extended_result( ld, lm, &oid, &data, 0 ) == - LDAP_SUCCESS ) { - if ( oid != NULL ) { - if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) - == 0 ) { - printf( - "\t%s Notice of Disconnection (OID: %s)\n", - s, oid ); - } else { - printf( "\t%s OID: %s\n", s, oid ); - } - ldap_memfree( oid ); - } - if ( data != NULL ) { - printf( "\t%s data:\n", s ); - bprint( data->bv_val, data->bv_len ); - ber_bvfree( data ); - } - } -} - -static void -print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ) -{ - BerElement *ber; - char *a, *dn, *ufn; - struct berval **vals; - int i, count; - LDAPMessage *e, *msg; - LDAPControl **ectrls; - - count = 0; - for ( msg = ldap_first_message( ld, res ); - msg != NULL && ( !onlyone || count == 0 ); - msg = ldap_next_message( ld, msg ), ++count ) { - if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) { - handle_result( ld, msg, 1 ); /* something else */ - continue; - } - e = msg; - - dn = ldap_get_dn( ld, e ); - printf( "\tDN: %s\n", dn ); - - ufn = ldap_dn2ufn( dn ); - printf( "\tUFN: %s\n", ufn ); -#ifdef WINSOCK - ldap_memfree( dn ); - ldap_memfree( ufn ); -#else /* WINSOCK */ - free( dn ); - free( ufn ); -#endif /* WINSOCK */ - - for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; - a = ldap_next_attribute( ld, e, ber ) ) { - printf( "\t\tATTR: %s\n", a ); - if ( (vals = ldap_get_values_len( ld, e, a )) - == NULL ) { - printf( "\t\t\t(no values)\n" ); - } else { - for ( i = 0; vals[i] != NULL; i++ ) { - int nonascii = 0; - unsigned long j; - - for ( j = 0; j < vals[i]->bv_len; j++ ) - if ( !isascii( vals[i]->bv_val[j] ) ) { - nonascii = 1; - break; - } - - if ( nonascii ) { - printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len ); -#ifdef BPRINT_NONASCII - bprint( vals[i]->bv_val, - vals[i]->bv_len ); -#endif /* BPRINT_NONASCII */ - continue; - } - printf( "\t\t\tlength (%ld) %s\n", - vals[i]->bv_len, vals[i]->bv_val ); - } - ber_bvecfree( vals ); - } - ldap_memfree( a ); - } - if ( ldap_get_lderrno( ld, NULL, NULL ) != LDAP_SUCCESS ) { - ldap_perror( ld, - "ldap_first_attribute/ldap_next_attribute" ); - } - if ( ber != NULL ) { - ber_free( ber, 0 ); - } - - if ( ldap_get_entry_controls( ld, e, &ectrls ) - != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_get_entry_controls" ); - } else { - int changenumpresent; - ber_int_t changetype; - char *prevdn; - ber_int_t changenum; - - if ( ldap_parse_entrychange_control( ld, ectrls, - &changetype, &prevdn, &changenumpresent, - &changenum ) == LDAP_SUCCESS ) { - fprintf( stderr, "EntryChangeNotification\n" - "\tchangeType: %s\n", - changetype_num2string( changetype )); - if ( prevdn != NULL ) { - fprintf( stderr, - "\tpreviousDN: \"%s\"\n", - prevdn ); - } - if ( changenumpresent ) { - fprintf( stderr, "\tchangeNumber: %d\n", - changenum ); - } - if ( prevdn != NULL ) { - free( prevdn ); - } - } - print_controls( ectrls, 1 ); - } - } -} - - -static char * -changetype_num2string( ber_int_t chgtype ) -{ - static char buf[ 25 ]; - char *s; - - switch( chgtype ) { - case LDAP_CHANGETYPE_ADD: - s = "add"; - break; - case LDAP_CHANGETYPE_DELETE: - s = "delete"; - break; - case LDAP_CHANGETYPE_MODIFY: - s = "modify"; - break; - case LDAP_CHANGETYPE_MODDN: - s = "moddn"; - break; - default: - s = buf; - sprintf( s, "unknown (%d)", chgtype ); - } - - return( s ); -} - - -static void -print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ) -{ - LDAPMessage *msg; - LDAPControl **ctrls; - char **refs; - int count; - - count = 0; - for ( msg = ldap_first_message( ld, res ); - msg != NULL && ( !onlyone || count == 0 ); - msg = ldap_next_message( ld, msg ), ++count ) { - if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_REFERENCE ) { - handle_result( ld, msg, 1 ); /* something else */ - continue; - } - - if ( ldap_parse_reference( ld, msg, &refs, &ctrls, 0 ) != - LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_parse_reference" ); - } else { - print_referrals( refs, 1 ); - print_controls( ctrls, 1 ); - } - } -} - - -static void -print_referrals( char **refs, int freeit ) -{ - int i; - - if ( refs == NULL ) { - return; - } - - fprintf( stderr, "Referrals:\n" ); - for ( i = 0; refs[ i ] != NULL; ++i ) { - fprintf( stderr, "\t%s\n", refs[ i ] ); - } - - if ( freeit ) { - ldap_value_free( refs ); - } -} - - -static void -print_controls( LDAPControl **ctrls, int freeit ) -{ - int i; - - if ( ctrls == NULL ) { - return; - } - - fprintf( stderr, "Controls:\n" ); - for ( i = 0; ctrls[ i ] != NULL; ++i ) { - if ( i > 0 ) { - fputs( "\t-----------\n", stderr ); - } - fprintf( stderr, "\toid: %s\n", ctrls[ i ]->ldctl_oid ); - fprintf( stderr, "\tcritical: %s\n", - ctrls[ i ]->ldctl_iscritical ? "YES" : "NO" ); - fputs( "\tvalue:\n", stderr ); - bprint( ctrls[ i ]->ldctl_value.bv_val, - ctrls[ i ]->ldctl_value.bv_len ); - } - - if ( freeit ) { - ldap_controls_free( ctrls ); - } -} - - -static int -entry2textwrite( void *fp, char *buf, int len ) -{ - return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len ); -} - - -/* similar to getfilter.c:break_into_words() */ -static char ** -string2words( char *str, char *delims ) -{ - char *word, **words; - int count; - char *lasts; - - if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) { - return( NULL ); - } - count = 0; - words[ count ] = NULL; - - word = ldap_utf8strtok_r( str, delims, &lasts ); - while ( word != NULL ) { - if (( words = (char **)realloc( words, - ( count + 2 ) * sizeof( char * ))) == NULL ) { - free( words ); - return( NULL ); - } - - words[ count ] = word; - words[ ++count ] = NULL; - word = ldap_utf8strtok_r( NULL, delims, &lasts ); - } - - return( words ); -} - - -static const char * -url_parse_err2string( int e ) -{ - const char *s = "unknown"; - - switch( e ) { - case LDAP_URL_ERR_NOTLDAP: - s = "URL doesn't begin with \"ldap://\""; - break; - case LDAP_URL_ERR_NODN: - s = "URL has no DN (required)"; - break; - case LDAP_URL_ERR_BADSCOPE: - s = "URL scope string is invalid"; - break; - case LDAP_URL_ERR_MEM: - s = "can't allocate memory space"; - break; - case LDAP_URL_ERR_PARAM: - s = "bad parameter to an URL function"; - break; - case LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION: - s = "unrecognized critical URL extension"; - break; - } - - return( s ); -} - - -/* - * Print arbitrary stuff, for debugging. - */ - -#define BPLEN 48 -static void -bprint( char *data, int len ) -{ - static char hexdig[] = "0123456789abcdef"; - char out[ BPLEN ]; - int i = 0; - - memset( out, 0, BPLEN ); - for ( ;; ) { - if ( len < 1 ) { - fprintf( stderr, "\t%s\n", ( i == 0 ) ? "(end)" : out ); - break; - } - -#ifndef HEX - if ( isgraph( (unsigned char)*data )) { - out[ i ] = ' '; - out[ i+1 ] = *data; - } else { -#endif - out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; - out[ i+1 ] = hexdig[ *data & 0x0f ]; -#ifndef HEX - } -#endif - i += 2; - len--; - data++; - - if ( i > BPLEN - 2 ) { - fprintf( stderr, "\t%s\n", out ); - memset( out, 0, BPLEN ); - i = 0; - continue; - } - out[ i++ ] = ' '; - } - - fflush( stderr ); -} diff --git a/ldap/c-sdk/libraries/libldap/tmplout.c b/ldap/c-sdk/libraries/libldap/tmplout.c deleted file mode 100644 index 0dded6b4c5..0000000000 --- a/ldap/c-sdk/libraries/libldap/tmplout.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * tmplout.c: display template library output routines for LDAP clients - * - */ - -#include "ldap-int.h" -#include "disptmpl.h" - -#if defined(_WINDOWS) || defined(aix) || defined(SCOOS) || defined(OSF1) || defined(SOLARIS) -#include /* for struct tm and ctime */ -#endif - - -/* This is totally lame, since it should be coming from time.h, but isn't. */ -#if defined(SOLARIS) -char *ctime_r(const time_t *, char *, int); -#endif - -static int do_entry2text( LDAP *ld, char *buf, char *base, LDAPMessage *entry, - struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, - writeptype writeproc, void *writeparm, char *eol, int rdncount, - unsigned long opts, char *urlprefix ); -static int do_entry2text_search( LDAP *ld, char *dn, char *base, - LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, - char ***defvals, writeptype writeproc, void *writeparm, char *eol, - int rdncount, unsigned long opts, char *urlprefix ); -static int do_vals2text( LDAP *ld, char *buf, char **vals, char *label, - int labelwidth, unsigned long syntaxid, writeptype writeproc, - void *writeparm, char *eol, int rdncount, char *urlprefix ); -static int max_label_len( struct ldap_disptmpl *tmpl ); -static int output_label( char *buf, char *label, int width, - writeptype writeproc, void *writeparm, char *eol, int html ); -static int output_dn( char *buf, char *dn, int width, int rdncount, - writeptype writeproc, void *writeparm, char *eol, char *urlprefix ); -static void strcat_escaped( char *s1, char *s2 ); -static char *time2text( char *ldtimestr, int dateonly ); -static long gtime( struct tm *tm ); -static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, - char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount, - writeptype writeproc, void *writeparm, char *eol, char *urlprefix ); - -#define DEF_LABEL_WIDTH 15 -#define SEARCH_TIMEOUT_SECS 120 -#define OCATTRNAME "objectClass" - - -#define NONFATAL_LDAP_ERR( err ) ( err == LDAP_SUCCESS || \ - err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED ) - -#define DEF_LDAP_URL_PREFIX "ldap:///" - - -int -LDAP_CALL -ldap_entry2text( - LDAP *ld, - char *buf, /* NULL for "use internal" */ - LDAPMessage *entry, - struct ldap_disptmpl *tmpl, - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, - unsigned long opts -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2text\n", 0, 0, 0 ); - - return( do_entry2text( ld, buf, NULL, entry, tmpl, defattrs, defvals, - writeproc, writeparm, eol, rdncount, opts, NULL )); - -} - - - -int -LDAP_CALL -ldap_entry2html( - LDAP *ld, - char *buf, /* NULL for "use internal" */ - LDAPMessage *entry, - struct ldap_disptmpl *tmpl, - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, - unsigned long opts, - char *base, - char *urlprefix -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2html\n", 0, 0, 0 ); - - if ( urlprefix == NULL ) { - urlprefix = DEF_LDAP_URL_PREFIX; - } - - return( do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, - writeproc, writeparm, eol, rdncount, opts, urlprefix )); -} - - -static int -do_entry2text( - LDAP *ld, - char *buf, /* NULL for use-internal */ - char *base, /* used for search actions */ - LDAPMessage *entry, - struct ldap_disptmpl *tmpl, - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, - unsigned long opts, - char *urlprefix /* if non-NULL, do HTML */ -) -{ - int i, err, html, show, labelwidth; - int freebuf, freevals; - char *dn, **vals; - struct ldap_tmplitem *rowp, *colp; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( writeproc == NULL || - !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { - err = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - if (( dn = ldap_get_dn( ld, entry )) == NULL ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( buf == NULL ) { - if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - NSLDAPI_FREE( dn ); - return( err ); - } - freebuf = 1; - } else { - freebuf = 0; - } - - html = ( urlprefix != NULL ); - - if ( html ) { - /* - * add HTML intro. and title - */ - if (!(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { - sprintf( buf, "%s%s%s%s - ", eol, eol, eol, - ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); - (*writeproc)( writeparm, buf, strlen( buf )); - output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); - sprintf( buf, "%s%s%s%s

%s - ", eol, eol, - eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); - (*writeproc)( writeparm, buf, strlen( buf )); - output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); - sprintf( buf, "

%s", eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - } - - if (( opts & LDAP_DISP_OPT_NONLEAF ) != 0 && - ( vals = ldap_explode_dn( dn, 0 )) != NULL ) { - char *untagged; - - /* - * add "Move Up" link - */ - sprintf( buf, "
1 ) { - strcat_escaped( buf, ", " ); - } - strcat_escaped( buf, vals[ i ] ); - } - if ( vals[ 1 ] != NULL ) { - untagged = strchr( vals[ 1 ], '=' ); - } else { - untagged = "=The World"; - } - sprintf( buf + strlen( buf ), - "%s\">Move Up To %s%s
", - ( vals[ 1 ] == NULL ) ? "??one" : "", - ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - - /* - * add "Browse" link - */ - untagged = strchr( vals[ 0 ], '=' ); - sprintf( buf, "Browse Below %s%s%s", - ( untagged != NULL ) ? untagged + 1 : vals[ 0 ], eol, eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - - ldap_value_free( vals ); - } - - (*writeproc)( writeparm, "
", 4 ); /* horizontal rule */ - } else { - (*writeproc)( writeparm, "\"", 1 ); - output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); - sprintf( buf, "\"%s", eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - } - - if ( tmpl != NULL && ( opts & LDAP_DISP_OPT_AUTOLABELWIDTH ) != 0 ) { - labelwidth = max_label_len( tmpl ) + 3; - } else { - labelwidth = DEF_LABEL_WIDTH;; - } - - err = LDAP_SUCCESS; - - if ( tmpl == NULL ) { - BerElement *ber; - char *attr; - - ber = NULL; - for ( attr = ldap_first_attribute( ld, entry, &ber ); - NONFATAL_LDAP_ERR( err ) && attr != NULL; - attr = ldap_next_attribute( ld, entry, ber )) { - if (( vals = ldap_get_values( ld, entry, attr )) == NULL ) { - freevals = 0; - if ( defattrs != NULL ) { - for ( i = 0; defattrs[ i ] != NULL; ++i ) { - if ( strcasecmp( attr, defattrs[ i ] ) == 0 ) { - break; - } - } - if ( defattrs[ i ] != NULL ) { - vals = defvals[ i ]; - } - } - } else { - freevals = 1; - } - - if ( islower( *attr )) { /* cosmetic -- upcase attr. name */ - *attr = toupper( *attr ); - } - - err = do_vals2text( ld, buf, vals, attr, labelwidth, - LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol, - rdncount, urlprefix ); - if ( freevals ) { - ldap_value_free( vals ); - } - } - if ( ber == NULL ) { - ber_free( ber, 0 ); - } - /* - * XXX check for errors in ldap_first_attribute/ldap_next_attribute - * here (but what should we do if there was one?) - */ - - } else { - for ( rowp = ldap_first_tmplrow( tmpl ); - NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM; - rowp = ldap_next_tmplrow( tmpl, rowp )) { - for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; - colp = ldap_next_tmplcol( tmpl, rowp, colp )) { - vals = NULL; - if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld, - entry, colp->ti_attrname )) == NULL ) { - freevals = 0; - if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp, - LDAP_DITEM_OPT_HIDEIFEMPTY ) && defattrs != NULL - && colp->ti_attrname != NULL ) { - for ( i = 0; defattrs[ i ] != NULL; ++i ) { - if ( strcasecmp( colp->ti_attrname, defattrs[ i ] ) - == 0 ) { - break; - } - } - if ( defattrs[ i ] != NULL ) { - vals = defvals[ i ]; - } - } - } else { - freevals = 1; - if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, - LDAP_DITEM_OPT_SORTVALUES ) && vals[ 0 ] != NULL - && vals[ 1 ] != NULL ) { - ldap_sort_values(ld, vals, ldap_sort_strcasecmp); - } - } - - /* - * don't bother even calling do_vals2text() if no values - * or boolean with value false and "hide if false" option set - */ - show = ( vals != NULL && vals[ 0 ] != NULL ); - if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) - == LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET( - colp, LDAP_DITEM_OPT_HIDEIFFALSE ) && - toupper( vals[ 0 ][ 0 ] ) != 'T' ) { - show = 0; - } - - if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) { - if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) { - if ( colp->ti_attrname == NULL || ( show && - toupper( vals[ 0 ][ 0 ] ) == 'T' )) { - err = searchaction( ld, buf, base, entry, dn, colp, - labelwidth, rdncount, writeproc, - writeparm, eol, urlprefix ); - } - } - show = 0; - } - - if ( show ) { - err = do_vals2text( ld, buf, vals, colp->ti_label, - labelwidth, colp->ti_syntaxid, writeproc, writeparm, - eol, rdncount, urlprefix ); - } - - if ( freevals ) { - ldap_value_free( vals ); - } - } - } - } - - if ( html && !(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { - sprintf( buf, "%s%s", eol, eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - } - - NSLDAPI_FREE( dn ); - if ( freebuf ) { - NSLDAPI_FREE( buf ); - } - - return( err ); -} - - -int -LDAP_CALL -ldap_entry2text_search( - LDAP *ld, - char *dn, /* if NULL, use entry */ - char *base, /* if NULL, no search actions */ - LDAPMessage *entry, /* if NULL, use dn */ - struct ldap_disptmpl* tmpllist, /* if NULL, load default file */ - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, /* if 0, display full DN */ - unsigned long opts -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2text_search\n", 0, 0, 0 ); - - return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs, - defvals, writeproc, writeparm, eol, rdncount, opts, NULL )); -} - - - -int -LDAP_CALL -ldap_entry2html_search( - LDAP *ld, - char *dn, /* if NULL, use entry */ - char *base, /* if NULL, no search actions */ - LDAPMessage *entry, /* if NULL, use dn */ - struct ldap_disptmpl* tmpllist, /* if NULL, load default file */ - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, /* if 0, display full DN */ - unsigned long opts, - char *urlprefix -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_entry2html_search\n", 0, 0, 0 ); - - return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs, - defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix )); -} - - -static int -do_entry2text_search( - LDAP *ld, - char *dn, /* if NULL, use entry */ - char *base, /* if NULL, no search actions */ - LDAPMessage *entry, /* if NULL, use dn */ - struct ldap_disptmpl* tmpllist, /* if NULL, no template used */ - char **defattrs, - char ***defvals, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, /* if 0, display full DN */ - unsigned long opts, - char *urlprefix -) -{ - int err, freedn, html; - char *buf, **fetchattrs, **vals; - LDAPMessage *ldmp; - struct ldap_disptmpl *tmpl; - struct timeval timeout; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( dn == NULL && entry == NULLMSG ) { - err = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - html = ( urlprefix != NULL ); - - timeout.tv_sec = SEARCH_TIMEOUT_SECS; - timeout.tv_usec = 0; - - if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - freedn = 0; - tmpl = NULL; - - if ( dn == NULL ) { - if (( dn = ldap_get_dn( ld, entry )) == NULL ) { - NSLDAPI_FREE( buf ); - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - freedn = 1; - } - - - if ( tmpllist != NULL ) { - ldmp = NULLMSG; - - if ( entry == NULL ) { - char *ocattrs[2]; - - ocattrs[0] = OCATTRNAME; - ocattrs[1] = NULL; -#ifdef CLDAP - if ( LDAP_IS_CLDAP( ld )) - err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, - "objectClass=*", ocattrs, 0, &ldmp, NULL ); - else -#endif /* CLDAP */ - err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, - "objectClass=*", ocattrs, 0, &timeout, &ldmp ); - - if ( err == LDAP_SUCCESS ) { - entry = ldap_first_entry( ld, ldmp ); - } - } - - if ( entry != NULL ) { - vals = ldap_get_values( ld, entry, OCATTRNAME ); - tmpl = ldap_oc2template( vals, tmpllist ); - if ( vals != NULL ) { - ldap_value_free( vals ); - } - } - if ( ldmp != NULL ) { - ldap_msgfree( ldmp ); - } - } - - entry = NULL; - - if ( tmpl == NULL ) { - fetchattrs = NULL; - } else { - fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER ); - } - -#ifdef CLDAP - if ( LDAP_IS_CLDAP( ld )) - err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", - fetchattrs, 0, &ldmp, NULL ); - else -#endif /* CLDAP */ - err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", - fetchattrs, 0, &timeout, &ldmp ); - - if ( freedn ) { - NSLDAPI_FREE( dn ); - } - if ( fetchattrs != NULL ) { - ldap_value_free( fetchattrs ); - } - - if ( err != LDAP_SUCCESS || - ( entry = ldap_first_entry( ld, ldmp )) == NULL ) { - NSLDAPI_FREE( buf ); - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, - writeproc, writeparm, eol, rdncount, opts, urlprefix ); - - NSLDAPI_FREE( buf ); - ldap_msgfree( ldmp ); - return( err ); -} - - -int -LDAP_CALL -ldap_vals2text( - LDAP *ld, - char *buf, /* NULL for "use internal" */ - char **vals, - char *label, - int labelwidth, /* 0 means use default */ - unsigned long syntaxid, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_vals2text\n", 0, 0, 0 ); - - return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid, - writeproc, writeparm, eol, rdncount, NULL )); -} - - -int -LDAP_CALL -ldap_vals2html( - LDAP *ld, - char *buf, /* NULL for "use internal" */ - char **vals, - char *label, - int labelwidth, /* 0 means use default */ - unsigned long syntaxid, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, - char *urlprefix -) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_vals2html\n", 0, 0, 0 ); - - if ( urlprefix == NULL ) { - urlprefix = DEF_LDAP_URL_PREFIX; - } - - return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid, - writeproc, writeparm, eol, rdncount, urlprefix )); -} - - -static int -do_vals2text( - LDAP *ld, - char *buf, /* NULL for "use internal" */ - char **vals, - char *label, - int labelwidth, /* 0 means use default */ - unsigned long syntaxid, - writeptype writeproc, - void *writeparm, - char *eol, - int rdncount, - char *urlprefix -) -{ - int err, i, html, writeoutval, freebuf, notascii; - char *p, *s, *outval; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || writeproc == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - if ( vals == NULL ) { - return( LDAP_SUCCESS ); - } - - html = ( urlprefix != NULL ); - - switch( LDAP_GET_SYN_TYPE( syntaxid )) { - case LDAP_SYN_TYPE_TEXT: - case LDAP_SYN_TYPE_BOOLEAN: - break; /* we only bother with these two types... */ - default: - return( LDAP_SUCCESS ); - } - - if ( labelwidth == 0 || labelwidth < 0 ) { - labelwidth = DEF_LABEL_WIDTH; - } - - if ( buf == NULL ) { - if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - freebuf = 1; - } else { - freebuf = 0; - } - - output_label( buf, label, labelwidth, writeproc, writeparm, eol, html ); - - for ( i = 0; vals[ i ] != NULL; ++i ) { - for ( p = vals[ i ]; *p != '\0'; ++p ) { - if ( !isascii( *p )) { - break; - } - } - notascii = ( *p != '\0' ); - outval = notascii ? "(unable to display non-ASCII text value)" - : vals[ i ]; - - writeoutval = 0; /* if non-zero, write outval after switch */ - - switch( syntaxid ) { - case LDAP_SYN_CASEIGNORESTR: - ++writeoutval; - break; - - case LDAP_SYN_RFC822ADDR: - if ( html ) { - strcpy( buf, "
%s
%s", outval, eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - } else { - ++writeoutval; - } - break; - - case LDAP_SYN_DN: /* for now */ - output_dn( buf, outval, labelwidth, rdncount, writeproc, - writeparm, eol, urlprefix ); - break; - - case LDAP_SYN_MULTILINESTR: - if ( i > 0 && !html ) { - output_label( buf, label, labelwidth, writeproc, - writeparm, eol, html ); - } - - p = s = outval; - while (( s = strchr( s, '$' )) != NULL ) { - *s++ = '\0'; - while ( ldap_utf8isspace( s )) { - ++s; - } - if ( html ) { - sprintf( buf, "
%s
%s", p, eol ); - } else { - sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol ); - } - (*writeproc)( writeparm, buf, strlen( buf )); - p = s; - } - outval = p; - ++writeoutval; - break; - - case LDAP_SYN_BOOLEAN: - outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE"; - ++writeoutval; - break; - - case LDAP_SYN_TIME: - case LDAP_SYN_DATE: - outval = time2text( outval, syntaxid == LDAP_SYN_DATE ); - ++writeoutval; - break; - - case LDAP_SYN_LABELEDURL: - if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) { - *p++ = '\0'; - while ( ldap_utf8isspace( p )) { - ++p; - } - s = outval; - } else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) { - *s++ = '\0'; - while ( ldap_utf8isspace( s )) { - ++s; - } - p = outval; - } else { - s = "URL"; - p = outval; - } - - /* - * at this point `s' points to the label & `p' to the URL - */ - if ( html ) { - sprintf( buf, "
%s
%s", p, s, eol ); - } else { - sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ", - s, eol, labelwidth + 2, " ",p , eol ); - } - (*writeproc)( writeparm, buf, strlen( buf )); - break; - - default: - sprintf( buf, " Can't display item type %ld%s", - syntaxid, eol ); - (*writeproc)( writeparm, buf, strlen( buf )); - } - - if ( writeoutval ) { - if ( html ) { - sprintf( buf, "
%s
%s", outval, eol ); - } else { - sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol ); - } - (*writeproc)( writeparm, buf, strlen( buf )); - } - } - - if ( freebuf ) { - NSLDAPI_FREE( buf ); - } - - return( LDAP_SUCCESS ); -} - - -static int -max_label_len( struct ldap_disptmpl *tmpl ) -{ - struct ldap_tmplitem *rowp, *colp; - int len, maxlen; - - maxlen = 0; - - for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM; - rowp = ldap_next_tmplrow( tmpl, rowp )) { - for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; - colp = ldap_next_tmplcol( tmpl, rowp, colp )) { - if (( len = strlen( colp->ti_label )) > maxlen ) { - maxlen = len; - } - } - } - - return( maxlen ); -} - - -static int -output_label( char *buf, char *label, int width, writeptype writeproc, - void *writeparm, char *eol, int html ) -{ - char *p; - - if ( html ) { - sprintf( buf, "
%s", label ); - } else { - auto size_t w; - sprintf( buf, " %s:", label ); - p = buf + strlen( buf ); - - for (w = ldap_utf8characters(buf); w < (size_t)width; ++w) { - *p++ = ' '; - } - - *p = '\0'; - strcat( buf, eol ); - } - - return ((*writeproc)( writeparm, buf, strlen( buf ))); -} - - -static int -output_dn( char *buf, char *dn, int width, int rdncount, - writeptype writeproc, void *writeparm, char *eol, char *urlprefix ) -{ - char **dnrdns; - int i; - - if (( dnrdns = ldap_explode_dn( dn, 1 )) == NULL ) { - return( -1 ); - } - - if ( urlprefix != NULL ) { - sprintf( buf, "
" ); - } else if ( width > 0 ) { - sprintf( buf, "%-*s", width, " " ); - } else { - *buf = '\0'; - } - - for ( i = 0; dnrdns[ i ] != NULL && ( rdncount == 0 || i < rdncount ); - ++i ) { - if ( i > 0 ) { - strcat( buf, ", " ); - } - strcat( buf, dnrdns[ i ] ); - } - - if ( urlprefix != NULL ) { - strcat( buf, "
" ); - } - - ldap_value_free( dnrdns ); - - strcat( buf, eol ); - - return ((*writeproc)( writeparm, buf, strlen( buf ))); -} - - - -#define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \ - ( c >= '@' && c <= 'Z' ) || \ - ( c == '_' ) || \ - ( c >= 'a' && c <= 'z' )) - -static void -strcat_escaped( char *s1, char *s2 ) -{ - char *p, *q; - char *hexdig = "0123456789ABCDEF"; - - p = s1 + strlen( s1 ); - for ( q = s2; *q != '\0'; ++q ) { - if ( HREF_CHAR_ACCEPTABLE( *q )) { - *p++ = *q; - } else { - *p++ = '%'; - *p++ = hexdig[ 0x0F & ((*(unsigned char*)q) >> 4) ]; - *p++ = hexdig[ 0x0F & *q ]; - } - } - - *p = '\0'; -} - - -#define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' )) - -static char * -time2text( char *ldtimestr, int dateonly ) -{ - int len; - struct tm t; - char *p, *timestr, zone, *fmterr = "badly formatted time"; - time_t gmttime; -/* CTIME for this platform doesn't use this. */ -#if !defined(SUNOS4) && !defined(BSDI) && !defined(LINUX1_2) && \ - !defined(SNI) && !defined(_WIN32) && !defined(macintosh) && !defined(LINUX) - char buf[26]; -#endif - - memset( (char *)&t, 0, sizeof( struct tm )); - if (( len = (int)strlen( ldtimestr )) < 13 ) { - return( fmterr ); - } - if ( len > 15 ) { /* throw away excess from 4-digit year time string */ - len = 15; - } else if ( len == 14 ) { - len = 13; /* assume we have a time w/2-digit year (len=13) */ - } - - for ( p = ldtimestr; p - ldtimestr + 1 < len; ++p ) { - if ( !isdigit( *p )) { - return( fmterr ); - } - } - - p = ldtimestr; - t.tm_year = GET2BYTENUM( p ); p += 2; - if ( len == 15 ) { - t.tm_year = 100 * (t.tm_year - 19); - t.tm_year += GET2BYTENUM( p ); p += 2; - } - else { - /* 2 digit years...assumed to be in the range (19)70 through - (20)69 ...less than 70 (for now, 38) means 20xx */ - if(t.tm_year < 70) { - t.tm_year += 100; - } - } - t.tm_mon = GET2BYTENUM( p ) - 1; p += 2; - t.tm_mday = GET2BYTENUM( p ); p += 2; - t.tm_hour = GET2BYTENUM( p ); p += 2; - t.tm_min = GET2BYTENUM( p ); p += 2; - t.tm_sec = GET2BYTENUM( p ); p += 2; - - if (( zone = *p ) == 'Z' ) { /* GMT */ - zone = '\0'; /* no need to indicate on screen, so we make it null */ - } - - gmttime = gtime( &t ); - timestr = NSLDAPI_CTIME( &gmttime, buf, sizeof(buf) ); - - timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */ - if ( dateonly ) { - strcpy( timestr + 11, timestr + 20 ); - } - - return( timestr ); -} - - - -/* gtime.c - inverse gmtime */ - -#if !defined( macintosh ) && !defined( _WINDOWS ) && !defined( DOS ) && !defined(XP_OS2) -#include -#endif /* !macintosh */ - -/* gtime(): the inverse of localtime(). - This routine was supplied by Mike Accetta at CMU many years ago. - */ - -static int dmsize[] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -#define dysize(y) \ - (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366))) - -/* -#define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900) -*/ -#define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y)) - -/* */ - -static long gtime ( struct tm *tm ) -{ - register int i, - sec, - mins, - hour, - mday, - mon, - year; - register long result; - - if ((sec = tm -> tm_sec) < 0 || sec > 59 - || (mins = tm -> tm_min) < 0 || mins > 59 - || (hour = tm -> tm_hour) < 0 || hour > 24 - || (mday = tm -> tm_mday) < 1 || mday > 31 - || (mon = tm -> tm_mon + 1) < 1 || mon > 12) - return ((long) -1); - if (hour == 24) { - hour = 0; - mday++; - } - year = YEAR (tm -> tm_year); - - result = 0L; - for (i = 1970; i < year; i++) - result += dysize (i); - if (dysize (year) == 366 && mon >= 3) - result++; - while (--mon) - result += dmsize[mon - 1]; - result += mday - 1; - result = 24 * result + hour; - result = 60 * result + mins; - result = 60 * result + sec; - - return result; -} - -static int -searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, char *dn, - struct ldap_tmplitem *tip, int labelwidth, int rdncount, - writeptype writeproc, void *writeparm, char *eol, char *urlprefix ) -{ - int err = LDAP_SUCCESS, lderr, i, count, html; - char **vals, **members; - char *value, *filtpattern, *attr, *selectname; - char *retattrs[2], filter[ 256 ]; - LDAPMessage *ldmp; - struct timeval timeout; - - html = ( urlprefix != NULL ); - - for ( i = 0; tip->ti_args != NULL && tip->ti_args[ i ] != NULL; ++i ) { - ; - } - if ( i < 3 ) { - return( LDAP_PARAM_ERROR ); - } - attr = tip->ti_args[ 0 ]; - filtpattern = tip->ti_args[ 1 ]; - retattrs[ 0 ] = tip->ti_args[ 2 ]; - retattrs[ 1 ] = NULL; - selectname = tip->ti_args[ 3 ]; - - vals = NULL; - if ( attr == NULL ) { - value = NULL; - } else if ( strcasecmp( attr, "-dnb" ) == 0 ) { - return( LDAP_PARAM_ERROR ); - } else if ( strcasecmp( attr, "-dnt" ) == 0 ) { - value = dn; - } else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) { - value = vals[ 0 ]; - } else { - value = NULL; - } - - ldap_build_filter( filter, sizeof( filter ), filtpattern, NULL, NULL, NULL, - value, NULL ); - - if ( html ) { - /* - * if we are generating HTML, we add an HREF link that embodies this - * search action as an LDAP URL, instead of actually doing the search - * now. - */ - sprintf( buf, "
%s

%s", - tip->ti_label, eol ); - if ((*writeproc)( writeparm, buf, strlen( buf )) < 0 ) { - return( LDAP_LOCAL_ERROR ); - } - return( LDAP_SUCCESS ); - } - - timeout.tv_sec = SEARCH_TIMEOUT_SECS; - timeout.tv_usec = 0; - -#ifdef CLDAP - if ( LDAP_IS_CLDAP( ld )) - lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs, - 0, &ldmp, NULL ); - else -#endif /* CLDAP */ - lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, - retattrs, 0, &timeout, &ldmp ); - - if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) { - if (( count = ldap_count_entries( ld, ldmp )) > 0 ) { - if (( members = (char **)NSLDAPI_MALLOC( (count + 1) - * sizeof(char *))) == NULL ) { - err = LDAP_NO_MEMORY; - } else { - for ( i = 0, entry = ldap_first_entry( ld, ldmp ); - entry != NULL; - entry = ldap_next_entry( ld, entry ), ++i ) { - members[ i ] = ldap_get_dn( ld, entry ); - } - members[ i ] = NULL; - - ldap_sort_values(ld,members, ldap_sort_strcasecmp); - - err = do_vals2text( ld, NULL, members, tip->ti_label, - html ? -1 : 0, LDAP_SYN_DN, writeproc, writeparm, - eol, rdncount, urlprefix ); - - ldap_value_free( members ); - } - } - ldap_msgfree( ldmp ); - } - - - if ( vals != NULL ) { - ldap_value_free( vals ); - } - - return(( err == LDAP_SUCCESS ) ? lderr : err ); -} diff --git a/ldap/c-sdk/libraries/libldap/tmpltest.c b/ldap/c-sdk/libraries/libldap/tmpltest.c deleted file mode 100644 index 35ee54e06d..0000000000 --- a/ldap/c-sdk/libraries/libldap/tmpltest.c +++ /dev/null @@ -1,319 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* tmpltest.c - implements a test/config templates. */ -#include -#include - -#ifdef _WINDOWS -#include -#endif - -#include "ldap-int.h" -#include "disptmpl.h" -#include "srchpref.h" - -#ifdef MACOS -#include -#include -#endif /* MACOS */ - -#ifdef NEEDPROTOS -void dump_tmpl( struct ldap_disptmpl *tmpl ); -void dump_srchpref( struct ldap_searchobj *sp ); -#else /* NEEDPROTOS */ -void dump_tmpl(); -void dump_srchpref(); -#endif /* NEEDPROTOS */ - - -#define NULLSTRINGIFNULL( s ) ( s == NULL ? "(null)" : s ) - - -int -main( int argc, char **argv ) -{ - struct ldap_disptmpl *templates, *dtp; - struct ldap_searchobj *so, *sop; - int err; - -#ifdef MACOS - ccommand( &argv ); - for ( argc = 0; argv[ argc ] != NULL; ++argc ) { - ; - } - cshow( stdout ); -#endif /* MACOS */ - - if (( err = ldap_init_templates( "ldaptemplates.conf", &templates )) - != 0 ) { - fprintf( stderr, "ldap_init_templates failed (%d)\n", err ); - exit( 1 ); - } - - if (( err = ldap_init_searchprefs( "ldapsearchprefs.conf", &so )) - != 0 ) { - fprintf( stderr, "ldap_init_searchprefs failed (%d)\n", err ); - exit( 1 ); - } - - if ( argc == 1 ) { - printf( "*** Display Templates:\n" ); - for ( dtp = ldap_first_disptmpl( templates ); dtp != NULLDISPTMPL; - dtp = ldap_next_disptmpl( templates, dtp )) { - dump_tmpl( dtp ); - printf( "\n\n" ); - } - - printf( "\n\n*** Search Objects:\n" ); - for ( sop = ldap_first_searchobj( so ); sop != NULLSEARCHOBJ; - sop = ldap_next_searchobj( so, sop )) { - dump_srchpref( sop ); - printf( "\n\n" ); - } - - } else { - if (( dtp = ldap_oc2template( ++argv, templates )) == NULL ) { - fprintf( stderr, "no matching template found\n" ); - } else { - dump_tmpl( dtp ); - } - } - - - ldap_free_templates( templates ); - ldap_free_searchprefs( so ); - - exit( 0 ); -} - - -static char *syn_name[] = { - "?", "CIS", "MLS", "DN", "BOOL", "JPEG", "JPEGBTN", "FAX", "FAXBTN", - "AUDIOBTN", "TIME", "DATE", "URL", "SEARCHACT", "LINKACT", "ADDDNACT", - "VERIFYACT", -}; - -static char *syn_type[] = { - "?", "txt", "img", "?", "bool", "?", "?", "?", "btn", - "?", "?", "?", "?", "?", "?", "?", - "action", "?" -}; - -static char *includeattrs[] = { "objectClass", "sn", NULL }; - -static char *item_opts[] = { - "ro", "sort", "1val", "hide", "required", "hideiffalse", NULL -}; - -static unsigned long item_opt_vals[] = { - LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, - LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, - LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, -}; - - -void -dump_tmpl( struct ldap_disptmpl *tmpl ) -{ - struct ldap_tmplitem *rowp, *colp; - int i, rowcnt, colcnt; - char **fetchattrs; - struct ldap_oclist *ocp; - struct ldap_adddeflist *adp; - - printf( "** Template \"%s\" (plural \"%s\", icon \"%s\")\n", - NULLSTRINGIFNULL( tmpl->dt_name ), - NULLSTRINGIFNULL( tmpl->dt_pluralname ), - NULLSTRINGIFNULL( tmpl->dt_iconname )); - - printf( "object class list:\n" ); - for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = ocp->oc_next ) { - for ( i = 0; ocp->oc_objclasses[ i ] != NULL; ++i ) { - printf( "%s%s", i == 0 ? " " : " & ", - NULLSTRINGIFNULL( ocp->oc_objclasses[ i ] )); - } - putchar( '\n' ); - } - putchar( '\n' ); - - printf( "template options: " ); - if ( tmpl->dt_options == 0L ) { - printf( "NONE\n" ); - } else { - printf( "%s %s %s\n", LDAP_IS_DISPTMPL_OPTION_SET( tmpl, - LDAP_DTMPL_OPT_ADDABLE ) ? "addable" : "", - LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALLOWMODRDN ) - ? "modrdn" : "", - LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALTVIEW ) - ? "altview" : "" ); - } - - printf( "authenticate as attribute: %s\n", tmpl->dt_authattrname != NULL ? - tmpl->dt_authattrname : "" ); - - printf( "default RDN attribute: %s\n", tmpl->dt_defrdnattrname != NULL ? - tmpl->dt_defrdnattrname : "NONE" ); - - printf( "default add location: %s\n", tmpl->dt_defaddlocation != NULL ? - tmpl->dt_defaddlocation : "NONE" ); - - printf( "\nnew entry value default rules:\n" ); - for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = adp->ad_next ) { - if ( adp->ad_source == LDAP_ADSRC_CONSTANTVALUE ) { - printf( " attribute %s <-- constant value \"%s\"\n", - NULLSTRINGIFNULL( adp->ad_attrname), - NULLSTRINGIFNULL( adp->ad_value )); - } else { - printf( " attribute %s <-- adder's DN\n", - NULLSTRINGIFNULL( adp->ad_attrname )); - } - } - putchar( '\n' ); - - printf( "\nfetch attributes & values:\n" ); - if (( fetchattrs = ldap_tmplattrs( tmpl, includeattrs, 1, - LDAP_SYN_OPT_DEFER )) == NULL ) { - printf( " \n" ); - } else { - for ( i = 0; fetchattrs[ i ] != NULL; ++i ) { - printf( " %s\n", fetchattrs[ i ] ); - free( fetchattrs[ i ] ); - } - free( (char *)fetchattrs ); - } - - printf( "\nfetch attributes only:\n" ); - if (( fetchattrs = ldap_tmplattrs( tmpl, NULL, 0, - LDAP_SYN_OPT_DEFER )) == NULL ) { - printf( " \n" ); - } else { - for ( i = 0; fetchattrs[ i ] != NULL; ++i ) { - printf( " %s\n", fetchattrs[ i ] ); - free( fetchattrs[ i ] ); - } - free( (char *)fetchattrs ); - } - - printf( "\ntemplate items:\n" ); - rowcnt = 0; - for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM; - rowp = ldap_next_tmplrow( tmpl, rowp )) { - ++rowcnt; - colcnt = 0; - for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; - colp = ldap_next_tmplcol( tmpl, rowp, colp )) { - ++colcnt; - printf( " %2d-%d: %s (%s%s", rowcnt, colcnt, - syn_name[ colp->ti_syntaxid & 0x0000FFFF ], - syn_type[ LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) >> 24 ], - (( LDAP_GET_SYN_OPTIONS( colp->ti_syntaxid ) & - LDAP_SYN_OPT_DEFER ) != 0 ) ? ",defer" : "" ); - - for ( i = 0; item_opts[ i ] != NULL; ++i ) { - if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, item_opt_vals[ i ] )) { - printf( ",%s", NULLSTRINGIFNULL( item_opts[ i ] )); - } - } - - printf( "), %s, %s", NULLSTRINGIFNULL( colp->ti_attrname ), - NULLSTRINGIFNULL( colp->ti_label )); - if ( colp->ti_args != NULL ) { - printf( ",args=" ); - for ( i = 0; colp->ti_args[ i ] != NULL; ++i ) { - printf( "<%s>", NULLSTRINGIFNULL( colp->ti_args[ i ] )); - } - } - - putchar( '\n' ); - } - } -} - - -void -dump_srchpref( struct ldap_searchobj *so ) -{ - int i; - struct ldap_searchattr *sa; - struct ldap_searchmatch *sm; - - printf( "Object type prompt: %s\n", - NULLSTRINGIFNULL( so->so_objtypeprompt )); - printf( "Options: %s\n", - LDAP_IS_SEARCHOBJ_OPTION_SET( so, LDAP_SEARCHOBJ_OPT_INTERNAL ) ? - "internal" : "NONE" ); - printf( "Prompt: %s\n", NULLSTRINGIFNULL( so->so_prompt )); - printf( "Scope: " ); - switch ( so->so_defaultscope ) { - case LDAP_SCOPE_BASE: - printf( "LDAP_SCOPE_BASE" ); - break; - case LDAP_SCOPE_ONELEVEL: - printf( "LDAP_SCOPE_ONELEVEL" ); - break; - case LDAP_SCOPE_SUBTREE: - printf( "LDAP_SCOPE_SUBTREE" ); - break; - default: - printf("*** unknown!" ); - } - puts( "\n" ); - printf( "Filter prefix: %s\n", - NULLSTRINGIFNULL( so->so_filterprefix )); - printf( "Filter tag: %s\n", - NULLSTRINGIFNULL( so->so_filtertag )); - printf( "Default select attr: %s\n", - NULLSTRINGIFNULL( so->so_defaultselectattr )); - printf( "Default select text: %s\n", - NULLSTRINGIFNULL( so->so_defaultselecttext )); - printf( "Searchable attributes ---- \n" ); - for ( sa = so->so_salist; sa != NULL; sa = sa->sa_next ) { - printf( " Label: %s\n", NULLSTRINGIFNULL( sa->sa_attrlabel )); - printf( " Attribute: %s\n", NULLSTRINGIFNULL( sa->sa_attr )); - printf( " Select attr: %s\n", NULLSTRINGIFNULL( sa->sa_selectattr )); - printf( " Select text: %s\n", NULLSTRINGIFNULL( sa->sa_selecttext )); - printf( " Match types ---- \n" ); - for ( i = 0, sm = so->so_smlist; sm != NULL; i++, sm = sm->sm_next ) { - if (( sa->sa_matchtypebitmap >> i ) & 1 ) { - printf( " %s (%s)\n", - NULLSTRINGIFNULL( sm->sm_matchprompt ), - NULLSTRINGIFNULL( sm->sm_filter )); - } - } - } -} diff --git a/ldap/c-sdk/libraries/libldap/ufn.c b/ldap/c-sdk/libraries/libldap/ufn.c deleted file mode 100644 index 54e737e158..0000000000 --- a/ldap/c-sdk/libraries/libldap/ufn.c +++ /dev/null @@ -1,563 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ -/* - * ufn.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -typedef int (LDAP_CALL *cancelptype)( void *cancelparm ); - -static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, - char *prefix, char **attrs, int attrsonly, - LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, - char *tag1, char *tag2, char *tag3 ); -static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ); -static LDAPMessage *ldap_ufn_expand( LDAP *ld, - LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char **dns, - char *filter, int scope, char **attrs, int aonly, int *err ); - -/* - * ldap_ufn_search_ctx - do user friendly searching; provide cancel feature; - * specify ldapfilter.conf tags for each phase of search - * - * ld LDAP descriptor - * ufncomp the exploded user friendly name to look for - * ncomp number of elements in ufncomp - * prefix where to start searching - * attrs list of attribute types to return for matches - * attrsonly 1 => attributes only 0 => attributes and values - * res will contain the result of the search - * cancelproc routine that returns non-zero if operation should be - * cancelled. This can be NULL. If it is non-NULL, the - * routine will be called periodically. - * cancelparm void * that is passed to cancelproc - * tag[123] the ldapfilter.conf tag that will be used in phases - * 1, 2, and 3 of the search, respectively - * - * Example: - * char *attrs[] = { "mail", "title", 0 }; - * char *ufncomp[] = { "howes", "umich", "us", 0 } - * LDAPMessage *res; - * error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly, - * &res, acancelproc, along, "ufn first", - * "ufn intermediate", "ufn last" ); - */ - -static int -ldap_ufn_search_ctx( - LDAP *ld, - char **ufncomp, - int ncomp, - char *prefix, - char **attrs, - int attrsonly, - LDAPMessage **res, - LDAP_CANCELPROC_CALLBACK *cancelproc, - void *cancelparm, - char *tag1, - char *tag2, - char *tag3 -) -{ - char *dn, *ftag = NULL; - char **dns = NULL; - int max, i, err, scope = 0, phase, tries; - LDAPFiltInfo *fi; - LDAPMessage *tmpcand; - LDAPMessage *candidates; - static char *objattrs[] = { "objectClass", NULL }; - - /* - * look up ufn components from most to least significant. - * there are 3 phases. - * phase 1 search the root for orgs or countries - * phase 2 search for orgs - * phase 3 search for a person - * in phases 1 and 2, we are building a list of candidate DNs, - * below which we will search for the final component of the ufn. - * for each component we try the filters listed in the - * filterconfig file, first one-level (except the last compoment), - * then subtree. if any of them produce any results, we go on to - * the next component. - */ - - *res = NULL; - candidates = NULL; - phase = 1; - for ( ncomp--; ncomp != -1; ncomp-- ) { - if ( *ufncomp[ncomp] == '"' ) { - char *quote; - - if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL ) - *quote = '\0'; - strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 ); - } - if ( ncomp == 0 ) - phase = 3; - - switch ( phase ) { - case 1: - ftag = tag1; - scope = LDAP_SCOPE_ONELEVEL; - break; - case 2: - ftag = tag2; - scope = LDAP_SCOPE_ONELEVEL; - break; - case 3: - ftag = tag3; - scope = LDAP_SCOPE_SUBTREE; - break; - } - - /* - * construct an array of DN's to search below from the - * list of candidates. - */ - - if ( candidates == NULL ) { - if ( prefix != NULL ) { - if ( (dns = (char **)NSLDAPI_MALLOC( - sizeof(char *) * 2 )) == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - dns[0] = nsldapi_strdup( prefix ); - dns[1] = NULL; - } else { - dns = NULL; - } - } else { - i = 0, max = 0; - for ( tmpcand = candidates; tmpcand != NULL && - tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT; - tmpcand = tmpcand->lm_chain ) - { - if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL ) - continue; - - if ( dns == NULL ) { - if ( (dns = (char **)NSLDAPI_MALLOC( - sizeof(char *) * 8 )) == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, - NULL, NULL ); - return( err ); - } - max = 8; - } else if ( i >= max ) { - if ( (dns = (char **)NSLDAPI_REALLOC( - dns, sizeof(char *) * 2 * max )) - == NULL ) { - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, - NULL, NULL ); - return( err ); - } - max *= 2; - } - dns[i++] = dn; - dns[i] = NULL; - } - ldap_msgfree( candidates ); - candidates = NULL; - } - tries = 0; - tryagain: - tries++; - for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag, - ufncomp[ncomp] ); fi != NULL; - fi = ldap_getnextfilter( ld->ld_filtd ) ) - { - if ( (candidates = ldap_ufn_expand( ld, cancelproc, - cancelparm, dns, fi->lfi_filter, scope, - phase == 3 ? attrs : objattrs, - phase == 3 ? attrsonly : 1, &err )) != NULL ) - { - break; - } - - if ( err == -1 || err == LDAP_USER_CANCELLED ) { - if ( dns != NULL ) { - ldap_value_free( dns ); - dns = NULL; - } - return( err ); - } - } - - if ( candidates == NULL ) { - if ( tries < 2 && phase != 3 ) { - scope = LDAP_SCOPE_SUBTREE; - goto tryagain; - } else { - if ( dns != NULL ) { - ldap_value_free( dns ); - dns = NULL; - } - return( err ); - } - } - - /* go on to the next component */ - if ( phase == 1 ) - phase++; - if ( dns != NULL ) { - ldap_value_free( dns ); - dns = NULL; - } - } - *res = candidates; - - return( err ); -} - -int -LDAP_CALL -ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly, - LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, - char *tag1, char *tag2, char *tag3 ) -{ - char **ufncomp, **prefixcomp; - char *pbuf; - int ncomp, pcomp, i, err = 0; - - /* getfilter stuff must be inited before we are called */ - if ( ld->ld_filtd == NULL ) { - err = LDAP_PARAM_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - /* call ldap_explode_dn() to break the ufn into its components */ - if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) { - err = LDAP_LOCAL_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ ) - ; /* NULL */ - - /* more than two components => try it fully qualified first */ - if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) { - err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs, - attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); - - if ( ldap_count_entries( ld, *res ) > 0 ) { - ldap_value_free( ufncomp ); - return( err ); - } else { - ldap_msgfree( *res ); - *res = NULL; - } - } - - if ( ld->ld_ufnprefix == NULL ) { - ldap_value_free( 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 ); - err = LDAP_LOCAL_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ ) - ; /* NULL */ - if ( (pbuf = (char *)NSLDAPI_MALLOC( strlen( ld->ld_ufnprefix ) + 1 )) - == NULL ) { - ldap_value_free( ufncomp ); - ldap_value_free( prefixcomp ); - err = LDAP_NO_MEMORY; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - for ( i = 0; i < pcomp; i++ ) { - int j; - - *pbuf = '\0'; - for ( j = i; j < pcomp; j++ ) { - strcat( pbuf, prefixcomp[j] ); - if ( j + 1 < pcomp ) - strcat( pbuf, "," ); - } - err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs, - attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); - - if ( ldap_count_entries( ld, *res ) > 0 ) { - break; - } else { - ldap_msgfree( *res ); - *res = NULL; - } - } - - ldap_value_free( ufncomp ); - ldap_value_free( prefixcomp ); - NSLDAPI_FREE( pbuf ); - - return( err ); -} - -/* - * same as ldap_ufn_search_ct, except without the ability to specify - * ldapfilter.conf tags. - */ -int -LDAP_CALL -ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly, - LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm ) -{ - return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc, - cancelparm, "ufn first", "ufn intermediate", "ufn last" ) ); -} - -/* - * same as ldap_ufn_search_c without the cancel function - */ -int -LDAP_CALL -ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly, - LDAPMessage **res ) -{ - struct timeval tv; - - tv.tv_sec = ld->ld_timelimit; - - return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, - ld->ld_timelimit ? ldap_ufn_timeout : NULL, - ld->ld_timelimit ? (void *) &tv : NULL, - "ufn first", "ufn intermediate", "ufn last" ) ); -} - - -/* - * ldap_msg_merge - merge two ldap search result chains. the more - * serious of the two error result codes is kept. - */ - -static LDAPMessage * -ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ) -{ - LDAPMessage *end, *aprev, *aend, *bprev, *bend; - - if ( a == NULL ) - return( b ); - - if ( b == NULL ) - return( a ); - - /* find the ends of the a and b chains */ - aprev = NULL; - for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain ) - aprev = aend; - bprev = NULL; - for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain ) - bprev = bend; - - /* keep result a */ - if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) { - /* remove result b */ - ldap_msgfree( bend ); - if ( bprev != NULL ) - bprev->lm_chain = NULL; - else - b = NULL; - end = aend; - if ( aprev != NULL ) - aprev->lm_chain = NULL; - else - a = NULL; - /* keep result b */ - } else { - /* remove result a */ - ldap_msgfree( aend ); - if ( aprev != NULL ) - aprev->lm_chain = NULL; - else - a = NULL; - end = bend; - if ( bprev != NULL ) - bprev->lm_chain = NULL; - else - b = NULL; - } - - if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) || - (b == NULL && aprev == NULL) ) - return( end ); - - if ( a == NULL ) { - bprev->lm_chain = end; - return( b ); - } else if ( b == NULL ) { - aprev->lm_chain = end; - return( a ); - } else { - bprev->lm_chain = end; - aprev->lm_chain = b; - return( a ); - } -} - -static LDAPMessage * -ldap_ufn_expand( LDAP *ld, LDAP_CANCELPROC_CALLBACK *cancelproc, - void *cancelparm, char **dns, char *filter, int scope, - char **attrs, int aonly, int *err ) -{ - LDAPMessage *tmpcand, *tmpres; - char *dn; - int i, msgid; - struct timeval tv; - - /* search for this component below the current candidates */ - tmpcand = NULL; - i = 0; - do { - if ( dns != NULL ) - dn = dns[i]; - else - dn = ""; - - if (( msgid = ldap_search( ld, dn, scope, filter, attrs, - aonly )) == -1 ) { - ldap_msgfree( tmpcand ); - tmpcand = NULL; - *err = LDAP_GET_LDERRNO( ld, NULL, NULL ); - /* - * Compiling with gcc-4.2 on Mac: - * gcc-4.2 -arch ppc -c -o ufn.o -gdwarf-2 -01 ufn.c - * having a return NULL statement here causes gcc to - * hang. Therefore set tmpcand to null (above) and break - * out of this loop to make gcc happy. - */ - break; - } - - tv.tv_sec = 0; - tv.tv_usec = 100000; /* 1/10 of a second */ - - do { - *err = ldap_result( ld, msgid, 1, &tv, &tmpres ); - if ( *err == 0 && cancelproc != NULL && - (*cancelproc)( cancelparm ) != 0 ) { - ldap_abandon( ld, msgid ); - *err = LDAP_USER_CANCELLED; - LDAP_SET_LDERRNO( ld, *err, NULL, NULL ); - } - } while ( *err == 0 ); - - if ( *err == LDAP_USER_CANCELLED || *err < 0 || - ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) { - ldap_msgfree( tmpcand ); - return( NULL ); - } - - tmpcand = ldap_msg_merge( ld, tmpcand, tmpres ); - - i++; - } while ( dns != NULL && dns[i] != NULL ); - - /* Catch the tmpcand = NULL case as required by breaking out the loop - * to prevent gcc-4.2 hanging on Mac. - */ - if (!tmpcand) - return NULL; - - if ( ldap_count_entries( ld, tmpcand ) > 0 ) { - return( tmpcand ); - } else { - ldap_msgfree( tmpcand ); - return( NULL ); - } -} - -/* - * ldap_ufn_setfilter - set the filter config file used in ufn searching - */ - -LDAPFiltDesc * -LDAP_CALL -ldap_ufn_setfilter( LDAP *ld, char *fname ) -{ - if ( ld->ld_filtd != NULL ) - ldap_getfilter_free( ld->ld_filtd ); - - return( ld->ld_filtd = ldap_init_getfilter( fname ) ); -} - -void -LDAP_CALL -ldap_ufn_setprefix( LDAP *ld, char *prefix ) -{ - if ( ld->ld_ufnprefix != NULL ) - NSLDAPI_FREE( ld->ld_ufnprefix ); - - ld->ld_ufnprefix = nsldapi_strdup( prefix ); -} - -int -LDAP_C -ldap_ufn_timeout( void *tvparam ) -{ - struct timeval *tv; - - tv = (struct timeval *)tvparam; - - if ( tv->tv_sec != 0 ) { - tv->tv_usec = tv->tv_sec * 1000000; /* sec => micro sec */ - tv->tv_sec = 0; - } - tv->tv_usec -= 100000; /* 1/10 of a second */ - - return( tv->tv_usec <= 0 ? 1 : 0 ); -} diff --git a/ldap/c-sdk/libraries/libldap/unbind.c b/ldap/c-sdk/libraries/libldap/unbind.c deleted file mode 100644 index 95ca49411f..0000000000 --- a/ldap/c-sdk/libraries/libldap/unbind.c +++ /dev/null @@ -1,248 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - */ - -/* - * unbind.c - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - -int -LDAP_CALL -ldap_unbind( LDAP *ld ) -{ - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 ); - - return( ldap_ld_free( ld, NULL, NULL, 1 ) ); -} - - -int -LDAP_CALL -ldap_unbind_s( LDAP *ld ) -{ - return( ldap_ld_free( ld, NULL, NULL, 1 )); -} - - -int -LDAP_CALL -ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - return( ldap_ld_free( ld, serverctrls, clientctrls, 1 )); -} - - -/* - * Dispose of the LDAP session ld, including all associated connections - * and resources. If close is non-zero, an unbind() request is sent as well. - */ -int -ldap_ld_free( LDAP *ld, LDAPControl **serverctrls, - LDAPControl **clientctrls, int close ) -{ - LDAPMessage *lm, *next; - int err = LDAP_SUCCESS; - LDAPRequest *lr, *nextlr; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ld->ld_sbp->sb_naddr == 0 ) { - LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); - /* free LDAP structure and outstanding requests/responses */ - for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) { - nextlr = lr->lr_next; - nsldapi_free_request( ld, lr, 0 ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); - - /* free and unbind from all open connections */ - LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); - while ( ld->ld_conns != NULL ) { - nsldapi_free_connection( ld, ld->ld_conns, serverctrls, - clientctrls, 1, close ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); - - } else { - int i; - - for ( i = 0; i < ld->ld_sbp->sb_naddr; ++i ) { - NSLDAPI_FREE( ld->ld_sbp->sb_addrs[ i ] ); - } - NSLDAPI_FREE( ld->ld_sbp->sb_addrs ); - NSLDAPI_FREE( ld->ld_sbp->sb_fromaddr ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_RESP_LOCK ); - for ( lm = ld->ld_responses; lm != NULL; lm = next ) { - next = lm->lm_next; - ldap_msgfree( lm ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_RESP_LOCK ); - - /* call cache unbind function to allow it to clean up after itself */ - if ( ld->ld_cache_unbind != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - (void)ld->ld_cache_unbind( ld, 0, 0 ); - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* call the dispose handle I/O callback if one is defined */ - if ( ld->ld_extdisposehandle_fn != NULL ) { - /* - * We always pass the session extended I/O argument to - * the dispose handle callback. - */ - ld->ld_extdisposehandle_fn( ld, ld->ld_ext_session_arg ); - } - - if ( ld->ld_error != NULL ) - NSLDAPI_FREE( ld->ld_error ); - if ( ld->ld_matched != NULL ) - NSLDAPI_FREE( ld->ld_matched ); - if ( ld->ld_host != NULL ) - NSLDAPI_FREE( ld->ld_host ); - if ( ld->ld_ufnprefix != NULL ) - NSLDAPI_FREE( ld->ld_ufnprefix ); - if ( ld->ld_filtd != NULL ) - ldap_getfilter_free( ld->ld_filtd ); - if ( ld->ld_abandoned != NULL ) - NSLDAPI_FREE( ld->ld_abandoned ); - if ( ld->ld_sbp != NULL ) - ber_sockbuf_free( ld->ld_sbp ); - if ( ld->ld_defhost != NULL ) - NSLDAPI_FREE( ld->ld_defhost ); - if ( ld->ld_servercontrols != NULL ) - ldap_controls_free( ld->ld_servercontrols ); - if ( ld->ld_clientcontrols != NULL ) - ldap_controls_free( ld->ld_clientcontrols ); - if ( ld->ld_preferred_language != NULL ) - NSLDAPI_FREE( ld->ld_preferred_language ); - nsldapi_iostatus_free( ld ); -#ifdef LDAP_SASLIO_HOOKS - NSLDAPI_FREE( ld->ld_def_sasl_mech ); - NSLDAPI_FREE( ld->ld_def_sasl_realm ); - NSLDAPI_FREE( ld->ld_def_sasl_authcid ); - NSLDAPI_FREE( ld->ld_def_sasl_authzid ); -#endif - - /* - * XXXmcs: should use cache function pointers to hook in memcache - */ - if ( ld->ld_memcache != NULL ) { - ldap_memcache_set( ld, NULL ); - } - - /* free all mutexes we have allocated */ - nsldapi_mutex_free_all( ld ); - NSLDAPI_FREE( ld->ld_mutex ); - - NSLDAPI_FREE( (char *) ld ); - - return( err ); -} - - - -int -nsldapi_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **serverctrls, - LDAPControl **clientctrls ) -{ - BerElement *ber; - int err, msgid; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_unbind\n", 0, 0, 0 ); - - /* create a message to send */ - if (( err = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( err ); - } - - /* fill it in */ - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if ( ber_printf( ber, "{itn", msgid, LDAP_REQ_UNBIND ) == -1 ) { - ber_free( ber, 1 ); - err = LDAP_ENCODING_ERROR; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - - if (( err = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( err ); - } - - /* send the message */ - err = nsldapi_send_ber_message( ld, sb, ber, 1 /* free ber */, - 0 /* will not handle EPIPE */ ); - if ( err != 0 ) { - ber_free( ber, 1 ); - if (err != -2 ) { - /* - * Message could not be sent, and the reason is - * something other than a "would block" error. - * Note that we ignore "would block" errors because - * it is not critical that an UnBind request - * actually reach the LDAP server. - */ - err = LDAP_SERVER_DOWN; - LDAP_SET_LDERRNO( ld, err, NULL, NULL ); - return( err ); - } - } - - return( LDAP_SUCCESS ); -} diff --git a/ldap/c-sdk/libraries/libldap/unescape.c b/ldap/c-sdk/libraries/libldap/unescape.c deleted file mode 100644 index 66d5bd27ff..0000000000 --- a/ldap/c-sdk/libraries/libldap/unescape.c +++ /dev/null @@ -1,84 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * LIBLDAP unescape.c -- LDAP URL un-escape routines - * We also tolerate URLs that look like: and - */ - -#include "ldap-int.h" - - -static int unhex( char c ); - - -void -nsldapi_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. - */ - char *p; - - for ( p = s; *s != '\0'; ++s ) { - if ( *s == '%' ) { - if ( *++s == '\0' ) { - break; - } - *p = unhex( *s ) << 4; - if ( *++s == '\0' ) { - break; - } - *p++ += unhex( *s ); - - } else { - *p++ = *s; - } - } - - *p = '\0'; -} - - -static int -unhex( char c ) -{ - return( c >= '0' && c <= '9' ? c - '0' - : c >= 'A' && c <= 'F' ? c - 'A' + 10 - : c - 'a' + 10 ); -} diff --git a/ldap/c-sdk/libraries/libldap/url.c b/ldap/c-sdk/libraries/libldap/url.c deleted file mode 100644 index 789ee3ac2a..0000000000 --- a/ldap/c-sdk/libraries/libldap/url.c +++ /dev/null @@ -1,527 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (c) 1996 Regents of the University of Michigan. - * All rights reserved. - * - */ -/* LIBLDAP url.c -- LDAP URL related routines - * - * LDAP URLs look like this: - * l d a p : / / [ hostport ] [ / dn [ ? [ attributes ] [ ? [ scope ] - * [ ? [ filter ] [ ? extensions ] ] ] ] ] - * - * where: - * hostport is a host or a host:port list that can be space-separated. - * attributes is a comma separated list - * scope is one of these three strings: base one sub (default=base) - * filter is a string-represented filter as in RFC 2254 - * extensions is a comma-separated list of name=value pairs. - * - * e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich - * - * To accomodate IPv6 addresses, the host portion of a host that appears - * in hostport can be enclosed in square brackets, e.g - * - * e.g., ldap://[fe80::a00:20ff:fee5:c0b4]:3389/dc=siroe,dc=com - * - * We also tolerate URLs that look like: and - */ - -#if 0 -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif -#endif - -#include "ldap-int.h" - - -static int skip_url_prefix( const char **urlp, int *enclosedp, int *securep ); - - -int -LDAP_CALL -ldap_is_ldap_url( const char *url ) -{ - int enclosed, secure; - - return( url != NULL - && skip_url_prefix( &url, &enclosed, &secure )); -} - - -static int -skip_url_prefix( const char **urlp, int *enclosedp, int *securep ) -{ -/* - * return non-zero if this looks like a LDAP URL; zero if not - * if non-zero returned, *urlp will be moved past "ldap://" part of URL - * The data that *urlp points to is not changed by this function. - */ - if ( *urlp == NULL ) { - return( 0 ); - } - - /* skip leading '<' (if any) */ - if ( **urlp == '<' ) { - *enclosedp = 1; - ++*urlp; - } else { - *enclosedp = 0; - } - - /* skip leading "URL:" (if any) */ - if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp( - *urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { - *urlp += LDAP_URL_URLCOLON_LEN; - } - - /* check for an "ldap://" prefix */ - if ( strlen( *urlp ) >= LDAP_URL_PREFIX_LEN && strncasecmp( *urlp, - LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { - /* skip over URL prefix and return success */ - *urlp += LDAP_URL_PREFIX_LEN; - *securep = 0; - return( 1 ); - } - - /* check for an "ldaps://" prefix */ - if ( strlen( *urlp ) >= LDAPS_URL_PREFIX_LEN && strncasecmp( *urlp, - LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { - /* skip over URL prefix and return success */ - *urlp += LDAPS_URL_PREFIX_LEN; - *securep = 1; - return( 1 ); - } - - return( 0 ); /* not an LDAP URL */ -} - - -int -LDAP_CALL -ldap_url_parse_no_defaults( const char *url, LDAPURLDesc **ludpp, int dn_required) -{ - return( nsldapi_url_parse( url, ludpp, dn_required ) ); -} - - -int -LDAP_CALL -ldap_url_parse( const char *url, LDAPURLDesc **ludpp ) -{ -/* - * Pick apart the pieces of an LDAP URL. - */ - int rc; - - if (( rc = nsldapi_url_parse( url, ludpp, 1 )) == 0 ) { - if ( (*ludpp)->lud_scope == -1 ) { - (*ludpp)->lud_scope = LDAP_SCOPE_BASE; - } - if ( (*ludpp)->lud_filter == NULL ) { - (*ludpp)->lud_filter = "(objectclass=*)"; - } - if ( *((*ludpp)->lud_dn) == '\0' ) { - (*ludpp)->lud_dn = NULL; - } - } else if ( rc == LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION ) { - rc = LDAP_URL_ERR_PARAM; /* mapped for backwards compatibility */ - } - - return( rc ); -} - - -/* - * like ldap_url_parse() with a few exceptions: - * 1) if dn_required is zero, a missing DN does not generate an error - * (we just leave the lud_dn field NULL) - * 2) no defaults are set for lud_scope and lud_filter (they are set to -1 - * and NULL respectively if no SCOPE or FILTER are present in the URL). - * 3) when there is a zero-length DN in a URL we do not set lud_dn to NULL. - * - * note that LDAPv3 URL extensions are ignored unless they are marked - * critical, in which case an LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION error - * is returned. - */ -int -nsldapi_url_parse( const char *url, LDAPURLDesc **ludpp, int dn_required ) -{ - - LDAPURLDesc *ludp; - char *urlcopy, *attrs, *scope, *extensions = NULL, *p, *q; - int enclosed, secure, i, nattrs, at_start; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_url_parse(%s)\n", url, 0, 0 ); - - if ( url == NULL || ludpp == NULL ) { - return( LDAP_URL_ERR_PARAM ); - } - - *ludpp = NULL; /* pessimistic */ - - if ( !skip_url_prefix( &url, &enclosed, &secure )) { - return( LDAP_URL_ERR_NOTLDAP ); - } - - /* allocate return struct */ - if (( ludp = (LDAPURLDesc *)NSLDAPI_CALLOC( 1, sizeof( LDAPURLDesc ))) - == NULLLDAPURLDESC ) { - return( LDAP_URL_ERR_MEM ); - } - - if ( secure ) { - ludp->lud_options |= LDAP_URL_OPT_SECURE; - } - - /* make working copy of the remainder of the URL */ - if (( urlcopy = nsldapi_strdup( url )) == NULL ) { - ldap_free_urldesc( ludp ); - return( LDAP_URL_ERR_MEM ); - } - - if ( enclosed && *((p = urlcopy + strlen( urlcopy ) - 1)) == '>' ) { - *p = '\0'; - } - - /* initialize scope and filter */ - ludp->lud_scope = -1; - ludp->lud_filter = NULL; - - /* lud_string is the only malloc'd string space we use */ - ludp->lud_string = urlcopy; - - /* scan forward for '/' that marks end of hostport and begin. of dn */ - if (( ludp->lud_dn = strchr( urlcopy, '/' )) == NULL ) { - if ( dn_required ) { - ldap_free_urldesc( ludp ); - return( LDAP_URL_ERR_NODN ); - } - } else { - /* terminate hostport; point to start of dn */ - *ludp->lud_dn++ = '\0'; - } - - - if ( *urlcopy == '\0' ) { - ludp->lud_host = NULL; - } else { - ludp->lud_host = urlcopy; - nsldapi_hex_unescape( ludp->lud_host ); - - /* - * Locate and strip off optional port number (:#) in host - * portion of URL. - * - * If more than one space-separated host is listed, we only - * look for a port number within the right-most one since - * ldap_init() will handle host parameters that look like - * host:port anyway. - */ - if (( p = strrchr( ludp->lud_host, ' ' )) == NULL ) { - p = ludp->lud_host; - } else { - ++p; - } - if ( *p == '[' && ( q = strchr( p, ']' )) != NULL ) { - /* square brackets present -- skip past them */ - p = q++; - } - if (( p = strchr( p, ':' )) != NULL ) { - *p++ = '\0'; - ludp->lud_port = atoi( p ); - if ( *ludp->lud_host == '\0' ) { - ludp->lud_host = NULL; /* no hostname */ - } - } - } - - /* scan for '?' that marks end of dn and beginning of attributes */ - attrs = NULL; - if ( ludp->lud_dn != NULL && - ( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) { - /* terminate dn; point to start of attrs. */ - *attrs++ = '\0'; - - /* scan for '?' that marks end of attrs and begin. of scope */ - if (( p = strchr( attrs, '?' )) != NULL ) { - /* - * terminate attrs; point to start of scope and scan for - * '?' that marks end of scope and begin. of filter - */ - *p++ = '\0'; - scope = p; - - if (( p = strchr( scope, '?' )) != NULL ) { - /* terminate scope; point to start of filter */ - *p++ = '\0'; - if ( *p != '\0' ) { - ludp->lud_filter = p; - /* - * scan for the '?' that marks the end - * of the filter and the start of any - * extensions - */ - if (( p = strchr( ludp->lud_filter, '?' )) - != NULL ) { - *p++ = '\0'; /* term. filter */ - extensions = p; - } - if ( *ludp->lud_filter == '\0' ) { - ludp->lud_filter = NULL; - } else { - nsldapi_hex_unescape( ludp->lud_filter ); - } - } - } - - if ( strcasecmp( scope, "one" ) == 0 ) { - ludp->lud_scope = LDAP_SCOPE_ONELEVEL; - } else if ( strcasecmp( scope, "base" ) == 0 ) { - ludp->lud_scope = LDAP_SCOPE_BASE; - } else if ( strcasecmp( scope, "sub" ) == 0 ) { - ludp->lud_scope = LDAP_SCOPE_SUBTREE; - } else if ( *scope != '\0' ) { - ldap_free_urldesc( ludp ); - return( LDAP_URL_ERR_BADSCOPE ); - } - } - } - - if ( ludp->lud_dn != NULL ) { - nsldapi_hex_unescape( ludp->lud_dn ); - } - - /* - * if attrs list was included, turn it into a null-terminated array - */ - if ( attrs != NULL && *attrs != '\0' ) { - nsldapi_hex_unescape( attrs ); - for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) { - if ( *p == ',' ) { - ++nattrs; - } - } - - if (( ludp->lud_attrs = (char **)NSLDAPI_CALLOC( nattrs + 1, - sizeof( char * ))) == NULL ) { - ldap_free_urldesc( ludp ); - return( LDAP_URL_ERR_MEM ); - } - - for ( i = 0, p = attrs; i < nattrs; ++i ) { - ludp->lud_attrs[ i ] = p; - if (( p = strchr( p, ',' )) != NULL ) { - *p++ ='\0'; - } - nsldapi_hex_unescape( ludp->lud_attrs[ i ] ); - } - } - - /* if extensions list was included, check for critical ones */ - if ( extensions != NULL && *extensions != '\0' ) { - /* Note: at present, we do not recognize ANY extensions */ - at_start = 1; - for ( p = extensions; *p != '\0'; ++p ) { - if ( at_start ) { - if ( *p == '!' ) { /* critical extension */ - ldap_free_urldesc( ludp ); - return( LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION ); - } - at_start = 0; - } else if ( *p == ',' ) { - at_start = 1; - } - } - } - - *ludpp = ludp; - - return( 0 ); -} - - -void -LDAP_CALL -ldap_free_urldesc( LDAPURLDesc *ludp ) -{ - if ( ludp != NULLLDAPURLDESC ) { - if ( ludp->lud_string != NULL ) { - NSLDAPI_FREE( ludp->lud_string ); - } - if ( ludp->lud_attrs != NULL ) { - NSLDAPI_FREE( ludp->lud_attrs ); - } - NSLDAPI_FREE( ludp ); - } -} - - -int -LDAP_CALL -ldap_url_search( LDAP *ld, const char *url, int attrsonly ) -{ - int err, msgid; - LDAPURLDesc *ludp; - BerElement *ber; - LDAPServer *srv; - char *host; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( -1 ); /* punt */ - } - - if ( ldap_url_parse( url, &ludp ) != 0 ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( -1 ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if ( nsldapi_build_search_req( ld, ludp->lud_dn, ludp->lud_scope, - ludp->lud_filter, ludp->lud_attrs, attrsonly, NULL, NULL, - -1, -1, msgid, &ber ) != LDAP_SUCCESS ) { - return( -1 ); - } - - err = 0; - - if ( ludp->lud_host == NULL ) { - host = ld->ld_defhost; - } else { - host = ludp->lud_host; - } - - if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) - == NULL || ( host != NULL && - ( srv->lsrv_host = nsldapi_strdup( host )) == NULL )) { - if ( srv != NULL ) { - NSLDAPI_FREE( srv ); - } - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - err = -1; - } else { - if ( ludp->lud_port != 0 ) { - /* URL includes a port - use it */ - srv->lsrv_port = ludp->lud_port; - } else if ( ludp->lud_host == NULL ) { - /* URL has no port or host - use port from ld */ - srv->lsrv_port = ld->ld_defport; - } else if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) == 0 ) { - /* ldap URL has a host but no port - use std. port */ - srv->lsrv_port = LDAP_PORT; - } else { - /* ldaps URL has a host but no port - use std. port */ - srv->lsrv_port = LDAPS_PORT; - } - } - - if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ) { - srv->lsrv_options |= LDAP_SRV_OPT_SECURE; - } - - if ( err != 0 ) { - ber_free( ber, 1 ); - } else { - err = nsldapi_send_server_request( ld, ber, msgid, NULL, srv, - NULL, NULL, 1 ); - } - - ldap_free_urldesc( ludp ); - return( err ); -} - - -int -LDAP_CALL -ldap_url_search_st( LDAP *ld, const char *url, int attrsonly, - struct timeval *timeout, LDAPMessage **res ) -{ - int msgid; - - /* - * It is an error to pass in a zero'd timeval. - */ - if ( timeout != NULL && timeout->tv_sec == 0 && - timeout->tv_usec == 0 ) { - if ( ld != NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - } - if ( res != NULL ) { - *res = NULL; - } - return( LDAP_PARAM_ERROR ); - } - - if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) { - (void) ldap_abandon( ld, msgid ); - LDAP_SET_LDERRNO( ld, LDAP_TIMEOUT, NULL, NULL ); - return( LDAP_TIMEOUT ); - } - - return( ldap_result2error( ld, *res, 0 )); -} - - -int -LDAP_CALL -ldap_url_search_s( LDAP *ld, const char *url, int attrsonly, LDAPMessage **res ) -{ - int msgid; - - if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - return( ldap_result2error( ld, *res, 0 )); -} diff --git a/ldap/c-sdk/libraries/libldap/userstatusctrl.c b/ldap/c-sdk/libraries/libldap/userstatusctrl.c deleted file mode 100644 index 1127d67bb7..0000000000 --- a/ldap/c-sdk/libraries/libldap/userstatusctrl.c +++ /dev/null @@ -1,228 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): abobrov@sun.com - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_create_userstatus_control: - - Parameters are - - ld LDAP pointer to the desired connection - - ctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client - - ctrlp the address of a place to put the constructed control -*/ - -int -LDAP_CALL -ldap_create_userstatus_control ( - LDAP *ld, - const char ctl_iscritical, - LDAPControl **ctrlp - ) -{ - int rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - rc = nsldapi_build_control( LDAP_CONTROL_ACCOUNT_USABLE, - NULL, 0, ctl_iscritical, ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); -} - -/* ldap_parse_userstatus_control: - - Parameters are - - ld LDAP pointer to the desired connection - - ctrlp An array of controls obtained from calling - ldap_parse_result on the set of results - returned by the server - - us the address of struct LDAPuserstatus - to parse control results to -*/ - -int -LDAP_CALL -ldap_parse_userstatus_control ( - LDAP *ld, - LDAPControl **ctrlp, - LDAPuserstatus *us - ) -{ - BerElement *ber = NULL; - int i, foundUSControl; - LDAPControl *USCtrlp = NULL; - ber_tag_t tag; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || us == NULL ) { - return( LDAP_PARAM_ERROR ); - } - - /* find the control in the list of controls if it exists */ - if ( ctrlp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - foundUSControl = 0; - for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundUSControl )); i++ ) { - foundUSControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_ACCOUNT_USABLE ); - } - if ( !foundUSControl ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } else { - /* let local var point to the control */ - USCtrlp = ctrlp[i-1]; - } - - /* allocate a Ber element with the contents of the control's struct berval */ - if ( ( ber = ber_init( &USCtrlp->ldctl_value ) ) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - memset( us, 0, sizeof(struct LDAPuserstatus) ); - - /* - * The control value should look like this: - * - * ACCOUNT_USABLE_RESPONSE::= CHOICE { - * is_available [0] INTEGER, ** seconds before expiration ** - * is_not_available [1] More_info - * } - * More_info::= SEQUENCE { - * inactive [0] BOOLEAN DEFAULT FALSE, - * reset [1] BOOLEAN DEFAULT FALSE, - * expired [2] BOOLEAN DEFAULT FALSE, - * remaining_grace [3] INTEGER OPTIONAL, - * seconds_before_unlock [4] INTEGER OPTIONAL - * } - */ - - if ( ( ber_scanf( ber, "t", &tag ) ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - - tag = (( tag & LBER_CONSTRUCTED ) == LBER_CONSTRUCTED ) ? 1 : 0; - - if ( !tag ) { - us->us_available = 1; - if ( ber_scanf( ber, "i", &us->us_expire ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - } else { - us->us_available = 0; - tag = 0; - if ( ( ber_scanf( ber, "{t", &tag ) ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - while ( tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET ) { - tag = tag & (~LBER_CLASS_CONTEXT); - switch (tag) - { - case 0: - if ( ber_scanf( ber, "b", &us->us_inactive ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - us->us_inactive = ( us->us_inactive != 0 ) ? 1 : 0; - break; - case 1: - if ( ber_scanf( ber, "b", &us->us_reset ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - us->us_reset = ( us->us_reset != 0 ) ? 1 : 0; - break; - case 2: - if ( ber_scanf( ber, "b", &us->us_expired ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - us->us_expired = ( us->us_expired != 0 ) ? 1 : 0; - break; - case 3: - if ( ber_scanf( ber, "i", &us->us_remaining ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - break; - case 4: - if ( ber_scanf( ber, "i", &us->us_seconds ) == LBER_ERROR ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - break; - default: - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - ber_scanf( ber, "t", &tag ); - } - } - - /* the ber encoding is no longer needed */ - ber_free( ber, 1 ); - return( LDAP_SUCCESS ); -} diff --git a/ldap/c-sdk/libraries/libldap/utf8.c b/ldap/c-sdk/libraries/libldap/utf8.c deleted file mode 100644 index 98957cc5b4..0000000000 --- a/ldap/c-sdk/libraries/libldap/utf8.c +++ /dev/null @@ -1,282 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* uft8.c - misc. utf8 "string" functions. */ -#include "ldap-int.h" - -static char UTF8len[64] -= {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6}; - -int -LDAP_CALL -ldap_utf8len (const char* s) - /* Return the number of char's in the character at *s. */ -{ - return ldap_utf8next((char*)s) - s; -} - -char* -LDAP_CALL -ldap_utf8next (char* s) - /* Return a pointer to the character immediately following *s. - Handle any valid UTF-8 character, including '\0' and ASCII. - Try to handle a misaligned pointer or a malformed character. - */ -{ - register unsigned char* next = (unsigned char*)s; - switch (UTF8len [(*next >> 2) & 0x3F]) { - case 0: /* erroneous: s points to the middle of a character. */ - case 6: if ((*++next & 0xC0) != 0x80) break; - case 5: if ((*++next & 0xC0) != 0x80) break; - case 4: if ((*++next & 0xC0) != 0x80) break; - case 3: if ((*++next & 0xC0) != 0x80) break; - case 2: if ((*++next & 0xC0) != 0x80) break; - case 1: ++next; - } - return (char*) next; -} - -char* -LDAP_CALL -ldap_utf8prev (char* s) - /* Return a pointer to the character immediately preceding *s. - Handle any valid UTF-8 character, including '\0' and ASCII. - Try to handle a misaligned pointer or a malformed character. - */ -{ - register unsigned char* prev = (unsigned char*)s; - unsigned char* limit = prev - 6; - while (((*--prev & 0xC0) == 0x80) && (prev != limit)) { - ; - } - return (char*) prev; -} - -int -LDAP_CALL -ldap_utf8copy (char* dst, const char* src) - /* Copy a character from src to dst; return the number of char's copied. - Handle any valid UTF-8 character, including '\0' and ASCII. - Try to handle a misaligned pointer or a malformed character. - */ -{ - register const unsigned char* s = (const unsigned char*)src; - switch (UTF8len [(*s >> 2) & 0x3F]) { - case 0: /* erroneous: s points to the middle of a character. */ - case 6: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; - case 5: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; - case 4: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; - case 3: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; - case 2: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; - case 1: *dst = *s++; - } - return s - (const unsigned char*)src; -} - -size_t -LDAP_CALL -ldap_utf8characters (const char* src) - /* Return the number of UTF-8 characters in the 0-terminated array s. */ -{ - register char* s = (char*)src; - size_t n; - for (n = 0; *s; LDAP_UTF8INC(s)) ++n; - return n; -} - -unsigned long LDAP_CALL -ldap_utf8getcc( const char** src ) -{ - register unsigned long c = 0; - register const unsigned char* s = (const unsigned char*)*src; - switch (UTF8len [(*s >> 2) & 0x3F]) { - case 0: /* erroneous: s points to the middle of a character. */ - c = (*s++) & 0x3F; goto more5; - case 1: c = (*s++); break; - case 2: c = (*s++) & 0x1F; goto more1; - case 3: c = (*s++) & 0x0F; goto more2; - case 4: c = (*s++) & 0x07; goto more3; - case 5: c = (*s++) & 0x03; goto more4; - case 6: c = (*s++) & 0x01; goto more5; - more5: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); - more4: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); - more3: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); - more2: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); - more1: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); - break; - } - *src = (const char*)s; - return c; -} - -char* -LDAP_CALL -ldap_utf8strtok_r( char* sp, const char* brk, char** next) -{ - const char *bp; - unsigned long sc, bc; - char *tok; - - if (sp == NULL && (sp = *next) == NULL) - return NULL; - - /* Skip leading delimiters; roughly, sp += strspn(sp, brk) */ - cont: - sc = LDAP_UTF8GETC(sp); - for (bp = brk; (bc = LDAP_UTF8GETCC(bp)) != 0;) { - if (sc == bc) - goto cont; - } - - if (sc == 0) { /* no non-delimiter characters */ - *next = NULL; - return NULL; - } - tok = LDAP_UTF8PREV(sp); - - /* Scan token; roughly, sp += strcspn(sp, brk) - * Note that brk must be 0-terminated; we stop if we see that, too. - */ - while (1) { - sc = LDAP_UTF8GETC(sp); - bp = brk; - do { - if ((bc = LDAP_UTF8GETCC(bp)) == sc) { - if (sc == 0) { - *next = NULL; - } else { - *next = sp; - *(LDAP_UTF8PREV(sp)) = 0; - } - return tok; - } - } while (bc != 0); - } - /* NOTREACHED */ -} - -int -LDAP_CALL -ldap_utf8isalnum( char* s ) -{ - register unsigned char c = *(unsigned char*)s; - if (0x80 & c) return 0; - if (c >= 'A' && c <= 'Z') return 1; - if (c >= 'a' && c <= 'z') return 1; - if (c >= '0' && c <= '9') return 1; - return 0; -} - -int -LDAP_CALL -ldap_utf8isalpha( char* s ) -{ - register unsigned char c = *(unsigned char*)s; - if (0x80 & c) return 0; - if (c >= 'A' && c <= 'Z') return 1; - if (c >= 'a' && c <= 'z') return 1; - return 0; -} - -int -LDAP_CALL -ldap_utf8isdigit( char* s ) -{ - register unsigned char c = *(unsigned char*)s; - if (0x80 & c) return 0; - if (c >= '0' && c <= '9') return 1; - return 0; -} - -int -LDAP_CALL -ldap_utf8isxdigit( char* s ) -{ - register unsigned char c = *(unsigned char*)s; - if (0x80 & c) return 0; - if (c >= '0' && c <= '9') return 1; - if (c >= 'A' && c <= 'F') return 1; - if (c >= 'a' && c <= 'f') return 1; - return 0; -} - -int -LDAP_CALL -ldap_utf8isspace( char* s ) -{ - register unsigned char *c = (unsigned char*)s; - int len = ldap_utf8len(s); - - if (len == 0) { - return 0; - } else if (len == 1) { - switch (*c) { - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x20: - return 1; - default: - return 0; - } - } else if (len == 2) { - if (*c == 0xc2) { - return *(c+1) == 0x80; - } - } else if (len == 3) { - if (*c == 0xE2) { - c++; - if (*c == 0x80) { - c++; - return (*c>=0x80 && *c<=0x8a); - } - } else if (*c == 0xE3) { - return (*(c+1)==0x80) && (*(c+2)==0x80); - } else if (*c==0xEF) { - return (*(c+1)==0xBB) && (*(c+2)==0xBF); - } - return 0; - } - - /* should never reach here */ - return 0; -} diff --git a/ldap/c-sdk/libraries/libldap/vlistctrl.c b/ldap/c-sdk/libraries/libldap/vlistctrl.c deleted file mode 100644 index e42d746412..0000000000 --- a/ldap/c-sdk/libraries/libldap/vlistctrl.c +++ /dev/null @@ -1,259 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* vlistctrl.c - virtual list control implementation. */ -#include "ldap-int.h" - - - -/* - * function to create a VirtualListViewRequest control that can be passed - * to ldap_search_ext() or ldap_search_ext_s(). *ctrlp will be set to a - * freshly allocated LDAPControl structure. Returns an LDAP error code - * (LDAP_SUCCESS if all goes well). - * - * Parameters - * ld LDAP pointer to the desired connection - * - * ldvlistp the control structure. - * - * ctrlp the address of a place to put the constructed control - - 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 { - byIndex [0] SEQUENCE { - index INTEGER (0 .. maxInt), - contentCount INTEGER (0 .. maxInt) } - byValue [1] greaterThanOrEqual assertionValue } - - 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. - index and contentCount identify the target entry - 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 the supplied value is the target entry. - - */ - -int -LDAP_CALL -ldap_create_virtuallist_control( - LDAP *ld, - LDAPVirtualList *ldvlistp, - LDAPControl **ctrlp -) -{ - BerElement *ber; - int rc; - - if (!NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - - if ( NULL == ctrlp || NULL == ldvlistp ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return ( LDAP_PARAM_ERROR ); - } - - /* create a ber package to hold the controlValue */ - if ( LDAP_SUCCESS != nsldapi_alloc_ber_with_options( ld, &ber ) ) - { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - if ( LBER_ERROR == ber_printf( ber, - "{ii", - ldvlistp->ldvlist_before_count, - ldvlistp->ldvlist_after_count )) - /* XXX lossy casts */ - { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if (NULL == ldvlistp->ldvlist_attrvalue) - { - if ( LBER_ERROR == ber_printf( ber, - "t{ii}}", - LDAP_TAG_VLV_BY_INDEX, - ldvlistp->ldvlist_index, - ldvlistp->ldvlist_size ) ) - /* XXX lossy casts */ - { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - else - { - if ( LBER_ERROR == ber_printf( ber, - "to}", - LDAP_TAG_VLV_BY_VALUE, - ldvlistp->ldvlist_attrvalue, - (int)strlen( ldvlistp->ldvlist_attrvalue )) ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - } - - - rc = nsldapi_build_control( LDAP_CONTROL_VLVREQUEST , - ber, - 1, - 1, - ctrlp ); - - LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); - return( rc ); - -} - - -/* - * function to find and parse a VirtualListViewResponse control contained in - * "ctrls" *target_posp, *list_sizep, and *errcodep are set based on its - * contents. Returns an LDAP error code that indicates whether the parsing - * itself was successful (LDAP_SUCCESS if all goes well). - - 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), - operatonsError (1), - unwillingToPerform (53), - insufficientAccessRights (50), - busy (51), - timeLimitExceeded (3), - adminLimitExceeded (11), - sortControlMissing (60), - indexRangeError (61), - other (80) } } - - */ -int -LDAP_CALL -ldap_parse_virtuallist_control -( - LDAP *ld, - LDAPControl **ctrls, - ber_int_t *target_posp, - ber_int_t *list_sizep, - int *errcodep -) -{ - BerElement *ber; - int i, foundListControl; - ber_int_t errcode; - LDAPControl *listCtrlp; - ber_int_t target_pos, list_size; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - /* only ldapv3 or higher can do virtual lists. */ - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - /* find the listControl in the list of controls if it exists */ - if ( ctrls == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } - - foundListControl = 0; - for ( i = 0; (( ctrls[i] != NULL ) && ( !foundListControl )); i++ ) { - foundListControl = !strcmp( ctrls[i]->ldctl_oid, - LDAP_CONTROL_VLVRESPONSE ); - } - if ( !foundListControl ) { - LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); - return ( LDAP_CONTROL_NOT_FOUND ); - } else { - /* let local var point to the listControl */ - listCtrlp = ctrls[i-1]; - } - - /* allocate a Ber element with the contents of the list_control's struct berval */ - if ( ( ber = ber_init( &listCtrlp->ldctl_value ) ) == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* decode the result from the Berelement */ - if ( LBER_ERROR == ber_scanf( ber, "{iie}", &target_pos, &list_size, - &errcode ) ) { - LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_DECODING_ERROR ); - } - - if ( target_posp != NULL ) { - *target_posp = target_pos; - } - if ( list_sizep != NULL ) { - *list_sizep = list_size; - } - if ( errcodep != NULL ) { - *errcodep = (int)errcode; - } - - /* the ber encoding is no longer needed */ - ber_free(ber,1); - - return(LDAP_SUCCESS); - -} diff --git a/ldap/c-sdk/libraries/libldap/whoami.c b/ldap/c-sdk/libraries/libldap/whoami.c deleted file mode 100644 index 35e10e71c7..0000000000 --- a/ldap/c-sdk/libraries/libldap/whoami.c +++ /dev/null @@ -1,130 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Sun LDAP C SDK. - * - * The Initial Developer of the Original Code is Sun Microsystems, Inc. - * - * Portions created by Sun Microsystems, Inc are Copyright (C) 2005 - * Sun Microsystems, Inc. All Rights Reserved. - * - * Contributor(s): abobrov@sun.com - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "ldap-int.h" - -/* ldap_whoami */ -int -LDAP_CALL -ldap_whoami ( - LDAP *ld, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ) -{ - int rc; - struct berval *requestdata = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - rc = ldap_extended_operation( ld, LDAP_EXOP_WHO_AM_I, requestdata, - serverctrls, clientctrls, msgidp ); - - return( rc ); -} - -/* ldap_parse_whoami */ -int -LDAP_CALL -ldap_parse_whoami ( - LDAP *ld, - LDAPMessage *result, - struct berval **authzid - ) -{ - int rc; - char *retoidp = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - if ( !result ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - *authzid = NULL; - - rc = ldap_parse_extended_result( ld, result, &retoidp, authzid, 0 ); - - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - ldap_memfree( retoidp ); - return( LDAP_SUCCESS ); -} - -/* ldap_whoami_s */ -int -LDAP_CALL -ldap_whoami_s ( - LDAP *ld, - struct berval **authzid, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ) -{ - int rc; - int msgid; - LDAPMessage *result = NULL; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - rc = ldap_whoami( ld, serverctrls, clientctrls, &msgid ); - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); - if ( rc == -1 ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - rc = ldap_parse_whoami( ld, result, authzid ); - - ldap_msgfree( result ); - - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libldif/libldif.def b/ldap/c-sdk/libraries/libldif/libldif.def deleted file mode 100644 index 1c5ad53820..0000000000 --- a/ldap/c-sdk/libraries/libldif/libldif.def +++ /dev/null @@ -1,58 +0,0 @@ -; -; ***** BEGIN LICENSE BLOCK ***** -; Version: MPL 1.1/GPL 2.0/LGPL 2.1 -; -; The contents of this file are subject to the Mozilla Public License Version -; 1.1 (the "License"); you may not use this file except in compliance with -; the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" basis, -; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -; for the specific language governing rights and limitations under the -; License. -; -; The Original Code is Mozilla Communicator client code. -; -; The Initial Developer of the Original Code is -; Netscape Communications Corporation. -; Portions created by the Initial Developer are Copyright (C) 1996-1999 -; the Initial Developer. All Rights Reserved. -; -; Contributor(s): -; -; Alternatively, the contents of this file may be used under the terms of -; either of the GNU General Public License Version 2 or later (the "GPL"), -; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -; in which case the provisions of the GPL or the LGPL are applicable instead -; of those above. If you wish to allow use of your version of this file only -; under the terms of either the GPL or the LGPL, and not to allow others to -; use your version of this file under the terms of the MPL, indicate your -; decision by deleting the provisions above and replace them with the notice -; and other provisions required by the GPL or the LGPL. If you do not delete -; the provisions above, a recipient may use your version of this file under -; the terms of any one of the MPL, the GPL or the LGPL. -; -; ***** END LICENSE BLOCK ***** - -LIBRARY LDIF60 -VERSION 6.0 -HEAPSIZE 4096 - -EXPORTS -; exports list (generated by genexports.pl) -; - ldif_parse_line - ldif_getline - ldif_put_type_and_value - ldif_put_type_and_value_nowrap - ldif_put_type_and_value_with_options - ldif_type_and_value - ldif_type_and_value_nowrap - ldif_type_and_value_with_options - ldif_base64_decode - ldif_base64_encode - ldif_base64_encode_nowrap - ldif_get_entry -; -; end of generated exports list. diff --git a/ldap/c-sdk/libraries/libldif/line64.c b/ldap/c-sdk/libraries/libldif/line64.c deleted file mode 100644 index a819825cce..0000000000 --- a/ldap/c-sdk/libraries/libldif/line64.c +++ /dev/null @@ -1,612 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* line64.c - routines for dealing with the slapd line format */ - -#include -#include -#include -#include -#ifndef macintosh -#include -#endif -#ifdef _WIN32 -#include -#elif !defined( macintosh ) -#include -#endif -#include "ldaplog.h" -#include "ldif.h" - -#ifndef isascii -#define isascii( c ) (!((c) & ~0177)) -#endif - -#define RIGHT2 0x03 -#define RIGHT4 0x0f -#define CONTINUED_LINE_MARKER '\001' - -#define ISBLANK(c) (c == ' ' || c == '\t' || c == '\n') /* not "\r\v\f" */ - -#define LDIF_OPT_ISSET( value, opt ) (((value) & (opt)) != 0 ) - -static char nib2b64[0x40f] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static unsigned char b642nib[0x80] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -static int ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, - int lenused, int wraplen ); - -/* - * ldif_parse_line - takes a line of the form "type:[:] value" and splits it - * into components "type" and "value". if a double colon separates type from - * value, then value is encoded in base 64, and parse_line un-decodes it - * (in place) before returning. - */ - -int -ldif_parse_line( - char *line, - char **type, - char **value, - int *vlen -) -{ - char *p, *s, *d; - int b64; - - /* skip any leading space */ - while ( ISBLANK( *line ) ) { - line++; - } - *type = line; - - for ( s = line; *s && *s != ':'; s++ ) - ; /* NULL */ - if ( *s == '\0' ) { - - /* Comment-out while we address calling libldif from ns-back-ldbm - on NT. 1 of 3 */ -#if defined( _WIN32 ) - /* -#endif - LDAPDebug( LDAP_DEBUG_PARSE, "ldif_parse_line: missing ':' " - "on line \"%s\"\n", line, 0, 0 ); -#if defined( _WIN32 ) - */ -#endif - return( -1 ); - } - - /* trim any space between type and : */ - for ( p = s - 1; p > line && ISBLANK( *p ); p-- ) { - *p = '\0'; - } - *s++ = '\0'; - - /* check for double : - indicates base 64 encoded value */ - if ( *s == ':' ) { - s++; - b64 = 1; - - /* single : - normally encoded value */ - } else { - b64 = 0; - } - - /* skip space between : and value */ - while ( ISBLANK( *s ) ) { - s++; - } - - /* - * If no value is present, return a zero-length string for - * *value, with *vlen set to zero. - */ - if ( *s == '\0' ) { - *value = s; - *vlen = 0; - return( 0 ); - } - - /* 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'; - - *value = s; - if ( b64 ) { - if (( *vlen = ldif_base64_decode( s, (unsigned char *)s )) - < 0 ) { - /* Comment-out while we address calling libldif from ns-back-ldbm - on NT. 3 of 3 */ -#if defined( _WIN32 ) - /* -#endif - LDAPDebug( LDAP_DEBUG_ANY, - "ldif_parse_line: invalid base 64 char on line \"%s\"\n", - line, 0, 0 ); -#if defined( _WIN32 ) - */ -#endif - return( -1 ); - } - s[ *vlen ] = '\0'; - } else { - *vlen = (int) (d - s); - } - - return( 0 ); -} - - -/* - * ldif_base64_decode - take the BASE64-encoded characters in "src" - * (a zero-terminated string) and decode them into the the buffer "dst". - * "src" and "dst" can be the same if in-place decoding is desired. - * "dst" must be large enough to hold the decoded octets. No more than - * 3 * strlen( src ) / 4 bytes will be produced. - * "dst" may contain zero octets anywhere within it, but it is not - * zero-terminated by this function. - * - * The number of bytes copied to "dst" is returned if all goes well. - * -1 is returned if the BASE64 encoding in "src" is invalid. - */ - -int -ldif_base64_decode( char *src, unsigned char *dst ) -{ - char *p, *stop; - unsigned char nib, *byte; - int i, len; - - stop = strchr( src, '\0' ); - byte = dst; - for ( p = src, len = 0; p < stop; p += 4, len += 3 ) { - for ( i = 0; i < 4; i++ ) { - if ( p[i] != '=' && (p[i] & 0x80 || - b642nib[ p[i] & 0x7f ] > 0x3f) ) { - return( -1 ); - } - } - - /* first digit */ - nib = b642nib[ p[0] & 0x7f ]; - byte[0] = nib << 2; - - /* second digit */ - nib = b642nib[ p[1] & 0x7f ]; - byte[0] |= nib >> 4; - - /* third digit */ - if ( p[2] == '=' ) { - len += 1; - break; - } - byte[1] = (nib & RIGHT4) << 4; - nib = b642nib[ p[2] & 0x7f ]; - byte[1] |= nib >> 2; - - /* fourth digit */ - if ( p[3] == '=' ) { - len += 2; - break; - } - byte[2] = (nib & RIGHT2) << 6; - nib = b642nib[ p[3] & 0x7f ]; - byte[2] |= nib; - - byte += 3; - } - - return( len ); -} - -/* - * ldif_getline - return the next "line" (minus newline) of input from a - * string buffer of lines separated by newlines, terminated by \n\n - * or \0. this routine handles continued lines, bundling them into - * a single big line before returning. if a line begins with a white - * space character, it is a continuation of the previous line. the white - * space character (nb: only one char), and preceeding newline are changed - * into CONTINUED_LINE_MARKER chars, to be deleted later by the - * ldif_parse_line() routine above. - * - * it takes a pointer to a pointer to the buffer on the first call, - * which it updates and must be supplied on subsequent calls. - * - * XXX need to update this function to also support as EOL. - * XXX supports as of 07/29/1998 (richm) - */ - -char * -ldif_getline( char **next ) -{ - char *l; - char c; - char *p; - - if ( *next == NULL || **next == '\n' || **next == '\0' ) { - return( NULL ); - } - - while ( **next == '#' ) { /* skip comment lines */ - if (( *next = strchr( *next, '\n' )) == NULL ) { - return( NULL ); - } - (*next)++; - } - - l = *next; - while ( (*next = strchr( *next, '\n' )) != NULL ) { - p = *next - 1; /* pointer to character previous to the newline */ - c = *(*next + 1); /* character after the newline */ - if ( ISBLANK( c ) && c != '\n' ) { - /* DOS EOL is \r\n, so if the character before */ - /* the \n is \r, continue it too */ - if (*p == '\r') - *p = CONTINUED_LINE_MARKER; - **next = CONTINUED_LINE_MARKER; - *(*next+1) = CONTINUED_LINE_MARKER; - } else { - /* DOS EOL is \r\n, so if the character before */ - /* the \n is \r, null it too */ - if (*p == '\r') - *p = '\0'; - *(*next)++ = '\0'; - break; - } - (*next)++; - } - - return( l ); -} - - -#define LDIF_SAFE_CHAR( c ) ( (c) != '\r' && (c) != '\n' ) -#define LDIF_CONSERVATIVE_CHAR( c ) ( LDIF_SAFE_CHAR(c) && isascii((c)) \ - && ( isprint((c)) || (c) == '\t' )) -#define LDIF_SAFE_INITCHAR( c ) ( LDIF_SAFE_CHAR(c) && (c) != ':' \ - && (c) != ' ' && (c) != '<' ) -#define LDIF_CONSERVATIVE_INITCHAR( c ) ( LDIF_SAFE_INITCHAR( c ) && \ - ! ( isascii((c)) && isspace((c)))) -#define LDIF_CONSERVATIVE_FINALCHAR( c ) ( (c) != ' ' ) - - -void -ldif_put_type_and_value_with_options( char **out, char *t, char *val, - int vlen, unsigned long options ) -{ - unsigned char *p, *byte, *stop; - char *save; - int b64, len, savelen, wraplen; - len = 0; - - if ( LDIF_OPT_ISSET( options, LDIF_OPT_NOWRAP )) { - wraplen = -1; - } else { - wraplen = LDIF_MAX_LINE_WIDTH; - } - - /* put the type + ": " */ - for ( p = (unsigned char *) t; *p; p++, len++ ) { - *(*out)++ = *p; - } - *(*out)++ = ':'; - len++; - if ( LDIF_OPT_ISSET( options, LDIF_OPT_VALUE_IS_URL )) { - *(*out)++ = '<'; /* add '<' for URLs */ - len++; - } - save = *out; - savelen = len; - b64 = 0; - - stop = (unsigned char *)val; - if ( val && vlen > 0 ) { - *(*out)++ = ' '; - stop = (unsigned char *) (val + vlen); - if ( LDIF_OPT_ISSET( options, LDIF_OPT_MINIMAL_ENCODING )) { - if ( !LDIF_SAFE_INITCHAR( val[0] )) { - b64 = 1; - } - } else { - if ( !LDIF_CONSERVATIVE_INITCHAR( val[0] ) || - !LDIF_CONSERVATIVE_FINALCHAR( val[vlen-1] )) { - b64 = 1; - } - } - } - - if ( !b64 ) { - for ( byte = (unsigned char *) val; byte < stop; - byte++, len++ ) { - if ( LDIF_OPT_ISSET( options, - LDIF_OPT_MINIMAL_ENCODING )) { - if ( !LDIF_SAFE_CHAR( *byte )) { - b64 = 1; - break; - } - } else if ( !LDIF_CONSERVATIVE_CHAR( *byte )) { - b64 = 1; - break; - } - - if ( wraplen != -1 && len > wraplen ) { - *(*out)++ = '\n'; - *(*out)++ = ' '; - len = 1; - } - *(*out)++ = *byte; - } - } - - if ( b64 ) { - *out = save; - *(*out)++ = ':'; - *(*out)++ = ' '; - len = ldif_base64_encode_internal( (unsigned char *)val, *out, vlen, - savelen + 2, wraplen ); - *out += len; - } - - *(*out)++ = '\n'; -} - -void -ldif_put_type_and_value( char **out, char *t, char *val, int vlen ) -{ - ldif_put_type_and_value_with_options( out, t, val, vlen, 0 ); -} - -void -ldif_put_type_and_value_nowrap( char **out, char *t, char *val, int vlen ) -{ - ldif_put_type_and_value_with_options( out, t, val, vlen, LDIF_OPT_NOWRAP ); -} - -/* - * ldif_base64_encode_internal - encode "srclen" bytes in "src", place BASE64 - * encoded bytes in "dst" and return the length of the BASE64 - * encoded string. "dst" is also zero-terminated by this function. - * - * If "lenused" >= 0, newlines will be included in "dst" and "lenused" if - * appropriate. "lenused" should be a count of characters already used - * on the current line. The LDIF lines we create will contain at most - * "wraplen" characters on each line, unless "wraplen" is -1, in which - * case output line length is unlimited. - * - * If "lenused" < 0, no newlines will be included, and the LDIF_BASE64_LEN() - * macro can be used to determine how many bytes will be placed in "dst." - */ - -static int -ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, int lenused, int wraplen ) -{ - unsigned char *byte, *stop; - unsigned char buf[3]; - char *out; - unsigned long bits; - int i, pad, len; - - len = 0; - out = dst; - stop = src + srclen; - - /* convert to base 64 (3 bytes => 4 base 64 digits) */ - for ( byte = src; byte < stop - 2; byte += 3 ) { - bits = (byte[0] & 0xff) << 16; - bits |= (byte[1] & 0xff) << 8; - bits |= (byte[2] & 0xff); - - for ( i = 0; i < 4; i++, bits <<= 6 ) { - if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) { - *out++ = '\n'; - *out++ = ' '; - lenused = 2; - } - - /* get b64 digit from high order 6 bits */ - *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; - } - } - - /* add padding if necessary */ - if ( byte < stop ) { - for ( i = 0; byte + i < stop; i++ ) { - buf[i] = byte[i]; - } - for ( pad = 0; i < 3; i++, pad++ ) { - buf[i] = '\0'; - } - byte = buf; - bits = (byte[0] & 0xff) << 16; - bits |= (byte[1] & 0xff) << 8; - bits |= (byte[2] & 0xff); - - for ( i = 0; i < 4; i++, bits <<= 6 ) { - if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) { - *out++ = '\n'; - *out++ = ' '; - lenused = 2; - } - - if (( i == 3 && pad > 0 ) || ( i == 2 && pad == 2 )) { - /* Pad as appropriate */ - *out++ = '='; - } else { - /* get b64 digit from low order 6 bits */ - *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; - } - } - } - - *out = '\0'; - - return( out - dst ); -} - -int -ldif_base64_encode( unsigned char *src, char *dst, int srclen, int lenused ) -{ - return ldif_base64_encode_internal( src, dst, srclen, lenused, LDIF_MAX_LINE_WIDTH ); -} - -int -ldif_base64_encode_nowrap( unsigned char *src, char *dst, int srclen, int lenused ) -{ - return ldif_base64_encode_internal( src, dst, srclen, lenused, -1 ); -} - - -/* - * return malloc'd, zero-terminated LDIF line - */ -char * -ldif_type_and_value_with_options( char *type, char *val, int vlen, - unsigned long options ) -{ - char *buf, *p; - int tlen; - - tlen = strlen( type ); - if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) != - NULL ) { - p = buf; - ldif_put_type_and_value_with_options( &p, type, val, vlen, options ); - *p = '\0'; - } - - return( buf ); -} - -char * -ldif_type_and_value( char *type, char *val, int vlen ) -{ - return ldif_type_and_value_with_options( type, val, vlen, 0 ); -} - -char * -ldif_type_and_value_nowrap( char *type, char *val, int vlen ) -{ - return ldif_type_and_value_with_options( type, val, vlen, LDIF_OPT_NOWRAP ); -} - -/* - * ldif_get_entry - read the next ldif entry from the FILE referenced - * by fp. return a pointer to a malloc'd, null-terminated buffer. also - * returned is the last line number read, in *lineno. - */ -char * -ldif_get_entry( FILE *fp, int *lineno ) -{ - char line[BUFSIZ]; - char *buf; - int max, cur, len, gotsome; - - buf = NULL; - max = cur = gotsome = 0; - while ( fgets( line, sizeof(line), fp ) != NULL ) { - if ( lineno != NULL ) { - (*lineno)++; - } - /* ldif entries are terminated by a \n on a line by itself */ - if ( line[0] == '\0' || line[0] == '\n' -#if !defined( XP_WIN32 ) - || ( line[0] == '\r' && line[1] == '\n' ) /* DOS format */ -#endif - ) { - if ( gotsome ) { - break; - } else { - continue; - } - } else if ( line[0] == '#' ) { - continue; - } - gotsome = 1; - len = strlen( line ); -#if !defined( XP_WIN32 ) - /* DOS format */ - if ( len > 0 && line[len-1] == '\r' ) { - --len; - line[len] = '\0'; - } else if ( len > 1 && line[len-2] == '\r' && line[len-1] == '\n' ) { - --len; - line[len-1] = line[len]; - line[len] = '\0'; - } -#endif - while ( cur + (len + 1) > max ) { - if ( buf == NULL ) { - max += BUFSIZ; - buf = (char *) malloc( max ); - } else { - max *= 2; - buf = (char *) realloc( buf, max ); - } - if ( buf == NULL ) { - return( NULL ); - } - } - - memcpy( buf + cur, line, len + 1 ); - cur += len; - } - - return( buf ); -} diff --git a/ldap/c-sdk/libraries/libldif/moz.build b/ldap/c-sdk/libraries/libldif/moz.build deleted file mode 100644 index 000775a249..0000000000 --- a/ldap/c-sdk/libraries/libldif/moz.build +++ /dev/null @@ -1,23 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include('/ldap/ldap-sdk.mozbuild') - -SharedLibrary('ldif60') - -SOURCES += [ - 'line64.c' -] - -LOCAL_INCLUDES += [ - '/ldap/c-sdk/include' -] - -if CONFIG['OS_ARCH'] == 'WINNT': - DEFFILE = SRCDIR + '/libldif.def' - -DEFINES['USE_WAITPID'] = True -DEFINES['NEEDPROTOS'] = True - diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-dns.c b/ldap/c-sdk/libraries/libprldap/ldappr-dns.c deleted file mode 100644 index a88bfe31c7..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-dns.c +++ /dev/null @@ -1,166 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * DNS callback functions for libldap that use the NSPR (Netscape - * Portable Runtime) thread API. - * - */ - -#include "ldappr-int.h" - -static LDAPHostEnt *prldap_gethostbyname( const char *name, - LDAPHostEnt *result, char *buffer, int buflen, int *statusp, - void *extradata ); -static LDAPHostEnt *prldap_gethostbyaddr( const char *addr, int length, - int type, LDAPHostEnt *result, char *buffer, int buflen, - int *statusp, void *extradata ); -static int prldap_getpeername( LDAP *ld, struct sockaddr *addr, - char *buffer, int buflen ); -static LDAPHostEnt *prldap_convert_hostent( LDAPHostEnt *ldhp, - PRHostEnt *prhp ); - - -/* - * Install NSPR DNS functions into ld (if ld is NULL, they are installed - * as the default functions for new LDAP * handles). - * - * Returns 0 if all goes well and -1 if not. - */ -int -prldap_install_dns_functions( LDAP *ld ) -{ - struct ldap_dns_fns dnsfns; - - memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) ); - dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE; - dnsfns.lddnsfn_gethostbyname = prldap_gethostbyname; - dnsfns.lddnsfn_gethostbyaddr = prldap_gethostbyaddr; - dnsfns.lddnsfn_getpeername = prldap_getpeername; - if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns ) != 0 ) { - return( -1 ); - } - - return( 0 ); -} - - -static LDAPHostEnt * -prldap_gethostbyname( const char *name, LDAPHostEnt *result, - char *buffer, int buflen, int *statusp, void *extradata ) -{ - PRHostEnt prhent; - - if( !statusp || ( *statusp = (int)PR_GetIPNodeByName( name, - PRLDAP_DEFAULT_ADDRESS_FAMILY, PR_AI_DEFAULT, - buffer, buflen, &prhent )) == PR_FAILURE ) { - return( NULL ); - } - - return( prldap_convert_hostent( result, &prhent )); -} - - -static LDAPHostEnt * -prldap_gethostbyaddr( const char *addr, int length, int type, - LDAPHostEnt *result, char *buffer, int buflen, int *statusp, - void *extradata ) -{ - PRHostEnt prhent; - PRNetAddr iaddr; - - if ( NULL == statusp ) { - return( NULL ); - } - - memset( &iaddr, 0, sizeof( iaddr )); - if ( PR_StringToNetAddr( addr, &iaddr ) == PR_FAILURE ) { - return( NULL ); - } - PRLDAP_SET_PORT( &iaddr, 0 ); - - if( PR_FAILURE == (*statusp = - PR_GetHostByAddr(&iaddr, buffer, buflen, &prhent ))) { - return( NULL ); - } - - return( prldap_convert_hostent( result, &prhent )); -} - - -static int -prldap_getpeername( LDAP *ld, struct sockaddr *addr, char *buffer, int buflen) -{ - PRLDAPIOSocketArg *sa; - PRNetAddr iaddr; - int ret; - - if (NULL != ld) { - ret = prldap_socket_arg_from_ld( ld, &sa ); - if (ret != LDAP_SUCCESS) { - return (-1); - } - ret = PR_GetPeerName(sa->prsock_prfd, &iaddr); - if( ret == PR_FAILURE ) { - return( -1 ); - } - *addr = *((struct sockaddr *)&iaddr.raw); - ret = PR_NetAddrToString(&iaddr, buffer, buflen); - if( ret == PR_FAILURE ) { - return( -1 ); - } - return (0); - } - return (-1); -} - - -/* - * Function: prldap_convert_hostent() - * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt - * Returns: the LDAPHostEnt pointer passed in. - */ -static LDAPHostEnt * -prldap_convert_hostent( LDAPHostEnt *ldhp, PRHostEnt *prhp ) -{ - ldhp->ldaphe_name = prhp->h_name; - ldhp->ldaphe_aliases = prhp->h_aliases; - ldhp->ldaphe_addrtype = prhp->h_addrtype; - ldhp->ldaphe_length = prhp->h_length; - ldhp->ldaphe_addr_list = prhp->h_addr_list; - return( ldhp ); -} diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-error.c b/ldap/c-sdk/libraries/libprldap/ldappr-error.c deleted file mode 100644 index b0cb6ed967..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-error.c +++ /dev/null @@ -1,335 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Utilities for manageing the relationship between NSPR errors and - * OS (errno-style) errors. - * - * The overall strategy used is to map NSPR errors into OS errors. - */ - -#include "ldappr-int.h" - -void -prldap_set_system_errno( int oserrno ) -{ - PR_SetError( PR_GetError(), oserrno ); -} - - -int -prldap_get_system_errno( void ) -{ - return( PR_GetOSError()); -} - -/* - * Retrieve the NSPR error number, convert to a system error code, and return - * the result. - */ -struct prldap_errormap_entry { - PRInt32 erm_nspr; /* NSPR error code */ - int erm_system; /* corresponding system error code */ -}; - -/* XXX: not sure if this extra mapping for Windows is good or correct */ -#ifdef _WINDOWS -#ifndef ENOTSUP -#define ENOTSUP -1 -#endif -#ifndef ETIMEDOUT -#define ETIMEDOUT WSAETIMEDOUT -#endif -#ifndef EADDRNOTAVAIL -#define EADDRNOTAVAIL WSAEADDRNOTAVAIL -#endif -#ifndef EAFNOSUPPORT -#define EAFNOSUPPORT WSAEAFNOSUPPORT -#endif -#ifndef EISCONN -#define EISCONN WSAEISCONN -#endif -#ifndef EADDRINUSE -#define EADDRINUSE WSAEADDRINUSE -#endif -#ifndef ECONNREFUSED -#define ECONNREFUSED WSAECONNREFUSED -#endif -#ifndef EHOSTUNREACH -#define EHOSTUNREACH WSAEHOSTUNREACH -#endif -#ifndef ENOTCONN -#define ENOTCONN WSAENOTCONN -#endif -#ifndef ENOTSOCK -#define ENOTSOCK WSAENOTSOCK -#endif -#ifndef EPROTOTYPE -#define EPROTOTYPE WSAEPROTOTYPE -#endif -#ifndef EOPNOTSUPP -#define EOPNOTSUPP WSAEOPNOTSUPP -#endif -#ifndef EPROTONOSUPPORT -#define EPROTONOSUPPORT WSAEPROTONOSUPPORT -#endif -#ifndef EOVERFLOW -#define EOVERFLOW -1 -#endif -#ifndef ECONNRESET -#define ECONNRESET WSAECONNRESET -#endif -#ifndef ELOOP -#define ELOOP WSAELOOP -#endif -#ifndef ENOTBLK -#define ENOTBLK -1 -#endif -#ifndef ETXTBSY -#define ETXTBSY -1 -#endif -#ifndef ENETDOWN -#define ENETDOWN WSAENETDOWN -#endif -#ifndef ESHUTDOWN -#define ESHUTDOWN WSAESHUTDOWN -#endif -#ifndef ECONNABORTED -#define ECONNABORTED WSAECONNABORTED -#endif -#endif /* _WINDOWS */ - -#if defined(macintosh) -/* - * Some Unix error defs. Under CW 7, we can't define OTUNIXERRORS because - * it generates many conflicts with errno.h. Define what we need here. - * These need to be in sync with OpenTransport.h - */ -#define EWOULDBLOCK 35 -#define ENOTSOCK 38 -#define EPROTOTYPE 41 -#define EPROTONOSUPPORT 43 -#define EOPNOTSUPP 45 -#define EADDRINUSE 48 -#define EADDRNOTAVAIL 49 -#define ENETDOWN 50 -#define ECONNABORTED 53 -#define ECONNRESET 54 -#define EISCONN 56 -#define ENOTCONN 57 -#define ESHUTDOWN 58 -#define ETIMEDOUT 60 -#define ECONNREFUSED 61 -#define EHOSTUNREACH 65 -#define EAFNOSUPPORT -1 -#define ELOOP -1 -#define ENOTBLK -1 -#define ENOTSUP -1 -#define EOVERFLOW -1 -#define ETXTBSY -1 -#endif /* macintosh */ - -#ifdef XP_OS2 -#define SOCBASEERR 0 -#endif -#ifndef ENOTSUP -#define ENOTSUP -1 -#endif -#ifndef EOVERFLOW -#define EOVERFLOW -1 -#endif -#ifndef EDEADLOCK -#define EDEADLOCK -1 -#endif -#ifndef EFAULT -#define EFAULT SOCEFAULT -#endif -#ifndef EPIPE -#define EPIPE SOCEPIPE -#endif -#ifndef EIO -#define EIO (SOCBASEERR+5) -#endif -#ifndef EDEADLK -#define EDEADLK (SOCBASEERR+11) -#endif -#ifndef ENOTBLK -#define ENOTBLK (SOCBASEERR+15) -#endif -#ifndef EBUSY -#define EBUSY (SOCBASEERR+16) -#endif -#ifndef ENOTDIR -#define ENOTDIR (SOCBASEERR+20) -#endif -#ifndef EISDIR -#define EISDIR (SOCBASEERR+21) -#endif -#ifndef ENFILE -#define ENFILE (SOCBASEERR+23) -#endif -#ifndef ETXTBSY -#define ETXTBSY (SOCBASEERR+26) -#endif -#ifndef EFBIG -#define EFBIG (SOCBASEERR+27) -#endif -#ifndef ESPIPE -#define ESPIPE (SOCBASEERR+29) -#endif -#ifndef EROFS -#define EROFS (SOCBASEERR+30) -#endif - -#ifdef BEOS -#define ENOTSUP -1 -#define ENOTBLK -1 -#define ETXTBSY -1 -#endif - -#if defined(BSDI) || defined(OPENBSD) || defined (NETBSD) -#define ENOTSUP -1 -#endif - -#if defined(OSF1) || defined(BSDI) || defined(VMS) || defined(OPENBSD) -#define EOVERFLOW -1 -#endif - -#if defined(__hpux) || defined(_AIX) || defined(OSF1) || defined(DARWIN) || \ - defined(BEOS) || defined(FREEBSD) || defined(BSDI) || defined(VMS) || \ - defined(OPENBSD) || defined(NETBSD) -#define EDEADLOCK -1 -#endif - -/* XXX: need to verify that the -1 entries are correct (no mapping) */ -static struct prldap_errormap_entry prldap_errormap[] = { - { PR_OUT_OF_MEMORY_ERROR, ENOMEM }, - { PR_BAD_DESCRIPTOR_ERROR, EBADF }, - { PR_WOULD_BLOCK_ERROR, EAGAIN }, - { PR_ACCESS_FAULT_ERROR, EFAULT }, - { PR_INVALID_METHOD_ERROR, EINVAL }, /* XXX: correct mapping ? */ - { PR_ILLEGAL_ACCESS_ERROR, EACCES }, /* XXX: correct mapping ? */ - { PR_UNKNOWN_ERROR, -1 }, - { PR_PENDING_INTERRUPT_ERROR, -1 }, - { PR_NOT_IMPLEMENTED_ERROR, ENOTSUP }, - { PR_IO_ERROR, EIO }, - { PR_IO_TIMEOUT_ERROR, ETIMEDOUT }, /* XXX: correct mapping ? */ - { PR_IO_PENDING_ERROR, -1 }, - { PR_DIRECTORY_OPEN_ERROR, ENOTDIR }, - { PR_INVALID_ARGUMENT_ERROR, EINVAL }, - { PR_ADDRESS_NOT_AVAILABLE_ERROR, EADDRNOTAVAIL }, - { PR_ADDRESS_NOT_SUPPORTED_ERROR, EAFNOSUPPORT }, - { PR_IS_CONNECTED_ERROR, EISCONN }, - { PR_BAD_ADDRESS_ERROR, EFAULT }, /* XXX: correct mapping ? */ - { PR_ADDRESS_IN_USE_ERROR, EADDRINUSE }, - { PR_CONNECT_REFUSED_ERROR, ECONNREFUSED }, - { PR_NETWORK_UNREACHABLE_ERROR, EHOSTUNREACH }, - { PR_CONNECT_TIMEOUT_ERROR, ETIMEDOUT }, - { PR_NOT_CONNECTED_ERROR, ENOTCONN }, - { PR_LOAD_LIBRARY_ERROR, -1 }, - { PR_UNLOAD_LIBRARY_ERROR, -1 }, - { PR_FIND_SYMBOL_ERROR, -1 }, - { PR_INSUFFICIENT_RESOURCES_ERROR, -1 }, - { PR_DIRECTORY_LOOKUP_ERROR, EHOSTUNREACH },/* an approximation */ - { PR_TPD_RANGE_ERROR, -1 }, - { PR_PROC_DESC_TABLE_FULL_ERROR, -1 }, - { PR_SYS_DESC_TABLE_FULL_ERROR, -1 }, - { PR_NOT_SOCKET_ERROR, ENOTSOCK }, - { PR_NOT_TCP_SOCKET_ERROR, EPROTOTYPE }, - { PR_SOCKET_ADDRESS_IS_BOUND_ERROR, -1 }, - { PR_NO_ACCESS_RIGHTS_ERROR, EACCES }, /* XXX: correct mapping ? */ - { PR_OPERATION_NOT_SUPPORTED_ERROR, EOPNOTSUPP }, - { PR_PROTOCOL_NOT_SUPPORTED_ERROR, EPROTONOSUPPORT }, - { PR_REMOTE_FILE_ERROR, -1 }, - { PR_BUFFER_OVERFLOW_ERROR, EOVERFLOW }, - { PR_CONNECT_RESET_ERROR, ECONNRESET }, - { PR_RANGE_ERROR, ERANGE }, - { PR_DEADLOCK_ERROR, EDEADLK }, - { PR_FILE_IS_LOCKED_ERROR, EDEADLOCK }, /* XXX: correct mapping ? */ - { PR_FILE_TOO_BIG_ERROR, EFBIG }, - { PR_NO_DEVICE_SPACE_ERROR, ENOSPC }, - { PR_PIPE_ERROR, EPIPE }, - { PR_NO_SEEK_DEVICE_ERROR, ESPIPE }, - { PR_IS_DIRECTORY_ERROR, EISDIR }, - { PR_LOOP_ERROR, ELOOP }, - { PR_NAME_TOO_LONG_ERROR, ENAMETOOLONG }, - { PR_FILE_NOT_FOUND_ERROR, ENOENT }, - { PR_NOT_DIRECTORY_ERROR, ENOTDIR }, - { PR_READ_ONLY_FILESYSTEM_ERROR, EROFS }, - { PR_DIRECTORY_NOT_EMPTY_ERROR, ENOTEMPTY }, - { PR_FILESYSTEM_MOUNTED_ERROR, EBUSY }, - { PR_NOT_SAME_DEVICE_ERROR, EXDEV }, - { PR_DIRECTORY_CORRUPTED_ERROR, -1 }, - { PR_FILE_EXISTS_ERROR, EEXIST }, - { PR_MAX_DIRECTORY_ENTRIES_ERROR, -1 }, - { PR_INVALID_DEVICE_STATE_ERROR, ENOTBLK }, /* XXX: correct mapping ? */ - { PR_DEVICE_IS_LOCKED_ERROR, -2 }, - { PR_NO_MORE_FILES_ERROR, ENFILE }, - { PR_END_OF_FILE_ERROR, -1 }, - { PR_FILE_SEEK_ERROR, ESPIPE }, /* XXX: correct mapping ? */ - { PR_FILE_IS_BUSY_ERROR, ETXTBSY }, - { PR_OPERATION_ABORTED_ERROR, -1 }, - { PR_IN_PROGRESS_ERROR, -1 }, - { PR_ALREADY_INITIATED_ERROR, -1 }, - { PR_GROUP_EMPTY_ERROR, -1 }, - { PR_INVALID_STATE_ERROR, -1 }, - { PR_NETWORK_DOWN_ERROR, ENETDOWN }, - { PR_SOCKET_SHUTDOWN_ERROR, ESHUTDOWN }, - { PR_CONNECT_ABORTED_ERROR, ECONNABORTED }, - { PR_HOST_UNREACHABLE_ERROR, EHOSTUNREACH }, - { PR_MAX_ERROR, -1 }, -}; - - -int -prldap_prerr2errno( void ) -{ - int oserr, i; - PRInt32 nsprerr; - - nsprerr = PR_GetError(); - - oserr = -1; /* unknown */ - for ( i = 0; prldap_errormap[i].erm_nspr != PR_MAX_ERROR; ++i ) { - if ( prldap_errormap[i].erm_nspr == nsprerr ) { - oserr = prldap_errormap[i].erm_system; - break; - } - } - - return( oserr ); -} diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-int.h b/ldap/c-sdk/libraries/libprldap/ldappr-int.h deleted file mode 100644 index ed4bfbce61..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-int.h +++ /dev/null @@ -1,139 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Internal header for libprldap -- glue NSPR (Netscape Portable Runtime) - * to libldap. - * - */ - -#include "ldap.h" -#include "nspr.h" -#include "ldappr.h" - -#include -#include -#include - -/* - * Macros: - */ - -/* #define PRLDAP_DEBUG 1 */ /* uncomment to enable debugging printfs */ - -/* - * All of the sockets we use are IPv6 capable. - * Change the following #define to PR_AF_INET to support IPv4 only. - */ -#define PRLDAP_DEFAULT_ADDRESS_FAMILY PR_AF_INET6 - -/* - * Max length for sending message with one PR_Send. - * If a single message is larger than this size, the message is divided - * into multiple pieces up to this length and sent out. This is necessary - * on Microsoft Windows at least where attempts to send really large - * messages in one PR_Send() call result in an error. - */ -#define PRLDAP_MAX_SEND_SIZE (8*1024*1024) /* 8MB */ - -/* - * Macro to set port to the 'port' field of a NSPR PRNetAddr union. - ** INPUTS: - ** PRNetAddr *myaddr A network address. - ** PRUint16 myport port to set to the 'port' field of 'addr'. - ** RETURN: none - */ -#define PRLDAP_SET_PORT(myaddr,myport) \ - ((myaddr)->raw.family == PR_AF_INET6 ? ((myaddr)->ipv6.port = PR_htons(myport)) : ((myaddr)->inet.port = PR_htons(myport))) - -/* - * Data structures: - */ - -/* data structure that populates the I/O callback session arg. */ -typedef struct lextiof_session_private { - PRPollDesc *prsess_pollds; /* for poll callback */ - int prsess_pollds_count; /* # of elements in pollds */ - int prsess_io_max_timeout; /* in milliseconds */ - void *prsess_appdata; /* application specific data */ -} PRLDAPIOSessionArg; - -/* data structure that populates the I/O callback socket-specific arg. */ -typedef struct lextiof_socket_private { - PRFileDesc *prsock_prfd; /* associated NSPR file desc. */ - int prsock_io_max_timeout; /* in milliseconds */ - void *prsock_appdata; /* application specific data */ -} PRLDAPIOSocketArg; - - -/* - * Function prototypes: - */ - -/* - * From ldapprio.c: - */ -int prldap_install_io_functions( LDAP *ld, int shared ); -int prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ); -int prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, - int io_max_timeout ); -int prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, - int *io_max_timeoutp ); -int prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ); -PRLDAPIOSocketArg *prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ); - - -/* - * From ldapprthreads.c: - */ -int prldap_install_thread_functions( LDAP *ld, int shared ); -int prldap_thread_new_handle( LDAP *ld, void *sessionarg ); -void prldap_thread_dispose_handle( LDAP *ld, void *sessionarg ); - - -/* - * From ldapprdns.c: - */ -int prldap_install_dns_functions( LDAP *ld ); - - -/* - * From ldapprerror.c: - */ -void prldap_set_system_errno( int e ); -int prldap_get_system_errno( void ); -int prldap_prerr2errno( void ); diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-io.c b/ldap/c-sdk/libraries/libprldap/ldappr-io.c deleted file mode 100644 index 863545146a..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-io.c +++ /dev/null @@ -1,744 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Extended I/O callback functions for libldap that use - * NSPR (Netscape Portable Runtime) I/O. - * - * High level strategy: we use the socket-specific arg to hold our own data - * structure that includes the NSPR file handle (PRFileDesc *), among other - * useful information. We use the default argument to hold an LDAP session - * handle specific data structure. - */ - -#include "ldappr-int.h" - -#define PRLDAP_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */ - -/* - * Local function prototypes: - */ -static PRIntervalTime prldap_timeout2it( int ms_timeout, int ms_maxtimeout ); -static int LDAP_CALLBACK prldap_read( int s, void *buf, int bufsize, - struct lextiof_socket_private *socketarg ); -static int LDAP_CALLBACK prldap_write( int s, const void *buf, int len, - struct lextiof_socket_private *socketarg ); -static int LDAP_CALLBACK prldap_poll( LDAP_X_PollFD fds[], int nfds, - int timeout, struct lextiof_session_private *sessionarg ); -static int LDAP_CALLBACK prldap_connect( const char *hostlist, int defport, - int timeout, unsigned long options, - struct lextiof_session_private *sessionarg, - struct lextiof_socket_private **socketargp ); -static int LDAP_CALLBACK prldap_close( int s, - struct lextiof_socket_private *socketarg ); -static int LDAP_CALLBACK prldap_newhandle( LDAP *ld, - struct lextiof_session_private *sessionarg ); -static void LDAP_CALLBACK prldap_disposehandle( LDAP *ld, - struct lextiof_session_private *sessionarg ); -static int LDAP_CALLBACK prldap_shared_newhandle( LDAP *ld, - struct lextiof_session_private *sessionarg ); -static void LDAP_CALLBACK prldap_shared_disposehandle( LDAP *ld, - struct lextiof_session_private *sessionarg ); -static PRLDAPIOSessionArg *prldap_session_arg_alloc( void ); -static void prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ); -static void prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ); -static void *prldap_safe_realloc( void *ptr, PRUint32 size ); - - - -/* - * Local macros: - */ -/* given a socket-specific arg, return the corresponding PRFileDesc * */ -#define PRLDAP_GET_PRFD( socketarg ) \ - (((PRLDAPIOSocketArg *)(socketarg))->prsock_prfd) - -/* - * Static variables. - */ -static int prldap_default_io_max_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT; - - -/* - * Install NSPR I/O functions into ld (if ld is NULL, they are installed - * as the default functions for new LDAP * handles). - * - * Returns 0 if all goes well and -1 if not. - */ -int -prldap_install_io_functions( LDAP *ld, int shared ) -{ - struct ldap_x_ext_io_fns iofns; - - memset( &iofns, 0, sizeof(iofns)); - iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; - iofns.lextiof_read = prldap_read; - iofns.lextiof_write = prldap_write; - iofns.lextiof_poll = prldap_poll; - iofns.lextiof_connect = prldap_connect; - iofns.lextiof_close = prldap_close; - if ( shared ) { - iofns.lextiof_newhandle = prldap_shared_newhandle; - iofns.lextiof_disposehandle = prldap_shared_disposehandle; - } else { - iofns.lextiof_newhandle = prldap_newhandle; - iofns.lextiof_disposehandle = prldap_disposehandle; - } - if ( NULL != ld ) { - /* - * If we are dealing with a real ld, we allocate the session specific - * data structure now. If not allocated here, it will be allocated - * inside prldap_newhandle() or prldap_shared_newhandle(). - */ - if ( NULL == - ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { - ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( -1 ); - } - } else { - iofns.lextiof_session_arg = NULL; - } - - if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns ) != 0 ) { - prldap_session_arg_free( - (PRLDAPIOSessionArg **) &iofns.lextiof_session_arg ); - return( -1 ); - } - - return( 0 ); -} - - -static PRIntervalTime -prldap_timeout2it( int ms_timeout, int ms_maxtimeout ) -{ - PRIntervalTime prit; - - if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_timeout ) { - prit = PR_INTERVAL_NO_WAIT; - } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout ) { - prit = PR_INTERVAL_NO_TIMEOUT; - } else { - prit = PR_MillisecondsToInterval( ms_timeout ); - } - - /* cap at maximum I/O timeout */ - if ( LDAP_X_IO_TIMEOUT_NO_WAIT == ms_maxtimeout ) { - prit = LDAP_X_IO_TIMEOUT_NO_WAIT; - } else if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT != ms_maxtimeout ) { - if ( LDAP_X_IO_TIMEOUT_NO_TIMEOUT == ms_timeout || - ms_timeout > ms_maxtimeout ) { - prit = PR_MillisecondsToInterval( ms_maxtimeout ); - } - } - -#ifdef PRLDAP_DEBUG - if ( PR_INTERVAL_NO_WAIT == prit ) { - fprintf( stderr, "prldap_timeout2it: NO_WAIT\n" ); - } else if ( PR_INTERVAL_NO_TIMEOUT == prit ) { - fprintf( stderr, "prldap_timeout2it: NO_TIMEOUT\n" ); - } else { - fprintf( stderr, "prldap_timeout2it: %dms\n", - PR_IntervalToMilliseconds(prit)); - } -#endif /* PRLDAP_DEBUG */ - - return( prit ); -} - - -static int LDAP_CALLBACK -prldap_read( int s, void *buf, int bufsize, - struct lextiof_socket_private *socketarg ) -{ - PRIntervalTime prit; - - prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, - socketarg->prsock_io_max_timeout ); - return( PR_Recv( PRLDAP_GET_PRFD(socketarg), buf, bufsize, 0, prit )); -} - - -static int LDAP_CALLBACK -prldap_write( int s, const void *buf, int len, - struct lextiof_socket_private *socketarg ) -{ - PRIntervalTime prit; - char *ptr = (char *)buf; - int rest = len; - - prit = prldap_timeout2it( LDAP_X_IO_TIMEOUT_NO_TIMEOUT, - socketarg->prsock_io_max_timeout ); - - while ( rest > 0 ) { - int rval; - if ( rest > PRLDAP_MAX_SEND_SIZE ) { - len = PRLDAP_MAX_SEND_SIZE; - } else { - len = rest; - } - /* - * Note the 4th parameter (flags) to PR_Send() has been obsoleted and - * must always be 0 - */ - rval = PR_Send( PRLDAP_GET_PRFD(socketarg), ptr, len, 0, prit ); - if ( 0 > rval ) { - return rval; - } - - if ( 0 == rval ) { - break; - } - - ptr += rval; - rest -= rval; - } - - return (int)( ptr - (char *)buf ); -} - - -struct prldap_eventmap_entry { - PRInt16 evm_nspr; /* corresponding NSPR PR_Poll() event */ - int evm_ldap; /* LDAP poll event */ -}; - -static struct prldap_eventmap_entry prldap_eventmap[] = { - { PR_POLL_READ, LDAP_X_POLLIN }, - { PR_POLL_EXCEPT, LDAP_X_POLLPRI }, - { PR_POLL_WRITE, LDAP_X_POLLOUT }, - { PR_POLL_ERR, LDAP_X_POLLERR }, - { PR_POLL_HUP, LDAP_X_POLLHUP }, - { PR_POLL_NVAL, LDAP_X_POLLNVAL }, -}; - -#define PRLDAP_EVENTMAP_ENTRIES \ - sizeof(prldap_eventmap)/sizeof(struct prldap_eventmap_entry ) - -static int LDAP_CALLBACK -prldap_poll( LDAP_X_PollFD fds[], int nfds, int timeout, - struct lextiof_session_private *sessionarg ) -{ - PRLDAPIOSessionArg *prsessp = sessionarg; - PRPollDesc *pds; - int i, j, rc; - - if ( NULL == prsessp ) { - prldap_set_system_errno( EINVAL ); - return( -1 ); - } - - /* allocate or resize NSPR poll descriptor array */ - if ( prsessp->prsess_pollds_count < nfds ) { - pds = prldap_safe_realloc( prsessp->prsess_pollds, - ( nfds + PRLDAP_POLL_ARRAY_GROWTH ) - * sizeof( PRPollDesc )); - if ( NULL == pds ) { - prldap_set_system_errno( prldap_prerr2errno()); - return( -1 ); - } - prsessp->prsess_pollds = pds; - prsessp->prsess_pollds_count = nfds + PRLDAP_POLL_ARRAY_GROWTH; - } else { - pds = prsessp->prsess_pollds; - } - - /* populate NSPR poll info. based on LDAP info. */ - for ( i = 0; i < nfds; ++i ) { - if ( NULL == fds[i].lpoll_socketarg ) { - pds[i].fd = NULL; - } else { - pds[i].fd = PRLDAP_GET_PRFD( fds[i].lpoll_socketarg ); - } - pds[i].in_flags = pds[i].out_flags = 0; - if ( fds[i].lpoll_fd >= 0 ) { - for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { - if (( fds[i].lpoll_events & prldap_eventmap[j].evm_ldap ) - != 0 ) { - pds[i].in_flags |= prldap_eventmap[j].evm_nspr; - } - } - } - fds[i].lpoll_revents = 0; /* clear revents */ - } - - /* call PR_Poll() to do the real work */ - rc = PR_Poll( pds, nfds, - prldap_timeout2it( timeout, prsessp->prsess_io_max_timeout )); - - /* populate LDAP info. based on NSPR results */ - for ( i = 0; i < nfds; ++i ) { - if ( pds[i].fd != NULL ) { - for ( j = 0; j < PRLDAP_EVENTMAP_ENTRIES; ++j ) { - if (( pds[i].out_flags & prldap_eventmap[j].evm_nspr ) - != 0 ) { - fds[i].lpoll_revents |= prldap_eventmap[j].evm_ldap; - } - } - } - } - - return( rc ); -} - - -/* - * Utility function to try one TCP connect() - * Returns 1 if successful and -1 if not. Sets the NSPR fd inside prsockp. - */ -static int -prldap_try_one_address( struct lextiof_socket_private *prsockp, - PRNetAddr *addrp, int timeout, unsigned long options ) -{ - /* - * Open a TCP socket: - */ - if (( prsockp->prsock_prfd = PR_OpenTCPSocket( - PR_NetAddrFamily(addrp) )) == NULL ) { - return( -1 ); - } - - /* - * Set nonblocking option if requested: - */ - if ( 0 != ( options & LDAP_X_EXTIOF_OPT_NONBLOCKING )) { - PRSocketOptionData optdata; - - optdata.option = PR_SockOpt_Nonblocking; - optdata.value.non_blocking = PR_TRUE; - if ( PR_SetSocketOption( prsockp->prsock_prfd, &optdata ) - != PR_SUCCESS ) { - prldap_set_system_errno( prldap_prerr2errno()); - PR_Close( prsockp->prsock_prfd ); - return( -1 ); - } - } - -#ifdef PRLDAP_DEBUG - { - char buf[ 256 ], *p, *fmtstr; - - if ( PR_SUCCESS != PR_NetAddrToString( addrp, buf, sizeof(buf ))) { - strcpy( buf, "conversion failed!" ); - } - if ( strncmp( buf, "::ffff:", 7 ) == 0 ) { - /* IPv4 address mapped into IPv6 address space */ - p = buf + 7; - fmtstr = "prldap_try_one_address(): Trying %s:%d...\n"; - } else { - p = buf; - fmtstr = "prldap_try_one_address(): Trying [%s]:%d...\n"; - } - fprintf( stderr, fmtstr, p, PR_ntohs( addrp->ipv6.port )); - } -#endif /* PRLDAP_DEBUG */ - - /* - * Try to open the TCP connection itself: - */ - if ( PR_SUCCESS != PR_Connect( prsockp->prsock_prfd, addrp, - prldap_timeout2it( timeout, prsockp->prsock_io_max_timeout )) - && PR_IN_PROGRESS_ERROR != PR_GetError() ) { - PR_Close( prsockp->prsock_prfd ); - prsockp->prsock_prfd = NULL; - return( -1 ); - } - -#ifdef PRLDAP_DEBUG - fputs( "prldap_try_one_address(): Connected.\n", stderr ); -#endif /* PRLDAP_DEBUG */ - - /* - * Success. Return a valid file descriptor (1 is always valid) - */ - return( 1 ); -} - - -/* - * XXXmcs: At present, this code ignores the timeout when doing DNS lookups. - */ -static int LDAP_CALLBACK -prldap_connect( const char *hostlist, int defport, int timeout, - unsigned long options, struct lextiof_session_private *sessionarg, - struct lextiof_socket_private **socketargp ) -{ - int rc, parse_err, port; - char *host; - struct ldap_x_hostlist_status *status; - struct lextiof_socket_private *prsockp; - PRNetAddr addr; - PRAddrInfo *infop = NULL; - - if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) { - prldap_set_system_errno( EINVAL ); - return( -1 ); - } - - if ( NULL == ( prsockp = prldap_socket_arg_alloc( sessionarg ))) { - prldap_set_system_errno( prldap_prerr2errno()); - return( -1 ); - } - - rc = -1; /* pessimistic */ - for ( parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port, - &status ); - rc < 0 && LDAP_SUCCESS == parse_err && NULL != host; - parse_err = ldap_x_hostlist_next( &host, &port, status )) { - /* - * First, call PR_GetAddrInfoByName; PR_GetAddrInfoByName could - * support both IPv4 and IPv6 addresses depending upon the system's - * configuration. All available addresses are returned and each of - * them is examined in prldap_try_one_address till it succeeds. - * Then, try converting the string address, in case the string - * address was not successfully handled in PR_GetAddrInfoByName. - */ - if ( NULL != ( infop = - PR_GetAddrInfoByName( host, PR_AF_UNSPEC, - (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME) ))) { - void *enump = NULL; - do { - memset( &addr, 0, sizeof( addr )); - enump = PR_EnumerateAddrInfo( enump, infop, port, &addr ); - if ( NULL == enump ) { - break; - } - rc = prldap_try_one_address( prsockp, &addr, timeout, options ); - } while ( rc < 0 ); - PR_FreeAddrInfo( infop ); - } else if ( PR_SUCCESS == PR_StringToNetAddr( host, &addr )) { - PRLDAP_SET_PORT( &addr, port ); - rc = prldap_try_one_address( prsockp, &addr, timeout, options ); - } - ldap_memfree( host ); - } - - if ( host ) { - ldap_memfree( host ); - } - ldap_x_hostlist_statusfree( status ); - - if ( rc < 0 ) { - prldap_set_system_errno( prldap_prerr2errno()); - prldap_socket_arg_free( &prsockp ); - } else { - *socketargp = prsockp; - } - - return( rc ); -} - - -static int LDAP_CALLBACK -prldap_close( int s, struct lextiof_socket_private *socketarg ) -{ - int rc; - - rc = 0; - if ( PR_Close( PRLDAP_GET_PRFD(socketarg)) != PR_SUCCESS ) { - rc = -1; - prldap_set_system_errno( prldap_prerr2errno()); - } - prldap_socket_arg_free( &socketarg ); - - return( rc ); -} - - -/* - * LDAP session handle creation callback. - * - * Allocate a session argument if not already done, and then call the - * thread's new handle function. - */ -static int LDAP_CALLBACK -prldap_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) -{ - - if ( NULL == sessionarg ) { - struct ldap_x_ext_io_fns iofns; - - memset( &iofns, 0, sizeof(iofns)); - iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; - if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, - (void *)&iofns ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - if ( NULL == - ( iofns.lextiof_session_arg = prldap_session_arg_alloc())) { - return( LDAP_NO_MEMORY ); - } - if ( ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, - (void *)&iofns ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - } - - return( LDAP_SUCCESS ); -} - - -/* only called/installed if shared is non-zero. */ -static int LDAP_CALLBACK -prldap_shared_newhandle( LDAP *ld, struct lextiof_session_private *sessionarg ) -{ - int rc; - - if (( rc = prldap_newhandle( ld, sessionarg )) == LDAP_SUCCESS ) { - rc = prldap_thread_new_handle( ld, sessionarg ); - } - - return( rc ); -} - - -static void LDAP_CALLBACK -prldap_disposehandle( LDAP *ld, struct lextiof_session_private *sessionarg ) -{ - prldap_session_arg_free( &sessionarg ); -} - - -/* only called/installed if shared is non-zero */ -static void LDAP_CALLBACK -prldap_shared_disposehandle( LDAP *ld, - struct lextiof_session_private *sessionarg ) -{ - prldap_thread_dispose_handle( ld, sessionarg ); - prldap_disposehandle( ld, sessionarg ); -} - - -/* - * Allocate a session argument. - */ -static PRLDAPIOSessionArg * -prldap_session_arg_alloc( void ) -{ - PRLDAPIOSessionArg *prsessp; - - prsessp = PR_Calloc( 1, sizeof( PRLDAPIOSessionArg )); - - if ( NULL != prsessp ) { - /* copy global defaults to the new session handle */ - prsessp->prsess_io_max_timeout = prldap_default_io_max_timeout; - } - - return( prsessp ); -} - - -static void -prldap_session_arg_free( PRLDAPIOSessionArg **prsesspp ) -{ - if ( NULL != prsesspp && NULL != *prsesspp ) { - if ( NULL != (*prsesspp)->prsess_pollds ) { - PR_Free( (*prsesspp)->prsess_pollds ); - (*prsesspp)->prsess_pollds = NULL; - } - PR_Free( *prsesspp ); - *prsesspp = NULL; - } -} - - -/* - * Given an LDAP session handle, retrieve a session argument. - * Returns an LDAP error code. - */ -int -prldap_session_arg_from_ld( LDAP *ld, PRLDAPIOSessionArg **sessargpp ) -{ - struct ldap_x_ext_io_fns iofns; - - if ( NULL == ld || NULL == sessargpp ) { - /* XXXmcs: NULL ld's are not supported */ - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - memset( &iofns, 0, sizeof(iofns)); - iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; - if ( ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - if ( NULL == iofns.lextiof_session_arg ) { - ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - *sessargpp = iofns.lextiof_session_arg; - return( LDAP_SUCCESS ); -} - - -/* - * Given an LDAP session handle, retrieve a socket argument. - * Returns an LDAP error code. - */ -int -prldap_socket_arg_from_ld( LDAP *ld, PRLDAPIOSocketArg **sockargpp ) -{ - Sockbuf *sbp; - struct lber_x_ext_io_fns extiofns; - - if ( NULL == ld || NULL == sockargpp ) { - /* XXXmcs: NULL ld's are not supported */ - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( ldap_get_option( ld, LDAP_X_OPT_SOCKBUF, (void *)&sbp ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - memset( &extiofns, 0, sizeof(extiofns)); - extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - if ( ber_sockbuf_get_option( sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, - (void *)&extiofns ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - if ( NULL == extiofns.lbextiofn_socket_arg ) { - ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - *sockargpp = extiofns.lbextiofn_socket_arg; - return( LDAP_SUCCESS ); -} - - -/* - * Allocate a socket argument. - */ -PRLDAPIOSocketArg * -prldap_socket_arg_alloc( PRLDAPIOSessionArg *sessionarg ) -{ - PRLDAPIOSocketArg *prsockp; - - prsockp = PR_Calloc( 1, sizeof( PRLDAPIOSocketArg )); - - if ( NULL != prsockp && NULL != sessionarg ) { - /* copy socket defaults from the session */ - prsockp->prsock_io_max_timeout = sessionarg->prsess_io_max_timeout; - } - - return( prsockp ); -} - - -static void -prldap_socket_arg_free( PRLDAPIOSocketArg **prsockpp ) -{ - if ( NULL != prsockpp && NULL != *prsockpp ) { - PR_Free( *prsockpp ); - *prsockpp = NULL; - } -} - - -static void * -prldap_safe_realloc( void *ptr, PRUint32 size ) -{ - void *p; - - if ( NULL == ptr ) { - p = PR_Malloc( size ); - } else { - p = PR_Realloc( ptr, size ); - } - - return( p ); -} - - - -/* returns an LDAP result code */ -int -prldap_set_io_max_timeout( PRLDAPIOSessionArg *prsessp, int io_max_timeout ) -{ - int rc = LDAP_SUCCESS; /* optimistic */ - - if ( NULL == prsessp ) { - prldap_default_io_max_timeout = io_max_timeout; - } else { - prsessp->prsess_io_max_timeout = io_max_timeout; - } - - return( rc ); -} - - -/* returns an LDAP result code */ -int -prldap_get_io_max_timeout( PRLDAPIOSessionArg *prsessp, int *io_max_timeoutp ) -{ - int rc = LDAP_SUCCESS; /* optimistic */ - - if ( NULL == io_max_timeoutp ) { - rc = LDAP_PARAM_ERROR; - } else if ( NULL == prsessp ) { - *io_max_timeoutp = prldap_default_io_max_timeout; - } else { - *io_max_timeoutp = prsessp->prsess_io_max_timeout; - } - - return( rc ); -} - -/* Check if NSPR layer has been installed for a LDAP session. - * Simply check whether prldap_connect() I/O function is installed - */ -PRBool -prldap_is_installed( LDAP *ld ) -{ - struct ldap_x_ext_io_fns iofns; - - /* Retrieve current I/O functions */ - memset( &iofns, 0, sizeof(iofns)); - iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; - if ( ld == NULL || ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, (void *)&iofns ) - != 0 || iofns.lextiof_connect != prldap_connect ) - { - return( PR_FALSE ); - } - - return( PR_TRUE ); -} - diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-public.c b/ldap/c-sdk/libraries/libprldap/ldappr-public.c deleted file mode 100644 index 6e9e597e6a..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-public.c +++ /dev/null @@ -1,454 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Public interface for libprldap -- use NSPR (Netscape Portable Runtime) - * I/O, threads, etc. with libldap. - * - */ - -#include "ldappr-int.h" -#include - -/* - * Function: prldap_init(). - * - * Create a new LDAP session handle, but with NSPR I/O, threading, and DNS - * functions installed. - * - * Pass a non-zero value for the 'shared' parameter if you plan to use - * this LDAP * handle from more than one thread. - * - * prldap_init() returns an LDAP session handle (or NULL if an error occurs). - */ -LDAP * LDAP_CALL -prldap_init( const char *defhost, int defport, int shared ) -{ - LDAP *ld; - - if (( ld = ldap_init( defhost, defport )) != NULL ) { - if ( prldap_install_routines( ld, shared ) != LDAP_SUCCESS ) { - prldap_set_system_errno( EINVAL ); /* XXXmcs: just a guess! */ - ldap_unbind( ld ); - ld = NULL; - } - } - - return( ld ); -} - - -/* - * Function: prldap_install_routines(). - * - * Install NSPR I/O, threading, and DNS functions so they will be used by - * 'ld'. - * - * If 'ld' is NULL, the functions are installed as the default functions - * for all new LDAP * handles). - * - * Pass a non-zero value for the 'shared' parameter if you plan to use - * this LDAP * handle from more than one thread. - * - * prldap_install_routines() returns an LDAP API error code (LDAP_SUCCESS - * if all goes well). - */ -int LDAP_CALL -prldap_install_routines( LDAP *ld, int shared ) -{ - - if ( prldap_install_io_functions( ld, shared ) != 0 - || prldap_install_thread_functions( ld, shared ) != 0 - || prldap_install_dns_functions( ld ) != 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_set_session_option(). - * - * Given an LDAP session handle or a session argument such is passed to - * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, set - * an option that affects the prldap layer. - * - * If 'ld' and 'session" are both NULL, the option is set as the default - * for all new prldap sessions. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). - */ -int LDAP_CALL -prldap_set_session_option( LDAP *ld, void *sessionarg, int option, ... ) -{ - int rc = LDAP_SUCCESS; /* optimistic */ - PRLDAPIOSessionArg *prsessp = NULL; - va_list ap; - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { - return( rc ); - } - } else if ( NULL != sessionarg ) { - prsessp = (PRLDAPIOSessionArg *)sessionarg; - } - - va_start( ap, option ); - switch ( option ) { - case PRLDAP_OPT_IO_MAX_TIMEOUT: - rc = prldap_set_io_max_timeout( prsessp, va_arg( ap, int )); - break; - default: - rc = LDAP_PARAM_ERROR; - } - va_end( ap ); - - return( rc ); -} - - -/* - * Function: prldap_get_session_option(). - * - * Given an LDAP session handle or a session argument such is passed to - * SOCKET, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks, retrieve - * the setting for an option that affects the prldap layer. - * - * If 'ld' and 'session" are both NULL, the default option value for all new - * new prldap sessions is retrieved. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). - */ -int LDAP_CALL prldap_get_session_option( LDAP *ld, void *sessionarg, - int option, ... ) -{ - int rc = LDAP_SUCCESS; /* optimistic */ - PRLDAPIOSessionArg *prsessp = NULL; - va_list ap; - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { - return( rc ); - } - } else if ( NULL != sessionarg ) { - prsessp = (PRLDAPIOSessionArg *)sessionarg; - } - - va_start( ap, option ); - switch ( option ) { - case PRLDAP_OPT_IO_MAX_TIMEOUT: - rc = prldap_get_io_max_timeout( prsessp, va_arg( ap, int * )); - break; - default: - rc = LDAP_PARAM_ERROR; - } - va_end( ap ); - - return( rc ); -} - - -/* - * Function: prldap_set_session_info(). - * - * Given an LDAP session handle, set some application-specific data. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). - */ -int LDAP_CALL -prldap_set_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip ) -{ - int rc; - PRLDAPIOSessionArg *prsessp; - - if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { - return( rc ); - } - } else if ( NULL != sessionarg ) { - prsessp = (PRLDAPIOSessionArg *)sessionarg; - } else { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - prsessp->prsess_appdata = seip->seinfo_appdata; - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_get_session_info(). - * - * Given an LDAP session handle, retrieve some application-specific data. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in - * which case the fields in the structure that seip points to are filled in). - */ -int LDAP_CALL -prldap_get_session_info( LDAP *ld, void *sessionarg, PRLDAPSessionInfo *seip ) -{ - int rc; - PRLDAPIOSessionArg *prsessp; - - if ( seip == NULL || PRLDAP_SESSIONINFO_SIZE != seip->seinfo_size ) { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_session_arg_from_ld( ld, &prsessp ))) { - return( rc ); - } - } else if ( NULL != sessionarg ) { - prsessp = (PRLDAPIOSessionArg *)sessionarg; - } else { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - seip->seinfo_appdata = prsessp->prsess_appdata; - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_set_socket_info(). - * - * Given an integer fd and a void * argument such as those passed to the - * extended I/O callback functions, set socket specific information. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well). - * - * Note: it is only safe to change soinfo_prfd from within the SOCKET - * extended I/O callback function. - */ -int LDAP_CALL -prldap_set_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip ) -{ - PRLDAPIOSocketArg *prsockp; - - if ( NULL == socketarg || NULL == soip || - PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { - return( LDAP_PARAM_ERROR ); - } - - prsockp = (PRLDAPIOSocketArg *)socketarg; - prsockp->prsock_prfd = soip->soinfo_prfd; - prsockp->prsock_appdata = soip->soinfo_appdata; - - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_get_socket_info(). - * - * Given an integer fd and a void * argument such as those passed to the - * extended I/O callback functions, retrieve socket specific information. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in - * which case the fields in the structure that soip points to are filled in). - */ -int LDAP_CALL -prldap_get_socket_info( int fd, void *socketarg, PRLDAPSocketInfo *soip ) -{ - PRLDAPIOSocketArg *prsockp; - - if ( NULL == socketarg || NULL == soip || - PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { - return( LDAP_PARAM_ERROR ); - } - - prsockp = (PRLDAPIOSocketArg *)socketarg; - soip->soinfo_prfd = prsockp->prsock_prfd; - soip->soinfo_appdata = prsockp->prsock_appdata; - - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_get_default_socket_info(). - * - * Given an LDAP session handle, retrieve socket specific information. - * If ld is NULL, LDAP_PARAM_ERROR is returned. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in - * which case the fields in the structure that soip points to are filled in). - */ -int LDAP_CALL -prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ) -{ - int rc; - PRLDAPIOSocketArg *prsockp; - - - if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) { - return( rc ); - } - } else { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - soip->soinfo_prfd = prsockp->prsock_prfd; - soip->soinfo_appdata = prsockp->prsock_appdata; - - return( LDAP_SUCCESS ); -} - - -/* - * Function: prldap_set_default_socket_info(). - * - * Given an LDAP session handle, set socket specific information. - * If ld is NULL, LDAP_PARAM_ERROR is returned. - * - * Returns an LDAP API error code (LDAP_SUCCESS if all goes well, in - * which case the fields in the structure that soip points to are filled in). - */ -int LDAP_CALL -prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ) -{ - int rc; - PRLDAPIOSocketArg *prsockp; - - - if ( NULL == soip || PRLDAP_SOCKETINFO_SIZE != soip->soinfo_size ) { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( NULL != ld ) { - if ( LDAP_SUCCESS != - ( rc = prldap_socket_arg_from_ld( ld, &prsockp ))) { - return( rc ); - } - } else { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - prsockp->prsock_prfd = soip->soinfo_prfd; - prsockp->prsock_appdata = soip->soinfo_appdata; - - return( LDAP_SUCCESS ); -} - - -/* -* Function: prldap_import_connection(). -* -* Given the LDAP handle the connection parameters for the -* file descriptor are imported into NSPR layer. -* -* Returns an LDAP API code (LDAP_SUCCESS) if all goes well. -*/ -int LDAP_CALL -prldap_import_connection (LDAP *ld) -{ - int rc = LDAP_SUCCESS; /* optimistic */ - int shared = 1; /* Assume shared init */ - LBER_SOCKET orig_socket = -1; - PRLDAPIOSessionArg *prsessp = NULL; - PRLDAPIOSocketArg *prsockp = NULL; - PRFileDesc *pr_socket = NULL; - - /* Check for invalid ld handle */ - if ( ld == NULL) { - ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - /* Retrieve TCP socket's integer file descriptor */ - if ( ldap_get_option( ld, LDAP_OPT_DESC, &orig_socket ) < 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - /* Check for NSPR functions on ld */ - if ( prldap_is_installed(ld)) { /* Error : NSPR already Installed */ - ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - if (LDAP_SUCCESS != (rc = prldap_install_routines(ld, shared))) { - return( rc ); - } - - if (LDAP_SUCCESS != (rc = prldap_session_arg_from_ld( ld, &prsessp ))) { - return( rc ); - } - - /* Get NSPR Socket Arg */ - if ( NULL == ( prsockp = prldap_socket_arg_alloc( prsessp ))) { - ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - - /* Import file descriptor of connection made via ldap_init() */ - if (NULL == (pr_socket = PR_ImportTCPSocket(orig_socket)) ) { - ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( LDAP_LOCAL_ERROR ); - } - - prsockp->prsock_prfd = pr_socket; - - /* Set Socket Arg in Extended I/O Layer */ - if ( ldap_set_option( ld, LDAP_X_OPT_SOCKETARG, prsockp) != 0 ) { - return( ldap_get_lderrno( ld, NULL, NULL )); - } - - return( rc ); -} diff --git a/ldap/c-sdk/libraries/libprldap/ldappr-threads.c b/ldap/c-sdk/libraries/libprldap/ldappr-threads.c deleted file mode 100644 index 1cfdc92635..0000000000 --- a/ldap/c-sdk/libraries/libprldap/ldappr-threads.c +++ /dev/null @@ -1,643 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Thread callback functions for libldap that use the NSPR (Netscape - * Portable Runtime) thread API. - * - */ - -#include "ldappr-int.h" - -/* - * Macros: - */ -/* - * Grow thread private data arrays 10 elements at a time. - */ -#define PRLDAP_TPD_ARRAY_INCREMENT 10 - -/* - * Structures and types: - */ -/* - * Structure used by libldap thread callbacks to maintain error information. - */ -typedef struct prldap_errorinfo { - int plei_magic; /* must be first in the structure */ - int plei_lderrno; - char *plei_matched; - char *plei_errmsg; -} PRLDAP_ErrorInfo; - -#define PRLDAP_ERRORINFO_MAGIC 0x4D4F5A45 /* 'MOZE' */ - - -/* - * Structure used to maintain thread-private data. At the present time, - * only error info. is thread-private. One of these structures is allocated - * for each thread. - */ -typedef struct prldap_tpd_header { - int ptpdh_tpd_count; /* # of data items allocated */ - void **ptpdh_dataitems; /* array of data items */ -} PRLDAP_TPDHeader; - -/* - * Structure used by associate a PRLDAP thread-private data index with an - * LDAP session handle. One of these exists for each active LDAP session - * handle. - */ -typedef struct prldap_tpd_map { - LDAP *prtm_ld; /* non-NULL if in use */ - PRUintn prtm_index; /* index into TPD array */ - struct prldap_tpd_map *prtm_next; -} PRLDAP_TPDMap; - - - -/* - * Static Variables: - */ -/* - * prldap_map_list points to all of the PRLDAP_TPDMap structures - * we have ever allocated. We recycle them as we open and close LDAP - * sessions. - */ -static PRLDAP_TPDMap *prldap_map_list = NULL; - - -/* - * The prldap_map_mutex is used to protect access to the prldap_map_list. - */ -static PRLock *prldap_map_mutex = NULL; - -/* - * The prldap_tpd_maxindex value is used to track the largest TPD array - * index we have used. - */ -static PRInt32 prldap_tpd_maxindex = -1; - -/* - * prldap_tpdindex is an NSPR thread private data index we use to - * maintain our own thread-private data. It is initialized inside - * prldap_init_tpd(). - */ -static PRUintn prldap_tpdindex = 0; - -/* - * The prldap_callonce_init_tpd structure is used by NSPR to ensure - * that prldap_init_tpd() is called at most once. - */ -static PRCallOnceType prldap_callonce_init_tpd = { 0, 0, 0 }; - - -/* - * Private function prototypes: - */ -static void prldap_set_ld_error( int err, char *matched, char *errmsg, - void *errorarg ); -static int prldap_get_ld_error( char **matchedp, char **errmsgp, - void *errorarg ); -static void *prldap_mutex_alloc( void ); -static void prldap_mutex_free( void *mutex ); -static int prldap_mutex_lock( void *mutex ); -static int prldap_mutex_unlock( void *mutex ); -static void *prldap_get_thread_id( void ); -static PRStatus prldap_init_tpd( void ); -static PRLDAP_TPDMap *prldap_allocate_map( LDAP *ld ); -static void prldap_return_map( PRLDAP_TPDMap *map ); -static PRUintn prldap_new_tpdindex( void ); -static int prldap_set_thread_private( PRInt32 tpdindex, void *priv ); -static void *prldap_get_thread_private( PRInt32 tpdindex ); -static PRLDAP_TPDHeader *prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, - int maxindex ); -static void prldap_tsd_destroy( void *priv ); - - -/* - * Install NSPR thread functions into ld (if ld is NULL, they are installed - * as the default functions for new LDAP * handles). - * - * Returns 0 if all goes well and -1 if not. - */ -int -prldap_install_thread_functions( LDAP *ld, int shared ) -{ - struct ldap_thread_fns tfns; - struct ldap_extra_thread_fns xtfns; - - if ( PR_CallOnce( &prldap_callonce_init_tpd, prldap_init_tpd ) - != PR_SUCCESS ) { - ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); - return( -1 ); - } - - /* set thread function pointers */ - memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); - tfns.ltf_get_errno = prldap_get_system_errno; - tfns.ltf_set_errno = prldap_set_system_errno; - if ( shared ) { - tfns.ltf_mutex_alloc = prldap_mutex_alloc; - tfns.ltf_mutex_free = prldap_mutex_free; - tfns.ltf_mutex_lock = prldap_mutex_lock; - tfns.ltf_mutex_unlock = prldap_mutex_unlock; - tfns.ltf_get_lderrno = prldap_get_ld_error; - tfns.ltf_set_lderrno = prldap_set_ld_error; - if ( ld != NULL ) { - /* - * If this is a real ld (i.e., we are not setting the global - * defaults) allocate thread private data for error information. - * If ld is NULL we do not do this here but it is done in - * prldap_thread_new_handle(). - */ - if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) - == NULL ) { - return( -1 ); - } - } - } - - if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, - (void *)&tfns ) != 0 ) { - prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); - return( -1 ); - } - - /* set extended thread function pointers */ - memset( &xtfns, '\0', sizeof(struct ldap_extra_thread_fns) ); - xtfns.ltf_threadid_fn = prldap_get_thread_id; - if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, - (void *)&xtfns ) != 0 ) { - return( -1 ); - } - - return( 0 ); -} - - -static void * -prldap_mutex_alloc( void ) -{ - return( (void *)PR_NewLock()); -} - - -static void -prldap_mutex_free( void *mutex ) -{ - PR_DestroyLock( (PRLock *)mutex ); -} - - -static int -prldap_mutex_lock( void *mutex ) -{ - PR_Lock( (PRLock *)mutex ); - return( 0 ); -} - - -static int -prldap_mutex_unlock( void *mutex ) -{ - if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) { - return( -1 ); - } - - return( 0 ); -} - - -static void * -prldap_get_thread_id( void ) -{ - return( (void *)PR_GetCurrentThread()); -} - - -static int -prldap_get_ld_error( char **matchedp, char **errmsgp, void *errorarg ) -{ - PRLDAP_TPDMap *map; - PRLDAP_ErrorInfo *eip; - - if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL && ( eip = - (PRLDAP_ErrorInfo *)prldap_get_thread_private( - map->prtm_index )) != NULL ) { - if ( matchedp != NULL ) { - *matchedp = eip->plei_matched; - } - if ( errmsgp != NULL ) { - *errmsgp = eip->plei_errmsg; - } - return( eip->plei_lderrno ); - } else { - if ( matchedp != NULL ) { - *matchedp = NULL; - } - if ( errmsgp != NULL ) { - *errmsgp = NULL; - } - return( LDAP_LOCAL_ERROR ); /* punt */ - } -} - - -static void -prldap_set_ld_error( int err, char *matched, char *errmsg, void *errorarg ) -{ - PRLDAP_TPDMap *map; - PRLDAP_ErrorInfo *eip; - - if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL ) { - if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( - map->prtm_index )) == NULL ) { - /* - * Error info. has not yet been allocated for this thread. - * Do so now. Note that we free this memory only for the - * thread that calls prldap_thread_dispose_handle(), which - * should be the one that called ldap_unbind() -- see - * prldap_return_map(). Not freeing the memory used by - * other threads is deemed acceptable since it will be - * recycled and used by other LDAP sessions. All of the - * thread-private memory is freed when a thread exits - * (inside the prldap_tsd_destroy() function). - */ - eip = (PRLDAP_ErrorInfo *)PR_Calloc( 1, - sizeof( PRLDAP_ErrorInfo )); - if ( eip == NULL ) { - return; /* punt */ - } - eip->plei_magic = PRLDAP_ERRORINFO_MAGIC; - (void)prldap_set_thread_private( map->prtm_index, eip ); - } - - eip->plei_lderrno = err; - - if ( eip->plei_matched != NULL ) { - ldap_memfree( eip->plei_matched ); - } - eip->plei_matched = matched; - - if ( eip->plei_errmsg != NULL ) { - ldap_memfree( eip->plei_errmsg ); - } - eip->plei_errmsg = errmsg; - } -} - - -/* - * Utility function to free a PRLDAP_ErrorInfo structure and everything - * it contains. - */ -static void -prldap_free_errorinfo( PRLDAP_ErrorInfo *eip ) -{ - if ( NULL != eip && PRLDAP_ERRORINFO_MAGIC == eip->plei_magic ) { - if ( eip->plei_matched != NULL ) { - ldap_memfree( eip->plei_matched ); - } - if ( eip->plei_errmsg != NULL ) { - ldap_memfree( eip->plei_errmsg ); - } - - PR_Free( eip ); - } -} - - -/* - * Called when a new LDAP * session handle is allocated. - * Allocate thread-private data for error information, but only if - * it has not already been allocated and the get_ld_error callback has - * been installed. If ld is not NULL when prldap_install_thread_functions() - * is called, we will have already allocated the thread-private data there. - */ -int -prldap_thread_new_handle( LDAP *ld, void *sessionarg ) -{ - struct ldap_thread_fns tfns; - - if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *)&tfns ) != 0 ) { - return( LDAP_LOCAL_ERROR ); - } - - if ( tfns.ltf_lderrno_arg == NULL && tfns.ltf_get_lderrno != NULL ) { - if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) == NULL - || ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, - (void *)&tfns ) != 0 ) { - return( LDAP_LOCAL_ERROR ); - } - } - - return( LDAP_SUCCESS ); -} - - -/* - * Called when an LDAP * session handle is being destroyed. - * Clean up our thread private data map. - */ -void -prldap_thread_dispose_handle( LDAP *ld, void *sessionarg ) -{ - struct ldap_thread_fns tfns; - - if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, - (void *)&tfns ) == 0 && - tfns.ltf_lderrno_arg != NULL ) { - prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); - } -} - - -static PRStatus -prldap_init_tpd( void ) -{ - if (( prldap_map_mutex = PR_NewLock()) == NULL || PR_NewThreadPrivateIndex( - &prldap_tpdindex, prldap_tsd_destroy ) != PR_SUCCESS ) { - return( PR_FAILURE ); - } - - prldap_map_list = NULL; - - return( PR_SUCCESS ); -} - - -/* - * Function: prldap_allocate_map() - * Description: allocate a thread-private data map to use for a new - * LDAP session handle. - * Returns: a pointer to the TPD map or NULL if none available. - */ -static PRLDAP_TPDMap * -prldap_allocate_map( LDAP *ld ) -{ - PRLDAP_TPDMap *map, *prevmap; - - PR_Lock( prldap_map_mutex ); - - /* - * first look for a map that is already allocated but free to be re-used - */ - prevmap = NULL; - for ( map = prldap_map_list; map != NULL; map = map->prtm_next ) { - if ( map->prtm_ld == NULL ) { - break; - } - prevmap = map; - } - - /* - * if none was found (map == NULL), try to allocate a new one and add it - * to the end of our global list. - */ - if ( map == NULL ) { - PRUintn tpdindex; - - tpdindex = prldap_new_tpdindex(); - map = (PRLDAP_TPDMap *)PR_Malloc( sizeof( PRLDAP_TPDMap )); - if ( map != NULL ) { - map->prtm_index = tpdindex; - map->prtm_next = NULL; - if ( prevmap == NULL ) { - prldap_map_list = map; - } else { - prevmap->prtm_next = map; - } - } - } - - if ( map != NULL ) { - map->prtm_ld = ld; /* now marked as "in use" */ - - /* - * If old thread-private error information exists, reset it. It may - * have been left behind by an old LDAP session that was used by - * this thread but disposed of by a different thread. - */ - if ( NULL != prldap_get_thread_private( map->prtm_index )) { - prldap_set_ld_error( LDAP_SUCCESS, NULL, NULL, map ); - } - } - - PR_Unlock( prldap_map_mutex ); - - return( map ); -} - - -/* - * Function: prldap_return_map() - * Description: return a thread-private data map to the pool of ones - * available for re-use. - */ -static void -prldap_return_map( PRLDAP_TPDMap *map ) -{ - PRLDAP_ErrorInfo *eip; - - PR_Lock( prldap_map_mutex ); - - /* - * Dispose of thread-private LDAP error information. Note that this - * only disposes of the memory consumed on THIS thread, but that is - * okay. See the comment in prldap_set_ld_error() for the reason why. - */ - if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( - map->prtm_index )) != NULL && - prldap_set_thread_private( map->prtm_index, NULL ) == 0 ) { - prldap_free_errorinfo( eip ); - } - - /* mark map as available for re-use */ - map->prtm_ld = NULL; - - PR_Unlock( prldap_map_mutex ); -} - - -/* - * Function: prldap_new_tpdindex() - * Description: allocate a thread-private data index. - * Returns: the new index. - */ -static PRUintn -prldap_new_tpdindex( void ) -{ - PRUintn tpdindex; - - tpdindex = (PRUintn)PR_AtomicIncrement( &prldap_tpd_maxindex ); - return( tpdindex ); -} - - -/* - * Function: prldap_set_thread_private() - * Description: store a piece of thread-private data. - * Returns: 0 if successful and -1 if not. - */ -static int -prldap_set_thread_private( PRInt32 tpdindex, void *priv ) -{ - PRLDAP_TPDHeader *tsdhdr; - - if ( tpdindex > prldap_tpd_maxindex ) { - return( -1 ); /* bad index */ - } - - tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); - if ( tsdhdr == NULL || tpdindex >= tsdhdr->ptpdh_tpd_count ) { - tsdhdr = prldap_tsd_realloc( tsdhdr, tpdindex ); - if ( tsdhdr == NULL ) { - return( -1 ); /* realloc failed */ - } - } - - tsdhdr->ptpdh_dataitems[ tpdindex ] = priv; - return( 0 ); -} - - -/* - * Function: prldap_get_thread_private() - * Description: retrieve a piece of thread-private data. If not set, - * NULL is returned. - * Returns: 0 if successful and -1 if not. - */ -static void * -prldap_get_thread_private( PRInt32 tpdindex ) -{ - PRLDAP_TPDHeader *tsdhdr; - - tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); - if ( tsdhdr == NULL ) { - return( NULL ); /* no thread private data */ - } - - if ( tpdindex >= tsdhdr->ptpdh_tpd_count - || tsdhdr->ptpdh_dataitems == NULL ) { - return( NULL ); /* fewer data items than requested index */ - } - - return( tsdhdr->ptpdh_dataitems[ tpdindex ] ); -} - - -/* - * Function: prldap_tsd_realloc() - * Description: enlarge the thread-private data array. - * Returns: the new PRLDAP_TPDHeader value (non-NULL if successful). - * Note: tsdhdr can be NULL (allocates a new PRLDAP_TPDHeader). - */ -static PRLDAP_TPDHeader * -prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, int maxindex ) -{ - void *newdataitems = NULL; - int count; - - if ( tsdhdr == NULL ) { - /* allocate a new thread private data header */ - if (( tsdhdr = PR_Calloc( 1, sizeof( PRLDAP_TPDHeader ))) == NULL ) { - return( NULL ); - } - (void)PR_SetThreadPrivate( prldap_tpdindex, tsdhdr ); - } - - /* - * Make the size of the new array the next highest multiple of - * the array increment value that is greater than maxindex. - */ - count = PRLDAP_TPD_ARRAY_INCREMENT * - ( 1 + ( maxindex / PRLDAP_TPD_ARRAY_INCREMENT )); - - /* increase the size of the data item array if necessary */ - if ( count > tsdhdr->ptpdh_tpd_count ) { - newdataitems = (PRLDAP_ErrorInfo *)PR_Calloc( count, sizeof( void * )); - if ( newdataitems == NULL ) { - return( NULL ); - } - if ( tsdhdr->ptpdh_dataitems != NULL ) { /* preserve old data */ - memcpy( newdataitems, tsdhdr->ptpdh_dataitems, - tsdhdr->ptpdh_tpd_count * sizeof( void * )); - PR_Free( tsdhdr->ptpdh_dataitems ); - } - - tsdhdr->ptpdh_tpd_count = count; - tsdhdr->ptpdh_dataitems = newdataitems; - } - - return( tsdhdr ); -} - - -/* - * Function: prldap_tsd_destroy() - * Description: Free a thread-private data array. Installed as an NSPR TPD - * destructor function - * Returns: nothing. - */ -static void -prldap_tsd_destroy( void *priv ) -{ - PRLDAP_TPDHeader *tsdhdr; - PRLDAP_ErrorInfo *eip; - int i; - - tsdhdr = (PRLDAP_TPDHeader *)priv; - if ( tsdhdr != NULL ) { - if ( tsdhdr->ptpdh_dataitems != NULL ) { - for ( i = 0; i < tsdhdr->ptpdh_tpd_count; ++i ) { - if ( tsdhdr->ptpdh_dataitems[ i ] != NULL ) { - eip = (PRLDAP_ErrorInfo *)tsdhdr->ptpdh_dataitems[ i ]; - if ( PRLDAP_ERRORINFO_MAGIC == eip->plei_magic ) { - prldap_free_errorinfo( eip ); - } else { - PR_Free( tsdhdr->ptpdh_dataitems[ i ] ); - } - tsdhdr->ptpdh_dataitems[ i ] = NULL; - } - } - PR_Free( tsdhdr->ptpdh_dataitems ); - tsdhdr->ptpdh_dataitems = NULL; - } - PR_Free( tsdhdr ); - } -} diff --git a/ldap/c-sdk/libraries/libprldap/libprldap.def b/ldap/c-sdk/libraries/libprldap/libprldap.def deleted file mode 100644 index a18e7ee824..0000000000 --- a/ldap/c-sdk/libraries/libprldap/libprldap.def +++ /dev/null @@ -1,59 +0,0 @@ -; -; ***** BEGIN LICENSE BLOCK ***** -; Version: MPL 1.1/GPL 2.0/LGPL 2.1 -; -; The contents of this file are subject to the Mozilla Public License Version -; 1.1 (the "License"); you may not use this file except in compliance with -; the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" basis, -; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -; for the specific language governing rights and limitations under the -; License. -; -; The Original Code is Mozilla Communicator client code. -; -; The Initial Developer of the Original Code is -; Netscape Communications Corporation. -; Portions created by the Initial Developer are Copyright (C) 1996-1999 -; the Initial Developer. All Rights Reserved. -; -; Contributor(s): -; -; Alternatively, the contents of this file may be used under the terms of -; either of the GNU General Public License Version 2 or later (the "GPL"), -; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -; in which case the provisions of the GPL or the LGPL are applicable instead -; of those above. If you wish to allow use of your version of this file only -; under the terms of either the GPL or the LGPL, and not to allow others to -; use your version of this file under the terms of the MPL, indicate your -; decision by deleting the provisions above and replace them with the notice -; and other provisions required by the GPL or the LGPL. If you do not delete -; the provisions above, a recipient may use your version of this file under -; the terms of any one of the MPL, the GPL or the LGPL. -; -; ***** END LICENSE BLOCK ***** - -LIBRARY PRLDAP60 -VERSION 6.0 -HEAPSIZE 4096 - -EXPORTS -; exports list (generated by genexports.pl) -; - - prldap_init - prldap_install_routines - prldap_set_session_info - prldap_get_session_info - prldap_set_socket_info - prldap_get_socket_info - prldap_set_session_option - prldap_get_session_option - prldap_is_installed - prldap_import_connection - prldap_set_default_socket_info - prldap_get_default_socket_info -; -; end of generated exports list. diff --git a/ldap/c-sdk/libraries/libprldap/moz.build b/ldap/c-sdk/libraries/libprldap/moz.build deleted file mode 100644 index 422557cc95..0000000000 --- a/ldap/c-sdk/libraries/libprldap/moz.build +++ /dev/null @@ -1,31 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include('/ldap/ldap-sdk.mozbuild') - -SharedLibrary('prldap60') - -SOURCES += [ - 'ldappr-dns.c', - 'ldappr-error.c', - 'ldappr-io.c', - 'ldappr-public.c', - 'ldappr-threads.c', -] - -if CONFIG['OS_ARCH'] == 'WINNT': - DEFFILE = SRCDIR + '/libprldap.def' - -DEFINES['USE_WAITPID'] = True -DEFINES['NEEDPROTOS'] = True - -LOCAL_INCLUDES += [ - '/ldap/c-sdk/include' -] - -USE_LIBS += [ - 'ldap60', - 'nspr' -] diff --git a/ldap/c-sdk/libraries/moz.build b/ldap/c-sdk/libraries/moz.build deleted file mode 100644 index 339783bfd7..0000000000 --- a/ldap/c-sdk/libraries/moz.build +++ /dev/null @@ -1,11 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -DIRS += [ - 'liblber', - 'libldif', - 'libldap', - 'libprldap' -] diff --git a/ldap/c-sdk/moz.build b/ldap/c-sdk/moz.build new file mode 100644 index 0000000000..4ce8c054e8 --- /dev/null +++ b/ldap/c-sdk/moz.build @@ -0,0 +1,19 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +Library('ldapsdks') + +DIRS += [ + 'liblber', + 'libldif', + 'libldap', + 'libprldap' +] + +USE_LIBS += [ + 'ldap60', + 'ldif60', + 'prldap60', +] \ No newline at end of file diff --git a/ldap/ldap-sdk.mozbuild b/ldap/ldap-sdk.mozbuild deleted file mode 100644 index 4377982c5a..0000000000 --- a/ldap/ldap-sdk.mozbuild +++ /dev/null @@ -1,26 +0,0 @@ -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -NO_VISIBILITY_FLAGS = True -DISABLE_STL_WRAPPING = True -ALLOW_COMPILER_WARNINGS = True - -if CONFIG['OS_TARGET'] == 'Linux': - DEFINES['LINUX'] = 1 - DEFINES['LINUX2_0'] = True - DEFINES['linux'] = 1 -elif CONFIG['OS_TARGET'] == 'Darwin': - DEFINES["DARWIN"] = 1 -elif CONFIG['OS_TARGET'] in ('OpenBSD', 'FreeBSD', 'NetBSD'): - DEFINES[CONFIG['OS_TARGET'].upper()] = True -elif CONFIG['OS_ARCH'] == 'WINNT': - DEFINES['_WINDOWS'] = True - -DEFINES['_PR_PTHREADS'] = True -DEFINES['NET_SSL'] = True -DEFINES['NS_DOMESTIC'] = True - -if CONFIG['MOZ_DEBUG']: - DEFINES['LDAP_DEBUG'] = True diff --git a/ldap/moz.build b/ldap/moz.build index cd511ceb1e..5f2f96490c 100644 --- a/ldap/moz.build +++ b/ldap/moz.build @@ -3,14 +3,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -Library('ldapsdks') - DIRS += [ - 'c-sdk/libraries' -] - -USE_LIBS += [ - 'ldap60', - 'ldif60', - 'prldap60', + 'c-sdk', + 'xpcom' ] diff --git a/ldap/xpcom/src/moz.build b/ldap/xpcom/src/moz.build index 06753e3173..dc63d61187 100644 --- a/ldap/xpcom/src/moz.build +++ b/ldap/xpcom/src/moz.build @@ -48,6 +48,6 @@ else: FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ - '/ldap/c-sdk/include', + '../../c-sdk/include', ] diff --git a/ldap/xpcom/src/nsLDAPURL.cpp b/ldap/xpcom/src/nsLDAPURL.cpp index 3757438486..752ee5b3bf 100644 --- a/ldap/xpcom/src/nsLDAPURL.cpp +++ b/ldap/xpcom/src/nsLDAPURL.cpp @@ -723,3 +723,28 @@ nsLDAPURL::GetHasRef(bool *result) { return mBaseURL->GetHasRef(result); } + + +NS_IMETHODIMP +nsLDAPURL::GetFilePath(nsACString &aFilePath) +{ + return mBaseURL->GetFilePath(aFilePath); +} + +NS_IMETHODIMP +nsLDAPURL::SetFilePath(const nsACString &aFilePath) +{ + return mBaseURL->SetFilePath(aFilePath); +} + +NS_IMETHODIMP +nsLDAPURL::GetQuery(nsACString &aQuery) +{ + return mBaseURL->GetQuery(aQuery); +} + +NS_IMETHODIMP +nsLDAPURL::SetQuery(const nsACString &aQuery) +{ + return mBaseURL->SetQuery(aQuery); +} \ No newline at end of file -- cgit v1.2.3