It would be nice to get this in before 8.0. I squashed the OpenLDAP changes into the first commit (see MR !912) which I will try to get upstream.
From: Hans Leidekker hans@codeweavers.com
Minimal set of files to compile libldap and liblber client libraries. --- configure.ac | 1 + libs/ldap/Makefile.in | 59 + libs/ldap/include/ac/assert.h | 57 + libs/ldap/include/ac/bytes.h | 78 + libs/ldap/include/ac/ctype.h | 33 + libs/ldap/include/ac/dirent.h | 54 + libs/ldap/include/ac/errno.h | 32 + libs/ldap/include/ac/fdset.h | 42 + libs/ldap/include/ac/localize.h | 44 + libs/ldap/include/ac/param.h | 39 + libs/ldap/include/ac/signal.h | 80 + libs/ldap/include/ac/socket.h | 269 +++ libs/ldap/include/ac/stdarg.h | 28 + libs/ldap/include/ac/stdlib.h | 48 + libs/ldap/include/ac/string.h | 118 + libs/ldap/include/ac/time.h | 39 + libs/ldap/include/ac/unistd.h | 72 + libs/ldap/include/lber.h | 691 ++++++ libs/ldap/include/lber_pvt.h | 222 ++ libs/ldap/include/lber_types.h | 63 + libs/ldap/include/ldap.h | 2817 ++++++++++++++++++++++ libs/ldap/include/ldap_avl.h | 165 ++ libs/ldap/include/ldap_cdefs.h | 248 ++ libs/ldap/include/ldap_config.h | 74 + libs/ldap/include/ldap_defaults.h | 71 + libs/ldap/include/ldap_features.h | 56 + libs/ldap/include/ldap_int_thread.h | 290 +++ libs/ldap/include/ldap_log.h | 211 ++ libs/ldap/include/ldap_pvt.h | 588 +++++ libs/ldap/include/ldap_pvt_thread.h | 342 +++ libs/ldap/include/ldap_pvt_uc.h | 161 ++ libs/ldap/include/ldap_queue.h | 593 +++++ libs/ldap/include/ldap_rq.h | 102 + libs/ldap/include/ldap_schema.h | 359 +++ libs/ldap/include/ldap_utf8.h | 106 + libs/ldap/include/ldif.h | 171 ++ libs/ldap/include/lutil.h | 375 +++ libs/ldap/include/lutil_lockf.h | 34 + libs/ldap/include/openldap.h | 39 + libs/ldap/include/portable.h | 1200 ++++++++++ libs/ldap/include/sasl.h | 120 + libs/ldap/liblber/bprint.c | 296 +++ libs/ldap/liblber/decode.c | 1026 ++++++++ libs/ldap/liblber/encode.c | 651 +++++ libs/ldap/liblber/io.c | 725 ++++++ libs/ldap/liblber/lber-int.h | 225 ++ libs/ldap/liblber/memory.c | 831 +++++++ libs/ldap/liblber/nt_err.c | 96 + libs/ldap/liblber/options.c | 237 ++ libs/ldap/liblber/sockbuf.c | 988 ++++++++ libs/ldap/libldap/abandon.c | 458 ++++ libs/ldap/libldap/add.c | 262 +++ libs/ldap/libldap/avl.c | 671 ++++++ libs/ldap/libldap/bind.c | 117 + libs/ldap/libldap/charray.c | 275 +++ libs/ldap/libldap/compare.c | 197 ++ libs/ldap/libldap/controls.c | 552 +++++ libs/ldap/libldap/cyrus.c | 1335 +++++++++++ libs/ldap/libldap/delete.c | 174 ++ libs/ldap/libldap/error.c | 395 ++++ libs/ldap/libldap/extended.c | 418 ++++ libs/ldap/libldap/fetch.c | 148 ++ libs/ldap/libldap/filter.c | 1114 +++++++++ libs/ldap/libldap/free.c | 107 + libs/ldap/libldap/getattr.c | 157 ++ libs/ldap/libldap/getdn.c | 3333 ++++++++++++++++++++++++++ libs/ldap/libldap/getentry.c | 124 + libs/ldap/libldap/getvalues.c | 210 ++ libs/ldap/libldap/init.c | 782 ++++++ libs/ldap/libldap/lbase64.c | 108 + libs/ldap/libldap/ldap-int.h | 925 ++++++++ libs/ldap/libldap/ldap-tls.h | 88 + libs/ldap/libldap/ldap_thr_debug.h | 197 ++ libs/ldap/libldap/ldif.c | 919 ++++++++ libs/ldap/libldap/modify.c | 232 ++ libs/ldap/libldap/modrdn.c | 272 +++ libs/ldap/libldap/open.c | 673 ++++++ libs/ldap/libldap/options.c | 1012 ++++++++ libs/ldap/libldap/os-ip.c | 1265 ++++++++++ libs/ldap/libldap/pagectrl.c | 270 +++ libs/ldap/libldap/print.c | 62 + libs/ldap/libldap/references.c | 147 ++ libs/ldap/libldap/request.c | 1714 ++++++++++++++ libs/ldap/libldap/result.c | 1401 +++++++++++ libs/ldap/libldap/sasl.c | 867 +++++++ libs/ldap/libldap/sasl_w.c | 349 +++ libs/ldap/libldap/schema.c | 3400 +++++++++++++++++++++++++++ libs/ldap/libldap/search.c | 544 +++++ libs/ldap/libldap/sortctrl.c | 552 +++++ libs/ldap/libldap/string.c | 177 ++ libs/ldap/libldap/tavl.c | 523 ++++ libs/ldap/libldap/thr_nt.c | 253 ++ libs/ldap/libldap/tls2.c | 1674 +++++++++++++ libs/ldap/libldap/tls_w.c | 659 ++++++ libs/ldap/libldap/unbind.c | 319 +++ libs/ldap/libldap/url.c | 1652 +++++++++++++ libs/ldap/libldap/utf-8.c | 562 +++++ libs/ldap/libldap/util-int.c | 1026 ++++++++ libs/ldap/libldap/vlvctrl.c | 361 +++ 99 files changed, 48298 insertions(+) create mode 100644 libs/ldap/Makefile.in create mode 100644 libs/ldap/include/ac/assert.h create mode 100644 libs/ldap/include/ac/bytes.h create mode 100644 libs/ldap/include/ac/ctype.h create mode 100644 libs/ldap/include/ac/dirent.h create mode 100644 libs/ldap/include/ac/errno.h create mode 100644 libs/ldap/include/ac/fdset.h create mode 100644 libs/ldap/include/ac/localize.h create mode 100644 libs/ldap/include/ac/param.h create mode 100644 libs/ldap/include/ac/signal.h create mode 100644 libs/ldap/include/ac/socket.h create mode 100644 libs/ldap/include/ac/stdarg.h create mode 100644 libs/ldap/include/ac/stdlib.h create mode 100644 libs/ldap/include/ac/string.h create mode 100644 libs/ldap/include/ac/time.h create mode 100644 libs/ldap/include/ac/unistd.h create mode 100644 libs/ldap/include/lber.h create mode 100644 libs/ldap/include/lber_pvt.h create mode 100644 libs/ldap/include/lber_types.h create mode 100644 libs/ldap/include/ldap.h create mode 100644 libs/ldap/include/ldap_avl.h create mode 100644 libs/ldap/include/ldap_cdefs.h create mode 100644 libs/ldap/include/ldap_config.h create mode 100644 libs/ldap/include/ldap_defaults.h create mode 100644 libs/ldap/include/ldap_features.h create mode 100644 libs/ldap/include/ldap_int_thread.h create mode 100644 libs/ldap/include/ldap_log.h create mode 100644 libs/ldap/include/ldap_pvt.h create mode 100644 libs/ldap/include/ldap_pvt_thread.h create mode 100644 libs/ldap/include/ldap_pvt_uc.h create mode 100644 libs/ldap/include/ldap_queue.h create mode 100644 libs/ldap/include/ldap_rq.h create mode 100644 libs/ldap/include/ldap_schema.h create mode 100644 libs/ldap/include/ldap_utf8.h create mode 100644 libs/ldap/include/ldif.h create mode 100644 libs/ldap/include/lutil.h create mode 100644 libs/ldap/include/lutil_lockf.h create mode 100644 libs/ldap/include/openldap.h create mode 100644 libs/ldap/include/portable.h create mode 100644 libs/ldap/include/sasl.h create mode 100644 libs/ldap/liblber/bprint.c create mode 100644 libs/ldap/liblber/decode.c create mode 100644 libs/ldap/liblber/encode.c create mode 100644 libs/ldap/liblber/io.c create mode 100644 libs/ldap/liblber/lber-int.h create mode 100644 libs/ldap/liblber/memory.c create mode 100644 libs/ldap/liblber/nt_err.c create mode 100644 libs/ldap/liblber/options.c create mode 100644 libs/ldap/liblber/sockbuf.c create mode 100644 libs/ldap/libldap/abandon.c create mode 100644 libs/ldap/libldap/add.c create mode 100644 libs/ldap/libldap/avl.c create mode 100644 libs/ldap/libldap/bind.c create mode 100644 libs/ldap/libldap/charray.c create mode 100644 libs/ldap/libldap/compare.c create mode 100644 libs/ldap/libldap/controls.c create mode 100644 libs/ldap/libldap/cyrus.c create mode 100644 libs/ldap/libldap/delete.c create mode 100644 libs/ldap/libldap/error.c create mode 100644 libs/ldap/libldap/extended.c create mode 100644 libs/ldap/libldap/fetch.c create mode 100644 libs/ldap/libldap/filter.c create mode 100644 libs/ldap/libldap/free.c create mode 100644 libs/ldap/libldap/getattr.c create mode 100644 libs/ldap/libldap/getdn.c create mode 100644 libs/ldap/libldap/getentry.c create mode 100644 libs/ldap/libldap/getvalues.c create mode 100644 libs/ldap/libldap/init.c create mode 100644 libs/ldap/libldap/lbase64.c create mode 100644 libs/ldap/libldap/ldap-int.h create mode 100644 libs/ldap/libldap/ldap-tls.h create mode 100644 libs/ldap/libldap/ldap_thr_debug.h create mode 100644 libs/ldap/libldap/ldif.c create mode 100644 libs/ldap/libldap/modify.c create mode 100644 libs/ldap/libldap/modrdn.c create mode 100644 libs/ldap/libldap/open.c create mode 100644 libs/ldap/libldap/options.c create mode 100644 libs/ldap/libldap/os-ip.c create mode 100644 libs/ldap/libldap/pagectrl.c create mode 100644 libs/ldap/libldap/print.c create mode 100644 libs/ldap/libldap/references.c create mode 100644 libs/ldap/libldap/request.c create mode 100644 libs/ldap/libldap/result.c create mode 100644 libs/ldap/libldap/sasl.c create mode 100644 libs/ldap/libldap/sasl_w.c create mode 100644 libs/ldap/libldap/schema.c create mode 100644 libs/ldap/libldap/search.c create mode 100644 libs/ldap/libldap/sortctrl.c create mode 100644 libs/ldap/libldap/string.c create mode 100644 libs/ldap/libldap/tavl.c create mode 100644 libs/ldap/libldap/thr_nt.c create mode 100644 libs/ldap/libldap/tls2.c create mode 100644 libs/ldap/libldap/tls_w.c create mode 100644 libs/ldap/libldap/unbind.c create mode 100644 libs/ldap/libldap/url.c create mode 100644 libs/ldap/libldap/utf-8.c create mode 100644 libs/ldap/libldap/util-int.c create mode 100644 libs/ldap/libldap/vlvctrl.c
diff --git a/configure.ac b/configure.ac index fe6a773d1c3..96a1712b0b7 100644 --- a/configure.ac +++ b/configure.ac @@ -3327,6 +3327,7 @@ WINE_CONFIG_MAKEFILE(libs/gsm) WINE_CONFIG_MAKEFILE(libs/jpeg) WINE_CONFIG_MAKEFILE(libs/jxr) WINE_CONFIG_MAKEFILE(libs/lcms2) +WINE_CONFIG_MAKEFILE(libs/ldap) WINE_CONFIG_MAKEFILE(libs/mfuuid) WINE_CONFIG_MAKEFILE(libs/mpg123) WINE_CONFIG_MAKEFILE(libs/png) diff --git a/libs/ldap/Makefile.in b/libs/ldap/Makefile.in new file mode 100644 index 00000000000..36caad1cf44 --- /dev/null +++ b/libs/ldap/Makefile.in @@ -0,0 +1,59 @@ +EXTLIB = libldap.a +EXTRAINCL = -I$(srcdir)/include +EXTRADEFS = -D_TIMEVAL_DEFINED + +C_SRCS = \ + liblber/bprint.c \ + liblber/decode.c \ + liblber/encode.c \ + liblber/io.c \ + liblber/memory.c \ + liblber/nt_err.c \ + liblber/options.c \ + liblber/sockbuf.c \ + libldap/abandon.c \ + libldap/add.c \ + libldap/avl.c \ + libldap/bind.c \ + libldap/charray.c \ + libldap/compare.c \ + libldap/controls.c \ + libldap/cyrus.c \ + libldap/delete.c \ + libldap/error.c \ + libldap/extended.c \ + libldap/fetch.c \ + libldap/filter.c \ + libldap/free.c \ + libldap/getattr.c \ + libldap/getdn.c \ + libldap/getentry.c \ + libldap/getvalues.c \ + libldap/init.c \ + libldap/lbase64.c \ + libldap/ldif.c \ + libldap/modify.c \ + libldap/modrdn.c \ + libldap/open.c \ + libldap/options.c \ + libldap/os-ip.c \ + libldap/pagectrl.c \ + libldap/print.c \ + libldap/references.c \ + libldap/request.c \ + libldap/result.c \ + libldap/sasl.c \ + libldap/sasl_w.c \ + libldap/schema.c \ + libldap/search.c \ + libldap/sortctrl.c \ + libldap/string.c \ + libldap/tavl.c \ + libldap/thr_nt.c \ + libldap/tls2.c \ + libldap/tls_w.c \ + libldap/unbind.c \ + libldap/url.c \ + libldap/utf-8.c \ + libldap/util-int.c \ + libldap/vlvctrl.c diff --git a/libs/ldap/include/ac/assert.h b/libs/ldap/include/ac/assert.h new file mode 100644 index 00000000000..dbb22951c35 --- /dev/null +++ b/libs/ldap/include/ac/assert.h @@ -0,0 +1,57 @@ +/* Generic assert.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_ASSERT_H +#define _AC_ASSERT_H + +#undef assert + +#ifdef LDAP_DEBUG + +#if defined( HAVE_ASSERT_H ) || defined( STDC_HEADERS ) + +#undef NDEBUG +#include <assert.h> + +#else /* !(HAVE_ASSERT_H || STDC_HEADERS) */ + +#define LDAP_NEED_ASSERT 1 + +/* + * no assert()... must be a very old compiler. + * create a replacement and hope it works + */ + +LBER_F (void) ber_pvt_assert LDAP_P(( const char *file, int line, + const char *test )); + +/* Can't use LDAP_STRING(test), that'd expand to "test" */ +#if defined(__STDC__) || defined(__cplusplus) +#define assert(test) \ + ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, #test ) ) +#else +#define assert(test) \ + ((test) ? (void)0 : ber_pvt_assert( __FILE__, __LINE__, "test" ) ) +#endif + +#endif /* (HAVE_ASSERT_H || STDC_HEADERS) */ + +#else /* !LDAP_DEBUG */ +/* no asserts */ +#define assert(test) ((void)0) +#endif /* LDAP_DEBUG */ + +#endif /* _AC_ASSERT_H */ diff --git a/libs/ldap/include/ac/bytes.h b/libs/ldap/include/ac/bytes.h new file mode 100644 index 00000000000..1856c99c76c --- /dev/null +++ b/libs/ldap/include/ac/bytes.h @@ -0,0 +1,78 @@ +/* Generic bytes.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_BYTES_H +#define _AC_BYTES_H + +/* cross compilers should define both AC_INT{2,4}_TYPE in CPPFLAGS */ + +#if !defined( AC_INT4_TYPE ) + /* use autoconf defines to provide sized typedefs */ +# if SIZEOF_LONG == 4 +# define AC_INT4_TYPE long +# elif SIZEOF_INT == 4 +# define AC_INT4_TYPE int +# elif SIZEOF_SHORT == 4 +# define AC_INT4_TYPE short +# else +# error "AC_INT4_TYPE?" +# endif +#endif + +typedef AC_INT4_TYPE ac_int4; +typedef signed AC_INT4_TYPE ac_sint4; +typedef unsigned AC_INT4_TYPE ac_uint4; + +#if !defined( AC_INT2_TYPE ) +# if SIZEOF_SHORT == 2 +# define AC_INT2_TYPE short +# elif SIZEOF_INT == 2 +# define AC_INT2_TYPE int +# elif SIZEOF_LONG == 2 +# define AC_INT2_TYPE long +# else +# error "AC_INT2_TYPE?" +# endif +#endif + +#if defined( AC_INT2_TYPE ) +typedef AC_INT2_TYPE ac_int2; +typedef signed AC_INT2_TYPE ac_sint2; +typedef unsigned AC_INT2_TYPE ac_uint2; +#endif + +#ifndef BYTE_ORDER +/* cross compilers should define BYTE_ORDER in CPPFLAGS */ + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +/* assume autoconf's AC_C_BIGENDIAN has been ran */ +/* if it hasn't, we assume (maybe falsely) the order is LITTLE ENDIAN */ +# ifdef WORDS_BIGENDIAN +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif + +#endif /* BYTE_ORDER */ + +#endif /* _AC_BYTES_H */ diff --git a/libs/ldap/include/ac/ctype.h b/libs/ldap/include/ac/ctype.h new file mode 100644 index 00000000000..e385f3acbc6 --- /dev/null +++ b/libs/ldap/include/ac/ctype.h @@ -0,0 +1,33 @@ +/* Generic ctype.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_CTYPE_H +#define _AC_CTYPE_H + +#include <ctype.h> + +#undef TOUPPER +#undef TOLOWER + +#ifdef C_UPPER_LOWER +# define TOUPPER(c) (islower(c) ? toupper(c) : (c)) +# define TOLOWER(c) (isupper(c) ? tolower(c) : (c)) +#else +# define TOUPPER(c) toupper(c) +# define TOLOWER(c) tolower(c) +#endif + +#endif /* _AC_CTYPE_H */ diff --git a/libs/ldap/include/ac/dirent.h b/libs/ldap/include/ac/dirent.h new file mode 100644 index 00000000000..93df7b6f2ae --- /dev/null +++ b/libs/ldap/include/ac/dirent.h @@ -0,0 +1,54 @@ +/* Generic dirent.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_DIRENT_H +#define _AC_DIRENT_H + +#ifdef HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#elif defined(_MSC_VER) +#include <windows.h> +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif +struct dirent { + char *d_name; +}; +typedef struct DIR { + HANDLE dir; + struct dirent data; + int first; + char buf[MAX_PATH+1]; +} DIR; +DIR *opendir(const char *name); +struct dirent *readdir(DIR *dir); +int closedir(DIR *dir); +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# ifdef HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# ifdef HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#endif /* _AC_DIRENT_H */ diff --git a/libs/ldap/include/ac/errno.h b/libs/ldap/include/ac/errno.h new file mode 100644 index 00000000000..8a7f32c909d --- /dev/null +++ b/libs/ldap/include/ac/errno.h @@ -0,0 +1,32 @@ +/* Generic errno.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_ERRNO_H +#define _AC_ERRNO_H + +#if defined( HAVE_ERRNO_H ) +# include <errno.h> +#elif defined( HAVE_SYS_ERRNO_H ) +# include <sys/errno.h> +#endif + +#if defined( HAVE_SYS_ERRLIST ) && defined( DECL_SYS_ERRLIST ) + /* have sys_errlist but need declaration */ + LDAP_LIBC_V(int) sys_nerr; + LDAP_LIBC_V(char) *sys_errlist[]; +#endif + +#endif /* _AC_ERRNO_H */ diff --git a/libs/ldap/include/ac/fdset.h b/libs/ldap/include/ac/fdset.h new file mode 100644 index 00000000000..620850b1fc7 --- /dev/null +++ b/libs/ldap/include/ac/fdset.h @@ -0,0 +1,42 @@ +/* redefine FD_SET */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * This header is to be included by portable.h to ensure + * tweaking of FD_SETSIZE is done early enough to be effective. + */ + +#ifndef _AC_FDSET_H +#define _AC_FDSET_H + +#if !defined( OPENLDAP_FD_SETSIZE ) && !defined( FD_SETSIZE ) +# define OPENLDAP_FD_SETSIZE 4096 +#endif + +#ifdef OPENLDAP_FD_SETSIZE + /* assume installer desires to enlarge fd_set */ +# ifdef HAVE_BITS_TYPES_H +# include <bits/types.h> +# endif +# ifdef __FD_SETSIZE +# undef __FD_SETSIZE +# define __FD_SETSIZE OPENLDAP_FD_SETSIZE +# else +# define FD_SETSIZE OPENLDAP_FD_SETSIZE +# endif +#endif + +#endif /* _AC_FDSET_H */ diff --git a/libs/ldap/include/ac/localize.h b/libs/ldap/include/ac/localize.h new file mode 100644 index 00000000000..9e19fe6e96b --- /dev/null +++ b/libs/ldap/include/ac/localize.h @@ -0,0 +1,44 @@ +/* localize.h (i18n/l10n) */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_LOCALIZE_H +#define _AC_LOCALIZE_H + +#ifdef LDAP_LOCALIZE + +# include <locale.h> +# include <libintl.h> + + /* enable i18n/l10n */ +# define gettext_noop(s) s +# define _(s) gettext(s) +# define N_(s) gettext_noop(s) +# define ldap_pvt_setlocale(c,l) ((void) setlocale(c, l)) +# define ldap_pvt_textdomain(d) ((void) textdomain(d)) +# define ldap_pvt_bindtextdomain(p,d) ((void) bindtextdomain(p, d)) + +#else + + /* disable i18n/l10n */ +# define _(s) s +# define N_(s) s +# define ldap_pvt_setlocale(c,l) ((void) 0) +# define ldap_pvt_textdomain(d) ((void) 0) +# define ldap_pvt_bindtextdomain(p,d) ((void) 0) + +#endif + +#endif /* _AC_LOCALIZE_H */ diff --git a/libs/ldap/include/ac/param.h b/libs/ldap/include/ac/param.h new file mode 100644 index 00000000000..a3f5d675e01 --- /dev/null +++ b/libs/ldap/include/ac/param.h @@ -0,0 +1,39 @@ +/* Generic param.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_PARAM_H +#define _AC_PARAM_H + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +/* MAXPATHLEN should come from <unistd.h> */ +#include <ac/unistd.h> + +#ifndef MAXPATHLEN +# if defined(PATH_MAX) +# define MAXPATHLEN PATH_MAX + +# elif defined(_MAX_PATH) +# define MAXPATHLEN _MAX_PATH + +# else +# define MAXPATHLEN 4096 +# endif +#endif + +#endif /* _AC_PARAM_H */ diff --git a/libs/ldap/include/ac/signal.h b/libs/ldap/include/ac/signal.h new file mode 100644 index 00000000000..1c7293bba21 --- /dev/null +++ b/libs/ldap/include/ac/signal.h @@ -0,0 +1,80 @@ +/* Generic signal.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_SIGNAL_H +#define _AC_SIGNAL_H + +#include <signal.h> + +#undef SIGNAL + +#if defined( HAVE_SIGACTION ) +#define SIGNAL lutil_sigaction +typedef void (*lutil_sig_t)(int); +LDAP_LUTIL_F(lutil_sig_t) lutil_sigaction( int sig, lutil_sig_t func ); +#define SIGNAL_REINSTALL(sig,act) (void)0 +#elif defined( HAVE_SIGSET ) +#define SIGNAL sigset +#define SIGNAL_REINSTALL sigset +#else +#define SIGNAL signal +#define SIGNAL_REINSTALL signal +#endif + +#if !defined( LDAP_SIGUSR1 ) || !defined( LDAP_SIGUSR2 ) +#undef LDAP_SIGUSR1 +#undef LDAP_SIGUSR2 + +# if defined(WINNT) || defined(_WINNT) || defined(_WIN32) +# define LDAP_SIGUSR1 SIGILL +# define LDAP_SIGUSR2 SIGTERM + +# elif !defined(HAVE_LINUX_THREADS) +# define LDAP_SIGUSR1 SIGUSR1 +# define LDAP_SIGUSR2 SIGUSR2 + +# else + /* + * Some versions of LinuxThreads unfortunately uses the only + * two signals reserved for user applications. This forces + * OpenLDAP to use other signals reserved for other uses. + */ + +# if defined( SIGSTKFLT ) +# define LDAP_SIGUSR1 SIGSTKFLT +# elif defined ( SIGSYS ) +# define LDAP_SIGUSR1 SIGSYS +# endif + +# if defined( SIGUNUSED ) +# define LDAP_SIGUSR2 SIGUNUSED +# elif defined ( SIGINFO ) +# define LDAP_SIGUSR2 SIGINFO +# elif defined ( SIGEMT ) +# define LDAP_SIGUSR2 SIGEMT +# endif +# endif +#endif + +#ifndef LDAP_SIGCHLD +#ifdef SIGCHLD +#define LDAP_SIGCHLD SIGCHLD +#elif SIGCLD +#define LDAP_SIGCHLD SIGCLD +#endif +#endif + +#endif /* _AC_SIGNAL_H */ diff --git a/libs/ldap/include/ac/socket.h b/libs/ldap/include/ac/socket.h new file mode 100644 index 00000000000..e2d32afb3a8 --- /dev/null +++ b/libs/ldap/include/ac/socket.h @@ -0,0 +1,269 @@ +/* Generic socket.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_SOCKET_H_ +#define _AC_SOCKET_H_ + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_POLL_H +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) +#include <sys/poll.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> + +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#include <netinet/in.h> + +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_ARPA_NAMESER_H +#include <arpa/nameser.h> +#endif + +#include <netdb.h> + +#ifdef HAVE_RESOLV_H +#include <resolv.h> +#endif + +#endif /* HAVE_SYS_SOCKET_H */ + +#ifdef HAVE_WINSOCK2 +#include <winsock2.h> +#include <ws2tcpip.h> +#elif HAVE_WINSOCK +#include <winsock.h> +#endif + +#ifdef HAVE_PCNFS +#include <tklib.h> +#endif /* HAVE_PCNFS */ + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (0x7f000001UL) +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#undef sock_errno +#undef sock_errstr +#define sock_errno() errno +#define sock_errstr(e, b, l) AC_STRERROR_R(e, b, l) +#define sock_errset(e) ((void) (errno = (e))) + +#ifdef HAVE_WINSOCK +# define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) +# define tcp_write( s, buf, len ) send( s, buf, len, 0 ) +# define ioctl( s, c, a ) ioctlsocket( (s), (c), (a) ) +# define ioctl_t u_long +# define AC_SOCKET_INVALID ((unsigned int) -1) + +# ifdef SD_BOTH +# define tcp_close( s ) (shutdown( s, SD_BOTH ), closesocket( s )) +# else +# define tcp_close( s ) closesocket( s ) +# endif + +#undef EWOULDBLOCK +#undef EINPROGRESS +#undef ETIMEDOUT +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EINPROGRESS WSAEINPROGRESS +#define ETIMEDOUT WSAETIMEDOUT + +#undef sock_errno +#undef sock_errstr +#undef sock_errset +#define sock_errno() WSAGetLastError() +#define sock_errstr(e, b, l) ber_pvt_wsa_err2string(e) +#define sock_errset(e) WSASetLastError(e) + +LBER_F( char * ) ber_pvt_wsa_err2string LDAP_P((int)); + +#elif MACOS +# define tcp_close( s ) tcpclose( s ) +# define tcp_read( s, buf, len ) tcpread( s, buf, len ) +# define tcp_write( s, buf, len ) tcpwrite( s, buf, len ) + +#elif DOS +# ifdef PCNFS +# define tcp_close( s ) close( s ) +# define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) +# define tcp_write( s, buf, len ) send( s, buf, len, 0 ) +# endif /* PCNFS */ +# ifdef NCSA +# define tcp_close( s ) do { netclose( s ); netshut() } while(0) +# define tcp_read( s, buf, len ) nread( s, buf, len ) +# define tcp_write( s, buf, len ) netwrite( s, buf, len ) +# endif /* NCSA */ + +#elif defined(HAVE_CLOSESOCKET) +# define tcp_close( s ) closesocket( s ) + +# ifdef __BEOS__ +# define tcp_read( s, buf, len ) recv( s, buf, len, 0 ) +# define tcp_write( s, buf, len ) send( s, buf, len, 0 ) +# endif + +#else +# define tcp_read( s, buf, len) read( s, buf, len ) +# define tcp_write( s, buf, len) write( s, buf, len ) + +# ifdef SHUT_RDWR +# define tcp_close( s ) (shutdown( s, SHUT_RDWR ), close( s )) +# else +# define tcp_close( s ) close( s ) +# endif + +#ifdef HAVE_PIPE +/* + * Only use pipe() on systems where file and socket descriptors + * are interchangeable + */ +# define USE_PIPE HAVE_PIPE +#endif + +#endif /* MACOS */ + +#ifndef ioctl_t +# define ioctl_t int +#endif + +#ifndef AC_SOCKET_INVALID +# define AC_SOCKET_INVALID (-1) +#endif +#ifndef AC_SOCKET_ERROR +# define AC_SOCKET_ERROR (-1) +#endif + +#if !defined( HAVE_INET_ATON ) && !defined( inet_aton ) +# define inet_aton ldap_pvt_inet_aton +struct in_addr; +LDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * )); +#endif + +#if defined(__WIN32) && defined(_ALPHA) +/* NT on Alpha is hosed. */ +# define AC_HTONL( l ) \ + ((((l)&0xffU)<<24) + (((l)&0xff00U)<<8) + \ + (((l)&0xff0000U)>>8) + (((l)&0xff000000U)>>24)) +# define AC_NTOHL(l) AC_HTONL(l) + +#else +# define AC_HTONL( l ) htonl( l ) +# define AC_NTOHL( l ) ntohl( l ) +#endif + +/* htons()/ntohs() may be broken much like htonl()/ntohl() */ +#define AC_HTONS( s ) htons( s ) +#define AC_NTOHS( s ) ntohs( s ) + +#ifdef LDAP_PF_LOCAL +# if !defined( AF_LOCAL ) && defined( AF_UNIX ) +# define AF_LOCAL AF_UNIX +# endif +# if !defined( PF_LOCAL ) && defined( PF_UNIX ) +# define PF_LOCAL PF_UNIX +# endif +#endif + +#ifndef INET_ADDRSTRLEN +# define INET_ADDRSTRLEN 16 +#endif +#ifndef INET6_ADDRSTRLEN +# define INET6_ADDRSTRLEN 46 +#endif + +#if defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) +# ifdef HAVE_GAI_STRERROR +# define AC_GAI_STRERROR(x) (gai_strerror((x))) +# else +# define AC_GAI_STRERROR(x) (ldap_pvt_gai_strerror((x))) + LDAP_F (char *) ldap_pvt_gai_strerror( int ); +# endif +#endif + +#if defined(LDAP_PF_LOCAL) && \ + !defined(HAVE_GETPEEREID) && \ + !defined(HAVE_GETPEERUCRED) && \ + !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \ + defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \ + defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)) +# define LDAP_PF_LOCAL_SENDMSG 1 +#endif + +#ifdef HAVE_GETPEEREID +#define LUTIL_GETPEEREID( s, uid, gid, bv ) getpeereid( s, uid, gid ) +#elif defined(LDAP_PF_LOCAL_SENDMSG) +struct berval; +LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t *, struct berval *bv ); +#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid, bv ) +#else +LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t * ); +#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid ) +#endif + +typedef union Sockaddr { + struct sockaddr sa_addr; + struct sockaddr_in sa_in_addr; +#ifdef LDAP_PF_INET6 + struct sockaddr_storage sa_storage; + struct sockaddr_in6 sa_in6_addr; +#endif +#ifdef LDAP_PF_LOCAL + struct sockaddr_un sa_un_addr; +#endif +} Sockaddr; + +/* DNS RFC defines max host name as 255. New systems seem to use 1024 */ +#ifndef NI_MAXHOST +#define NI_MAXHOST 256 +#endif + +#ifdef HAVE_POLL +# ifndef INFTIM +# define INFTIM (-1) +# endif +#undef POLL_OTHER +#define POLL_OTHER (POLLERR|POLLHUP) +#undef POLL_READ +#define POLL_READ (POLLIN|POLLPRI|POLL_OTHER) +#undef POLL_WRITE +#define POLL_WRITE (POLLOUT|POLL_OTHER) +#endif + +#endif /* _AC_SOCKET_H_ */ diff --git a/libs/ldap/include/ac/stdarg.h b/libs/ldap/include/ac/stdarg.h new file mode 100644 index 00000000000..7ba29737e33 --- /dev/null +++ b/libs/ldap/include/ac/stdarg.h @@ -0,0 +1,28 @@ +/* Generic stdarg.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_STDARG_H +#define _AC_STDARG_H 1 + +/* require STDC variable argument support */ + +#include <stdarg.h> + +#ifndef HAVE_STDARG +# define HAVE_STDARG 1 +#endif + +#endif /* _AC_STDARG_H */ diff --git a/libs/ldap/include/ac/stdlib.h b/libs/ldap/include/ac/stdlib.h new file mode 100644 index 00000000000..243b892e2c3 --- /dev/null +++ b/libs/ldap/include/ac/stdlib.h @@ -0,0 +1,48 @@ +/* Generic stdlib.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_STDLIB_H +#define _AC_STDLIB_H + +#if defined( HAVE_CSRIMALLOC ) +#include <stdio.h> +#define MALLOC_TRACE +#include <libmalloc.h> +#endif + +#include <stdlib.h> + +/* Ignore malloc.h if we have STDC_HEADERS */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include <malloc.h> +#endif + +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# define EXIT_FAILURE 1 +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#if defined(LINE_MAX) +# define AC_LINE_MAX LINE_MAX +#else +# define AC_LINE_MAX 2048 /* POSIX MIN */ +#endif + +#endif /* _AC_STDLIB_H */ diff --git a/libs/ldap/include/ac/string.h b/libs/ldap/include/ac/string.h new file mode 100644 index 00000000000..c4c135410e6 --- /dev/null +++ b/libs/ldap/include/ac/string.h @@ -0,0 +1,118 @@ +/* Generic string.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_STRING_H +#define _AC_STRING_H + +#ifdef STDC_HEADERS +# include <string.h> + +#else +# ifdef HAVE_STRING_H +# include <string.h> +# endif +# if defined(HAVE_STRINGS_H) && (!defined(HAVE_STRING_H) || defined(BOTH_STRINGS_H)) +# include <strings.h> +# endif + +# ifdef HAVE_MEMORY_H +# include <memory.h> +# endif + +# ifndef HAVE_STRRCHR +# undef strchr +# define strchr index +# undef strrchr +# define strrchr rindex +# endif + +# ifndef HAVE_MEMCPY +# undef memcpy +# define memcpy(d, s, n) ((void) bcopy ((s), (d), (n))) +# undef memmove +# define memmove(d, s, n) ((void) bcopy ((s), (d), (n))) +# endif +#endif + +/* use ldap_pvt_strtok instead of strtok or strtok_r! */ +LDAP_F(char *) ldap_pvt_strtok LDAP_P(( char *str, + const char *delim, char **pos )); + +#ifndef HAVE_STRDUP + /* strdup() is missing, declare our own version */ +# undef strdup +# define strdup(s) ber_strdup(s) +#elif !defined(_WIN32) + /* some systems fail to declare strdup */ + /* Windows does not require this declaration */ + LDAP_LIBC_F(char *) (strdup)(); +#endif + +/* + * some systems fail to declare strcasecmp() and strncasecmp() + * we need them declared so we can obtain pointers to them + */ + +/* we don't want these declared for Windows or Mingw */ +#ifndef _WIN32 +int (strcasecmp)(); +int (strncasecmp)(); +#endif + +#ifndef SAFEMEMCPY +# if defined( HAVE_MEMMOVE ) +# define SAFEMEMCPY( d, s, n ) memmove((d), (s), (n)) +# elif defined( HAVE_BCOPY ) +# define SAFEMEMCPY( d, s, n ) bcopy((s), (d), (n)) +# else + /* nothing left but memcpy() */ +# define SAFEMEMCPY( d, s, n ) memcpy((d), (s), (n)) +# endif +#endif + +#define AC_MEMCPY( d, s, n ) (SAFEMEMCPY((d),(s),(n))) +#define AC_FMEMCPY( d, s, n ) do { \ + if((n) == 1) *((char*)(d)) = *((char*)(s)); \ + else AC_MEMCPY( (d), (s), (n) ); \ + } while(0) + +#ifdef NEED_MEMCMP_REPLACEMENT + int (lutil_memcmp)(const void *b1, const void *b2, size_t len); +#define memcmp lutil_memcmp +#endif + +void *(lutil_memrchr)(const void *b, int c, size_t n); +/* GNU extension (glibc >= 2.1.91), only declared when defined(_GNU_SOURCE) */ +#if defined(HAVE_MEMRCHR) && defined(_GNU_SOURCE) +#define lutil_memrchr(b, c, n) memrchr(b, c, n) +#endif /* ! HAVE_MEMRCHR */ + +#define STRLENOF(s) (sizeof(s)-1) + +#if defined( HAVE_NONPOSIX_STRERROR_R ) +# define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l))) +#elif defined( HAVE_STRERROR_R ) +# define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l)) == 0 ? (b) : "Unknown error") +#elif defined( HAVE_SYS_ERRLIST ) +# define AC_STRERROR_R(e,b,l) ((e) > -1 && (e) < sys_nerr \ + ? sys_errlist[(e)] : "Unknown error" ) +#elif defined( HAVE_STRERROR ) +# define AC_STRERROR_R(e,b,l) (strerror(e)) /* NOTE: may be NULL */ +#else +# define AC_STRERROR_R(e,b,l) ("Unknown error") +#endif + +#endif /* _AC_STRING_H */ diff --git a/libs/ldap/include/ac/time.h b/libs/ldap/include/ac/time.h new file mode 100644 index 00000000000..f36b9402831 --- /dev/null +++ b/libs/ldap/include/ac/time.h @@ -0,0 +1,39 @@ +/* Generic time.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_TIME_H +#define _AC_TIME_H + +#ifdef TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#elif defined(HAVE_SYS_TIME_H) +# include <sys/time.h> +# ifdef HAVE_SYS_TIMEB_H +# include <sys/timeb.h> +# endif +#else +# include <time.h> +#endif + +#if defined(_WIN32) && !defined(HAVE_CLOCK_GETTIME) + struct timespec { + time_t tv_sec; + int tv_nsec; + }; +#endif + +#endif /* _AC_TIME_H */ diff --git a/libs/ldap/include/ac/unistd.h b/libs/ldap/include/ac/unistd.h new file mode 100644 index 00000000000..d9c4529aa01 --- /dev/null +++ b/libs/ldap/include/ac/unistd.h @@ -0,0 +1,72 @@ +/* Generic unistd.h */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _AC_UNISTD_H +#define _AC_UNISTD_H + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_PROCESS_H +# include <process.h> +#endif + +/* note: callers of crypt(3) should include <ac/crypt.h> */ + +#if defined(HAVE_GETPASSPHRASE) +LDAP_LIBC_F(char*)(getpassphrase)(); + +#else +#define getpassphrase(p) lutil_getpass(p) +LDAP_LUTIL_F(char*)(lutil_getpass) LDAP_P((const char *getpass)); +#endif + +/* getopt() defines may be in separate include file */ +#ifdef HAVE_GETOPT_H +# include <getopt.h> + +#elif !defined(HAVE_GETOPT) + /* no getopt, assume we need getopt-compat.h */ +# include <getopt-compat.h> + +#else + /* assume we need to declare these externs */ + LDAP_LIBC_V (char *) optarg; + LDAP_LIBC_V (int) optind, opterr, optopt; +#endif + +/* use lutil file locking */ +#define ldap_lockf(x) lutil_lockf(x) +#define ldap_unlockf(x) lutil_unlockf(x) +#include <lutil_lockf.h> + +/* + * Windows: although sleep() will be resolved by both MSVC and Mingw GCC + * linkers, the function is not declared in header files. This is + * because Windows' version of the function is called _sleep(), and it + * is declared in stdlib.h + */ + +#ifdef _WIN32 +#define sleep _sleep +#endif + +#endif /* _AC_UNISTD_H */ diff --git a/libs/ldap/include/lber.h b/libs/ldap/include/lber.h new file mode 100644 index 00000000000..d474eb06352 --- /dev/null +++ b/libs/ldap/include/lber.h @@ -0,0 +1,691 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ + +#ifndef _LBER_H +#define _LBER_H + +#include <lber_types.h> +#include <string.h> + +LDAP_BEGIN_DECL + +/* + * ber_tag_t represents the identifier octets at the beginning of BER + * elements. OpenLDAP treats them as mere big-endian unsigned integers. + * + * Actually the BER identifier octets look like this: + * + * Bits of 1st octet: + * ______ + * 8 7 | CLASS + * 0 0 = UNIVERSAL + * 0 1 = APPLICATION + * 1 0 = CONTEXT-SPECIFIC + * 1 1 = PRIVATE + * _____ + * | 6 | DATA-TYPE + * 0 = PRIMITIVE + * 1 = CONSTRUCTED + * ___________ + * | 5 ... 1 | TAG-NUMBER + * + * For ASN.1 tag numbers >= 0x1F, TAG-NUMBER above is 0x1F and the next + * BER octets contain the actual ASN.1 tag number: Big-endian, base + * 128, 8.bit = 1 in all but the last octet, minimum number of octets. + */ + +/* BER classes and mask (in 1st identifier octet) */ +#define LBER_CLASS_UNIVERSAL ((ber_tag_t) 0x00U) +#define LBER_CLASS_APPLICATION ((ber_tag_t) 0x40U) +#define LBER_CLASS_CONTEXT ((ber_tag_t) 0x80U) +#define LBER_CLASS_PRIVATE ((ber_tag_t) 0xc0U) +#define LBER_CLASS_MASK ((ber_tag_t) 0xc0U) + +/* BER encoding type and mask (in 1st identifier octet) */ +#define LBER_PRIMITIVE ((ber_tag_t) 0x00U) +#define LBER_CONSTRUCTED ((ber_tag_t) 0x20U) +#define LBER_ENCODING_MASK ((ber_tag_t) 0x20U) + +#define LBER_BIG_TAG_MASK ((ber_tag_t) 0x1fU) +#define LBER_MORE_TAG_MASK ((ber_tag_t) 0x80U) + +/* + * LBER_ERROR and LBER_DEFAULT are values that can never appear + * as valid BER tags, so it is safe to use them to report errors. + * Valid tags have (tag & (ber_tag_t) 0xFF) != 0xFF. + */ +#define LBER_ERROR ((ber_tag_t) -1) +#define LBER_DEFAULT ((ber_tag_t) -1) + +/* general BER types we know about */ +#define LBER_BOOLEAN ((ber_tag_t) 0x01UL) +#define LBER_INTEGER ((ber_tag_t) 0x02UL) +#define LBER_BITSTRING ((ber_tag_t) 0x03UL) +#define LBER_OCTETSTRING ((ber_tag_t) 0x04UL) +#define LBER_NULL ((ber_tag_t) 0x05UL) +#define LBER_ENUMERATED ((ber_tag_t) 0x0aUL) +#define LBER_SEQUENCE ((ber_tag_t) 0x30UL) /* constructed */ +#define LBER_SET ((ber_tag_t) 0x31UL) /* constructed */ + +/* LBER BerElement options */ +#define LBER_USE_DER 0x01 + +/* get/set options for BerElement */ +#define LBER_OPT_BER_OPTIONS 0x01 +#define LBER_OPT_BER_DEBUG 0x02 +#define LBER_OPT_BER_REMAINING_BYTES 0x03 +#define LBER_OPT_BER_TOTAL_BYTES 0x04 +#define LBER_OPT_BER_BYTES_TO_WRITE 0x05 +#define LBER_OPT_BER_MEMCTX 0x06 + +#define LBER_OPT_DEBUG_LEVEL LBER_OPT_BER_DEBUG +#define LBER_OPT_REMAINING_BYTES LBER_OPT_BER_REMAINING_BYTES +#define LBER_OPT_TOTAL_BYTES LBER_OPT_BER_TOTAL_BYTES +#define LBER_OPT_BYTES_TO_WRITE LBER_OPT_BER_BYTES_TO_WRITE + +#define LBER_OPT_LOG_PRINT_FN 0x8001 +#define LBER_OPT_MEMORY_FNS 0x8002 +#define LBER_OPT_ERROR_FN 0x8003 +#define LBER_OPT_LOG_PRINT_FILE 0x8004 + +/* get/set Memory Debug options */ +#define LBER_OPT_MEMORY_INUSE 0x8005 /* for memory debugging */ +#define LBER_OPT_LOG_PROC 0x8006 /* for external logging function */ + +typedef int* (*BER_ERRNO_FN) LDAP_P(( void )); + +typedef void (*BER_LOG_PRINT_FN) LDAP_P(( LDAP_CONST char *buf )); + +typedef void* (BER_MEMALLOC_FN) LDAP_P(( ber_len_t size, void *ctx )); +typedef void* (BER_MEMCALLOC_FN) LDAP_P(( ber_len_t n, ber_len_t size, void *ctx )); +typedef void* (BER_MEMREALLOC_FN) LDAP_P(( void *p, ber_len_t size, void *ctx )); +typedef void (BER_MEMFREE_FN) LDAP_P(( void *p, void *ctx )); + +typedef struct lber_memory_fns { + BER_MEMALLOC_FN *bmf_malloc; + BER_MEMCALLOC_FN *bmf_calloc; + BER_MEMREALLOC_FN *bmf_realloc; + BER_MEMFREE_FN *bmf_free; +} BerMemoryFunctions; + +/* LBER Sockbuf_IO options */ +#define LBER_SB_OPT_GET_FD 1 +#define LBER_SB_OPT_SET_FD 2 +#define LBER_SB_OPT_HAS_IO 3 +#define LBER_SB_OPT_SET_NONBLOCK 4 +#define LBER_SB_OPT_GET_SSL 7 +#define LBER_SB_OPT_DATA_READY 8 +#define LBER_SB_OPT_SET_READAHEAD 9 +#define LBER_SB_OPT_DRAIN 10 +#define LBER_SB_OPT_NEEDS_READ 11 +#define LBER_SB_OPT_NEEDS_WRITE 12 +#define LBER_SB_OPT_GET_MAX_INCOMING 13 +#define LBER_SB_OPT_SET_MAX_INCOMING 14 + +/* Only meaningful ifdef LDAP_PF_LOCAL_SENDMSG */ +#define LBER_SB_OPT_UNGET_BUF 15 + +/* Largest option used by the library */ +#define LBER_SB_OPT_OPT_MAX 15 + +/* LBER IO operations stacking levels */ +#define LBER_SBIOD_LEVEL_PROVIDER 10 +#define LBER_SBIOD_LEVEL_TRANSPORT 20 +#define LBER_SBIOD_LEVEL_APPLICATION 30 + +/* get/set options for Sockbuf */ +#define LBER_OPT_SOCKBUF_DESC 0x1000 +#define LBER_OPT_SOCKBUF_OPTIONS 0x1001 +#define LBER_OPT_SOCKBUF_DEBUG 0x1002 + +/* on/off values */ +LBER_V( char ) ber_pvt_opt_on; +#define LBER_OPT_ON ((void *) &ber_pvt_opt_on) +#define LBER_OPT_OFF ((void *) 0) + +#define LBER_OPT_SUCCESS (0) +#define LBER_OPT_ERROR (-1) + +typedef struct berelement BerElement; +typedef struct sockbuf Sockbuf; + +typedef struct sockbuf_io Sockbuf_IO; + +/* Structure for LBER IO operation descriptor */ +typedef struct sockbuf_io_desc { + int sbiod_level; + Sockbuf *sbiod_sb; + Sockbuf_IO *sbiod_io; + void *sbiod_pvt; + struct sockbuf_io_desc *sbiod_next; +} Sockbuf_IO_Desc; + +/* Structure for LBER IO operation functions */ +struct sockbuf_io { + int (*sbi_setup)( Sockbuf_IO_Desc *sbiod, void *arg ); + int (*sbi_remove)( Sockbuf_IO_Desc *sbiod ); + int (*sbi_ctrl)( Sockbuf_IO_Desc *sbiod, int opt, void *arg); + + ber_slen_t (*sbi_read)( Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len ); + ber_slen_t (*sbi_write)( Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len ); + + int (*sbi_close)( Sockbuf_IO_Desc *sbiod ); +}; + +/* Helper macros for LBER IO functions */ +#define LBER_SBIOD_READ_NEXT( sbiod, buf, len ) \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_read( (sbiod)->sbiod_next, \ + buf, len ) ) +#define LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ) \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_write( (sbiod)->sbiod_next, \ + buf, len ) ) +#define LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ) \ + ( (sbiod)->sbiod_next ? \ + ( (sbiod)->sbiod_next->sbiod_io->sbi_ctrl( \ + (sbiod)->sbiod_next, opt, arg ) ) : 0 ) + +/* structure for returning a sequence of octet strings + length */ +typedef struct berval { + ber_len_t bv_len; + char *bv_val; +} BerValue; + +typedef BerValue *BerVarray; /* To distinguish from a single bv */ + +/* this should be moved to lber-int.h */ + +/* + * in bprint.c: + */ +LBER_F( void ) +ber_error_print LDAP_P(( + LDAP_CONST char *data )); + +LBER_F( void ) +ber_bprint LDAP_P(( + LDAP_CONST char *data, ber_len_t len )); + +LBER_F( void ) +ber_dump LDAP_P(( + BerElement *ber, int inout )); + +/* + * in decode.c: + */ +typedef int (*BERDecodeCallback) LDAP_P(( + BerElement *ber, + void *data, + int mode )); + +LBER_F( ber_tag_t ) +ber_get_tag LDAP_P(( + BerElement *ber )); + +LBER_F( ber_tag_t ) +ber_skip_tag LDAP_P(( + BerElement *ber, + ber_len_t *len )); + +LBER_F( ber_tag_t ) +ber_peek_tag LDAP_P(( + BerElement *ber, + ber_len_t *len )); + +LBER_F( ber_tag_t ) +ber_skip_raw LDAP_P(( + BerElement *ber, + struct berval *bv )); + +LBER_F( ber_tag_t ) +ber_skip_element LDAP_P(( + BerElement *ber, + struct berval *bv )); + +LBER_F( ber_tag_t ) +ber_peek_element LDAP_P(( + LDAP_CONST BerElement *ber, + struct berval *bv )); + +LBER_F( ber_tag_t ) +ber_get_int LDAP_P(( + BerElement *ber, + ber_int_t *num )); + +LBER_F( ber_tag_t ) +ber_get_enum LDAP_P(( + BerElement *ber, + ber_int_t *num )); + +LBER_F( int ) +ber_decode_int LDAP_P(( + const struct berval *bv, + ber_int_t *num )); + +LBER_F( ber_tag_t ) +ber_get_stringb LDAP_P(( + BerElement *ber, + char *buf, + ber_len_t *len )); + +#define LBER_BV_ALLOC 0x01 /* allocate/copy result, otherwise in-place */ +#define LBER_BV_NOTERM 0x02 /* omit NUL-terminator if parsing in-place */ +#define LBER_BV_STRING 0x04 /* fail if berval contains embedded \0 */ +/* LBER_BV_STRING currently accepts a terminating \0 in the berval, because + * Active Directory sends that in at least the diagonsticMessage field. + */ + +LBER_F( ber_tag_t ) +ber_get_stringbv LDAP_P(( + BerElement *ber, + struct berval *bv, + int options )); + +LBER_F( ber_tag_t ) +ber_get_stringa LDAP_P(( + BerElement *ber, + char **buf )); + +LBER_F( ber_tag_t ) +ber_get_stringal LDAP_P(( + BerElement *ber, + struct berval **bv )); + +LBER_F( ber_tag_t ) +ber_get_bitstringa LDAP_P(( + BerElement *ber, + char **buf, + ber_len_t *len )); + +LBER_F( ber_tag_t ) +ber_get_null LDAP_P(( + BerElement *ber )); + +LBER_F( ber_tag_t ) +ber_get_boolean LDAP_P(( + BerElement *ber, + ber_int_t *boolval )); + +LBER_F( ber_tag_t ) +ber_first_element LDAP_P(( + BerElement *ber, + ber_len_t *len, + char **last )); + +LBER_F( ber_tag_t ) +ber_next_element LDAP_P(( + BerElement *ber, + ber_len_t *len, + LDAP_CONST char *last )); + +LBER_F( ber_tag_t ) +ber_scanf LDAP_P(( + BerElement *ber, + LDAP_CONST char *fmt, + ... )); + +LBER_F( int ) +ber_decode_oid LDAP_P(( + struct berval *in, + struct berval *out )); + +/* + * in encode.c + */ +LBER_F( int ) +ber_encode_oid LDAP_P(( + struct berval *in, + struct berval *out )); + +typedef int (*BEREncodeCallback) LDAP_P(( + BerElement *ber, + void *data )); + +LBER_F( int ) +ber_put_enum LDAP_P(( + BerElement *ber, + ber_int_t num, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_int LDAP_P(( + BerElement *ber, + ber_int_t num, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_ostring LDAP_P(( + BerElement *ber, + LDAP_CONST char *str, + ber_len_t len, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_berval LDAP_P(( + BerElement *ber, + struct berval *bv, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_string LDAP_P(( + BerElement *ber, + LDAP_CONST char *str, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_bitstring LDAP_P(( + BerElement *ber, + LDAP_CONST char *str, + ber_len_t bitlen, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_null LDAP_P(( + BerElement *ber, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_boolean LDAP_P(( + BerElement *ber, + ber_int_t boolval, + ber_tag_t tag )); + +LBER_F( int ) +ber_start_seq LDAP_P(( + BerElement *ber, + ber_tag_t tag )); + +LBER_F( int ) +ber_start_set LDAP_P(( + BerElement *ber, + ber_tag_t tag )); + +LBER_F( int ) +ber_put_seq LDAP_P(( + BerElement *ber )); + +LBER_F( int ) +ber_put_set LDAP_P(( + BerElement *ber )); + +LBER_F( int ) +ber_printf LDAP_P(( + BerElement *ber, + LDAP_CONST char *fmt, + ... )); + + +/* + * in io.c: + */ + +LBER_F( ber_slen_t ) +ber_skip_data LDAP_P(( + BerElement *ber, + ber_len_t len )); + +LBER_F( ber_slen_t ) +ber_read LDAP_P(( + BerElement *ber, + char *buf, + ber_len_t len )); + +LBER_F( ber_slen_t ) +ber_write LDAP_P(( + BerElement *ber, + LDAP_CONST char *buf, + ber_len_t len, + int zero )); /* nonzero is unsupported from OpenLDAP 2.4.18 */ + +LBER_F( void ) +ber_free LDAP_P(( + BerElement *ber, + int freebuf )); + +LBER_F( void ) +ber_free_buf LDAP_P(( BerElement *ber )); + +LBER_F( int ) +ber_flush2 LDAP_P(( + Sockbuf *sb, + BerElement *ber, + int freeit )); +#define LBER_FLUSH_FREE_NEVER (0x0) /* traditional behavior */ +#define LBER_FLUSH_FREE_ON_SUCCESS (0x1) /* traditional behavior */ +#define LBER_FLUSH_FREE_ON_ERROR (0x2) +#define LBER_FLUSH_FREE_ALWAYS (LBER_FLUSH_FREE_ON_SUCCESS|LBER_FLUSH_FREE_ON_ERROR) + +LBER_F( int ) +ber_flush LDAP_P(( + Sockbuf *sb, + BerElement *ber, + int freeit )); /* DEPRECATED */ + +LBER_F( BerElement * ) +ber_alloc LDAP_P(( void )); /* DEPRECATED */ + +LBER_F( BerElement * ) +der_alloc LDAP_P(( void )); /* DEPRECATED */ + +LBER_F( BerElement * ) +ber_alloc_t LDAP_P(( + int beroptions )); + +LBER_F( BerElement * ) +ber_dup LDAP_P(( + BerElement *ber )); + +LBER_F( ber_tag_t ) +ber_get_next LDAP_P(( + Sockbuf *sb, + ber_len_t *len, + BerElement *ber )); + +LBER_F( void ) +ber_init2 LDAP_P(( + BerElement *ber, + struct berval *bv, + int options )); + +LBER_F( void ) +ber_init_w_nullc LDAP_P(( /* DEPRECATED */ + BerElement *ber, + int options )); + +LBER_F( void ) +ber_reset LDAP_P(( + BerElement *ber, + int was_writing )); + +LBER_F( BerElement * ) +ber_init LDAP_P(( + struct berval *bv )); + +LBER_F( int ) +ber_flatten LDAP_P(( + BerElement *ber, + struct berval **bvPtr )); + +LBER_F( int ) +ber_flatten2 LDAP_P(( + BerElement *ber, + struct berval *bv, + int alloc )); + +LBER_F( int ) +ber_remaining LDAP_P(( + BerElement *ber )); + +/* + * LBER ber accessor functions + */ + +LBER_F( int ) +ber_get_option LDAP_P(( + void *item, + int option, + void *outvalue)); + +LBER_F( int ) +ber_set_option LDAP_P(( + void *item, + int option, + LDAP_CONST void *invalue)); + +/* + * LBER sockbuf.c + */ + +LBER_F( Sockbuf * ) +ber_sockbuf_alloc LDAP_P(( + void )); + +LBER_F( void ) +ber_sockbuf_free LDAP_P(( + Sockbuf *sb )); + +LBER_F( int ) +ber_sockbuf_add_io LDAP_P(( + Sockbuf *sb, + Sockbuf_IO *sbio, + int layer, + void *arg )); + +LBER_F( int ) +ber_sockbuf_remove_io LDAP_P(( + Sockbuf *sb, + Sockbuf_IO *sbio, + int layer )); + +LBER_F( int ) +ber_sockbuf_ctrl LDAP_P(( + Sockbuf *sb, + int opt, + void *arg )); + +LBER_V( Sockbuf_IO ) ber_sockbuf_io_tcp; +LBER_V( Sockbuf_IO ) ber_sockbuf_io_readahead; +LBER_V( Sockbuf_IO ) ber_sockbuf_io_fd; +LBER_V( Sockbuf_IO ) ber_sockbuf_io_debug; +LBER_V( Sockbuf_IO ) ber_sockbuf_io_udp; + +/* + * LBER memory.c + */ +LBER_F( void * ) +ber_memalloc LDAP_P(( + ber_len_t s )); + +LBER_F( void * ) +ber_memrealloc LDAP_P(( + void* p, + ber_len_t s )); + +LBER_F( void * ) +ber_memcalloc LDAP_P(( + ber_len_t n, + ber_len_t s )); + +LBER_F( void ) +ber_memfree LDAP_P(( + void* p )); + +LBER_F( void ) +ber_memvfree LDAP_P(( + void** vector )); + +LBER_F( void ) +ber_bvfree LDAP_P(( + struct berval *bv )); + +LBER_F( void ) +ber_bvecfree LDAP_P(( + struct berval **bv )); + +LBER_F( int ) +ber_bvecadd LDAP_P(( + struct berval ***bvec, + struct berval *bv )); + +LBER_F( struct berval * ) +ber_dupbv LDAP_P(( + struct berval *dst, struct berval *src )); + +LBER_F( struct berval * ) +ber_bvdup LDAP_P(( + struct berval *src )); + +LBER_F( struct berval * ) +ber_mem2bv LDAP_P(( + LDAP_CONST char *, ber_len_t len, int duplicate, struct berval *bv)); + +LBER_F( struct berval * ) +ber_str2bv LDAP_P(( + LDAP_CONST char *, ber_len_t len, int duplicate, struct berval *bv)); + +#define ber_bvstr(a) ((ber_str2bv)((a), 0, 0, NULL)) +#define ber_bvstrdup(a) ((ber_str2bv)((a), 0, 1, NULL)) + +LBER_F( char * ) +ber_strdup LDAP_P(( + LDAP_CONST char * )); + +LBER_F( ber_len_t ) +ber_strnlen LDAP_P(( + LDAP_CONST char *s, ber_len_t len )); + +LBER_F( char * ) +ber_strndup LDAP_P(( + LDAP_CONST char *s, ber_len_t l )); + +LBER_F( struct berval * ) +ber_bvreplace LDAP_P(( + struct berval *dst, LDAP_CONST struct berval *src )); + +LBER_F( void ) +ber_bvarray_free LDAP_P(( BerVarray p )); + +LBER_F( int ) +ber_bvarray_add LDAP_P(( BerVarray *p, BerValue *bv )); + +#define ber_bvcmp(v1,v2) \ + ((v1)->bv_len < (v2)->bv_len \ + ? -1 : ((v1)->bv_len > (v2)->bv_len \ + ? 1 : memcmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) + +/* + * error.c + */ +LBER_F( int * ) ber_errno_addr LDAP_P((void)); +#define ber_errno (*(ber_errno_addr)()) + +#define LBER_ERROR_NONE 0 +#define LBER_ERROR_PARAM 0x1 +#define LBER_ERROR_MEMORY 0x2 + +LDAP_END_DECL + +#endif /* _LBER_H */ diff --git a/libs/ldap/include/lber_pvt.h b/libs/ldap/include/lber_pvt.h new file mode 100644 index 00000000000..da89d0d3119 --- /dev/null +++ b/libs/ldap/include/lber_pvt.h @@ -0,0 +1,222 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * lber_pvt.h - Header for ber_pvt_ functions. + * These are meant to be internal to OpenLDAP Software. + */ + +#ifndef _LBER_PVT_H +#define _LBER_PVT_H 1 + +#include <lber.h> + +LDAP_BEGIN_DECL + +/* for allocating aligned buffers (on the stack) */ +#define LBER_ALIGNED_BUFFER(uname,size) \ + union uname { \ + char buffer[size]; \ + /* force alignment */ \ + int ialign; \ + long lalign; \ + float falign; \ + double dalign; \ + char* palign; \ + } + +#define LBER_ELEMENT_SIZEOF (256) /* must be >= sizeof(BerElement) */ +typedef LBER_ALIGNED_BUFFER(lber_berelement_u,LBER_ELEMENT_SIZEOF) + BerElementBuffer; + +typedef struct sockbuf_buf { + ber_len_t buf_size; + ber_len_t buf_ptr; + ber_len_t buf_end; + char *buf_base; +} Sockbuf_Buf; + +/* + * bprint.c + */ +LBER_V( BER_LOG_PRINT_FN ) ber_pvt_log_print; + +LBER_F( int ) +ber_pvt_log_printf LDAP_P(( + int errlvl, + int loglvl, + const char *fmt, + ... )) LDAP_GCCATTR((format(printf, 3, 4))); + +/* + * sockbuf.c + */ +LBER_F( ber_slen_t ) +ber_pvt_sb_do_write LDAP_P(( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )); + +LBER_F( void ) +ber_pvt_sb_buf_init LDAP_P(( Sockbuf_Buf *buf )); + +LBER_F( void ) +ber_pvt_sb_buf_destroy LDAP_P(( Sockbuf_Buf *buf )); + +LBER_F( int ) +ber_pvt_sb_grow_buffer LDAP_P(( Sockbuf_Buf *buf, ber_len_t minsize )); + +LBER_F( ber_len_t ) +ber_pvt_sb_copy_out LDAP_P(( Sockbuf_Buf *sbb, char *buf, ber_len_t len )); + +LBER_F( int ) +ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb )); + +/* + * memory.c + */ +LBER_F( void * ) +ber_memalloc_x LDAP_P(( + ber_len_t s, void *ctx)); + +LBER_F( void * ) +ber_memrealloc_x LDAP_P(( + void* p, + ber_len_t s, void *ctx )); + +LBER_F( void * ) +ber_memcalloc_x LDAP_P(( + ber_len_t n, + ber_len_t s, void *ctx )); + +LBER_F( void ) +ber_memfree_x LDAP_P(( + void* p, void *ctx )); + +LBER_F( void ) +ber_memvfree_x LDAP_P(( + void** vector, void *ctx )); + +LBER_F( void ) +ber_bvfree_x LDAP_P(( + struct berval *bv, void *ctx )); + +LBER_F( void ) +ber_bvecfree_x LDAP_P(( + struct berval **bv, void *ctx )); + +LBER_F( int ) +ber_bvecadd_x LDAP_P(( + struct berval ***bvec, + struct berval *bv, void *ctx )); + +LBER_F( struct berval * ) +ber_dupbv_x LDAP_P(( + struct berval *dst, struct berval *src, void *ctx )); + +LBER_F( struct berval * ) +ber_str2bv_x LDAP_P(( + LDAP_CONST char *, ber_len_t len, int dup, struct berval *bv, void *ctx)); + +LBER_F( struct berval * ) +ber_mem2bv_x LDAP_P(( + LDAP_CONST char *, ber_len_t len, int dup, struct berval *bv, void *ctx)); + +LBER_F( char * ) +ber_strdup_x LDAP_P(( + LDAP_CONST char *, void *ctx )); + +LBER_F( struct berval * ) +ber_bvreplace_x LDAP_P(( + struct berval *dst, LDAP_CONST struct berval *src, void *ctx )); + +LBER_F( void ) +ber_bvarray_free_x LDAP_P(( BerVarray p, void *ctx )); + +LBER_F( int ) +ber_bvarray_add_x LDAP_P(( BerVarray *p, BerValue *bv, void *ctx )); + +LBER_F( int ) +ber_bvarray_dup_x LDAP_P(( BerVarray *dst, BerVarray src, void *ctx )); + +#if 0 +#define ber_bvstrcmp(v1,v2) \ + ((v1)->bv_len < (v2)->bv_len \ + ? -1 : ((v1)->bv_len > (v2)->bv_len \ + ? 1 : strncmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) +#else + /* avoid strncmp() */ +#define ber_bvstrcmp(v1,v2) ber_bvcmp((v1),(v2)) +#endif + +#define ber_bvstrcasecmp(v1,v2) \ + ((v1)->bv_len < (v2)->bv_len \ + ? -1 : ((v1)->bv_len > (v2)->bv_len \ + ? 1 : strncasecmp((v1)->bv_val, (v2)->bv_val, (v1)->bv_len) )) + +#define ber_bvccmp(v1,c) \ + ( (v1)->bv_len == 1 && (v1)->bv_val[0] == (c) ) + +#define ber_strccmp(s,c) \ + ( (s)[0] == (c) && (s)[1] == '\0' ) + +#define ber_bvchr(bv,c) \ + ((char *) memchr( (bv)->bv_val, (c), (bv)->bv_len )) + +#define ber_bvrchr(bv,c) \ + ((char *) lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len )) + +#define ber_bvchr_post(dst,bv,c) \ + do { \ + (dst)->bv_val = memchr( (bv)->bv_val, (c), (bv)->bv_len ); \ + (dst)->bv_len = (dst)->bv_val ? (bv)->bv_len - ((dst)->bv_val - (bv)->bv_val) : 0; \ + } while (0) + +#define ber_bvchr_pre(dst,bv,c) \ + do { \ + (dst)->bv_val = memchr( (bv)->bv_val, (c), (bv)->bv_len ); \ + (dst)->bv_len = (dst)->bv_val ? ((dst)->bv_val - (bv)->bv_val) : (bv)->bv_len; \ + (dst)->bv_val = (bv)->bv_val; \ + } while (0) + +#define ber_bvrchr_post(dst,bv,c) \ + do { \ + (dst)->bv_val = lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len ); \ + (dst)->bv_len = (dst)->bv_val ? (bv)->bv_len - ((dst)->bv_val - (bv)->bv_val) : 0; \ + } while (0) + +#define ber_bvrchr_pre(dst,bv,c) \ + do { \ + (dst)->bv_val = lutil_memrchr( (bv)->bv_val, (c), (bv)->bv_len ); \ + (dst)->bv_len = (dst)->bv_val ? ((dst)->bv_val - (bv)->bv_val) : (bv)->bv_len; \ + (dst)->bv_val = (bv)->bv_val; \ + } while (0) + +#define BER_STRLENOF(s) (sizeof(s)-1) +#define BER_BVC(s) { BER_STRLENOF(s), (char *)(s) } +#define BER_BVNULL { 0L, NULL } +#define BER_BVZERO(bv) \ + do { \ + (bv)->bv_len = 0; \ + (bv)->bv_val = NULL; \ + } while (0) +#define BER_BVSTR(bv,s) \ + do { \ + (bv)->bv_len = BER_STRLENOF(s); \ + (bv)->bv_val = (s); \ + } while (0) +#define BER_BVISNULL(bv) ((bv)->bv_val == NULL) +#define BER_BVISEMPTY(bv) ((bv)->bv_len == 0) + +LDAP_END_DECL + +#endif diff --git a/libs/ldap/include/lber_types.h b/libs/ldap/include/lber_types.h new file mode 100644 index 00000000000..c32b803a89a --- /dev/null +++ b/libs/ldap/include/lber_types.h @@ -0,0 +1,63 @@ +/* include/lber_types.h. Generated from lber_types.hin by configure. */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * LBER types + */ + +#ifndef _LBER_TYPES_H +#define _LBER_TYPES_H + +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +/* LBER boolean, enum, integers (32 bits or larger) */ +#define LBER_INT_T int + +/* LBER tags (32 bits or larger) */ +#define LBER_TAG_T long + +/* LBER socket descriptor */ +#define LBER_SOCKET_T int + +/* LBER lengths (32 bits or larger) */ +#define LBER_LEN_T long + +/* ------------------------------------------------------------ */ + +/* booleans, enumerations, and integers */ +typedef LBER_INT_T ber_int_t; + +/* signed and unsigned versions */ +typedef signed LBER_INT_T ber_sint_t; +typedef unsigned LBER_INT_T ber_uint_t; + +/* tags */ +typedef unsigned LBER_TAG_T ber_tag_t; + +/* "socket" descriptors */ +typedef LBER_SOCKET_T ber_socket_t; + +/* lengths */ +typedef unsigned LBER_LEN_T ber_len_t; + +/* signed lengths */ +typedef signed LBER_LEN_T ber_slen_t; + +LDAP_END_DECL + +#endif /* _LBER_TYPES_H */ diff --git a/libs/ldap/include/ldap.h b/libs/ldap/include/ldap.h new file mode 100644 index 00000000000..672e413ff5c --- /dev/null +++ b/libs/ldap/include/ldap.h @@ -0,0 +1,2817 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ + +#ifndef _LDAP_H +#define _LDAP_H + +/* pull in lber */ +#include <lber.h> + +/* include version and API feature defines */ +#include <ldap_features.h> + +LDAP_BEGIN_DECL + +#define LDAP_VERSION1 1 +#define LDAP_VERSION2 2 +#define LDAP_VERSION3 3 + +#define LDAP_VERSION_MIN LDAP_VERSION2 +#define LDAP_VERSION LDAP_VERSION2 +#define LDAP_VERSION_MAX LDAP_VERSION3 + +/* + * We use 3000+n here because it is above 1823 (for RFC 1823), + * above 2000+rev of IETF LDAPEXT draft (now quite dated), + * yet below allocations for new RFCs (just in case there is + * someday an RFC produced). + */ +#define LDAP_API_VERSION 3001 +#define LDAP_VENDOR_NAME "OpenLDAP" + +/* OpenLDAP API Features */ +#define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION + +#if defined( LDAP_API_FEATURE_X_OPENLDAP_REENTRANT ) +# define LDAP_API_FEATURE_THREAD_SAFE 1 +#endif +#if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) +# define LDAP_API_FEATURE_SESSION_THREAD_SAFE 1 +# define LDAP_API_FEATURE_OPERATION_THREAD_SAFE 1 +#endif + + +#define LDAP_PORT 389 /* ldap:/// default LDAP port */ +#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ + +#define LDAP_ROOT_DSE "" +#define LDAP_NO_ATTRS "1.1" +#define LDAP_ALL_USER_ATTRIBUTES "*" +#define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+" /* RFC 3673 */ + +/* RFC 4511: maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) -- */ +#define LDAP_MAXINT (2147483647) + +/* + * LDAP_OPTions + * 0x0000 - 0x0fff reserved for api options + * 0x1000 - 0x3fff reserved for api extended options + * 0x4000 - 0x7fff reserved for private and experimental options + */ + +#define LDAP_OPT_API_INFO 0x0000 +#define LDAP_OPT_DESC 0x0001 /* historic */ +#define LDAP_OPT_DEREF 0x0002 +#define LDAP_OPT_SIZELIMIT 0x0003 +#define LDAP_OPT_TIMELIMIT 0x0004 +/* 0x05 - 0x07 not defined */ +#define LDAP_OPT_REFERRALS 0x0008 +#define LDAP_OPT_RESTART 0x0009 +/* 0x0a - 0x10 not defined */ +#define LDAP_OPT_PROTOCOL_VERSION 0x0011 +#define LDAP_OPT_SERVER_CONTROLS 0x0012 +#define LDAP_OPT_CLIENT_CONTROLS 0x0013 +/* 0x14 not defined */ +#define LDAP_OPT_API_FEATURE_INFO 0x0015 +/* 0x16 - 0x2f not defined */ +#define LDAP_OPT_HOST_NAME 0x0030 +#define LDAP_OPT_RESULT_CODE 0x0031 +#define LDAP_OPT_ERROR_NUMBER LDAP_OPT_RESULT_CODE +#define LDAP_OPT_DIAGNOSTIC_MESSAGE 0x0032 +#define LDAP_OPT_ERROR_STRING LDAP_OPT_DIAGNOSTIC_MESSAGE +#define LDAP_OPT_MATCHED_DN 0x0033 +/* 0x0034 - 0x3fff not defined */ +/* 0x0091 used by Microsoft for LDAP_OPT_AUTO_RECONNECT */ +#define LDAP_OPT_SSPI_FLAGS 0x0092 +/* 0x0093 used by Microsoft for LDAP_OPT_SSL_INFO */ +/* 0x0094 used by Microsoft for LDAP_OPT_REF_DEREF_CONN_PER_MSG */ +#define LDAP_OPT_SIGN 0x0095 +#define LDAP_OPT_ENCRYPT 0x0096 +#define LDAP_OPT_SASL_METHOD 0x0097 +/* 0x0098 used by Microsoft for LDAP_OPT_AREC_EXCLUSIVE */ +#define LDAP_OPT_SECURITY_CONTEXT 0x0099 +/* 0x009A used by Microsoft for LDAP_OPT_ROOTDSE_CACHE */ +/* 0x009B - 0x3fff not defined */ + +/* API Extensions */ +#define LDAP_OPT_API_EXTENSION_BASE 0x4000 /* API extensions */ + +/* private and experimental options */ +/* OpenLDAP specific options */ +#define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */ +#define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */ +#define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */ +#define LDAP_OPT_NETWORK_TIMEOUT 0x5005 /* socket level timeout */ +#define LDAP_OPT_URI 0x5006 +#define LDAP_OPT_REFERRAL_URLS 0x5007 /* Referral URLs */ +#define LDAP_OPT_SOCKBUF 0x5008 /* sockbuf */ +#define LDAP_OPT_DEFBASE 0x5009 /* searchbase */ +#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */ +#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */ +#define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */ +#define LDAP_OPT_KEEPCONN 0x5013 /* keep the connection on read error or NoD */ +#define LDAP_OPT_SOCKET_BIND_ADDRESSES 0x5014 /* user configured bind IPs */ +#define LDAP_OPT_TCP_USER_TIMEOUT 0x5015 /* set TCP_USER_TIMEOUT if the OS supports it, ignored otherwise */ + +/* OpenLDAP TLS options */ +#define LDAP_OPT_X_TLS 0x6000 +#define LDAP_OPT_X_TLS_CTX 0x6001 /* OpenSSL CTX* */ +#define LDAP_OPT_X_TLS_CACERTFILE 0x6002 +#define LDAP_OPT_X_TLS_CACERTDIR 0x6003 +#define LDAP_OPT_X_TLS_CERTFILE 0x6004 +#define LDAP_OPT_X_TLS_KEYFILE 0x6005 +#define LDAP_OPT_X_TLS_REQUIRE_CERT 0x6006 +#define LDAP_OPT_X_TLS_PROTOCOL_MIN 0x6007 +#define LDAP_OPT_X_TLS_CIPHER_SUITE 0x6008 +#define LDAP_OPT_X_TLS_RANDOM_FILE 0x6009 +#define LDAP_OPT_X_TLS_SSL_CTX 0x600a /* OpenSSL SSL* */ +#define LDAP_OPT_X_TLS_CRLCHECK 0x600b +#define LDAP_OPT_X_TLS_CONNECT_CB 0x600c +#define LDAP_OPT_X_TLS_CONNECT_ARG 0x600d +#define LDAP_OPT_X_TLS_DHFILE 0x600e +#define LDAP_OPT_X_TLS_NEWCTX 0x600f +#define LDAP_OPT_X_TLS_CRLFILE 0x6010 /* GNUtls only */ +#define LDAP_OPT_X_TLS_PACKAGE 0x6011 +#define LDAP_OPT_X_TLS_ECNAME 0x6012 +#define LDAP_OPT_X_TLS_VERSION 0x6013 /* read-only */ +#define LDAP_OPT_X_TLS_CIPHER 0x6014 /* read-only */ +#define LDAP_OPT_X_TLS_PEERCERT 0x6015 /* read-only */ +#define LDAP_OPT_X_TLS_CACERT 0x6016 +#define LDAP_OPT_X_TLS_CERT 0x6017 +#define LDAP_OPT_X_TLS_KEY 0x6018 +#define LDAP_OPT_X_TLS_PEERKEY_HASH 0x6019 +#define LDAP_OPT_X_TLS_REQUIRE_SAN 0x601a +#define LDAP_OPT_X_TLS_PROTOCOL_MAX 0x601b + +#define LDAP_OPT_X_TLS_NEVER 0 +#define LDAP_OPT_X_TLS_HARD 1 +#define LDAP_OPT_X_TLS_DEMAND 2 +#define LDAP_OPT_X_TLS_ALLOW 3 +#define LDAP_OPT_X_TLS_TRY 4 + +#define LDAP_OPT_X_TLS_CRL_NONE 0 +#define LDAP_OPT_X_TLS_CRL_PEER 1 +#define LDAP_OPT_X_TLS_CRL_ALL 2 + +/* for LDAP_OPT_X_TLS_PROTOCOL_MIN/MAX */ +#define LDAP_OPT_X_TLS_PROTOCOL(maj,min) (((maj) << 8) + (min)) +#define LDAP_OPT_X_TLS_PROTOCOL_SSL2 (2 << 8) +#define LDAP_OPT_X_TLS_PROTOCOL_SSL3 (3 << 8) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ((3 << 8) + 1) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 ((3 << 8) + 4) + +#define LDAP_OPT_X_SASL_CBINDING_NONE 0 +#define LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE 1 +#define LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT 2 + +/* OpenLDAP SASL options */ +#define LDAP_OPT_X_SASL_MECH 0x6100 +#define LDAP_OPT_X_SASL_REALM 0x6101 +#define LDAP_OPT_X_SASL_AUTHCID 0x6102 +#define LDAP_OPT_X_SASL_AUTHZID 0x6103 +#define LDAP_OPT_X_SASL_SSF 0x6104 /* read-only */ +#define LDAP_OPT_X_SASL_SSF_EXTERNAL 0x6105 /* write-only */ +#define LDAP_OPT_X_SASL_SECPROPS 0x6106 /* write-only */ +#define LDAP_OPT_X_SASL_SSF_MIN 0x6107 +#define LDAP_OPT_X_SASL_SSF_MAX 0x6108 +#define LDAP_OPT_X_SASL_MAXBUFSIZE 0x6109 +#define LDAP_OPT_X_SASL_MECHLIST 0x610a /* read-only */ +#define LDAP_OPT_X_SASL_NOCANON 0x610b +#define LDAP_OPT_X_SASL_USERNAME 0x610c /* read-only */ +#define LDAP_OPT_X_SASL_GSS_CREDS 0x610d +#define LDAP_OPT_X_SASL_CBINDING 0x610e + +/* + * OpenLDAP per connection tcp-keepalive settings + * (Linux only, ignored where unsupported) + */ +#define LDAP_OPT_X_KEEPALIVE_IDLE 0x6300 +#define LDAP_OPT_X_KEEPALIVE_PROBES 0x6301 +#define LDAP_OPT_X_KEEPALIVE_INTERVAL 0x6302 + +/* Private API Extensions -- reserved for application use */ +#define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000 /* Private API inclusive */ + +/* + * ldap_get_option() and ldap_set_option() return values. + * As later versions may return other values indicating + * failure, current applications should only compare returned + * value against LDAP_OPT_SUCCESS. + */ +#define LDAP_OPT_SUCCESS 0 +#define LDAP_OPT_ERROR (-1) + +/* option on/off values */ +#define LDAP_OPT_ON ((void *) &ber_pvt_opt_on) +#define LDAP_OPT_OFF ((void *) 0) + +typedef struct ldapapiinfo { + int ldapai_info_version; /* version of LDAPAPIInfo */ +#define LDAP_API_INFO_VERSION (1) + int ldapai_api_version; /* revision of API supported */ + int ldapai_protocol_version; /* highest LDAP version supported */ + char **ldapai_extensions; /* names of API extensions */ + char *ldapai_vendor_name; /* name of supplier */ + int ldapai_vendor_version; /* supplier-specific version * 100 */ +} LDAPAPIInfo; + +typedef struct ldap_apifeature_info { + int ldapaif_info_version; /* version of LDAPAPIFeatureInfo */ +#define LDAP_FEATURE_INFO_VERSION (1) /* apifeature_info struct version */ + char* ldapaif_name; /* LDAP_API_FEATURE_* (less prefix) */ + int ldapaif_version; /* value of LDAP_API_FEATURE_... */ +} LDAPAPIFeatureInfo; + +/* + * LDAP Control structure + */ +typedef struct ldapcontrol { + char * ldctl_oid; /* numericoid of control */ + struct berval ldctl_value; /* encoded value of control */ + char ldctl_iscritical; /* criticality */ +} LDAPControl; + +/* LDAP Controls */ +/* standard track controls */ +#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2" /* RFC 3296 */ +#define LDAP_CONTROL_PROXY_AUTHZ "2.16.840.1.113730.3.4.18" /* RFC 4370 */ +#define LDAP_CONTROL_SUBENTRIES "1.3.6.1.4.1.4203.1.10.1" /* RFC 3672 */ + +#define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.3344810.2.3"/* RFC 3876 */ + +#define LDAP_CONTROL_ASSERT "1.3.6.1.1.12" /* RFC 4528 */ +#define LDAP_CONTROL_PRE_READ "1.3.6.1.1.13.1" /* RFC 4527 */ +#define LDAP_CONTROL_POST_READ "1.3.6.1.1.13.2" /* RFC 4527 */ + +#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473" /* RFC 2891 */ +#define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474" /* RFC 2891 */ + +/* non-standard track controls */ +#define LDAP_CONTROL_PAGEDRESULTS "1.2.840.113556.1.4.319" /* RFC 2696 */ + +#define LDAP_CONTROL_AUTHZID_REQUEST "2.16.840.1.113730.3.4.16" /* RFC 3829 */ +#define LDAP_CONTROL_AUTHZID_RESPONSE "2.16.840.1.113730.3.4.15" /* RFC 3829 */ + +/* LDAP Content Synchronization Operation -- RFC 4533 */ +#define LDAP_SYNC_OID "1.3.6.1.4.1.4203.1.9.1" +#define LDAP_CONTROL_SYNC LDAP_SYNC_OID ".1" +#define LDAP_CONTROL_SYNC_STATE LDAP_SYNC_OID ".2" +#define LDAP_CONTROL_SYNC_DONE LDAP_SYNC_OID ".3" +#define LDAP_SYNC_INFO LDAP_SYNC_OID ".4" + +#define LDAP_SYNC_NONE 0x00 +#define LDAP_SYNC_REFRESH_ONLY 0x01 +#define LDAP_SYNC_RESERVED 0x02 +#define LDAP_SYNC_REFRESH_AND_PERSIST 0x03 + +#define LDAP_SYNC_REFRESH_PRESENTS 0 +#define LDAP_SYNC_REFRESH_DELETES 1 + +#define LDAP_TAG_SYNC_NEW_COOKIE ((ber_tag_t) 0x80U) +#define LDAP_TAG_SYNC_REFRESH_DELETE ((ber_tag_t) 0xa1U) +#define LDAP_TAG_SYNC_REFRESH_PRESENT ((ber_tag_t) 0xa2U) +#define LDAP_TAG_SYNC_ID_SET ((ber_tag_t) 0xa3U) + +#define LDAP_TAG_SYNC_COOKIE ((ber_tag_t) 0x04U) +#define LDAP_TAG_REFRESHDELETES ((ber_tag_t) 0x01U) +#define LDAP_TAG_REFRESHDONE ((ber_tag_t) 0x01U) +#define LDAP_TAG_RELOAD_HINT ((ber_tag_t) 0x01U) + +#define LDAP_SYNC_PRESENT 0 +#define LDAP_SYNC_ADD 1 +#define LDAP_SYNC_MODIFY 2 +#define LDAP_SYNC_DELETE 3 +#define LDAP_SYNC_NEW_COOKIE 4 + +/* LDAP Don't Use Copy Control (RFC 6171) */ +#define LDAP_CONTROL_DONTUSECOPY "1.3.6.1.1.22" + +/* Password policy Controls *//* work in progress */ +/* ITS#3458: released; disabled by default */ +#define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1" +#define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" + +/* various works in progress */ +#define LDAP_CONTROL_NOOP "1.3.6.1.4.1.4203.666.5.2" +#define LDAP_CONTROL_NO_SUBORDINATES "1.3.6.1.4.1.4203.666.5.11" +#define LDAP_CONTROL_RELAX "1.3.6.1.4.1.4203.666.5.12" +#define LDAP_CONTROL_MANAGEDIT LDAP_CONTROL_RELAX +#define LDAP_CONTROL_SLURP "1.3.6.1.4.1.4203.666.5.13" +#define LDAP_CONTROL_VALSORT "1.3.6.1.4.1.4203.666.5.14" +#define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16" +#define LDAP_CONTROL_X_WHATFAILED "1.3.6.1.4.1.4203.666.5.17" + +/* LDAP Chaining Behavior Control *//* work in progress */ +/* <draft-sermersheim-ldap-chaining>; + * see also LDAP_NO_REFERRALS_FOUND, LDAP_CANNOT_CHAIN */ +#define LDAP_CONTROL_X_CHAINING_BEHAVIOR "1.3.6.1.4.1.4203.666.11.3" + +#define LDAP_CHAINING_PREFERRED 0 +#define LDAP_CHAINING_REQUIRED 1 +#define LDAP_REFERRALS_PREFERRED 2 +#define LDAP_REFERRALS_REQUIRED 3 + +/* MS Active Directory controls (for compatibility) */ +#define LDAP_CONTROL_X_LAZY_COMMIT "1.2.840.113556.1.4.619" +#define LDAP_CONTROL_X_INCREMENTAL_VALUES "1.2.840.113556.1.4.802" +#define LDAP_CONTROL_X_DOMAIN_SCOPE "1.2.840.113556.1.4.1339" +#define LDAP_CONTROL_X_PERMISSIVE_MODIFY "1.2.840.113556.1.4.1413" +#define LDAP_CONTROL_X_SEARCH_OPTIONS "1.2.840.113556.1.4.1340" +#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */ +#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all subordinate NCs */ +#define LDAP_CONTROL_X_TREE_DELETE "1.2.840.113556.1.4.805" + +/* MS Active Directory controls - not implemented in slapd(8) */ +#define LDAP_CONTROL_X_SERVER_NOTIFICATION "1.2.840.113556.1.4.528" +#define LDAP_CONTROL_X_EXTENDED_DN "1.2.840.113556.1.4.529" +#define LDAP_CONTROL_X_SHOW_DELETED "1.2.840.113556.1.4.417" +#define LDAP_CONTROL_X_DIRSYNC "1.2.840.113556.1.4.841" + +#define LDAP_CONTROL_X_DIRSYNC_OBJECT_SECURITY 0x00000001 +#define LDAP_CONTROL_X_DIRSYNC_ANCESTORS_FIRST 0x00000800 +#define LDAP_CONTROL_X_DIRSYNC_PUBLIC_DATA_ONLY 0x00002000 +#define LDAP_CONTROL_X_DIRSYNC_INCREMENTAL_VALUES 0x80000000 + + +/* <draft-wahl-ldap-session> */ +#define LDAP_CONTROL_X_SESSION_TRACKING "1.3.6.1.4.1.21008.108.63.1" +#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID \ + LDAP_CONTROL_X_SESSION_TRACKING ".1" +#define LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID \ + LDAP_CONTROL_X_SESSION_TRACKING ".2" +#define LDAP_CONTROL_X_SESSION_TRACKING_USERNAME \ + LDAP_CONTROL_X_SESSION_TRACKING ".3" +/* various expired works */ + +/* LDAP Duplicated Entry Control Extension *//* not implemented in slapd(8) */ +#define LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1" +#define LDAP_CONTROL_DUPENT_RESPONSE "2.16.840.1.113719.1.27.101.2" +#define LDAP_CONTROL_DUPENT_ENTRY "2.16.840.1.113719.1.27.101.3" +#define LDAP_CONTROL_DUPENT LDAP_CONTROL_DUPENT_REQUEST + +/* LDAP Persistent Search Control *//* not implemented in slapd(8) */ +#define LDAP_CONTROL_PERSIST_REQUEST "2.16.840.1.113730.3.4.3" +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE "2.16.840.1.113730.3.4.7" +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD 0x1 +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE 0x2 +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY 0x4 +#define LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME 0x8 + +/* LDAP VLV */ +#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9" +#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" + +/* Sun's analogue to ppolicy */ +#define LDAP_CONTROL_X_ACCOUNT_USABILITY "1.3.6.1.4.1.42.2.27.9.5.8" + +#define LDAP_TAG_X_ACCOUNT_USABILITY_AVAILABLE ((ber_tag_t) 0x80U) /* primitive + 0 */ +#define LDAP_TAG_X_ACCOUNT_USABILITY_NOT_AVAILABLE ((ber_tag_t) 0xA1U) /* constructed + 1 */ + +#define LDAP_TAG_X_ACCOUNT_USABILITY_INACTIVE ((ber_tag_t) 0x80U) /* primitive + 0 */ +#define LDAP_TAG_X_ACCOUNT_USABILITY_RESET ((ber_tag_t) 0x81U) /* primitive + 1 */ +#define LDAP_TAG_X_ACCOUNT_USABILITY_EXPIRED ((ber_tag_t) 0x82U) /* primitive + 2 */ +#define LDAP_TAG_X_ACCOUNT_USABILITY_REMAINING_GRACE ((ber_tag_t) 0x83U) /* primitive + 3 */ +#define LDAP_TAG_X_ACCOUNT_USABILITY_UNTIL_UNLOCK ((ber_tag_t) 0x84U) /* primitive + 4 */ + +/* Netscape Password policy response controls */ +/* <draft-vchu-ldap-pwd-policy> */ +#define LDAP_CONTROL_X_PASSWORD_EXPIRED "2.16.840.1.113730.3.4.4" +#define LDAP_CONTROL_X_PASSWORD_EXPIRING "2.16.840.1.113730.3.4.5" + +/* LDAP Unsolicited Notifications */ +#define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" /* RFC 4511 */ +#define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION + +/* LDAP Extended Operations */ +#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 4511 */ + +#define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1" /* RFC 3062 */ +#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_GEN ((ber_tag_t) 0x80U) + +#define LDAP_EXOP_CANCEL "1.3.6.1.1.8" /* RFC 3909 */ +#define LDAP_EXOP_X_CANCEL LDAP_EXOP_CANCEL + +#define LDAP_EXOP_REFRESH "1.3.6.1.4.1.1466.101.119.1" /* RFC 2589 */ +#define LDAP_TAG_EXOP_REFRESH_REQ_DN ((ber_tag_t) 0x80U) +#define LDAP_TAG_EXOP_REFRESH_REQ_TTL ((ber_tag_t) 0x81U) +#define LDAP_TAG_EXOP_REFRESH_RES_TTL ((ber_tag_t) 0x81U) + +#define LDAP_EXOP_VERIFY_CREDENTIALS "1.3.6.1.4.1.4203.666.6.5" +#define LDAP_EXOP_X_VERIFY_CREDENTIALS LDAP_EXOP_VERIFY_CREDENTIALS + +#define LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ((ber_tag_t) 0x80U) +#define LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS ((ber_tag_t) 0x81U) +#define LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ((ber_tag_t) 0xa2U) /* context specific + constructed + 2 */ + +#define LDAP_EXOP_WHO_AM_I "1.3.6.1.4.1.4203.1.11.3" /* RFC 4532 */ +#define LDAP_EXOP_X_WHO_AM_I LDAP_EXOP_WHO_AM_I + +/* various works in progress */ +#define LDAP_EXOP_TURN "1.3.6.1.1.19" /* RFC 4531 */ +#define LDAP_EXOP_X_TURN LDAP_EXOP_TURN + +/* LDAP Distributed Procedures <draft-sermersheim-ldap-distproc> */ +/* a work in progress */ +#define LDAP_X_DISTPROC_BASE "1.3.6.1.4.1.4203.666.11.6" +#define LDAP_EXOP_X_CHAINEDREQUEST LDAP_X_DISTPROC_BASE ".1" +#define LDAP_FEATURE_X_CANCHAINOPS LDAP_X_DISTPROC_BASE ".2" +#define LDAP_CONTROL_X_RETURNCONTREF LDAP_X_DISTPROC_BASE ".3" +#define LDAP_URLEXT_X_LOCALREFOID LDAP_X_DISTPROC_BASE ".4" +#define LDAP_URLEXT_X_REFTYPEOID LDAP_X_DISTPROC_BASE ".5" +#define LDAP_URLEXT_X_SEARCHEDSUBTREEOID \ + LDAP_X_DISTPROC_BASE ".6" +#define LDAP_URLEXT_X_FAILEDNAMEOID LDAP_X_DISTPROC_BASE ".7" +#define LDAP_URLEXT_X_LOCALREF "x-localReference" +#define LDAP_URLEXT_X_REFTYPE "x-referenceType" +#define LDAP_URLEXT_X_SEARCHEDSUBTREE "x-searchedSubtree" +#define LDAP_URLEXT_X_FAILEDNAME "x-failedName" + +#define LDAP_TXN "1.3.6.1.1.21" /* RFC 5805 */ +#define LDAP_EXOP_TXN_START LDAP_TXN ".1" +#define LDAP_CONTROL_TXN_SPEC LDAP_TXN ".2" +#define LDAP_EXOP_TXN_END LDAP_TXN ".3" +#define LDAP_EXOP_TXN_ABORTED_NOTICE LDAP_TXN ".4" + +/* LDAP Features */ +#define LDAP_FEATURE_ALL_OP_ATTRS "1.3.6.1.4.1.4203.1.5.1" /* RFC 3673 */ +#define LDAP_FEATURE_OBJECTCLASS_ATTRS \ + "1.3.6.1.4.1.4203.1.5.2" /* @objectClass - new number to be assigned */ +#define LDAP_FEATURE_ABSOLUTE_FILTERS "1.3.6.1.4.1.4203.1.5.3" /* (&) (|) */ +#define LDAP_FEATURE_LANGUAGE_TAG_OPTIONS "1.3.6.1.4.1.4203.1.5.4" +#define LDAP_FEATURE_LANGUAGE_RANGE_OPTIONS "1.3.6.1.4.1.4203.1.5.5" +#define LDAP_FEATURE_MODIFY_INCREMENT "1.3.6.1.1.14" + +/* LDAP Experimental (works in progress) Features */ +#define LDAP_FEATURE_SUBORDINATE_SCOPE \ + "1.3.6.1.4.1.4203.666.8.1" /* "children" */ +#define LDAP_FEATURE_CHILDREN_SCOPE LDAP_FEATURE_SUBORDINATE_SCOPE + +/* + * specific LDAP instantiations of BER types we know about + */ + +/* Overview of LBER tag construction + * + * Bits + * ______ + * 8 7 | CLASS + * 0 0 = UNIVERSAL + * 0 1 = APPLICATION + * 1 0 = CONTEXT-SPECIFIC + * 1 1 = PRIVATE + * _____ + * | 6 | DATA-TYPE + * 0 = PRIMITIVE + * 1 = CONSTRUCTED + * ___________ + * | 5 ... 1 | TAG-NUMBER + */ + +/* general stuff */ +#define LDAP_TAG_MESSAGE ((ber_tag_t) 0x30U) /* constructed + 16 */ +#define LDAP_TAG_MSGID ((ber_tag_t) 0x02U) /* integer */ + +#define LDAP_TAG_LDAPDN ((ber_tag_t) 0x04U) /* octet string */ +#define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octet string */ + +#define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */ +#define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */ + +#define LDAP_TAG_NEWSUPERIOR ((ber_tag_t) 0x80U) /* context-specific + primitive + 0 */ + +#define LDAP_TAG_EXOP_REQ_OID ((ber_tag_t) 0x80U) /* context specific + primitive */ +#define LDAP_TAG_EXOP_REQ_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */ +#define LDAP_TAG_EXOP_RES_OID ((ber_tag_t) 0x8aU) /* context specific + primitive */ +#define LDAP_TAG_EXOP_RES_VALUE ((ber_tag_t) 0x8bU) /* context specific + primitive */ + +#define LDAP_TAG_IM_RES_OID ((ber_tag_t) 0x80U) /* context specific + primitive */ +#define LDAP_TAG_IM_RES_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */ + +#define LDAP_TAG_SASL_RES_CREDS ((ber_tag_t) 0x87U) /* context specific + primitive */ + +/* LDAP Request Messages */ +#define LDAP_REQ_BIND ((ber_tag_t) 0x60U) /* application + constructed */ +#define LDAP_REQ_UNBIND ((ber_tag_t) 0x42U) /* application + primitive */ +#define LDAP_REQ_SEARCH ((ber_tag_t) 0x63U) /* application + constructed */ +#define LDAP_REQ_MODIFY ((ber_tag_t) 0x66U) /* application + constructed */ +#define LDAP_REQ_ADD ((ber_tag_t) 0x68U) /* application + constructed */ +#define LDAP_REQ_DELETE ((ber_tag_t) 0x4aU) /* application + primitive */ +#define LDAP_REQ_MODDN ((ber_tag_t) 0x6cU) /* application + constructed */ +#define LDAP_REQ_MODRDN LDAP_REQ_MODDN +#define LDAP_REQ_RENAME LDAP_REQ_MODDN +#define LDAP_REQ_COMPARE ((ber_tag_t) 0x6eU) /* application + constructed */ +#define LDAP_REQ_ABANDON ((ber_tag_t) 0x50U) /* application + primitive */ +#define LDAP_REQ_EXTENDED ((ber_tag_t) 0x77U) /* application + constructed */ + +/* LDAP Response Messages */ +#define LDAP_RES_BIND ((ber_tag_t) 0x61U) /* application + constructed */ +#define LDAP_RES_SEARCH_ENTRY ((ber_tag_t) 0x64U) /* application + constructed */ +#define LDAP_RES_SEARCH_REFERENCE ((ber_tag_t) 0x73U) /* V3: application + constructed */ +#define LDAP_RES_SEARCH_RESULT ((ber_tag_t) 0x65U) /* application + constructed */ +#define LDAP_RES_MODIFY ((ber_tag_t) 0x67U) /* application + constructed */ +#define LDAP_RES_ADD ((ber_tag_t) 0x69U) /* application + constructed */ +#define LDAP_RES_DELETE ((ber_tag_t) 0x6bU) /* application + constructed */ +#define LDAP_RES_MODDN ((ber_tag_t) 0x6dU) /* application + constructed */ +#define LDAP_RES_MODRDN LDAP_RES_MODDN /* application + constructed */ +#define LDAP_RES_RENAME LDAP_RES_MODDN /* application + constructed */ +#define LDAP_RES_COMPARE ((ber_tag_t) 0x6fU) /* application + constructed */ +#define LDAP_RES_EXTENDED ((ber_tag_t) 0x78U) /* V3: application + constructed */ +#define LDAP_RES_INTERMEDIATE ((ber_tag_t) 0x79U) /* V3+: application + constructed */ + +#define LDAP_RES_ANY (-1) +#define LDAP_RES_UNSOLICITED (0) + + +/* sasl methods */ +#define LDAP_SASL_SIMPLE ((char*)0) +#define LDAP_SASL_NULL ("") + + +/* authentication methods available */ +#define LDAP_AUTH_NONE ((ber_tag_t) 0x00U) /* no authentication */ +#define LDAP_AUTH_SIMPLE ((ber_tag_t) 0x80U) /* context specific + primitive */ +#define LDAP_AUTH_SASL ((ber_tag_t) 0xa3U) /* context specific + constructed */ +#define LDAP_AUTH_KRBV4 ((ber_tag_t) 0xffU) /* means do both of the following */ +#define LDAP_AUTH_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */ +#define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* context specific + primitive */ + +/* used by the Windows API but not used on the wire */ +#define LDAP_AUTH_NEGOTIATE ((ber_tag_t) 0x04FFU) + +/* filter types */ +#define LDAP_FILTER_AND ((ber_tag_t) 0xa0U) /* context specific + constructed */ +#define LDAP_FILTER_OR ((ber_tag_t) 0xa1U) /* context specific + constructed */ +#define LDAP_FILTER_NOT ((ber_tag_t) 0xa2U) /* context specific + constructed */ +#define LDAP_FILTER_EQUALITY ((ber_tag_t) 0xa3U) /* context specific + constructed */ +#define LDAP_FILTER_SUBSTRINGS ((ber_tag_t) 0xa4U) /* context specific + constructed */ +#define LDAP_FILTER_GE ((ber_tag_t) 0xa5U) /* context specific + constructed */ +#define LDAP_FILTER_LE ((ber_tag_t) 0xa6U) /* context specific + constructed */ +#define LDAP_FILTER_PRESENT ((ber_tag_t) 0x87U) /* context specific + primitive */ +#define LDAP_FILTER_APPROX ((ber_tag_t) 0xa8U) /* context specific + constructed */ +#define LDAP_FILTER_EXT ((ber_tag_t) 0xa9U) /* context specific + constructed */ + +/* extended filter component types */ +#define LDAP_FILTER_EXT_OID ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_FILTER_EXT_TYPE ((ber_tag_t) 0x82U) /* context specific */ +#define LDAP_FILTER_EXT_VALUE ((ber_tag_t) 0x83U) /* context specific */ +#define LDAP_FILTER_EXT_DNATTRS ((ber_tag_t) 0x84U) /* context specific */ + +/* substring filter component types */ +#define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ +#define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ + +/* search scopes */ +#define LDAP_SCOPE_BASE ((ber_int_t) 0x0000) +#define LDAP_SCOPE_BASEOBJECT LDAP_SCOPE_BASE +#define LDAP_SCOPE_ONELEVEL ((ber_int_t) 0x0001) +#define LDAP_SCOPE_ONE LDAP_SCOPE_ONELEVEL +#define LDAP_SCOPE_SUBTREE ((ber_int_t) 0x0002) +#define LDAP_SCOPE_SUB LDAP_SCOPE_SUBTREE +#define LDAP_SCOPE_SUBORDINATE ((ber_int_t) 0x0003) /* OpenLDAP extension */ +#define LDAP_SCOPE_CHILDREN LDAP_SCOPE_SUBORDINATE +#define LDAP_SCOPE_DEFAULT ((ber_int_t) -1) /* OpenLDAP extension */ + +/* substring filter component types */ +#define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */ +#define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */ +#define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */ + +/* + * LDAP Result Codes + */ +#define LDAP_SUCCESS 0x00 + +#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) + +#define LDAP_OPERATIONS_ERROR 0x01 +#define LDAP_PROTOCOL_ERROR 0x02 +#define LDAP_TIMELIMIT_EXCEEDED 0x03 +#define LDAP_SIZELIMIT_EXCEEDED 0x04 +#define LDAP_COMPARE_FALSE 0x05 +#define LDAP_COMPARE_TRUE 0x06 +#define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07 +#define LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_AUTH_METHOD_NOT_SUPPORTED +#define LDAP_STRONG_AUTH_REQUIRED 0x08 +#define LDAP_STRONGER_AUTH_REQUIRED LDAP_STRONG_AUTH_REQUIRED +#define LDAP_PARTIAL_RESULTS 0x09 /* LDAPv2+ (not LDAPv3) */ + +#define LDAP_REFERRAL 0x0a /* LDAPv3 */ +#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */ +#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */ +#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */ +#define LDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */ + +#define LDAP_ATTR_ERROR(n) LDAP_RANGE((n),0x10,0x15) /* 16-21 */ + +#define LDAP_NO_SUCH_ATTRIBUTE 0x10 +#define LDAP_UNDEFINED_TYPE 0x11 +#define LDAP_INAPPROPRIATE_MATCHING 0x12 +#define LDAP_CONSTRAINT_VIOLATION 0x13 +#define LDAP_TYPE_OR_VALUE_EXISTS 0x14 +#define LDAP_INVALID_SYNTAX 0x15 + +#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ + +#define LDAP_NO_SUCH_OBJECT 0x20 +#define LDAP_ALIAS_PROBLEM 0x21 +#define LDAP_INVALID_DN_SYNTAX 0x22 +#define LDAP_IS_LEAF 0x23 /* not LDAPv3 */ +#define LDAP_ALIAS_DEREF_PROBLEM 0x24 + +#define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x2F,0x32) /* 47-50 */ + +#define LDAP_X_PROXY_AUTHZ_FAILURE 0x2F /* LDAPv3 proxy authorization */ +#define LDAP_INAPPROPRIATE_AUTH 0x30 +#define LDAP_INVALID_CREDENTIALS 0x31 +#define LDAP_INSUFFICIENT_ACCESS 0x32 + +#define LDAP_SERVICE_ERROR(n) LDAP_RANGE((n),0x33,0x36) /* 51-54 */ + +#define LDAP_BUSY 0x33 +#define LDAP_UNAVAILABLE 0x34 +#define LDAP_UNWILLING_TO_PERFORM 0x35 +#define LDAP_LOOP_DETECT 0x36 + +#define LDAP_UPDATE_ERROR(n) LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */ + +#define LDAP_NAMING_VIOLATION 0x40 +#define LDAP_OBJECT_CLASS_VIOLATION 0x41 +#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 +#define LDAP_NOT_ALLOWED_ON_RDN 0x43 +#define LDAP_ALREADY_EXISTS 0x44 +#define LDAP_NO_OBJECT_CLASS_MODS 0x45 +#define LDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */ +#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 + +#define LDAP_VLV_ERROR 0x4C + +#define LDAP_OTHER 0x50 + +/* LCUP operation codes (113-117) - not implemented */ +#define LDAP_CUP_RESOURCES_EXHAUSTED 0x71 +#define LDAP_CUP_SECURITY_VIOLATION 0x72 +#define LDAP_CUP_INVALID_DATA 0x73 +#define LDAP_CUP_UNSUPPORTED_SCHEME 0x74 +#define LDAP_CUP_RELOAD_REQUIRED 0x75 + +/* Cancel operation codes (118-121) */ +#define LDAP_CANCELLED 0x76 +#define LDAP_NO_SUCH_OPERATION 0x77 +#define LDAP_TOO_LATE 0x78 +#define LDAP_CANNOT_CANCEL 0x79 + +/* Assertion control (122) */ +#define LDAP_ASSERTION_FAILED 0x7A + +/* Proxied Authorization Denied (123) */ +#define LDAP_PROXIED_AUTHORIZATION_DENIED 0x7B + +/* Experimental result codes */ +#define LDAP_E_ERROR(n) LDAP_RANGE((n),0x1000,0x3FFF) + +/* LDAP Sync (4096) */ +#define LDAP_SYNC_REFRESH_REQUIRED 0x1000 + + +/* Private Use result codes */ +#define LDAP_X_ERROR(n) LDAP_RANGE((n),0x4000,0xFFFF) + +#define LDAP_X_SYNC_REFRESH_REQUIRED 0x4100 /* defunct */ +#define LDAP_X_ASSERTION_FAILED 0x410f /* defunct */ + +/* for the LDAP No-Op control */ +#define LDAP_X_NO_OPERATION 0x410e + +/* for the Chaining Behavior control (consecutive result codes requested; + * see <draft-sermersheim-ldap-chaining> ) */ +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR +#define LDAP_X_NO_REFERRALS_FOUND 0x4110 +#define LDAP_X_CANNOT_CHAIN 0x4111 +#endif + +/* for Distributed Procedures (see <draft-sermersheim-ldap-distproc>) */ +#ifdef LDAP_X_DISTPROC_BASE +#define LDAP_X_INVALIDREFERENCE 0x4112 +#endif + +#define LDAP_TXN_SPECIFY_OKAY 0x4120 +#define LDAP_TXN_ID_INVALID 0x4121 + +/* API Error Codes + * + * Based on draft-ietf-ldap-c-api-xx + * but with new negative code values + */ +#define LDAP_API_ERROR(n) ((n)<0) +#define LDAP_API_RESULT(n) ((n)<=0) + +#define LDAP_SERVER_DOWN (-1) +#define LDAP_LOCAL_ERROR (-2) +#define LDAP_ENCODING_ERROR (-3) +#define LDAP_DECODING_ERROR (-4) +#define LDAP_TIMEOUT (-5) +#define LDAP_AUTH_UNKNOWN (-6) +#define LDAP_FILTER_ERROR (-7) +#define LDAP_USER_CANCELLED (-8) +#define LDAP_PARAM_ERROR (-9) +#define LDAP_NO_MEMORY (-10) +#define LDAP_CONNECT_ERROR (-11) +#define LDAP_NOT_SUPPORTED (-12) +#define LDAP_CONTROL_NOT_FOUND (-13) +#define LDAP_NO_RESULTS_RETURNED (-14) +#define LDAP_MORE_RESULTS_TO_RETURN (-15) /* Obsolete */ +#define LDAP_CLIENT_LOOP (-16) +#define LDAP_REFERRAL_LIMIT_EXCEEDED (-17) +#define LDAP_X_CONNECTING (-18) + + +/* + * 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. + */ + +typedef struct ldapmsg LDAPMessage; + +/* for modifications */ +typedef struct ldapmod { + int mod_op; + +#define LDAP_MOD_OP (0x0007) +#define LDAP_MOD_ADD (0x0000) +#define LDAP_MOD_DELETE (0x0001) +#define LDAP_MOD_REPLACE (0x0002) +#define LDAP_MOD_INCREMENT (0x0003) /* OpenLDAP extension */ +#define LDAP_MOD_BVALUES (0x0080) +/* IMPORTANT: do not use code 0x1000 (or above), + * it is used internally by the backends! + * (see ldap/servers/slapd/slap.h) + */ + + char *mod_type; + union mod_vals_u { + char **modv_strvals; + struct berval **modv_bvals; + } mod_vals; +#define mod_values mod_vals.modv_strvals +#define mod_bvalues mod_vals.modv_bvals +} LDAPMod; + +/* + * structure representing an ldap session which can + * encompass connections to multiple servers (in the + * face of referrals). + */ +typedef struct ldap LDAP; + +#define LDAP_DEREF_NEVER 0x00 +#define LDAP_DEREF_SEARCHING 0x01 +#define LDAP_DEREF_FINDING 0x02 +#define LDAP_DEREF_ALWAYS 0x03 + +#define LDAP_NO_LIMIT 0 + +/* how many messages to retrieve results for */ +#define LDAP_MSG_ONE 0x00 +#define LDAP_MSG_ALL 0x01 +#define LDAP_MSG_RECEIVED 0x02 + +/* + * types for ldap URL handling + */ +typedef struct ldap_url_desc { + struct ldap_url_desc *lud_next; + char *lud_scheme; + char *lud_host; + int lud_port; + char *lud_dn; + char **lud_attrs; + int lud_scope; + char *lud_filter; + char **lud_exts; + int lud_crit_exts; +} LDAPURLDesc; + +#define LDAP_URL_SUCCESS 0x00 /* Success */ +#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ +#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ + +#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ +#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ +#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ +#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ +#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ +#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ +#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ +#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ + +/* + * LDAP sync (RFC4533) API + */ + +typedef struct ldap_sync_t ldap_sync_t; + +typedef enum { + /* these are private - the client should never see them */ + LDAP_SYNC_CAPI_NONE = -1, + + LDAP_SYNC_CAPI_PHASE_FLAG = 0x10U, + LDAP_SYNC_CAPI_IDSET_FLAG = 0x20U, + LDAP_SYNC_CAPI_DONE_FLAG = 0x40U, + + /* these are passed to ls_search_entry() */ + LDAP_SYNC_CAPI_PRESENT = LDAP_SYNC_PRESENT, + LDAP_SYNC_CAPI_ADD = LDAP_SYNC_ADD, + LDAP_SYNC_CAPI_MODIFY = LDAP_SYNC_MODIFY, + LDAP_SYNC_CAPI_DELETE = LDAP_SYNC_DELETE, + + /* these are passed to ls_intermediate() */ + LDAP_SYNC_CAPI_PRESENTS = ( LDAP_SYNC_CAPI_PHASE_FLAG | LDAP_SYNC_CAPI_PRESENT ), + LDAP_SYNC_CAPI_DELETES = ( LDAP_SYNC_CAPI_PHASE_FLAG | LDAP_SYNC_CAPI_DELETE ), + + LDAP_SYNC_CAPI_PRESENTS_IDSET = ( LDAP_SYNC_CAPI_PRESENTS | LDAP_SYNC_CAPI_IDSET_FLAG ), + LDAP_SYNC_CAPI_DELETES_IDSET = ( LDAP_SYNC_CAPI_DELETES | LDAP_SYNC_CAPI_IDSET_FLAG ), + + LDAP_SYNC_CAPI_DONE = ( LDAP_SYNC_CAPI_DONE_FLAG | LDAP_SYNC_CAPI_PRESENTS ) +} ldap_sync_refresh_t; + +/* + * Called when an entry is returned by ldap_result(). + * If phase is LDAP_SYNC_CAPI_ADD or LDAP_SYNC_CAPI_MODIFY, + * the entry has been either added or modified, and thus + * the complete view of the entry should be in the LDAPMessage. + * If phase is LDAP_SYNC_CAPI_PRESENT or LDAP_SYNC_CAPI_DELETE, + * only the DN should be in the LDAPMessage. + */ +typedef int (*ldap_sync_search_entry_f) LDAP_P(( + ldap_sync_t *ls, + LDAPMessage *msg, + struct berval *entryUUID, + ldap_sync_refresh_t phase )); + +/* + * Called when a reference is returned; the client should know + * what to do with it. + */ +typedef int (*ldap_sync_search_reference_f) LDAP_P(( + ldap_sync_t *ls, + LDAPMessage *msg )); + +/* + * Called when specific intermediate/final messages are returned. + * If phase is LDAP_SYNC_CAPI_PRESENTS or LDAP_SYNC_CAPI_DELETES, + * a "presents" or "deletes" phase begins. + * If phase is LDAP_SYNC_CAPI_DONE, a special "presents" phase + * with refreshDone set to "TRUE" has been returned, to indicate + * that the refresh phase of a refreshAndPersist is complete. + * In the above cases, syncUUIDs is NULL. + * + * If phase is LDAP_SYNC_CAPI_PRESENTS_IDSET or + * LDAP_SYNC_CAPI_DELETES_IDSET, syncUUIDs is an array of UUIDs + * that are either present or have been deleted. + */ +typedef int (*ldap_sync_intermediate_f) LDAP_P(( + ldap_sync_t *ls, + LDAPMessage *msg, + BerVarray syncUUIDs, + ldap_sync_refresh_t phase )); + +/* + * Called when a searchResultDone is returned. In refreshAndPersist, + * this can only occur if the search for any reason is being terminated + * by the server. + */ +typedef int (*ldap_sync_search_result_f) LDAP_P(( + ldap_sync_t *ls, + LDAPMessage *msg, + int refreshDeletes )); + +/* + * This structure contains all information about the persistent search; + * the caller is responsible for connecting, setting version, binding, tls... + */ +struct ldap_sync_t { + /* conf search params */ + char *ls_base; + int ls_scope; + char *ls_filter; + char **ls_attrs; + int ls_timelimit; + int ls_sizelimit; + + /* poll timeout */ + int ls_timeout; + + /* helpers - add as appropriate */ + ldap_sync_search_entry_f ls_search_entry; + ldap_sync_search_reference_f ls_search_reference; + ldap_sync_intermediate_f ls_intermediate; + ldap_sync_search_result_f ls_search_result; + + /* set by the caller as appropriate */ + void *ls_private; + + /* conn stuff */ + LDAP *ls_ld; + + /* --- the parameters below are private - do not modify --- */ + + /* FIXME: make the structure opaque, and provide an interface + * to modify the public values? */ + + /* result stuff */ + int ls_msgid; + + /* sync stuff */ + /* needed by refreshOnly */ + int ls_reloadHint; + + /* opaque - need to pass between sessions, updated by the API */ + struct berval ls_cookie; + + /* state variable - do not modify */ + ldap_sync_refresh_t ls_refreshPhase; +}; + +/* + * End of LDAP sync (RFC4533) API + */ + +/* + * Connection callbacks... + */ +struct ldap_conncb; +struct sockaddr; + +/* Called after a connection is established */ +typedef int (ldap_conn_add_f) LDAP_P(( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, struct sockaddr *addr, + struct ldap_conncb *ctx )); +/* Called before a connection is closed */ +typedef void (ldap_conn_del_f) LDAP_P(( LDAP *ld, Sockbuf *sb, struct ldap_conncb *ctx )); + +/* Callbacks are pushed on a stack. Last one pushed is first one executed. The + * delete callback is called with a NULL Sockbuf just before freeing the LDAP handle. + */ +typedef struct ldap_conncb { + ldap_conn_add_f *lc_add; + ldap_conn_del_f *lc_del; + void *lc_arg; +} ldap_conncb; + +/* + * The API draft spec says we should declare (or cause to be declared) + * 'struct timeval'. We don't. See IETF LDAPext discussions. + */ +struct timeval; + +/* + * in options.c: + */ +LDAP_F( int ) +ldap_get_option LDAP_P(( + LDAP *ld, + int option, + void *outvalue)); + +LDAP_F( int ) +ldap_set_option LDAP_P(( + LDAP *ld, + int option, + LDAP_CONST void *invalue)); + +/* V3 REBIND Function Callback Prototype */ +typedef int (LDAP_REBIND_PROC) LDAP_P(( + LDAP *ld, LDAP_CONST char *url, + ber_tag_t request, ber_int_t msgid, + void *params )); + +LDAP_F( int ) +ldap_set_rebind_proc LDAP_P(( + LDAP *ld, + LDAP_REBIND_PROC *rebind_proc, + void *params )); + +/* V3 referral selection Function Callback Prototype */ +typedef int (LDAP_NEXTREF_PROC) LDAP_P(( + LDAP *ld, char ***refsp, int *cntp, + void *params )); + +LDAP_F( int ) +ldap_set_nextref_proc LDAP_P(( + LDAP *ld, + LDAP_NEXTREF_PROC *nextref_proc, + void *params )); + +/* V3 URLLIST Function Callback Prototype */ +typedef int (LDAP_URLLIST_PROC) LDAP_P(( + LDAP *ld, + LDAPURLDesc **urllist, + LDAPURLDesc **url, + void *params )); + +LDAP_F( int ) +ldap_set_urllist_proc LDAP_P(( + LDAP *ld, + LDAP_URLLIST_PROC *urllist_proc, + void *params )); + +/* + * in controls.c: + */ +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_create_control LDAP_P(( /* deprecated, use ldap_control_create */ + LDAP_CONST char *requestOID, + BerElement *ber, + int iscritical, + LDAPControl **ctrlp )); + +LDAP_F( LDAPControl * ) +ldap_find_control LDAP_P(( /* deprecated, use ldap_control_find */ + LDAP_CONST char *oid, + LDAPControl **ctrls )); +#endif + +LDAP_F( int ) +ldap_control_create LDAP_P(( + LDAP_CONST char *requestOID, + int iscritical, + struct berval *value, + int dupval, + LDAPControl **ctrlp )); + +LDAP_F( LDAPControl * ) +ldap_control_find LDAP_P(( + LDAP_CONST char *oid, + LDAPControl **ctrls, + LDAPControl ***nextctrlp )); + +LDAP_F( void ) +ldap_control_free LDAP_P(( + LDAPControl *ctrl )); + +LDAP_F( void ) +ldap_controls_free LDAP_P(( + LDAPControl **ctrls )); + +LDAP_F( LDAPControl ** ) +ldap_controls_dup LDAP_P(( + LDAPControl *LDAP_CONST *controls )); + +LDAP_F( LDAPControl * ) +ldap_control_dup LDAP_P(( + LDAP_CONST LDAPControl *c )); + +/* + * in dnssrv.c: + */ +LDAP_F( int ) +ldap_domain2dn LDAP_P(( + LDAP_CONST char* domain, + char** dn )); + +LDAP_F( int ) +ldap_dn2domain LDAP_P(( + LDAP_CONST char* dn, + char** domain )); + +LDAP_F( int ) +ldap_domain2hostlist LDAP_P(( + LDAP_CONST char *domain, + char** hostlist )); + +/* + * in extended.c: + */ +LDAP_F( int ) +ldap_extended_operation LDAP_P(( + LDAP *ld, + LDAP_CONST char *reqoid, + struct berval *reqdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_extended_operation_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *reqoid, + struct berval *reqdata, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + char **retoidp, + struct berval **retdatap )); + +LDAP_F( int ) +ldap_parse_extended_result LDAP_P(( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + int freeit )); + +LDAP_F( int ) +ldap_parse_intermediate LDAP_P(( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + LDAPControl ***serverctrls, + int freeit )); + + +/* + * in abandon.c: + */ +LDAP_F( int ) +ldap_abandon_ext LDAP_P(( + LDAP *ld, + int msgid, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_abandon LDAP_P(( /* deprecated, use ldap_abandon_ext */ + LDAP *ld, + int msgid )); +#endif + +/* + * in add.c: + */ +LDAP_F( int ) +ldap_add_ext LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_add_ext_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_add LDAP_P(( /* deprecated, use ldap_add_ext */ + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs )); + +LDAP_F( int ) +ldap_add_s LDAP_P(( /* deprecated, use ldap_add_ext_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs )); +#endif + + +/* + * in sasl.c: + */ +LDAP_F( int ) +ldap_sasl_bind LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +/* Interaction flags (should be passed about in a control) + * Automatic (default): use defaults, prompt otherwise + * Interactive: prompt always + * Quiet: never prompt + */ +#define LDAP_SASL_AUTOMATIC 0U +#define LDAP_SASL_INTERACTIVE 1U +#define LDAP_SASL_QUIET 2U + +/* + * V3 SASL Interaction Function Callback Prototype + * when using Cyrus SASL, interact is pointer to sasl_interact_t + * should likely passed in a control (and provided controls) + */ +typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P(( + LDAP *ld, unsigned flags, void* defaults, void *interact )); + +LDAP_F( int ) +ldap_sasl_interactive_bind LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *saslMechanism, + LDAPControl **serverControls, + LDAPControl **clientControls, + + /* should be client controls */ + unsigned flags, + LDAP_SASL_INTERACT_PROC *proc, + void *defaults, + + /* as obtained from ldap_result() */ + LDAPMessage *result, + + /* returned during bind processing */ + const char **rmech, + int *msgid )); + +LDAP_F( int ) +ldap_sasl_interactive_bind_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *saslMechanism, + LDAPControl **serverControls, + LDAPControl **clientControls, + + /* should be client controls */ + unsigned flags, + LDAP_SASL_INTERACT_PROC *proc, + void *defaults )); + +LDAP_F( int ) +ldap_sasl_bind_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct berval **servercredp )); + +LDAP_F( int ) +ldap_parse_sasl_bind_result LDAP_P(( + LDAP *ld, + LDAPMessage *res, + struct berval **servercredp, + int freeit )); + +#if LDAP_DEPRECATED +/* + * in bind.c: + * (deprecated) + */ +LDAP_F( int ) +ldap_bind LDAP_P(( /* deprecated, use ldap_sasl_bind */ + LDAP *ld, + LDAP_CONST char *who, + LDAP_CONST char *passwd, + int authmethod )); + +LDAP_F( int ) +ldap_bind_s LDAP_P(( /* deprecated, use ldap_sasl_bind_s */ + LDAP *ld, + LDAP_CONST char *who, + LDAP_CONST char *cred, + int authmethod )); + +/* + * in sbind.c: + */ +LDAP_F( int ) +ldap_simple_bind LDAP_P(( /* deprecated, use ldap_sasl_bind */ + LDAP *ld, + LDAP_CONST char *who, + LDAP_CONST char *passwd )); + +LDAP_F( int ) +ldap_simple_bind_s LDAP_P(( /* deprecated, use ldap_sasl_bind_s */ + LDAP *ld, + LDAP_CONST char *who, + LDAP_CONST char *passwd )); + +#endif + + +/* + * in compare.c: + */ +LDAP_F( int ) +ldap_compare_ext LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + struct berval *bvalue, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_compare_ext_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + struct berval *bvalue, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_compare LDAP_P(( /* deprecated, use ldap_compare_ext */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + LDAP_CONST char *value )); + +LDAP_F( int ) +ldap_compare_s LDAP_P(( /* deprecated, use ldap_compare_ext_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + LDAP_CONST char *value )); +#endif + + +/* + * in delete.c: + */ +LDAP_F( int ) +ldap_delete_ext LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_delete_ext_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_delete LDAP_P(( /* deprecated, use ldap_delete_ext */ + LDAP *ld, + LDAP_CONST char *dn )); + +LDAP_F( int ) +ldap_delete_s LDAP_P(( /* deprecated, use ldap_delete_ext_s */ + LDAP *ld, + LDAP_CONST char *dn )); +#endif + + +/* + * in error.c: + */ +LDAP_F( int ) +ldap_parse_result LDAP_P(( + LDAP *ld, + LDAPMessage *res, + int *errcodep, + char **matcheddnp, + char **diagmsgp, + char ***referralsp, + LDAPControl ***serverctrls, + int freeit )); + +LDAP_F( char * ) +ldap_err2string LDAP_P(( + int err )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_result2error LDAP_P(( /* deprecated, use ldap_parse_result */ + LDAP *ld, + LDAPMessage *r, + int freeit )); + +LDAP_F( void ) +ldap_perror LDAP_P(( /* deprecated, use ldap_err2string */ + LDAP *ld, + LDAP_CONST char *s )); +#endif + + +/* + * in modify.c: + */ +LDAP_F( int ) +ldap_modify_ext LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_modify_ext_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_modify LDAP_P(( /* deprecated, use ldap_modify_ext */ + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods )); + +LDAP_F( int ) +ldap_modify_s LDAP_P(( /* deprecated, use ldap_modify_ext_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods )); +#endif + + +/* + * in modrdn.c: + */ +LDAP_F( int ) +ldap_rename LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_rename_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_rename2 LDAP_P(( /* deprecated, use ldap_rename */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn )); + +LDAP_F( int ) +ldap_rename2_s LDAP_P(( /* deprecated, use ldap_rename_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn )); + +LDAP_F( int ) +ldap_modrdn LDAP_P(( /* deprecated, use ldap_rename */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn )); + +LDAP_F( int ) +ldap_modrdn_s LDAP_P(( /* deprecated, use ldap_rename_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn )); + +LDAP_F( int ) +ldap_modrdn2 LDAP_P(( /* deprecated, use ldap_rename */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + int deleteoldrdn )); + +LDAP_F( int ) +ldap_modrdn2_s LDAP_P(( /* deprecated, use ldap_rename_s */ + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + int deleteoldrdn)); +#endif + + +/* + * in open.c: + */ +#if LDAP_DEPRECATED +LDAP_F( LDAP * ) +ldap_init LDAP_P(( /* deprecated, use ldap_create or ldap_initialize */ + LDAP_CONST char *host, + int port )); + +LDAP_F( LDAP * ) +ldap_open LDAP_P(( /* deprecated, use ldap_create or ldap_initialize */ + LDAP_CONST char *host, + int port )); +#endif + +LDAP_F( int ) +ldap_create LDAP_P(( + LDAP **ldp )); + +LDAP_F( int ) +ldap_initialize LDAP_P(( + LDAP **ldp, + LDAP_CONST char *url )); + +LDAP_F( LDAP * ) +ldap_dup LDAP_P(( + LDAP *old )); + +LDAP_F( int ) +ldap_connect( LDAP *ld ); + +/* + * in tls.c + */ + +LDAP_F( int ) +ldap_tls_inplace LDAP_P(( + LDAP *ld )); + +LDAP_F( int ) +ldap_start_tls LDAP_P(( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_install_tls LDAP_P(( + LDAP *ld )); + +LDAP_F( int ) +ldap_start_tls_s LDAP_P(( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls )); + +/* + * in messages.c: + */ +LDAP_F( LDAPMessage * ) +ldap_first_message LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +LDAP_F( LDAPMessage * ) +ldap_next_message LDAP_P(( + LDAP *ld, + LDAPMessage *msg )); + +LDAP_F( int ) +ldap_count_messages LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +/* + * in references.c: + */ +LDAP_F( LDAPMessage * ) +ldap_first_reference LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +LDAP_F( LDAPMessage * ) +ldap_next_reference LDAP_P(( + LDAP *ld, + LDAPMessage *ref )); + +LDAP_F( int ) +ldap_count_references LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +LDAP_F( int ) +ldap_parse_reference LDAP_P(( + LDAP *ld, + LDAPMessage *ref, + char ***referralsp, + LDAPControl ***serverctrls, + int freeit)); + + +/* + * in getentry.c: + */ +LDAP_F( LDAPMessage * ) +ldap_first_entry LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +LDAP_F( LDAPMessage * ) +ldap_next_entry LDAP_P(( + LDAP *ld, + LDAPMessage *entry )); + +LDAP_F( int ) +ldap_count_entries LDAP_P(( + LDAP *ld, + LDAPMessage *chain )); + +LDAP_F( int ) +ldap_get_entry_controls LDAP_P(( + LDAP *ld, + LDAPMessage *entry, + LDAPControl ***serverctrls)); + + +/* + * in addentry.c + */ +LDAP_F( LDAPMessage * ) +ldap_delete_result_entry LDAP_P(( + LDAPMessage **list, + LDAPMessage *e )); + +LDAP_F( void ) +ldap_add_result_entry LDAP_P(( + LDAPMessage **list, + LDAPMessage *e )); + + +/* + * in getdn.c + */ +LDAP_F( char * ) +ldap_get_dn LDAP_P(( + LDAP *ld, + LDAPMessage *entry )); + +typedef struct ldap_ava { + struct berval la_attr; + struct berval la_value; + unsigned la_flags; +#define LDAP_AVA_NULL 0x0000U +#define LDAP_AVA_STRING 0x0001U +#define LDAP_AVA_BINARY 0x0002U +#define LDAP_AVA_NONPRINTABLE 0x0004U +#define LDAP_AVA_FREE_ATTR 0x0010U +#define LDAP_AVA_FREE_VALUE 0x0020U + + void *la_private; +} LDAPAVA; + +typedef LDAPAVA** LDAPRDN; +typedef LDAPRDN* LDAPDN; + +/* DN formats */ +#define LDAP_DN_FORMAT_LDAP 0x0000U +#define LDAP_DN_FORMAT_LDAPV3 0x0010U +#define LDAP_DN_FORMAT_LDAPV2 0x0020U +#define LDAP_DN_FORMAT_DCE 0x0030U +#define LDAP_DN_FORMAT_UFN 0x0040U /* dn2str only */ +#define LDAP_DN_FORMAT_AD_CANONICAL 0x0050U /* dn2str only */ +#define LDAP_DN_FORMAT_LBER 0x00F0U /* for testing only */ +#define LDAP_DN_FORMAT_MASK 0x00F0U + +/* DN flags */ +#define LDAP_DN_PRETTY 0x0100U +#define LDAP_DN_SKIP 0x0200U +#define LDAP_DN_P_NOLEADTRAILSPACES 0x1000U +#define LDAP_DN_P_NOSPACEAFTERRDN 0x2000U +#define LDAP_DN_PEDANTIC 0xF000U + +LDAP_F( void ) ldap_rdnfree LDAP_P(( LDAPRDN rdn )); +LDAP_F( void ) ldap_dnfree LDAP_P(( LDAPDN dn )); + +LDAP_F( int ) +ldap_bv2dn LDAP_P(( + struct berval *bv, + LDAPDN *dn, + unsigned flags )); + +LDAP_F( int ) +ldap_str2dn LDAP_P(( + LDAP_CONST char *str, + LDAPDN *dn, + unsigned flags )); + +LDAP_F( int ) +ldap_dn2bv LDAP_P(( + LDAPDN dn, + struct berval *bv, + unsigned flags )); + +LDAP_F( int ) +ldap_dn2str LDAP_P(( + LDAPDN dn, + char **str, + unsigned flags )); + +LDAP_F( int ) +ldap_bv2rdn LDAP_P(( + struct berval *bv, + LDAPRDN *rdn, + char **next, + unsigned flags )); + +LDAP_F( int ) +ldap_str2rdn LDAP_P(( + LDAP_CONST char *str, + LDAPRDN *rdn, + char **next, + unsigned flags )); + +LDAP_F( int ) +ldap_rdn2bv LDAP_P(( + LDAPRDN rdn, + struct berval *bv, + unsigned flags )); + +LDAP_F( int ) +ldap_rdn2str LDAP_P(( + LDAPRDN rdn, + char **str, + unsigned flags )); + +LDAP_F( int ) +ldap_dn_normalize LDAP_P(( + LDAP_CONST char *in, unsigned iflags, + char **out, unsigned oflags )); + +LDAP_F( char * ) +ldap_dn2ufn LDAP_P(( /* deprecated, use ldap_str2dn/dn2str */ + LDAP_CONST char *dn )); + +LDAP_F( char ** ) +ldap_explode_dn LDAP_P(( /* deprecated, ldap_str2dn */ + LDAP_CONST char *dn, + int notypes )); + +LDAP_F( char ** ) +ldap_explode_rdn LDAP_P(( /* deprecated, ldap_str2rdn */ + LDAP_CONST char *rdn, + int notypes )); + +typedef int LDAPDN_rewrite_func + LDAP_P(( LDAPDN dn, unsigned flags, void *ctx )); + +LDAP_F( int ) +ldap_X509dn2bv LDAP_P(( void *x509_name, struct berval *dn, + LDAPDN_rewrite_func *func, unsigned flags )); + +LDAP_F( char * ) +ldap_dn2dcedn LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ + LDAP_CONST char *dn )); + +LDAP_F( char * ) +ldap_dcedn2dn LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ + LDAP_CONST char *dce )); + +LDAP_F( char * ) +ldap_dn2ad_canonical LDAP_P(( /* deprecated, ldap_str2dn/dn2str */ + LDAP_CONST char *dn )); + +LDAP_F( int ) +ldap_get_dn_ber LDAP_P(( + LDAP *ld, LDAPMessage *e, BerElement **berout, struct berval *dn )); + +LDAP_F( int ) +ldap_get_attribute_ber LDAP_P(( + LDAP *ld, LDAPMessage *e, BerElement *ber, struct berval *attr, + struct berval **vals )); + +/* + * in getattr.c + */ +LDAP_F( char * ) +ldap_first_attribute LDAP_P(( + LDAP *ld, + LDAPMessage *entry, + BerElement **ber )); + +LDAP_F( char * ) +ldap_next_attribute LDAP_P(( + LDAP *ld, + LDAPMessage *entry, + BerElement *ber )); + + +/* + * in getvalues.c + */ +LDAP_F( struct berval ** ) +ldap_get_values_len LDAP_P(( + LDAP *ld, + LDAPMessage *entry, + LDAP_CONST char *target )); + +LDAP_F( int ) +ldap_count_values_len LDAP_P(( + struct berval **vals )); + +LDAP_F( void ) +ldap_value_free_len LDAP_P(( + struct berval **vals )); + +#if LDAP_DEPRECATED +LDAP_F( char ** ) +ldap_get_values LDAP_P(( /* deprecated, use ldap_get_values_len */ + LDAP *ld, + LDAPMessage *entry, + LDAP_CONST char *target )); + +LDAP_F( int ) +ldap_count_values LDAP_P(( /* deprecated, use ldap_count_values_len */ + char **vals )); + +LDAP_F( void ) +ldap_value_free LDAP_P(( /* deprecated, use ldap_value_free_len */ + char **vals )); +#endif + +/* + * in result.c: + */ +LDAP_F( int ) +ldap_result LDAP_P(( + LDAP *ld, + int msgid, + int all, + struct timeval *timeout, + LDAPMessage **result )); + +LDAP_F( int ) +ldap_msgtype LDAP_P(( + LDAPMessage *lm )); + +LDAP_F( int ) +ldap_msgid LDAP_P(( + LDAPMessage *lm )); + +LDAP_F( int ) +ldap_msgfree LDAP_P(( + LDAPMessage *lm )); + +LDAP_F( int ) +ldap_msgdelete LDAP_P(( + LDAP *ld, + int msgid )); + + +/* + * in search.c: + */ +LDAP_F( int ) +ldap_bv2escaped_filter_value LDAP_P(( + struct berval *in, + struct berval *out )); + +LDAP_F( int ) +ldap_search_ext LDAP_P(( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct timeval *timeout, + int sizelimit, + int *msgidp )); + +LDAP_F( int ) +ldap_search_ext_s LDAP_P(( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + struct timeval *timeout, + int sizelimit, + LDAPMessage **res )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_search LDAP_P(( /* deprecated, use ldap_search_ext */ + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly )); + +LDAP_F( int ) +ldap_search_s LDAP_P(( /* deprecated, use ldap_search_ext_s */ + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res )); + +LDAP_F( int ) +ldap_search_st LDAP_P(( /* deprecated, use ldap_search_ext_s */ + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + struct timeval *timeout, + LDAPMessage **res )); +#endif + +/* + * in unbind.c + */ +LDAP_F( int ) +ldap_unbind_ext LDAP_P(( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls)); + +LDAP_F( int ) +ldap_unbind_ext_s LDAP_P(( + LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls)); + +LDAP_F( int ) +ldap_destroy LDAP_P(( + LDAP *ld)); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_unbind LDAP_P(( /* deprecated, use ldap_unbind_ext */ + LDAP *ld )); + +LDAP_F( int ) +ldap_unbind_s LDAP_P(( /* deprecated, use ldap_unbind_ext_s */ + LDAP *ld )); +#endif + +/* + * in filter.c + */ +LDAP_F( int ) +ldap_put_vrFilter LDAP_P(( + BerElement *ber, + const char *vrf )); + +/* + * in free.c + */ + +LDAP_F( void * ) +ldap_memalloc LDAP_P(( + ber_len_t s )); + +LDAP_F( void * ) +ldap_memrealloc LDAP_P(( + void* p, + ber_len_t s )); + +LDAP_F( void * ) +ldap_memcalloc LDAP_P(( + ber_len_t n, + ber_len_t s )); + +LDAP_F( void ) +ldap_memfree LDAP_P(( + void* p )); + +LDAP_F( void ) +ldap_memvfree LDAP_P(( + void** v )); + +LDAP_F( char * ) +ldap_strdup LDAP_P(( + LDAP_CONST char * )); + +LDAP_F( void ) +ldap_mods_free LDAP_P(( + LDAPMod **mods, + int freemods )); + + +#if LDAP_DEPRECATED +/* + * in sort.c (deprecated, use custom code instead) + */ +typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */ + LDAP_CONST char *left, + LDAP_CONST char *right )); + +typedef int (LDAP_SORT_AV_CMP_PROC) LDAP_P(( /* deprecated */ + LDAP_CONST void *left, + LDAP_CONST void *right )); + +LDAP_F( int ) /* deprecated */ +ldap_sort_entries LDAP_P(( LDAP *ld, + LDAPMessage **chain, + LDAP_CONST char *attr, + LDAP_SORT_AD_CMP_PROC *cmp )); + +LDAP_F( int ) /* deprecated */ +ldap_sort_values LDAP_P(( + LDAP *ld, + char **vals, + LDAP_SORT_AV_CMP_PROC *cmp )); + +LDAP_F( int ) /* deprecated */ +ldap_sort_strcasecmp LDAP_P(( + LDAP_CONST void *a, + LDAP_CONST void *b )); +#endif + +/* + * in url.c + */ +LDAP_F( int ) +ldap_is_ldap_url LDAP_P(( + LDAP_CONST char *url )); + +LDAP_F( int ) +ldap_is_ldaps_url LDAP_P(( + LDAP_CONST char *url )); + +LDAP_F( int ) +ldap_is_ldapi_url LDAP_P(( + LDAP_CONST char *url )); + +#ifdef LDAP_CONNECTIONLESS +LDAP_F( int ) +ldap_is_ldapc_url LDAP_P(( + LDAP_CONST char *url )); +#endif + +LDAP_F( int ) +ldap_url_parse LDAP_P(( + LDAP_CONST char *url, + LDAPURLDesc **ludpp )); + +LDAP_F( char * ) +ldap_url_desc2str LDAP_P(( + LDAPURLDesc *ludp )); + +LDAP_F( void ) +ldap_free_urldesc LDAP_P(( + LDAPURLDesc *ludp )); + + +/* + * LDAP Cancel Extended Operation <draft-zeilenga-ldap-cancel-xx.txt> + * in cancel.c + */ +#define LDAP_API_FEATURE_CANCEL 1000 + +LDAP_F( int ) +ldap_cancel LDAP_P(( LDAP *ld, + int cancelid, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_cancel_s LDAP_P(( LDAP *ld, + int cancelid, + LDAPControl **sctrl, + LDAPControl **cctrl )); + +/* + * LDAP Turn Extended Operation <draft-zeilenga-ldap-turn-xx.txt> + * in turn.c + */ +#define LDAP_API_FEATURE_TURN 1000 + +LDAP_F( int ) +ldap_turn LDAP_P(( LDAP *ld, + int mutual, + LDAP_CONST char* identifier, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_turn_s LDAP_P(( LDAP *ld, + int mutual, + LDAP_CONST char* identifier, + LDAPControl **sctrl, + LDAPControl **cctrl )); + +/* + * LDAP Paged Results + * in pagectrl.c + */ +#define LDAP_API_FEATURE_PAGED_RESULTS 2000 + +LDAP_F( int ) +ldap_create_page_control_value LDAP_P(( + LDAP *ld, + ber_int_t pagesize, + struct berval *cookie, + struct berval *value )); + +LDAP_F( int ) +ldap_create_page_control LDAP_P(( + LDAP *ld, + ber_int_t pagesize, + struct berval *cookie, + int iscritical, + LDAPControl **ctrlp )); + +#if LDAP_DEPRECATED +LDAP_F( int ) +ldap_parse_page_control LDAP_P(( + /* deprecated, use ldap_parse_pageresponse_control */ + LDAP *ld, + LDAPControl **ctrls, + ber_int_t *count, + struct berval **cookie )); +#endif + +LDAP_F( int ) +ldap_parse_pageresponse_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *count, + struct berval *cookie )); + +/* + * LDAP Server Side Sort + * in sortctrl.c + */ +#define LDAP_API_FEATURE_SERVER_SIDE_SORT 2000 + +/* structure for a sort-key */ +typedef struct ldapsortkey { + char *attributeType; + char *orderingRule; + int reverseOrder; +} LDAPSortKey; + +LDAP_F( int ) +ldap_create_sort_keylist LDAP_P(( + LDAPSortKey ***sortKeyList, + char *keyString )); + +LDAP_F( void ) +ldap_free_sort_keylist LDAP_P(( + LDAPSortKey **sortkeylist )); + +LDAP_F( int ) +ldap_create_sort_control_value LDAP_P(( + LDAP *ld, + LDAPSortKey **keyList, + struct berval *value )); + +LDAP_F( int ) +ldap_create_sort_control LDAP_P(( + LDAP *ld, + LDAPSortKey **keyList, + int iscritical, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_sortresponse_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *result, + char **attribute )); + +/* + * LDAP Virtual List View + * in vlvctrl.c + */ +#define LDAP_API_FEATURE_VIRTUAL_LIST_VIEW 2000 + +/* structure for virtual list */ +typedef struct ldapvlvinfo { + ber_int_t ldvlv_version; + ber_int_t ldvlv_before_count; + ber_int_t ldvlv_after_count; + ber_int_t ldvlv_offset; + ber_int_t ldvlv_count; + struct berval * ldvlv_attrvalue; + struct berval * ldvlv_context; + void * ldvlv_extradata; +} LDAPVLVInfo; + +LDAP_F( int ) +ldap_create_vlv_control_value LDAP_P(( + LDAP *ld, + LDAPVLVInfo *ldvlistp, + struct berval *value)); + +LDAP_F( int ) +ldap_create_vlv_control LDAP_P(( + LDAP *ld, + LDAPVLVInfo *ldvlistp, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_vlvresponse_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrls, + ber_int_t *target_posp, + ber_int_t *list_countp, + struct berval **contextp, + int *errcodep )); + +/* + * LDAP Verify Credentials + */ +#define LDAP_API_FEATURE_VERIFY_CREDENTIALS 1000 + +LDAP_F( int ) +ldap_verify_credentials LDAP_P(( + LDAP *ld, + struct berval *cookie, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **ctrls, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_verify_credentials_s LDAP_P(( + LDAP *ld, + struct berval *cookie, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **vcictrls, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *code, + char **diagmsgp, + struct berval **scookie, + struct berval **servercredp, + LDAPControl ***vcoctrls)); + + +LDAP_F( int ) +ldap_parse_verify_credentials LDAP_P(( + LDAP *ld, + LDAPMessage *res, + int *code, + char **diagmsgp, + struct berval **cookie, + struct berval **servercredp, + LDAPControl ***vcctrls)); + +/* not yet implemented */ +/* #define LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE 1000 */ +#ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE +LDAP_F( int ) +ldap_verify_credentials_interactive LDAP_P(( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *saslMechanism, + LDAPControl **vcControls, + LDAPControl **serverControls, + LDAPControl **clientControls, + + /* should be client controls */ + unsigned flags, + LDAP_SASL_INTERACT_PROC *proc, + void *defaults, + void *context, + + /* as obtained from ldap_result() */ + LDAPMessage *result, + + /* returned during bind processing */ + const char **rmech, + int *msgid )); +#endif + +/* + * LDAP Who Am I? + * in whoami.c + */ +#define LDAP_API_FEATURE_WHOAMI 1000 + +LDAP_F( int ) +ldap_parse_whoami LDAP_P(( + LDAP *ld, + LDAPMessage *res, + struct berval **authzid )); + +LDAP_F( int ) +ldap_whoami LDAP_P(( LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_whoami_s LDAP_P(( + LDAP *ld, + struct berval **authzid, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +/* + * LDAP Password Modify + * in passwd.c + */ +#define LDAP_API_FEATURE_PASSWD_MODIFY 1000 + +LDAP_F( int ) +ldap_parse_passwd LDAP_P(( + LDAP *ld, + LDAPMessage *res, + struct berval *newpasswd )); + +LDAP_F( int ) +ldap_passwd LDAP_P(( LDAP *ld, + struct berval *user, + struct berval *oldpw, + struct berval *newpw, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_passwd_s LDAP_P(( + LDAP *ld, + struct berval *user, + struct berval *oldpw, + struct berval *newpw, + struct berval *newpasswd, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST +/* + * LDAP Password Policy controls + * in ppolicy.c + */ +#define LDAP_API_FEATURE_PASSWORD_POLICY 1000 + +typedef enum passpolicyerror_enum { + PP_passwordExpired = 0, + PP_accountLocked = 1, + PP_changeAfterReset = 2, + PP_passwordModNotAllowed = 3, + PP_mustSupplyOldPassword = 4, + PP_insufficientPasswordQuality = 5, + PP_passwordTooShort = 6, + PP_passwordTooYoung = 7, + PP_passwordInHistory = 8, + PP_passwordTooLong = 9, + PP_noError = 65535 +} LDAPPasswordPolicyError; + +LDAP_F( int ) +ldap_create_passwordpolicy_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_passwordpolicy_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *expirep, + ber_int_t *gracep, + LDAPPasswordPolicyError *errorp )); + +LDAP_F( const char * ) +ldap_passwordpolicy_err2txt LDAP_P(( LDAPPasswordPolicyError )); +#endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ + +LDAP_F( int ) +ldap_parse_password_expiring_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + long *secondsp )); + +/* + * LDAP Dynamic Directory Services Refresh -- RFC 2589 + * in dds.c + */ +#define LDAP_API_FEATURE_REFRESH 1000 + +LDAP_F( int ) +ldap_parse_refresh LDAP_P(( + LDAP *ld, + LDAPMessage *res, + ber_int_t *newttl )); + +LDAP_F( int ) +ldap_refresh LDAP_P(( LDAP *ld, + struct berval *dn, + ber_int_t ttl, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_refresh_s LDAP_P(( + LDAP *ld, + struct berval *dn, + ber_int_t ttl, + ber_int_t *newttl, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +/* + * LDAP Transactions + */ +LDAP_F( int ) +ldap_txn_start LDAP_P(( LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_txn_start_s LDAP_P(( LDAP *ld, + LDAPControl **sctrl, + LDAPControl **cctrl, + struct berval **rettxnid )); + +LDAP_F( int ) +ldap_txn_end LDAP_P(( LDAP *ld, + int commit, + struct berval *txnid, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp )); + +LDAP_F( int ) +ldap_txn_end_s LDAP_P(( LDAP *ld, + int commit, + struct berval *txnid, + LDAPControl **sctrl, + LDAPControl **cctrl, + int *retidp )); + +/* + * in ldap_sync.c + */ + +/* + * initialize the persistent search structure + */ +LDAP_F( ldap_sync_t * ) +ldap_sync_initialize LDAP_P(( + ldap_sync_t *ls )); + +/* + * destroy the persistent search structure + */ +LDAP_F( void ) +ldap_sync_destroy LDAP_P(( + ldap_sync_t *ls, + int freeit )); + +/* + * initialize a refreshOnly sync + */ +LDAP_F( int ) +ldap_sync_init LDAP_P(( + ldap_sync_t *ls, + int mode )); + +/* + * initialize a refreshOnly sync + */ +LDAP_F( int ) +ldap_sync_init_refresh_only LDAP_P(( + ldap_sync_t *ls )); + +/* + * initialize a refreshAndPersist sync + */ +LDAP_F( int ) +ldap_sync_init_refresh_and_persist LDAP_P(( + ldap_sync_t *ls )); + +/* + * poll for new responses + */ +LDAP_F( int ) +ldap_sync_poll LDAP_P(( + ldap_sync_t *ls )); + +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + +/* + * in stctrl.c + */ +LDAP_F( int ) +ldap_create_session_tracking_value LDAP_P(( + LDAP *ld, + char *sessionSourceIp, + char *sessionSourceName, + char *formatOID, + struct berval *sessionTrackingIdentifier, + struct berval *value )); + +LDAP_F( int ) +ldap_create_session_tracking_control LDAP_P(( + LDAP *ld, + char *sessionSourceIp, + char *sessionSourceName, + char *formatOID, + struct berval *sessionTrackingIdentifier, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_session_tracking_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + struct berval *ip, + struct berval *name, + struct berval *oid, + struct berval *id )); + +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ + +/* + * in msctrl.c + */ +#ifdef LDAP_CONTROL_X_DIRSYNC +LDAP_F( int ) +ldap_create_dirsync_value LDAP_P(( + LDAP *ld, + int flags, + int maxAttrCount, + struct berval *cookie, + struct berval *value )); + +LDAP_F( int ) +ldap_create_dirsync_control LDAP_P(( + LDAP *ld, + int flags, + int maxAttrCount, + struct berval *cookie, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_dirsync_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + int *continueFlag, + struct berval *cookie )); +#endif /* LDAP_CONTROL_X_DIRSYNC */ + +#ifdef LDAP_CONTROL_X_EXTENDED_DN +LDAP_F( int ) +ldap_create_extended_dn_value LDAP_P(( + LDAP *ld, + int flag, + struct berval *value )); + +LDAP_F( int ) +ldap_create_extended_dn_control LDAP_P(( + LDAP *ld, + int flag, + LDAPControl **ctrlp )); +#endif /* LDAP_CONTROL_X_EXTENDED_DN */ + +#ifdef LDAP_CONTROL_X_SHOW_DELETED +LDAP_F( int ) +ldap_create_show_deleted_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp )); +#endif /* LDAP_CONTROL_X_SHOW_DELETED */ + +#ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION +LDAP_F( int ) +ldap_create_server_notification_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp )); +#endif /* LDAP_CONTROL_X_SERVER_NOTIFICATION */ + +/* + * in assertion.c + */ +LDAP_F (int) +ldap_create_assertion_control_value LDAP_P(( + LDAP *ld, + char *assertion, + struct berval *value )); + +LDAP_F( int ) +ldap_create_assertion_control LDAP_P(( + LDAP *ld, + char *filter, + int iscritical, + LDAPControl **ctrlp )); + +/* + * in deref.c + */ + +typedef struct LDAPDerefSpec { + char *derefAttr; + char **attributes; +} LDAPDerefSpec; + +typedef struct LDAPDerefVal { + char *type; + BerVarray vals; + struct LDAPDerefVal *next; +} LDAPDerefVal; + +typedef struct LDAPDerefRes { + char *derefAttr; + struct berval derefVal; + LDAPDerefVal *attrVals; + struct LDAPDerefRes *next; +} LDAPDerefRes; + +LDAP_F( int ) +ldap_create_deref_control_value LDAP_P(( + LDAP *ld, + LDAPDerefSpec *ds, + struct berval *value )); + +LDAP_F( int ) +ldap_create_deref_control LDAP_P(( + LDAP *ld, + LDAPDerefSpec *ds, + int iscritical, + LDAPControl **ctrlp )); + +LDAP_F( void ) +ldap_derefresponse_free LDAP_P(( + LDAPDerefRes *dr )); + +LDAP_F( int ) +ldap_parse_derefresponse_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + LDAPDerefRes **drp )); + +LDAP_F( int ) +ldap_parse_deref_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrls, + LDAPDerefRes **drp )); + +/* + * in psearch.c + */ + +LDAP_F( int ) +ldap_create_persistentsearch_control_value LDAP_P(( + LDAP *ld, + int changetypes, + int changesonly, + int return_echg_ctls, + struct berval *value )); + +LDAP_F( int ) +ldap_create_persistentsearch_control LDAP_P(( + LDAP *ld, + int changetypes, + int changesonly, + int return_echg_ctls, + int isCritical, + LDAPControl **ctrlp )); + +LDAP_F( int ) +ldap_parse_entrychange_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + int *chgtypep, + struct berval *prevdnp, + int *chgnumpresentp, + long *chgnump )); + +/* in account_usability.c */ + +LDAP_F( int ) +ldap_create_accountusability_control LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp )); + +typedef struct LDAPAccountUsabilityMoreInfo { + ber_int_t inactive; + ber_int_t reset; + ber_int_t expired; + ber_int_t remaining_grace; + ber_int_t seconds_before_unlock; +} LDAPAccountUsabilityMoreInfo; + +typedef union LDAPAccountUsability { + ber_int_t seconds_remaining; + LDAPAccountUsabilityMoreInfo more_info; +} LDAPAccountUsability; + +LDAP_F( int ) +ldap_parse_accountusability_control LDAP_P(( + LDAP *ld, + LDAPControl *ctrl, + int *availablep, + LDAPAccountUsability *usabilityp )); + + +/* + * high level LDIF to LDAP structure support + */ +#define LDIF_DEFAULT_ADD 0x01 /* if changetype missing, assume LDAP_ADD */ +#define LDIF_ENTRIES_ONLY 0x02 /* ignore changetypes other than add */ +#define LDIF_NO_CONTROLS 0x04 /* ignore control specifications */ +#define LDIF_MODS_ONLY 0x08 /* no changetypes, assume LDAP_MODIFY */ +#define LDIF_NO_DN 0x10 /* dn is not present */ + +typedef struct ldifrecord { + ber_tag_t lr_op; /* type of operation - LDAP_REQ_MODIFY, LDAP_REQ_ADD, etc. */ + struct berval lr_dn; /* DN of operation */ + LDAPControl **lr_ctrls; /* controls specified for operation */ + /* some ops such as LDAP_REQ_DELETE require only a DN */ + /* other ops require different data - the ldif_ops union + is used to specify the data for each type of operation */ + union ldif_ops_u { + LDAPMod **lr_mods; /* list of mods for LDAP_REQ_MODIFY, LDAP_REQ_ADD */ +#define lrop_mods ldif_ops.lr_mods + struct ldif_op_rename_s { + struct berval lr_newrdn; /* LDAP_REQ_MODDN, LDAP_REQ_MODRDN, LDAP_REQ_RENAME */ +#define lrop_newrdn ldif_ops.ldif_op_rename.lr_newrdn + struct berval lr_newsuperior; /* LDAP_REQ_MODDN, LDAP_REQ_MODRDN, LDAP_REQ_RENAME */ +#define lrop_newsup ldif_ops.ldif_op_rename.lr_newsuperior + int lr_deleteoldrdn; /* LDAP_REQ_MODDN, LDAP_REQ_MODRDN, LDAP_REQ_RENAME */ +#define lrop_delold ldif_ops.ldif_op_rename.lr_deleteoldrdn + } ldif_op_rename; /* rename/moddn/modrdn */ + /* the following are for future support */ + struct ldif_op_ext_s { + struct berval lr_extop_oid; /* LDAP_REQ_EXTENDED */ +#define lrop_extop_oid ldif_ops.ldif_op_ext.lr_extop_oid + struct berval lr_extop_data; /* LDAP_REQ_EXTENDED */ +#define lrop_extop_data ldif_ops.ldif_op_ext.lr_extop_data + } ldif_op_ext; /* extended operation */ + struct ldif_op_cmp_s { + struct berval lr_cmp_attr; /* LDAP_REQ_COMPARE */ +#define lrop_cmp_attr ldif_ops.ldif_op_cmp.lr_cmp_attr + struct berval lr_cmp_bvalue; /* LDAP_REQ_COMPARE */ +#define lrop_cmp_bval ldif_ops.ldif_op_cmp.lr_cmp_bvalue + } ldif_op_cmp; /* compare operation */ + } ldif_ops; + /* PRIVATE STUFF - DO NOT TOUCH */ + /* for efficiency, the implementation allocates memory */ + /* in large blobs, and makes the above fields point to */ + /* locations inside those blobs - one consequence is that */ + /* you cannot simply free the above allocated fields, nor */ + /* assign them to be owned by another memory context which */ + /* might free them (unless providing your own mem ctx) */ + /* we use the fields below to keep track of those blobs */ + /* so we that we can free them later */ + void *lr_ctx; /* the memory context or NULL */ + int lr_lines; + LDAPMod *lr_lm; + unsigned char *lr_mops; + char *lr_freeval; + struct berval *lr_vals; + struct berval *lr_btype; +} LDIFRecord; + +/* free internal fields - does not free the LDIFRecord */ +LDAP_F( void ) +ldap_ldif_record_done LDAP_P(( + LDIFRecord *lr )); + +LDAP_F( int ) +ldap_parse_ldif_record LDAP_P(( + struct berval *rbuf, + unsigned long linenum, + LDIFRecord *lr, + const char *errstr, + unsigned int flags )); + +LDAP_END_DECL +#endif /* _LDAP_H */ diff --git a/libs/ldap/include/ldap_avl.h b/libs/ldap/include/ldap_avl.h new file mode 100644 index 00000000000..4bb1c397801 --- /dev/null +++ b/libs/ldap/include/ldap_avl.h @@ -0,0 +1,165 @@ +/* ldap_avl.h - avl tree definitions */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1993 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. + */ + + +#ifndef _AVL +#define _AVL + +#include <ldap_cdefs.h> + +/* + * this structure represents a generic avl tree node. + */ + +LDAP_BEGIN_DECL + +typedef struct avlnode Avlnode; + +struct avlnode { + void* avl_data; + struct avlnode *avl_link[2]; + char avl_bits[2]; + signed char avl_bf; +}; + +#define avl_left avl_link[0] +#define avl_right avl_link[1] +#define avl_lbit avl_bits[0] +#define avl_rbit avl_bits[1] + +typedef struct tavlnode TAvlnode; + +struct tavlnode { + void* avl_data; + struct tavlnode *avl_link[2]; + char avl_bits[2]; + signed char avl_bf; +}; + +#ifdef AVL_INTERNAL + +/* balance factor values */ +#define LH (-1) +#define EH 0 +#define RH 1 + +#define avl_bf2str(bf) ((bf) == -1 ? "LH" : (bf) == 0 ? "EH" : (bf) == 1 ? "RH" : "(unknown)" ) + +/* thread bits */ +#define AVL_CHILD 0 +#define AVL_THREAD 1 + +/* avl routines */ +#define ldap_avl_getone(x) ((x) == 0 ? 0 : (x)->avl_data) +#define ldap_avl_onenode(x) ((x) == 0 || ((x)->avl_left == 0 && (x)->avl_right == 0)) + +#endif /* AVL_INTERNALS */ + +#define ldap_avl_child(x,dir) ((x)->avl_bits[dir]) == AVL_CHILD ? \ + (x)->avl_link[dir] : NULL +#define ldap_avl_lchild(x) ldap_avl_child(x,0) +#define ldap_avl_rchild(x) ldap_avl_child(x,1) + +typedef int (*AVL_APPLY) LDAP_P((void *, void*)); +typedef int (*AVL_CMP) LDAP_P((const void*, const void*)); +typedef int (*AVL_DUP) LDAP_P((void*, void*)); +typedef void (*AVL_FREE) LDAP_P((void*)); + +LDAP_AVL_F( int ) +ldap_avl_free LDAP_P(( Avlnode *root, AVL_FREE dfree )); + +LDAP_AVL_F( int ) +ldap_avl_insert LDAP_P((Avlnode **, void*, AVL_CMP, AVL_DUP)); + +LDAP_AVL_F( void* ) +ldap_avl_delete LDAP_P((Avlnode **, void*, AVL_CMP)); + +LDAP_AVL_F( void* ) +ldap_avl_find LDAP_P((Avlnode *, const void*, AVL_CMP)); + +LDAP_AVL_F( Avlnode* ) +ldap_avl_find2 LDAP_P((Avlnode *, const void*, AVL_CMP)); + +LDAP_AVL_F( void* ) +ldap_avl_find_lin LDAP_P((Avlnode *, const void*, AVL_CMP)); + +#ifdef AVL_NONREENTRANT +LDAP_AVL_F( void* ) +ldap_avl_getfirst LDAP_P((Avlnode *)); + +LDAP_AVL_F( void* ) +ldap_avl_getnext LDAP_P((void)); +#endif + +LDAP_AVL_F( int ) +ldap_avl_dup_error LDAP_P((void*, void*)); + +LDAP_AVL_F( int ) +ldap_avl_dup_ok LDAP_P((void*, void*)); + +LDAP_AVL_F( int ) +ldap_avl_apply LDAP_P((Avlnode *, AVL_APPLY, void*, int, int)); + +LDAP_AVL_F( int ) +ldap_avl_prefixapply LDAP_P((Avlnode *, void*, AVL_CMP, void*, AVL_CMP, void*, int)); + +LDAP_AVL_F( int ) +ldap_tavl_free LDAP_P(( TAvlnode *root, AVL_FREE dfree )); + +LDAP_AVL_F( int ) +ldap_tavl_insert LDAP_P((TAvlnode **, void*, AVL_CMP, AVL_DUP)); + +LDAP_AVL_F( void* ) +ldap_tavl_delete LDAP_P((TAvlnode **, void*, AVL_CMP)); + +LDAP_AVL_F( void* ) +ldap_tavl_find LDAP_P((TAvlnode *, const void*, AVL_CMP)); + +LDAP_AVL_F( TAvlnode* ) +ldap_tavl_find2 LDAP_P((TAvlnode *, const void*, AVL_CMP)); + +LDAP_AVL_F( TAvlnode* ) +ldap_tavl_find3 LDAP_P((TAvlnode *, const void*, AVL_CMP, int *ret)); + +#define TAVL_DIR_LEFT 0 +#define TAVL_DIR_RIGHT 1 + +LDAP_AVL_F( TAvlnode* ) +ldap_tavl_end LDAP_P((TAvlnode *, int direction)); + +LDAP_AVL_F( TAvlnode* ) +ldap_tavl_next LDAP_P((TAvlnode *, int direction)); + +/* apply traversal types */ +#define AVL_PREORDER 1 +#define AVL_INORDER 2 +#define AVL_POSTORDER 3 +/* what apply returns if it ran out of nodes */ +#define AVL_NOMORE (-6) + +LDAP_END_DECL + +#endif /* _AVL */ diff --git a/libs/ldap/include/ldap_cdefs.h b/libs/ldap/include/ldap_cdefs.h new file mode 100644 index 00000000000..fe00db1de1c --- /dev/null +++ b/libs/ldap/include/ldap_cdefs.h @@ -0,0 +1,248 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* LDAP C Defines */ + +#ifndef _LDAP_CDEFS_H +#define _LDAP_CDEFS_H + +#if defined(__cplusplus) || defined(c_plusplus) +# define LDAP_BEGIN_DECL extern "C" { +# define LDAP_END_DECL } +#else +# define LDAP_BEGIN_DECL /* begin declarations */ +# define LDAP_END_DECL /* end declarations */ +#endif + +#if !defined(LDAP_NO_PROTOTYPES) && ( defined(LDAP_NEEDS_PROTOTYPES) || \ + defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) ) + + /* ANSI C or C++ */ +# define LDAP_P(protos) protos +# define LDAP_CONCAT1(x,y) x ## y +# define LDAP_CONCAT(x,y) LDAP_CONCAT1(x,y) +# define LDAP_STRING(x) #x /* stringify without expanding x */ +# define LDAP_XSTRING(x) LDAP_STRING(x) /* expand x, then stringify */ + +#ifndef LDAP_CONST +# define LDAP_CONST const +#endif + +#else /* no prototypes */ + + /* traditional C */ +# define LDAP_P(protos) () +# define LDAP_CONCAT(x,y) x/**/y +# define LDAP_STRING(x) "x" + +#ifndef LDAP_CONST +# define LDAP_CONST /* no const */ +#endif + +#endif /* no prototypes */ + +#if (__GNUC__) * 1000 + (__GNUC_MINOR__) >= 2006 +# define LDAP_GCCATTR(attrs) __attribute__(attrs) +#else +# define LDAP_GCCATTR(attrs) +#endif + +/* + * Support for Windows DLLs. + * + * When external source code includes header files for dynamic libraries, + * the external source code is "importing" DLL symbols into its resulting + * object code. On Windows, symbols imported from DLLs must be explicitly + * indicated in header files with the __declspec(dllimport) directive. + * This is not totally necessary for functions because the compiler + * (gcc or MSVC) will generate stubs when this directive is absent. + * However, this is required for imported variables. + * + * The LDAP libraries, i.e. liblber and libldap, can be built as + * static or shared, based on configuration. Just about all other source + * code in OpenLDAP use these libraries. If the LDAP libraries + * are configured as shared, 'configure' defines the LDAP_LIBS_DYNAMIC + * macro. When other source files include LDAP library headers, the + * LDAP library symbols will automatically be marked as imported. When + * the actual LDAP libraries are being built, the symbols will not + * be marked as imported because the LBER_LIBRARY or LDAP_LIBRARY macros + * will be respectively defined. + * + * Any project outside of OpenLDAP with source code wanting to use + * LDAP dynamic libraries should explicitly define LDAP_LIBS_DYNAMIC. + * This will ensure that external source code appropriately marks symbols + * that will be imported. + * + * The slapd executable, itself, can be used as a dynamic library. + * For example, if a backend module is compiled as shared, it will + * import symbols from slapd. When this happens, the slapd symbols + * must be marked as imported in header files that the backend module + * includes. Remember that slapd links with various static libraries. + * If the LDAP libraries were configured as static, their object + * code is also part of the monolithic slapd executable. Thus, when + * a backend module imports symbols from slapd, it imports symbols from + * all of the static libraries in slapd as well. Thus, the SLAP_IMPORT + * macro, when defined, will appropriately mark symbols as imported. + * This macro should be used by shared backend modules as well as any + * other external source code that imports symbols from the slapd + * executable as if it were a DLL. + * + * Note that we don't actually have to worry about using the + * __declspec(dllexport) directive anywhere. This is because both + * MSVC and Mingw provide alternate (more effective) methods for exporting + * symbols out of binaries, i.e. the use of a DEF file. + * + * NOTE ABOUT BACKENDS: Backends can be configured as static or dynamic. + * When a backend is configured as dynamic, slapd will load the backend + * explicitly and populate function pointer structures by calling + * the backend's well-known initialization function. Because of this + * procedure, slapd never implicitly imports symbols from dynamic backends. + * This makes it unnecessary to tag various backend functions with the + * __declspec(dllimport) directive. This is because neither slapd nor + * any other external binary should ever be implicitly loading a backend + * dynamic module. + * + * Backends are supposed to be self-contained. However, it appears that + * back-meta DOES implicitly import symbols from back-ldap. This means + * that the __declspec(dllimport) directive should be marked on back-ldap + * functions (in its header files) if and only if we're compiling for + * windows AND back-ldap has been configured as dynamic AND back-meta + * is the client of back-ldap. When client is slapd, there is no effect + * since slapd does not implicitly import symbols. + * + * TODO(?): Currently, back-meta nor back-ldap is supported for Mingw32. + * Thus, there's no need to worry about this right now. This is something that + * may or may not have to be addressed in the future. + */ + +/* LBER library */ +#if defined(_WIN32) && \ + ((defined(LDAP_LIBS_DYNAMIC) && !defined(LBER_LIBRARY)) || \ + (!defined(LDAP_LIBS_DYNAMIC) && defined(SLAPD_IMPORT))) +# define LBER_F(type) extern __declspec(dllimport) type +# define LBER_V(type) extern __declspec(dllimport) type +#else +# define LBER_F(type) extern type +# define LBER_V(type) extern type +#endif + +/* LDAP library */ +#if defined(_WIN32) && \ + ((defined(LDAP_LIBS_DYNAMIC) && !defined(LDAP_LIBRARY)) || \ + (!defined(LDAP_LIBS_DYNAMIC) && defined(SLAPD_IMPORT))) +# define LDAP_F(type) extern __declspec(dllimport) type +# define LDAP_V(type) extern __declspec(dllimport) type +#else +# define LDAP_F(type) extern type +# define LDAP_V(type) extern type +#endif + +/* AVL library */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_AVL_F(type) extern __declspec(dllimport) type +# define LDAP_AVL_V(type) extern __declspec(dllimport) type +#else +# define LDAP_AVL_F(type) extern type +# define LDAP_AVL_V(type) extern type +#endif + +/* LDIF library */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_LDIF_F(type) extern __declspec(dllimport) type +# define LDAP_LDIF_V(type) extern __declspec(dllimport) type +#else +# define LDAP_LDIF_F(type) extern type +# define LDAP_LDIF_V(type) extern type +#endif + +/* LUNICODE library */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_LUNICODE_F(type) extern __declspec(dllimport) type +# define LDAP_LUNICODE_V(type) extern __declspec(dllimport) type +#else +# define LDAP_LUNICODE_F(type) extern type +# define LDAP_LUNICODE_V(type) extern type +#endif + +/* LUTIL library */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_LUTIL_F(type) extern __declspec(dllimport) type +# define LDAP_LUTIL_V(type) extern __declspec(dllimport) type +#else +# define LDAP_LUTIL_F(type) extern type +# define LDAP_LUTIL_V(type) extern type +#endif + +/* REWRITE library */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_REWRITE_F(type) extern __declspec(dllimport) type +# define LDAP_REWRITE_V(type) extern __declspec(dllimport) type +#else +# define LDAP_REWRITE_F(type) extern type +# define LDAP_REWRITE_V(type) extern type +#endif + +/* SLAPD (as a dynamic library exporting symbols) */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_SLAPD_F(type) extern __declspec(dllimport) type +# define LDAP_SLAPD_V(type) extern __declspec(dllimport) type +#else +# define LDAP_SLAPD_F(type) extern type +# define LDAP_SLAPD_V(type) extern type +#endif + +/* SLAPD (as a dynamic library exporting symbols) */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define LDAP_SLAPI_F(type) extern __declspec(dllimport) type +# define LDAP_SLAPI_V(type) extern __declspec(dllimport) type +#else +# define LDAP_SLAPI_F(type) extern type +# define LDAP_SLAPI_V(type) extern type +#endif + +/* SLAPD (as a dynamic library exporting symbols) */ +#if defined(_WIN32) && defined(SLAPD_IMPORT) +# define SLAPI_F(type) extern __declspec(dllimport) type +# define SLAPI_V(type) extern __declspec(dllimport) type +#else +# define SLAPI_F(type) extern type +# define SLAPI_V(type) extern type +#endif + +/* + * C library. Mingw32 links with the dynamic C run-time library by default, + * so the explicit definition of CSTATIC will keep dllimport from + * being defined, if desired. + * + * MSVC defines the _DLL macro when the compiler is invoked with /MD or /MDd, + * which means the resulting object code will be linked with the dynamic + * C run-time library. + * + * Technically, it shouldn't be necessary to redefine any functions that + * the headers for the C library should already contain. Nevertheless, this + * is here as a safe-guard. + * + * TODO: Determine if these macros ever get expanded for Windows. If not, + * the declspec expansion can probably be removed. + */ +#if (defined(__MINGW32__) && !defined(CSTATIC)) || \ + (defined(_MSC_VER) && defined(_DLL)) +# define LDAP_LIBC_F(type) extern __declspec(dllimport) type +# define LDAP_LIBC_V(type) extern __declspec(dllimport) type +#else +# define LDAP_LIBC_F(type) extern type +# define LDAP_LIBC_V(type) extern type +#endif + +#endif /* _LDAP_CDEFS_H */ diff --git a/libs/ldap/include/ldap_config.h b/libs/ldap/include/ldap_config.h new file mode 100644 index 00000000000..d092849d7a4 --- /dev/null +++ b/libs/ldap/include/ldap_config.h @@ -0,0 +1,74 @@ +/* Generated from ./ldap_config.hin on Wed 22 Dec 2021 05:22:52 PM CET */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * This file works in conjunction with OpenLDAP configure system. + * If you do no like the values below, adjust your configure options. + */ + +#ifndef _LDAP_CONFIG_H +#define _LDAP_CONFIG_H + +/* directory separator */ +#ifndef LDAP_DIRSEP +#ifndef _WIN32 +#define LDAP_DIRSEP "/" +#else +#define LDAP_DIRSEP "\" +#endif +#endif + +/* directory for temporary files */ +#if defined(_WIN32) +# define LDAP_TMPDIR "C:\." /* we don't have much of a choice */ +#elif defined( _P_tmpdir ) +# define LDAP_TMPDIR _P_tmpdir +#elif defined( P_tmpdir ) +# define LDAP_TMPDIR P_tmpdir +#elif defined( _PATH_TMPDIR ) +# define LDAP_TMPDIR _PATH_TMPDIR +#else +# define LDAP_TMPDIR LDAP_DIRSEP "tmp" +#endif + +/* directories */ +#ifndef LDAP_BINDIR +#define LDAP_BINDIR "" +#endif +#ifndef LDAP_SBINDIR +#define LDAP_SBINDIR "" +#endif +#ifndef LDAP_DATADIR +#define LDAP_DATADIR "" +#endif +#ifndef LDAP_SYSCONFDIR +#define LDAP_SYSCONFDIR "" +#endif +#ifndef LDAP_LIBEXECDIR +#define LDAP_LIBEXECDIR "" +#endif +#ifndef LDAP_MODULEDIR +#define LDAP_MODULEDIR "" +#endif +#ifndef LDAP_RUNDIR +#define LDAP_RUNDIR "" +#endif +#ifndef LDAP_LOCALEDIR +#define LDAP_LOCALEDIR "" +#endif + + +#endif /* _LDAP_CONFIG_H */ diff --git a/libs/ldap/include/ldap_defaults.h b/libs/ldap/include/ldap_defaults.h new file mode 100644 index 00000000000..93d2729da12 --- /dev/null +++ b/libs/ldap/include/ldap_defaults.h @@ -0,0 +1,71 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ + +/* + * This file controls defaults for OpenLDAP package. + * You probably do not need to edit the defaults provided by this file. + */ + +#ifndef _LDAP_DEFAULTS_H +#define _LDAP_DEFAULTS_H + + +#include <ldap_config.h> + +#define LDAP_CONF_FILE LDAP_SYSCONFDIR LDAP_DIRSEP "ldap.conf" +#define LDAP_USERRC_FILE "ldaprc" +#define LDAP_ENV_PREFIX "LDAP" + +/* default ldapi:// socket */ +#define LDAPI_SOCK LDAP_RUNDIR LDAP_DIRSEP "run" LDAP_DIRSEP "ldapi" + +/* + * SLAPD DEFINITIONS + */ + /* location of the default slapd config file */ +#define SLAPD_DEFAULT_CONFIGFILE LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.conf" +#define SLAPD_DEFAULT_CONFIGDIR LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.d" +#define SLAPD_DEFAULT_DB_DIR LDAP_RUNDIR LDAP_DIRSEP "openldap-data" +#define SLAPD_DEFAULT_DB_MODE 0600 +#define SLAPD_DEFAULT_UCDATA LDAP_DATADIR LDAP_DIRSEP "ucdata" + /* default max deref depth for aliases */ +#define SLAPD_DEFAULT_MAXDEREFDEPTH 15 + /* default sizelimit on number of entries from a search */ +#define SLAPD_DEFAULT_SIZELIMIT 500 + /* default timelimit to spend on a search */ +#define SLAPD_DEFAULT_TIMELIMIT 3600 + +/* the following DNs must be normalized! */ + /* dn of the default subschema subentry */ +#define SLAPD_SCHEMA_DN "cn=Subschema" + /* dn of the default "monitor" subentry */ +#define SLAPD_MONITOR_DN "cn=Monitor" + +/* + * LLOADD DEFINITIONS + */ +#define LLOADD_DEFAULT_CONFIGFILE LDAP_SYSCONFDIR LDAP_DIRSEP "lloadd.conf" + +#endif /* _LDAP_CONFIG_H */ diff --git a/libs/ldap/include/ldap_features.h b/libs/ldap/include/ldap_features.h new file mode 100644 index 00000000000..c5e817a3fdd --- /dev/null +++ b/libs/ldap/include/ldap_features.h @@ -0,0 +1,56 @@ +/* include/ldap_features.h. Generated from ldap_features.hin by configure. */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * LDAP Features + */ + +#ifndef _LDAP_FEATURES_H +#define _LDAP_FEATURES_H 1 + +/* OpenLDAP API version macros */ +#define LDAP_VENDOR_VERSION 000000 +#define LDAP_VENDOR_VERSION_MAJOR 2 +#define LDAP_VENDOR_VERSION_MINOR X +#define LDAP_VENDOR_VERSION_PATCH X + +/* +** WORK IN PROGRESS! +** +** OpenLDAP reentrancy/thread-safeness should be dynamically +** checked using ldap_get_option(). +** +** If built with thread support, the -lldap implementation is: +** LDAP_API_FEATURE_THREAD_SAFE (basic thread safety) +** LDAP_API_FEATURE_SESSION_THREAD_SAFE +** LDAP_API_FEATURE_OPERATION_THREAD_SAFE +** +** The preprocessor flag LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE +** can be used to determine if -lldap is thread safe at compile +** time. +** +*/ + +/* is -lldap reentrant or not */ +#define LDAP_API_FEATURE_X_OPENLDAP_REENTRANT 1 + +/* is -lldap thread safe or not */ +#define LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE 1 + +/* LDAP v2 Referrals */ +/* #undef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ + +#endif /* LDAP_FEATURES */ diff --git a/libs/ldap/include/ldap_int_thread.h b/libs/ldap/include/ldap_int_thread.h new file mode 100644 index 00000000000..6eaccc7a72a --- /dev/null +++ b/libs/ldap/include/ldap_int_thread.h @@ -0,0 +1,290 @@ +/* ldap_int_thread.h - ldap internal thread wrappers header file */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + + +LDAP_BEGIN_DECL + +/* Can be done twice. See libldap/ldap_thr_debug.h. */ +LDAP_F(int) ldap_int_thread_initialize LDAP_P(( void )); +LDAP_F(int) ldap_int_thread_destroy LDAP_P(( void )); + +LDAP_END_DECL + +#ifndef _LDAP_INT_THREAD_H +#define _LDAP_INT_THREAD_H + +#if defined( HAVE_PTHREADS ) +/********************************** + * * + * definitions for POSIX Threads * + * * + **********************************/ + +#include <pthread.h> +#ifdef HAVE_SCHED_H +#include <sched.h> +#endif + +LDAP_BEGIN_DECL + +typedef pthread_t ldap_int_thread_t; +typedef pthread_mutex_t ldap_int_thread_mutex_t; +typedef pthread_cond_t ldap_int_thread_cond_t; +typedef pthread_key_t ldap_int_thread_key_t; + +#define ldap_int_thread_equal(a, b) pthread_equal((a), (b)) + +#if defined( _POSIX_REENTRANT_FUNCTIONS ) || \ + defined( _POSIX_THREAD_SAFE_FUNCTIONS ) || \ + defined( _POSIX_THREADSAFE_FUNCTIONS ) +#define HAVE_REENTRANT_FUNCTIONS 1 +#endif + +#if defined( HAVE_PTHREAD_GETCONCURRENCY ) || \ + defined( HAVE_THR_GETCONCURRENCY ) +#define LDAP_THREAD_HAVE_GETCONCURRENCY 1 +#endif + +#if defined( HAVE_PTHREAD_SETCONCURRENCY ) || \ + defined( HAVE_THR_SETCONCURRENCY ) +#define LDAP_THREAD_HAVE_SETCONCURRENCY 1 +#endif + +#if defined( HAVE_PTHREAD_RWLOCK_DESTROY ) +#define LDAP_THREAD_HAVE_RDWR 1 +typedef pthread_rwlock_t ldap_int_thread_rdwr_t; +#endif + +#ifndef LDAP_INT_MUTEX_NULL +#define LDAP_INT_MUTEX_NULL PTHREAD_MUTEX_INITIALIZER +#define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) +#endif + +LDAP_END_DECL + +#elif defined( HAVE_GNU_PTH ) +/*********************************** + * * + * thread definitions for GNU Pth * + * * + ***********************************/ + +#define PTH_SYSCALL_SOFT 1 +#include <pth.h> + +LDAP_BEGIN_DECL + +typedef pth_t ldap_int_thread_t; +typedef pth_mutex_t ldap_int_thread_mutex_t; +typedef pth_cond_t ldap_int_thread_cond_t; +typedef pth_key_t ldap_int_thread_key_t; + +#if 0 +#define LDAP_THREAD_HAVE_RDWR 1 +typedef pth_rwlock_t ldap_int_thread_rdwr_t; +#endif + +#ifndef LDAP_INT_MUTEX_NULL +#define LDAP_INT_MUTEX_NULL PTH_MUTEX_INIT +#define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) +#endif + +LDAP_END_DECL + +#elif defined( HAVE_THR ) +/******************************************** + * * + * thread definitions for Solaris LWP (THR) * + * * + ********************************************/ + +#include <thread.h> +#include <synch.h> + +LDAP_BEGIN_DECL + +typedef thread_t ldap_int_thread_t; +typedef mutex_t ldap_int_thread_mutex_t; +typedef cond_t ldap_int_thread_cond_t; +typedef thread_key_t ldap_int_thread_key_t; + +#define HAVE_REENTRANT_FUNCTIONS 1 + +#ifdef HAVE_THR_GETCONCURRENCY +#define LDAP_THREAD_HAVE_GETCONCURRENCY 1 +#endif +#ifdef HAVE_THR_SETCONCURRENCY +#define LDAP_THREAD_HAVE_SETCONCURRENCY 1 +#endif + +#ifndef LDAP_INT_MUTEX_NULL +#define LDAP_INT_MUTEX_NULL DEFAULTMUTEX +#define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) +#endif + +#elif defined(HAVE_NT_THREADS) +/************************************* + * * + * thread definitions for NT threads * + * * + *************************************/ + +#include <process.h> +#include <windows.h> + +LDAP_BEGIN_DECL + +typedef unsigned long ldap_int_thread_t; +typedef HANDLE ldap_int_thread_mutex_t; +typedef HANDLE ldap_int_thread_cond_t; +typedef DWORD ldap_int_thread_key_t; + +LDAP_F( int ) +ldap_int_mutex_firstcreate LDAP_P(( ldap_int_thread_mutex_t *mutex )); + +#ifndef LDAP_INT_MUTEX_NULL +#define LDAP_INT_MUTEX_NULL ((HANDLE)0) +#define LDAP_INT_MUTEX_FIRSTCREATE(m) \ + ldap_int_mutex_firstcreate(&(m)) +#endif + +LDAP_END_DECL + +#else +/*********************************** + * * + * thread definitions for no * + * underlying library support * + * * + ***********************************/ + +#ifndef NO_THREADS +#define NO_THREADS 1 +#endif + +LDAP_BEGIN_DECL + +typedef int ldap_int_thread_t; +typedef int ldap_int_thread_mutex_t; +typedef int ldap_int_thread_cond_t; +typedef int ldap_int_thread_key_t; + +#define LDAP_THREAD_HAVE_TPOOL 1 +typedef int ldap_int_thread_pool_t; + +#ifndef LDAP_INT_MUTEX_NULL +#define LDAP_INT_MUTEX_NULL 0 +#define LDAP_INT_MUTEX_FIRSTCREATE(m) ((void) 0) +#endif + +LDAP_END_DECL + +#endif /* no threads support */ + + +LDAP_BEGIN_DECL + +#ifndef ldap_int_thread_equal +#define ldap_int_thread_equal(a, b) ((a) == (b)) +#endif + +#ifndef LDAP_THREAD_HAVE_RDWR +typedef struct ldap_int_thread_rdwr_s * ldap_int_thread_rdwr_t; +#endif + +LDAP_F(int) ldap_int_thread_pool_startup ( void ); +LDAP_F(int) ldap_int_thread_pool_shutdown ( void ); + +#ifndef LDAP_THREAD_HAVE_TPOOL +typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t; +#endif +LDAP_END_DECL + + +#if defined(LDAP_THREAD_DEBUG) && !((LDAP_THREAD_DEBUG +0) & 2U) +#define LDAP_THREAD_DEBUG_WRAP 1 +#endif + +#ifdef LDAP_THREAD_DEBUG_WRAP +/************************************** + * * + * definitions for type-wrapped debug * + * * + **************************************/ + +LDAP_BEGIN_DECL + +#ifndef LDAP_UINTPTR_T /* May be configured in CPPFLAGS */ +#define LDAP_UINTPTR_T unsigned long +#endif + +typedef enum { + ldap_debug_magic = -(int) (((unsigned)-1)/19) +} ldap_debug_magic_t; + +typedef enum { + /* Could fill in "locked" etc here later */ + ldap_debug_state_inited = (int) (((unsigned)-1)/11), + ldap_debug_state_destroyed +} ldap_debug_state_t; + +typedef struct { + /* Enclosed in magic numbers in the hope of catching overwrites */ + ldap_debug_magic_t magic; /* bit pattern to recognize usages */ + LDAP_UINTPTR_T self; /* ~(LDAP_UINTPTR_T)&(this struct) */ + union ldap_debug_mem_u { /* Dummy memory reference */ + unsigned char *ptr; + LDAP_UINTPTR_T num; + } mem; + ldap_debug_state_t state; /* doubles as another magic number */ +} ldap_debug_usage_info_t; + +typedef struct { + ldap_int_thread_mutex_t wrapped; + ldap_debug_usage_info_t usage; + ldap_int_thread_t owner; +} ldap_debug_thread_mutex_t; + +#define LDAP_DEBUG_MUTEX_NULL {LDAP_INT_MUTEX_NULL, {0,0,{0},0} /*,owner*/} +#define LDAP_DEBUG_MUTEX_FIRSTCREATE(m) \ + ((void) ((m).usage.state || ldap_pvt_thread_mutex_init(&(m)))) + +typedef struct { + ldap_int_thread_cond_t wrapped; + ldap_debug_usage_info_t usage; +} ldap_debug_thread_cond_t; + +typedef struct { + ldap_int_thread_rdwr_t wrapped; + ldap_debug_usage_info_t usage; +} ldap_debug_thread_rdwr_t; + +#ifndef NDEBUG +#define LDAP_INT_THREAD_ASSERT_MUTEX_OWNER(mutex) \ + ldap_debug_thread_assert_mutex_owner( \ + __FILE__, __LINE__, "owns(" #mutex ")", mutex ) +LDAP_F(void) ldap_debug_thread_assert_mutex_owner LDAP_P(( + LDAP_CONST char *file, + int line, + LDAP_CONST char *msg, + ldap_debug_thread_mutex_t *mutex )); +#endif /* NDEBUG */ + +LDAP_END_DECL + +#endif /* LDAP_THREAD_DEBUG_WRAP */ + +#endif /* _LDAP_INT_THREAD_H */ diff --git a/libs/ldap/include/ldap_log.h b/libs/ldap/include/ldap_log.h new file mode 100644 index 00000000000..54d90f62084 --- /dev/null +++ b/libs/ldap/include/ldap_log.h @@ -0,0 +1,211 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ + +#ifndef LDAP_LOG_H +#define LDAP_LOG_H + +#include <stdio.h> +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +/* + * debug reporting levels. + * + * They start with the syslog levels, and + * go down in importance. The normal + * debugging levels begin with LDAP_LEVEL_ENTRY + * + */ + +/* + * The "OLD_DEBUG" means that all logging occurs at LOG_DEBUG + */ + +#ifdef OLD_DEBUG +/* original behavior: all logging occurs at the same severity level */ +#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) +#define LDAP_LEVEL_EMERG ldap_syslog_level +#define LDAP_LEVEL_ALERT ldap_syslog_level +#define LDAP_LEVEL_CRIT ldap_syslog_level +#define LDAP_LEVEL_ERR ldap_syslog_level +#define LDAP_LEVEL_WARNING ldap_syslog_level +#define LDAP_LEVEL_NOTICE ldap_syslog_level +#define LDAP_LEVEL_INFO ldap_syslog_level +#define LDAP_LEVEL_DEBUG ldap_syslog_level +#else /* !LDAP_DEBUG || !LDAP_SYSLOG */ +#define LDAP_LEVEL_EMERG (7) +#define LDAP_LEVEL_ALERT (7) +#define LDAP_LEVEL_CRIT (7) +#define LDAP_LEVEL_ERR (7) +#define LDAP_LEVEL_WARNING (7) +#define LDAP_LEVEL_NOTICE (7) +#define LDAP_LEVEL_INFO (7) +#define LDAP_LEVEL_DEBUG (7) +#endif /* !LDAP_DEBUG || !LDAP_SYSLOG */ + +#else /* ! OLD_DEBUG */ +/* map syslog onto LDAP severity levels */ +#ifdef LOG_DEBUG +#define LDAP_LEVEL_EMERG LOG_EMERG +#define LDAP_LEVEL_ALERT LOG_ALERT +#define LDAP_LEVEL_CRIT LOG_CRIT +#define LDAP_LEVEL_ERR LOG_ERR +#define LDAP_LEVEL_WARNING LOG_WARNING +#define LDAP_LEVEL_NOTICE LOG_NOTICE +#define LDAP_LEVEL_INFO LOG_INFO +#define LDAP_LEVEL_DEBUG LOG_DEBUG +#else /* ! LOG_DEBUG */ +#define LDAP_LEVEL_EMERG (0) +#define LDAP_LEVEL_ALERT (1) +#define LDAP_LEVEL_CRIT (2) +#define LDAP_LEVEL_ERR (3) +#define LDAP_LEVEL_WARNING (4) +#define LDAP_LEVEL_NOTICE (5) +#define LDAP_LEVEL_INFO (6) +#define LDAP_LEVEL_DEBUG (7) +#endif /* ! LOG_DEBUG */ +#endif /* ! OLD_DEBUG */ +#if 0 +/* in case we need to reuse the unused bits of severity */ +#define LDAP_LEVEL_MASK(s) ((s) & 0x7) +#else +#define LDAP_LEVEL_MASK(s) (s) +#endif + +/* (yet) unused */ +#define LDAP_LEVEL_ENTRY (0x08) /* log function entry points */ +#define LDAP_LEVEL_ARGS (0x10) /* log function call parameters */ +#define LDAP_LEVEL_RESULTS (0x20) /* Log function results */ +#define LDAP_LEVEL_DETAIL1 (0x40) /* log level 1 function operational details */ +#define LDAP_LEVEL_DETAIL2 (0x80) /* Log level 2 function operational details */ +/* end of (yet) unused */ + +/* original subsystem selection mechanism */ +#define LDAP_DEBUG_TRACE 0x0001 +#define LDAP_DEBUG_PACKETS 0x0002 +#define LDAP_DEBUG_ARGS 0x0004 +#define LDAP_DEBUG_CONNS 0x0008 +#define LDAP_DEBUG_BER 0x0010 +#define LDAP_DEBUG_FILTER 0x0020 +#define LDAP_DEBUG_CONFIG 0x0040 +#define LDAP_DEBUG_ACL 0x0080 +#define LDAP_DEBUG_STATS 0x0100 +#define LDAP_DEBUG_STATS2 0x0200 +#define LDAP_DEBUG_SHELL 0x0400 +#define LDAP_DEBUG_PARSE 0x0800 +#if 0 /* no longer used (nor supported) */ +#define LDAP_DEBUG_CACHE 0x1000 +#define LDAP_DEBUG_INDEX 0x2000 +#endif +#define LDAP_DEBUG_SYNC 0x4000 + +#define LDAP_DEBUG_NONE 0x8000 +#define LDAP_DEBUG_ANY (-1) + +/* debugging stuff */ +#ifdef LDAP_DEBUG + /* + * This is a bogus extern declaration for the compiler. No need to ensure + * a 'proper' dllimport. + */ +#ifndef ldap_debug +extern int ldap_debug; +#endif /* !ldap_debug */ + +#ifdef LDAP_SYSLOG +extern int ldap_syslog; +extern int ldap_syslog_level; + +#ifdef HAVE_EBCDIC +#define syslog eb_syslog +extern void eb_syslog(int pri, const char *fmt, ...); +#endif /* HAVE_EBCDIC */ + +#endif /* LDAP_SYSLOG */ +#endif /* LDAP_DEBUG */ + +/* we keep libldap working with preprocessors that can't do variadic macros */ +#ifndef LDAP_INT_DEBUG +/* this doesn't below as part of ldap.h */ +#ifdef LDAP_DEBUG +#ifdef LDAP_SYSLOG + +#define LogTest(level) ( ( ldap_debug | ldap_syslog ) & (level) ) +#define Log(level, severity, ...) \ + do { \ + if ( ldap_debug & (level) ) \ + lutil_debug( ldap_debug, (level), __VA_ARGS__ ); \ + if ( ldap_syslog & (level) ) \ + syslog( LDAP_LEVEL_MASK((severity)), __VA_ARGS__ ); \ + } while ( 0 ) + +#else /* ! LDAP_SYSLOG */ + +#define LogTest(level) ( ldap_debug & (level) ) +#define Log(level, severity, ...) \ + do { \ + if ( ldap_debug & (level) ) \ + lutil_debug( ldap_debug, (level), __VA_ARGS__ ); \ + } while ( 0 ) + +#endif /* ! LDAP_SYSLOG */ +#else /* ! LDAP_DEBUG */ + +/* TODO: in case LDAP_DEBUG is undefined, make sure logs with appropriate + * severity gets thru anyway */ +#define LogTest(level) ( 0 ) +#define Log(level, severity, ...) ((void) 0) + +#endif /* ! LDAP_DEBUG */ + +#define Debug(level, ...) \ + Log((level), ldap_syslog_level, __VA_ARGS__ ) +#endif /* ! LDAP_INT_DEBUG */ + +/* Actually now in liblber/debug.c */ +LDAP_LUTIL_F(int) lutil_debug_file LDAP_P(( FILE *file )); + +LDAP_LUTIL_F(void) lutil_debug LDAP_P(( + int debug, int level, + const char* fmt, ... )) LDAP_GCCATTR((format(printf, 3, 4))); + +#ifdef LDAP_DEFINE_LDAP_DEBUG +/* This struct matches the head of ldapoptions in <ldap-int.h> */ +struct ldapoptions_prefix { + short ldo_valid; + int ldo_debug; +}; +#define ldap_debug \ + (*(int *) ((char *)&ldap_int_global_options \ + + offsetof(struct ldapoptions_prefix, ldo_debug))) + +struct ldapoptions; +LDAP_V ( struct ldapoptions ) ldap_int_global_options; +#endif /* LDAP_DEFINE_LDAP_DEBUG */ + +LDAP_END_DECL + +#endif /* LDAP_LOG_H */ diff --git a/libs/ldap/include/ldap_pvt.h b/libs/ldap/include/ldap_pvt.h new file mode 100644 index 00000000000..779da39586b --- /dev/null +++ b/libs/ldap/include/ldap_pvt.h @@ -0,0 +1,588 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* ldap-pvt.h - Header for ldap_pvt_ functions. + * These are meant to be internal to OpenLDAP Software. + */ + +#ifndef _LDAP_PVT_H +#define _LDAP_PVT_H 1 + +#include <openldap.h> /* get public interfaces */ +#include <lber.h> /* get ber_slen_t */ +#include <lber_pvt.h> /* get Sockbuf_Buf */ + +LDAP_BEGIN_DECL + +LDAP_F ( int ) +ldap_pvt_url_scheme2proto LDAP_P(( + const char * )); +LDAP_F ( int ) +ldap_pvt_url_scheme2tls LDAP_P(( + const char * )); +LDAP_F ( int ) +ldap_pvt_url_scheme2proxied LDAP_P(( + const char * )); + +LDAP_F ( int ) +ldap_pvt_url_scheme_port LDAP_P(( + const char *, int )); + +struct ldap_url_desc; /* avoid pulling in <ldap.h> */ + +#define LDAP_PVT_URL_PARSE_NONE (0x00U) +#define LDAP_PVT_URL_PARSE_NOEMPTY_HOST (0x01U) +#define LDAP_PVT_URL_PARSE_DEF_PORT (0x02U) +#define LDAP_PVT_URL_PARSE_NOEMPTY_DN (0x04U) +#define LDAP_PVT_URL_PARSE_NODEF_SCOPE (0x08U) +#define LDAP_PVT_URL_PARSE_HISTORIC (LDAP_PVT_URL_PARSE_NODEF_SCOPE | \ + LDAP_PVT_URL_PARSE_NOEMPTY_HOST | \ + LDAP_PVT_URL_PARSE_DEF_PORT) + +LDAP_F( int ) +ldap_url_parse_ext LDAP_P(( + LDAP_CONST char *url, + struct ldap_url_desc **ludpp, + unsigned flags )); + +LDAP_F (int) ldap_url_parselist LDAP_P(( /* deprecated, use ldap_url_parselist_ext() */ + struct ldap_url_desc **ludlist, + const char *url )); + +LDAP_F (int) ldap_url_parselist_ext LDAP_P(( + struct ldap_url_desc **ludlist, + const char *url, + const char *sep, + unsigned flags )); + +LDAP_F (char *) ldap_url_list2urls LDAP_P(( + struct ldap_url_desc *ludlist )); + +LDAP_F (void) ldap_free_urllist LDAP_P(( + struct ldap_url_desc *ludlist )); + +LDAP_F (int) ldap_pvt_scope2bv LDAP_P (( + int scope, struct berval *bv )); + +LDAP_F (LDAP_CONST char *) ldap_pvt_scope2str LDAP_P (( + int scope )); + +LDAP_F (int) ldap_pvt_bv2scope LDAP_P (( + struct berval *bv )); + +LDAP_F (int) ldap_pvt_str2scope LDAP_P (( + LDAP_CONST char * )); + +LDAP_F( char * ) +ldap_pvt_ctime LDAP_P(( + const time_t *tp, + char *buf )); + +# if defined( HAVE_GMTIME_R ) +# define USE_GMTIME_R +# define ldap_pvt_gmtime(timep, result) gmtime_r((timep), (result)) +# else +LDAP_F( struct tm * ) +ldap_pvt_gmtime LDAP_P(( + LDAP_CONST time_t *timep, + struct tm *result )); +#endif + +# if defined( HAVE_LOCALTIME_R ) +# define USE_LOCALTIME_R +# define ldap_pvt_localtime(timep, result) localtime_r((timep), (result)) +# else +LDAP_F( struct tm * ) +ldap_pvt_localtime LDAP_P(( + LDAP_CONST time_t *timep, + struct tm *result )); +# endif + +#if defined( USE_GMTIME_R ) && defined( USE_LOCALTIME_R ) +# define ldap_pvt_gmtime_lock() (0) +# define ldap_pvt_gmtime_unlock() (0) +#else +LDAP_F( int ) +ldap_pvt_gmtime_lock LDAP_P(( void )); + +LDAP_F( int ) +ldap_pvt_gmtime_unlock LDAP_P(( void )); +#endif /* USE_GMTIME_R && USE_LOCALTIME_R */ + +/* Get current time as a structured time */ +struct lutil_tm; +LDAP_F( void ) +ldap_pvt_gettime LDAP_P(( struct lutil_tm * )); + +#ifdef _WIN32 +#define gettimeofday(tv,tz) ldap_pvt_gettimeofday(tv,tz) +struct timeval; +LDAP_F( int ) +ldap_pvt_gettimeofday LDAP_P(( struct timeval *tv, void *unused )); +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif +#define clock_gettime(clkid,tv) ldap_pvt_clock_gettime(clkid,tv) +struct timespec; +LDAP_F( int ) +ldap_pvt_clock_gettime LDAP_P(( int clkid, struct timespec *tv )); +#endif + +/* use this macro to allocate buffer for ldap_pvt_csnstr */ +#define LDAP_PVT_CSNSTR_BUFSIZE 64 +LDAP_F( size_t ) +ldap_pvt_csnstr( char *buf, size_t len, unsigned int replica, unsigned int mod ); + +LDAP_F( char *) ldap_pvt_get_fqdn LDAP_P(( char * )); + +struct hostent; /* avoid pulling in <netdb.h> */ + +LDAP_F( int ) +ldap_pvt_gethostbyname_a LDAP_P(( + const char *name, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr )); + +LDAP_F( int ) +ldap_pvt_gethostbyaddr_a LDAP_P(( + const char *addr, + int len, + int type, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr )); + +struct sockaddr; + +LDAP_F( int ) +ldap_pvt_get_hname LDAP_P(( + const struct sockaddr * sa, + int salen, + char *name, + int namelen, + char **herr )); + +#ifdef LDAP_PF_LOCAL +#define LDAP_IPADDRLEN (MAXPATHLEN + sizeof("PATH=")) +#elif defined(LDAP_PF_INET6) +#define LDAP_IPADDRLEN sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535") +#else +#define LDAP_IPADDRLEN sizeof("IP=255.255.255.255:65336") +#endif + +union Sockaddr; + +LDAP_F (void) +ldap_pvt_sockaddrstr LDAP_P(( + union Sockaddr *sa, + struct berval * )); + + +/* charray.c */ + +LDAP_F( int ) +ldap_charray_add LDAP_P(( + char ***a, + const char *s )); + +LDAP_F( int ) +ldap_charray_merge LDAP_P(( + char ***a, + char **s )); + +LDAP_F( void ) +ldap_charray_free LDAP_P(( char **a )); + +LDAP_F( int ) +ldap_charray_inlist LDAP_P(( + char **a, + const char *s )); + +LDAP_F( char ** ) +ldap_charray_dup LDAP_P(( char **a )); + +LDAP_F( char ** ) +ldap_str2charray LDAP_P(( + const char *str, + const char *brkstr )); + +LDAP_F( char * ) +ldap_charray2str LDAP_P(( + char **array, const char* sep )); + +/* getdn.c */ + +#ifdef LDAP_AVA_NULL /* in ldap.h */ +LDAP_F( void ) ldap_rdnfree_x LDAP_P(( LDAPRDN rdn, void *ctx )); +LDAP_F( void ) ldap_dnfree_x LDAP_P(( LDAPDN dn, void *ctx )); + +LDAP_F( int ) ldap_bv2dn_x LDAP_P(( + struct berval *bv, LDAPDN *dn, unsigned flags, void *ctx )); +LDAP_F( int ) ldap_dn2bv_x LDAP_P(( + LDAPDN dn, struct berval *bv, unsigned flags, void *ctx )); +LDAP_F( int ) ldap_bv2rdn_x LDAP_P(( + struct berval *, LDAPRDN *, char **, unsigned flags, void *ctx )); +LDAP_F( int ) ldap_rdn2bv_x LDAP_P(( + LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx )); +#endif /* LDAP_AVA_NULL */ + +/* url.c */ +LDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s )); + +/* + * these macros assume 'x' is an ASCII x + * and assume the "C" locale + */ +#define LDAP_ASCII(c) (!((c) & 0x80)) +#define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') +#define LDAP_LOWER(c) ((c) >= 'a' && (c) <= 'z') +#define LDAP_UPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define LDAP_ALPHA(c) (LDAP_LOWER(c) || LDAP_UPPER(c)) +#define LDAP_ALNUM(c) (LDAP_ALPHA(c) || LDAP_DIGIT(c)) + +#define LDAP_LDH(c) (LDAP_ALNUM(c) || (c) == '-') + +#define LDAP_HEXLOWER(c) ((c) >= 'a' && (c) <= 'f') +#define LDAP_HEXUPPER(c) ((c) >= 'A' && (c) <= 'F') +#define LDAP_HEX(c) (LDAP_DIGIT(c) || \ + LDAP_HEXLOWER(c) || LDAP_HEXUPPER(c)) + +/* controls.c */ +struct ldapcontrol; +LDAP_F (int) +ldap_pvt_put_control LDAP_P(( + const struct ldapcontrol *c, + BerElement *ber )); +LDAP_F (int) ldap_pvt_get_controls LDAP_P(( + BerElement *be, + struct ldapcontrol ***ctrlsp)); + +#ifdef HAVE_CYRUS_SASL +/* cyrus.c */ +struct sasl_security_properties; /* avoid pulling in <sasl.h> */ +LDAP_F (int) ldap_pvt_sasl_secprops LDAP_P(( + const char *in, + struct sasl_security_properties *secprops )); +LDAP_F (void) ldap_pvt_sasl_secprops_unparse LDAP_P(( + struct sasl_security_properties *secprops, + struct berval *out )); + +LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void)); +LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex)); +LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex)); +LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex)); + +LDAP_F (int) ldap_pvt_sasl_cbinding_parse LDAP_P(( const char *arg )); +LDAP_F (void *) ldap_pvt_sasl_cbinding LDAP_P(( void *ssl, int type, + int is_server )); +#endif /* HAVE_CYRUS_SASL */ + +struct sockbuf; /* avoid pulling in <lber.h> */ +LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * )); +LDAP_F (void) ldap_pvt_sasl_remove LDAP_P(( struct sockbuf * )); + +/* + * SASL encryption support for LBER Sockbufs + */ + +struct sb_sasl_generic_data; + +struct sb_sasl_generic_ops { + void (*init)(struct sb_sasl_generic_data *p, + ber_len_t *min_send, + ber_len_t *max_send, + ber_len_t *max_recv); + ber_int_t (*encode)(struct sb_sasl_generic_data *p, + unsigned char *buf, + ber_len_t len, + Sockbuf_Buf *dst); + ber_int_t (*decode)(struct sb_sasl_generic_data *p, + const Sockbuf_Buf *src, + Sockbuf_Buf *dst); + void (*reset_buf)(struct sb_sasl_generic_data *p, + Sockbuf_Buf *buf); + void (*fini)(struct sb_sasl_generic_data *p); +}; + +struct sb_sasl_generic_install { + const struct sb_sasl_generic_ops *ops; + void *ops_private; +}; + +struct sb_sasl_generic_data { + const struct sb_sasl_generic_ops *ops; + void *ops_private; + Sockbuf_IO_Desc *sbiod; + ber_len_t min_send; + ber_len_t max_send; + ber_len_t max_recv; + Sockbuf_Buf sec_buf_in; + Sockbuf_Buf buf_in; + Sockbuf_Buf buf_out; + unsigned int flags; +#define LDAP_PVT_SASL_PARTIAL_WRITE 1 +}; + +#ifndef LDAP_PVT_SASL_LOCAL_SSF +#define LDAP_PVT_SASL_LOCAL_SSF 71 /* SSF for Unix Domain Sockets */ +#endif /* ! LDAP_PVT_SASL_LOCAL_SSF */ + +struct ldap; +struct ldapmsg; +struct ldifrecord; + +/* abandon */ +LDAP_F ( int ) ldap_pvt_discard LDAP_P(( + struct ldap *ld, ber_int_t msgid )); + +/* init.c */ +LDAP_F( int ) +ldap_pvt_conf_option LDAP_P(( + char *cmd, char *opt, int userconf )); + +/* ldifutil.c */ +LDAP_F( int ) +ldap_parse_ldif_record_x LDAP_P(( + struct berval *rbuf, + unsigned long linenum, + struct ldifrecord *lr, + const char *errstr, + unsigned int flags, + void *ctx )); + +/* messages.c */ +LDAP_F( BerElement * ) +ldap_get_message_ber LDAP_P(( + struct ldapmsg * )); + +/* open */ +LDAP_F (int) ldap_open_internal_connection LDAP_P(( + struct ldap **ldp, ber_socket_t *fdp )); + +/* sasl.c */ +LDAP_F (int) ldap_pvt_sasl_generic_install LDAP_P(( Sockbuf *sb, + struct sb_sasl_generic_install *install_arg )); +LDAP_F (void) ldap_pvt_sasl_generic_remove LDAP_P(( Sockbuf *sb )); + +/* search.c */ +LDAP_F( int ) ldap_pvt_put_filter LDAP_P(( + BerElement *ber, + const char *str )); + +LDAP_F( char * ) +ldap_pvt_find_wildcard LDAP_P(( const char *s )); + +LDAP_F( ber_slen_t ) +ldap_pvt_filter_value_unescape LDAP_P(( char *filter )); + +LDAP_F( ber_len_t ) +ldap_bv2escaped_filter_value_len LDAP_P(( struct berval *in )); + +LDAP_F( int ) +ldap_bv2escaped_filter_value_x LDAP_P(( struct berval *in, struct berval *out, + int inplace, void *ctx )); + +LDAP_F (int) ldap_pvt_search LDAP_P(( + struct ldap *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + struct ldapcontrol **sctrls, + struct ldapcontrol **cctrls, + struct timeval *timeout, + int sizelimit, + int deref, + int *msgidp )); + +LDAP_F(int) ldap_pvt_search_s LDAP_P(( + struct ldap *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + struct ldapcontrol **sctrls, + struct ldapcontrol **cctrls, + struct timeval *timeout, + int sizelimit, + int deref, + struct ldapmsg **res )); + +/* string.c */ +LDAP_F( char * ) +ldap_pvt_str2upper LDAP_P(( char *str )); + +LDAP_F( char * ) +ldap_pvt_str2lower LDAP_P(( char *str )); + +LDAP_F( struct berval * ) +ldap_pvt_str2upperbv LDAP_P(( char *str, struct berval *bv )); + +LDAP_F( struct berval * ) +ldap_pvt_str2lowerbv LDAP_P(( char *str, struct berval *bv )); + +/* tls.c */ +LDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldap *ld, + int option, const char *arg )); +LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldap *ld, + int option, void *arg )); +LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldap *ld, + int option, void *arg )); + +LDAP_F (void) ldap_pvt_tls_destroy LDAP_P(( void )); +LDAP_F (int) ldap_pvt_tls_init LDAP_P(( int do_threads )); +LDAP_F (int) ldap_pvt_tls_init_def_ctx LDAP_P(( int is_server )); +LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg )); +LDAP_F (int) ldap_pvt_tls_connect LDAP_P(( struct ldap *ld, Sockbuf *sb, const char *host )); +LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb )); +LDAP_F (void *) ldap_pvt_tls_sb_ctx LDAP_P(( Sockbuf *sb )); +LDAP_F (void) ldap_pvt_tls_ctx_free LDAP_P(( void * )); + +typedef int LDAPDN_rewrite_dummy LDAP_P (( void *dn, unsigned flags )); + +typedef int (LDAP_TLS_CONNECT_CB) LDAP_P (( struct ldap *ld, void *ssl, + void *ctx, void *arg )); + +LDAP_F (int) ldap_pvt_tls_get_my_dn LDAP_P(( void *ctx, struct berval *dn, + LDAPDN_rewrite_dummy *func, unsigned flags )); +LDAP_F (int) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, struct berval *dn, + LDAPDN_rewrite_dummy *func, unsigned flags )); +LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx )); +LDAP_F (int) ldap_pvt_tls_get_unique LDAP_P(( void *ctx, struct berval *buf, int is_server )); +LDAP_F (int) ldap_pvt_tls_get_endpoint LDAP_P(( void *ctx, struct berval *buf, int is_server )); +LDAP_F (const char *) ldap_pvt_tls_get_version LDAP_P(( void *ctx )); +LDAP_F (const char *) ldap_pvt_tls_get_cipher LDAP_P(( void *ctx )); + +LDAP_END_DECL + +/* + * Multiple precision stuff + * + * May use OpenSSL's BIGNUM if built with TLS, + * or GNU's multiple precision library. But if + * long long is available, that's big enough + * and much more efficient. + * + * If none is available, unsigned long data is used. + */ + +LDAP_BEGIN_DECL + +#ifdef USE_MP_BIGNUM +/* + * Use OpenSSL's BIGNUM + */ +#include <openssl/crypto.h> +#include <openssl/bn.h> + +typedef BIGNUM* ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT (NULL) + +#define ldap_pvt_mp_init(mp) \ + do { (mp) = BN_new(); } while (0) + +/* FIXME: we rely on mpr being initialized */ +#define ldap_pvt_mp_init_set(mpr,mpv) \ + do { ldap_pvt_mp_init((mpr)); BN_add((mpr), (mpr), (mpv)); } while (0) + +#define ldap_pvt_mp_add(mpr,mpv) \ + BN_add((mpr), (mpr), (mpv)) + +#define ldap_pvt_mp_add_ulong(mp,v) \ + BN_add_word((mp), (v)) + +#define ldap_pvt_mp_clear(mp) \ + do { BN_free((mp)); (mp) = 0; } while (0) + +#elif defined(USE_MP_GMP) +/* + * Use GNU's multiple precision library + */ +#include <gmp.h> + +typedef mpz_t ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT { 0 } + +#define ldap_pvt_mp_init(mp) \ + mpz_init((mp)) + +#define ldap_pvt_mp_init_set(mpr,mpv) \ + mpz_init_set((mpr), (mpv)) + +#define ldap_pvt_mp_add(mpr,mpv) \ + mpz_add((mpr), (mpr), (mpv)) + +#define ldap_pvt_mp_add_ulong(mp,v) \ + mpz_add_ui((mp), (mp), (v)) + +#define ldap_pvt_mp_clear(mp) \ + mpz_clear((mp)) + +#else +/* + * Use unsigned long long + */ + +#ifdef USE_MP_LONG_LONG +typedef unsigned long long ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT (0LL) +#elif defined(USE_MP_LONG) +typedef unsigned long ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT (0L) +#elif defined(HAVE_LONG_LONG) +typedef unsigned long long ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT (0LL) +#else +typedef unsigned long ldap_pvt_mp_t; +#define LDAP_PVT_MP_INIT (0L) +#endif + +#define ldap_pvt_mp_init(mp) \ + do { (mp) = 0; } while (0) + +#define ldap_pvt_mp_init_set(mpr,mpv) \ + do { (mpr) = (mpv); } while (0) + +#define ldap_pvt_mp_add(mpr,mpv) \ + do { (mpr) += (mpv); } while (0) + +#define ldap_pvt_mp_add_ulong(mp,v) \ + do { (mp) += (v); } while (0) + +#define ldap_pvt_mp_clear(mp) \ + do { (mp) = 0; } while (0) + +#endif /* MP */ + +#include "ldap_pvt_uc.h" + +LDAP_END_DECL + +LDAP_BEGIN_DECL + +#include <limits.h> /* get CHAR_BIT */ + +/* Buffer space for sign, decimal digits and \0. Note: log10(2) < 146/485. */ +#define LDAP_PVT_INTTYPE_CHARS(type) (((sizeof(type)*CHAR_BIT-1)*146)/485 + 3) + +LDAP_END_DECL + +#endif /* _LDAP_PVT_H */ diff --git a/libs/ldap/include/ldap_pvt_thread.h b/libs/ldap/include/ldap_pvt_thread.h new file mode 100644 index 00000000000..18462ab57b5 --- /dev/null +++ b/libs/ldap/include/ldap_pvt_thread.h @@ -0,0 +1,342 @@ +/* ldap_pvt_thread.h - ldap threads header file */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _LDAP_PVT_THREAD_H +#define _LDAP_PVT_THREAD_H /* libldap/ldap_thr_debug.h #undefines this */ + +#include "ldap_cdefs.h" +#include "ldap_int_thread.h" + +LDAP_BEGIN_DECL + +#ifndef LDAP_PVT_THREAD_H_DONE +typedef ldap_int_thread_t ldap_pvt_thread_t; +#ifdef LDAP_THREAD_DEBUG_WRAP +typedef ldap_debug_thread_mutex_t ldap_pvt_thread_mutex_t; +typedef ldap_debug_thread_cond_t ldap_pvt_thread_cond_t; +typedef ldap_debug_thread_rdwr_t ldap_pvt_thread_rdwr_t; +#define LDAP_PVT_MUTEX_FIRSTCREATE LDAP_DEBUG_MUTEX_FIRSTCREATE +#define LDAP_PVT_MUTEX_NULL LDAP_DEBUG_MUTEX_NULL +#else +typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t; +typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t; +typedef ldap_int_thread_rdwr_t ldap_pvt_thread_rdwr_t; +#define LDAP_PVT_MUTEX_FIRSTCREATE LDAP_INT_MUTEX_FIRSTCREATE +#define LDAP_PVT_MUTEX_NULL LDAP_INT_MUTEX_NULL +#endif +typedef ldap_int_thread_key_t ldap_pvt_thread_key_t; +#endif /* !LDAP_PVT_THREAD_H_DONE */ + +#define ldap_pvt_thread_equal ldap_int_thread_equal + +LDAP_F( int ) +ldap_pvt_thread_initialize LDAP_P(( void )); + +LDAP_F( int ) +ldap_pvt_thread_destroy LDAP_P(( void )); + +LDAP_F( unsigned int ) +ldap_pvt_thread_sleep LDAP_P(( unsigned int s )); + +LDAP_F( int ) +ldap_pvt_thread_get_concurrency LDAP_P(( void )); + +LDAP_F( int ) +ldap_pvt_thread_set_concurrency LDAP_P(( int )); + +#define LDAP_PVT_THREAD_CREATE_JOINABLE 0 +#define LDAP_PVT_THREAD_CREATE_DETACHED 1 + +#ifndef LDAP_PVT_THREAD_H_DONE +#define LDAP_PVT_THREAD_SET_STACK_SIZE +/* The size may be explicitly #defined to zero to disable it. */ +#if defined( LDAP_PVT_THREAD_STACK_SIZE ) && LDAP_PVT_THREAD_STACK_SIZE == 0 +# undef LDAP_PVT_THREAD_SET_STACK_SIZE +#elif !defined( LDAP_PVT_THREAD_STACK_SIZE ) + /* LARGE stack. Will be twice as large on 64 bit machine. */ +# define LDAP_PVT_THREAD_STACK_SIZE ( 1 * 1024 * 1024 * sizeof(void *) ) +#endif +#endif /* !LDAP_PVT_THREAD_H_DONE */ + +LDAP_F( int ) +ldap_pvt_thread_create LDAP_P(( + ldap_pvt_thread_t * thread, + int detach, + void *(*start_routine)( void * ), + void *arg)); + +LDAP_F( void ) +ldap_pvt_thread_exit LDAP_P(( void *retval )); + +LDAP_F( int ) +ldap_pvt_thread_join LDAP_P(( ldap_pvt_thread_t thread, void **status )); + +LDAP_F( int ) +ldap_pvt_thread_kill LDAP_P(( ldap_pvt_thread_t thread, int signo )); + +LDAP_F( int ) +ldap_pvt_thread_yield LDAP_P(( void )); + +LDAP_F( int ) +ldap_pvt_thread_cond_init LDAP_P(( ldap_pvt_thread_cond_t *cond )); + +LDAP_F( int ) +ldap_pvt_thread_cond_destroy LDAP_P(( ldap_pvt_thread_cond_t *cond )); + +LDAP_F( int ) +ldap_pvt_thread_cond_signal LDAP_P(( ldap_pvt_thread_cond_t *cond )); + +LDAP_F( int ) +ldap_pvt_thread_cond_broadcast LDAP_P(( ldap_pvt_thread_cond_t *cond )); + +LDAP_F( int ) +ldap_pvt_thread_cond_wait LDAP_P(( + ldap_pvt_thread_cond_t *cond, + ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_init LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_recursive_init LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_destroy LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_lock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_trylock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( int ) +ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex )); + +LDAP_F( ldap_pvt_thread_t ) +ldap_pvt_thread_self LDAP_P(( void )); + +#ifdef LDAP_INT_THREAD_ASSERT_MUTEX_OWNER +#define LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER LDAP_INT_THREAD_ASSERT_MUTEX_OWNER +#else +#define LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER(mutex) ((void) 0) +#endif + +LDAP_F( int ) +ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_destroy LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_rlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_rtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_runlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_wlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_wtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_key_create LDAP_P((ldap_pvt_thread_key_t *keyp)); + +LDAP_F( int ) +ldap_pvt_thread_key_destroy LDAP_P((ldap_pvt_thread_key_t key)); + +LDAP_F( int ) +ldap_pvt_thread_key_setdata LDAP_P((ldap_pvt_thread_key_t key, void *data)); + +LDAP_F( int ) +ldap_pvt_thread_key_getdata LDAP_P((ldap_pvt_thread_key_t key, void **data)); + +#ifdef LDAP_DEBUG +LDAP_F( int ) +ldap_pvt_thread_rdwr_readers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_writers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); + +LDAP_F( int ) +ldap_pvt_thread_rdwr_active LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp)); +#endif /* LDAP_DEBUG */ + +#define LDAP_PVT_THREAD_EINVAL EINVAL +#define LDAP_PVT_THREAD_EBUSY EINVAL + +#ifndef LDAP_PVT_THREAD_H_DONE +typedef ldap_int_thread_pool_t ldap_pvt_thread_pool_t; + +typedef void * (ldap_pvt_thread_start_t) LDAP_P((void *ctx, void *arg)); +typedef int (ldap_pvt_thread_walk_t) LDAP_P((ldap_pvt_thread_start_t *start, void *start_arg, void *arg)); +typedef void (ldap_pvt_thread_pool_keyfree_t) LDAP_P((void *key, void *data)); +#endif /* !LDAP_PVT_THREAD_H_DONE */ + +LDAP_F( int ) +ldap_pvt_thread_pool_init LDAP_P(( + ldap_pvt_thread_pool_t *pool_out, + int max_threads, + int max_pending )); + +LDAP_F( int ) +ldap_pvt_thread_pool_init_q LDAP_P(( + ldap_pvt_thread_pool_t *pool_out, + int max_threads, + int max_pending, + int num_qs )); + +LDAP_F( int ) +ldap_pvt_thread_pool_submit LDAP_P(( + ldap_pvt_thread_pool_t *pool, + ldap_pvt_thread_start_t *start, + void *arg )); + +LDAP_F( int ) +ldap_pvt_thread_pool_submit2 LDAP_P(( + ldap_pvt_thread_pool_t *pool, + ldap_pvt_thread_start_t *start, + void *arg, + void **cookie )); + +LDAP_F( int ) +ldap_pvt_thread_pool_retract LDAP_P(( + void *cookie )); + +LDAP_F( int ) +ldap_pvt_thread_pool_walk LDAP_P(( + ldap_pvt_thread_pool_t *pool, + ldap_pvt_thread_start_t *start, + ldap_pvt_thread_walk_t *cb, + void *arg )); + +LDAP_F( int ) +ldap_pvt_thread_pool_maxthreads LDAP_P(( + ldap_pvt_thread_pool_t *pool, + int max_threads )); + +LDAP_F( int ) +ldap_pvt_thread_pool_queues LDAP_P(( + ldap_pvt_thread_pool_t *pool, + int numqs )); + +#ifndef LDAP_PVT_THREAD_H_DONE +typedef enum { + LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN = -1, + LDAP_PVT_THREAD_POOL_PARAM_MAX, + LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING, + LDAP_PVT_THREAD_POOL_PARAM_OPEN, + LDAP_PVT_THREAD_POOL_PARAM_STARTING, + LDAP_PVT_THREAD_POOL_PARAM_ACTIVE, + LDAP_PVT_THREAD_POOL_PARAM_PAUSING, + LDAP_PVT_THREAD_POOL_PARAM_PENDING, + LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD, + LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX, + LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX, + LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX, + LDAP_PVT_THREAD_POOL_PARAM_STATE +} ldap_pvt_thread_pool_param_t; +#endif /* !LDAP_PVT_THREAD_H_DONE */ + +LDAP_F( int ) +ldap_pvt_thread_pool_query LDAP_P(( + ldap_pvt_thread_pool_t *pool, + ldap_pvt_thread_pool_param_t param, void *value )); + +LDAP_F( int ) +ldap_pvt_thread_pool_pausing LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_backload LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( void ) +ldap_pvt_thread_pool_idle LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( void ) +ldap_pvt_thread_pool_unidle LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_pausecheck LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_pausecheck_native LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_pause LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_resume LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_destroy LDAP_P(( + ldap_pvt_thread_pool_t *pool, + int run_pending )); + +LDAP_F( int ) +ldap_pvt_thread_pool_close LDAP_P(( + ldap_pvt_thread_pool_t *pool, + int run_pending )); + +LDAP_F( int ) +ldap_pvt_thread_pool_free LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + +LDAP_F( int ) +ldap_pvt_thread_pool_getkey LDAP_P(( + void *ctx, + void *key, + void **data, + ldap_pvt_thread_pool_keyfree_t **kfree )); + +LDAP_F( int ) +ldap_pvt_thread_pool_setkey LDAP_P(( + void *ctx, + void *key, + void *data, + ldap_pvt_thread_pool_keyfree_t *kfree, + void **olddatap, + ldap_pvt_thread_pool_keyfree_t **oldkfreep )); + +LDAP_F( void ) +ldap_pvt_thread_pool_purgekey LDAP_P(( void *key )); + +LDAP_F( void *) +ldap_pvt_thread_pool_context LDAP_P(( void )); + +LDAP_F( void ) +ldap_pvt_thread_pool_context_reset LDAP_P(( void *key )); + +LDAP_F( ldap_pvt_thread_t ) +ldap_pvt_thread_pool_tid LDAP_P(( void *ctx )); + +LDAP_END_DECL + +#define LDAP_PVT_THREAD_H_DONE +#endif /* _LDAP_PVT_THREAD_H */ diff --git a/libs/ldap/include/ldap_pvt_uc.h b/libs/ldap/include/ldap_pvt_uc.h new file mode 100644 index 00000000000..76382ac9150 --- /dev/null +++ b/libs/ldap/include/ldap_pvt_uc.h @@ -0,0 +1,161 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * ldap_pvt_uc.h - Header for Unicode functions. + * These are meant to be used by the OpenLDAP distribution only. + * These should be named ldap_pvt_....() + */ + +#ifndef _LDAP_PVT_UC_H +#define _LDAP_PVT_UC_H 1 + +#include <lber.h> /* get ber_slen_t */ + +#include <ac/bytes.h> + +LDAP_BEGIN_DECL + +/* + * UTF-8 (in utf-8.c) + */ + +/* UCDATA uses UCS-2 passed in a 4 byte unsigned int */ +typedef ac_uint4 ldap_unicode_t; + +/* Convert a string with csize octets per character to UTF-8 */ +LDAP_F( int ) ldap_ucs_to_utf8s LDAP_P(( + struct berval *ucs, int csize, struct berval *utf8s )); + + +/* returns the number of bytes in the UTF-8 string */ +LDAP_F (ber_len_t) ldap_utf8_bytes( const char * ); +/* returns the number of UTF-8 characters in the string */ +LDAP_F (ber_len_t) ldap_utf8_chars( const char * ); +/* returns the length (in bytes) of the UTF-8 character */ +LDAP_F (int) ldap_utf8_offset( const char * ); +/* returns the length (in bytes) indicated by the UTF-8 character */ +LDAP_F (int) ldap_utf8_charlen( const char * ); + +/* returns the length (in bytes) indicated by the UTF-8 character + * also checks that shortest possible encoding was used + */ +LDAP_F (int) ldap_utf8_charlen2( const char * ); + +/* copies a UTF-8 character and returning number of bytes copied */ +LDAP_F (int) ldap_utf8_copy( char *, const char *); + +/* returns pointer of next UTF-8 character in string */ +LDAP_F (char*) ldap_utf8_next( const char * ); +/* returns pointer of previous UTF-8 character in string */ +LDAP_F (char*) ldap_utf8_prev( const char * ); + +/* primitive ctype routines -- not aware of non-ascii characters */ +LDAP_F (int) ldap_utf8_isascii( const char * ); +LDAP_F (int) ldap_utf8_isalpha( const char * ); +LDAP_F (int) ldap_utf8_isalnum( const char * ); +LDAP_F (int) ldap_utf8_isdigit( const char * ); +LDAP_F (int) ldap_utf8_isxdigit( const char * ); +LDAP_F (int) ldap_utf8_isspace( const char * ); + +/* span characters not in set, return bytes spanned */ +LDAP_F (ber_len_t) ldap_utf8_strcspn( const char* str, const char *set); +/* span characters in set, return bytes spanned */ +LDAP_F (ber_len_t) ldap_utf8_strspn( const char* str, const char *set); +/* return first occurrence of character in string */ +LDAP_F (char *) ldap_utf8_strchr( const char* str, const char *chr); +/* return first character of set in string */ +LDAP_F (char *) ldap_utf8_strpbrk( const char* str, const char *set); +/* reentrant tokenizer */ +LDAP_F (char*) ldap_utf8_strtok( char* sp, const char* sep, char **last); + +/* Optimizations */ +LDAP_V (const char) ldap_utf8_lentab[128]; +LDAP_V (const char) ldap_utf8_mintab[32]; + +#define LDAP_UTF8_ISASCII(p) ( !(*(const unsigned char *)(p) & 0x80 ) ) +#define LDAP_UTF8_CHARLEN(p) ( LDAP_UTF8_ISASCII(p) \ + ? 1 : ldap_utf8_lentab[*(const unsigned char *)(p) ^ 0x80] ) + +/* This is like CHARLEN but additionally validates to make sure + * the char used the shortest possible encoding. + * 'l' is used to temporarily hold the result of CHARLEN. + */ +#define LDAP_UTF8_CHARLEN2(p, l) ( ( ( l = LDAP_UTF8_CHARLEN( p )) < 3 || \ + ( ldap_utf8_mintab[*(const unsigned char *)(p) & 0x1f] & (p)[1] ) ) ? \ + l : 0 ) + +#define LDAP_UTF8_OFFSET(p) ( LDAP_UTF8_ISASCII(p) \ + ? 1 : ldap_utf8_offset((p)) ) + +#define LDAP_UTF8_COPY(d,s) ( LDAP_UTF8_ISASCII(s) \ + ? (*(d) = *(s), 1) : ldap_utf8_copy((d),(s)) ) + +#define LDAP_UTF8_NEXT(p) ( LDAP_UTF8_ISASCII(p) \ + ? (char *)(p)+1 : ldap_utf8_next((p)) ) + +#define LDAP_UTF8_INCR(p) ((p) = LDAP_UTF8_NEXT(p)) + +/* For symmetry */ +#define LDAP_UTF8_PREV(p) (ldap_utf8_prev((p))) +#define LDAP_UTF8_DECR(p) ((p)=LDAP_UTF8_PREV((p))) + + +/* these probably should be renamed */ +LDAP_LUNICODE_F(int) ucstrncmp( + const ldap_unicode_t *, + const ldap_unicode_t *, + ber_len_t ); + +LDAP_LUNICODE_F(int) ucstrncasecmp( + const ldap_unicode_t *, + const ldap_unicode_t *, + ber_len_t ); + +LDAP_LUNICODE_F(ldap_unicode_t *) ucstrnchr( + const ldap_unicode_t *, + ber_len_t, + ldap_unicode_t ); + +LDAP_LUNICODE_F(ldap_unicode_t *) ucstrncasechr( + const ldap_unicode_t *, + ber_len_t, + ldap_unicode_t ); + +LDAP_LUNICODE_F(void) ucstr2upper( + ldap_unicode_t *, + ber_len_t ); + +#define LDAP_UTF8_NOCASEFOLD 0x0U +#define LDAP_UTF8_CASEFOLD 0x1U +#define LDAP_UTF8_ARG1NFC 0x2U +#define LDAP_UTF8_ARG2NFC 0x4U +#define LDAP_UTF8_APPROX 0x8U + +LDAP_LUNICODE_F(struct berval *) UTF8bvnormalize( + struct berval *, + struct berval *, + unsigned, + void *memctx ); + +LDAP_LUNICODE_F(int) UTF8bvnormcmp( + struct berval *, + struct berval *, + unsigned, + void *memctx ); + +LDAP_END_DECL + +#endif diff --git a/libs/ldap/include/ldap_queue.h b/libs/ldap/include/ldap_queue.h new file mode 100644 index 00000000000..6d32370107e --- /dev/null +++ b/libs/ldap/include/ldap_queue.h @@ -0,0 +1,593 @@ +/* ldap_queue.h -- queue macros */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2001-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.5 2001/09/30 21:12:54 luigi Exp $ + * + * See also: ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change + */ +/* ACKNOWLEDGEMENTS: + * This work is derived from FreeBSD queue.h work. Adapted for use in + * OpenLDAP Software by Kurt D. Zeilenga. + */ + +#ifndef _LDAP_QUEUE_H_ +#define _LDAP_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * singly-linked tail queues, lists, tail queues, and circular queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. Also, it is possible to rotate the queue, + * rejoining the ends and splitting it so that a given element becomes the + * new head or tail. + * + * For details on the use of these macros, see the queue(3) manual page. + * All macros are prefixed with LDAP_. + * + * SLIST_ LIST_ STAILQ_ TAILQ_ CIRCLEQ_ + * _HEAD + + + + + + * _ENTRY + + + + + + * _INIT + + + + + + * _ENTRY_INIT + + + + + + * _EMPTY + + + + + + * _FIRST + + + + + + * _NEXT + + + + + + * _PREV - - - + + + * _LAST - - + + + + * _FOREACH + + + + + + * _FOREACH_REVERSE - - - + + + * _INSERT_HEAD + + + + + + * _INSERT_BEFORE - + - + + + * _INSERT_AFTER + + + + + + * _INSERT_TAIL - - + + + + * _REMOVE_HEAD + - + - - + * _REMOVE + + + + + + * + */ + +/* + * Singly-linked List definitions. + */ +#define LDAP_SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define LDAP_SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LDAP_SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define LDAP_SLIST_ENTRY_INITIALIZER(entry) \ + { NULL } + +/* + * Singly-linked List functions. + */ +#define LDAP_SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define LDAP_SLIST_FIRST(head) ((head)->slh_first) + +#define LDAP_SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +#define LDAP_SLIST_INIT(head) { \ + (head)->slh_first = NULL; \ +} + +#define LDAP_SLIST_ENTRY_INIT(var, field) { \ + (var)->field.sle_next = NULL; \ +} + +#define LDAP_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define LDAP_SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define LDAP_SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define LDAP_SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define LDAP_SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + LDAP_SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while( curelm->field.sle_next != (elm) ) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (0) + +/* + * Singly-linked Tail queue definitions. + */ +#define LDAP_STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define LDAP_STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define LDAP_STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define LDAP_STAILQ_ENTRY_INITIALIZER(entry) \ + { NULL } + +/* + * Singly-linked Tail queue functions. + */ +#define LDAP_STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define LDAP_STAILQ_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (0) + +#define LDAP_STAILQ_ENTRY_INIT(var, field) { \ + (var)->field.stqe_next = NULL; \ +} + +#define LDAP_STAILQ_FIRST(head) ((head)->stqh_first) + +#define LDAP_STAILQ_LAST(head, type, field) \ + (LDAP_STAILQ_EMPTY(head) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + +#define LDAP_STAILQ_FOREACH(var, head, field) \ + for((var) = (head)->stqh_first; (var); (var) = (var)->field.stqe_next) + +#define LDAP_STAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ +} while (0) + +#define LDAP_STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ +} while (0) + +#define LDAP_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (tqelm)->field.stqe_next = (elm); \ +} while (0) + +#define LDAP_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define LDAP_STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = \ + (head)->stqh_first->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (0) + +#define LDAP_STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (0) + +#define LDAP_STAILQ_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + LDAP_STAILQ_REMOVE_HEAD(head, field); \ + } \ + else { \ + struct type *curelm = (head)->stqh_first; \ + while( curelm->field.stqe_next != (elm) ) \ + curelm = curelm->field.stqe_next; \ + if((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LDAP_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LDAP_LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LDAP_LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LDAP_LIST_ENTRY_INITIALIZER(entry) \ + { NULL, NULL } + +/* + * List functions. + */ + +#define LDAP_LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LDAP_LIST_FIRST(head) ((head)->lh_first) + +#define LDAP_LIST_FOREACH(var, head, field) \ + for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next) + +#define LDAP_LIST_INIT(head) do { \ + (head)->lh_first = NULL; \ +} while (0) + +#define LDAP_LIST_ENTRY_INIT(var, field) do { \ + (var)->field.le_next = NULL; \ + (var)->field.le_prev = NULL; \ +} while (0) + +#define LDAP_LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LDAP_LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LDAP_LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LDAP_LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LDAP_LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define LDAP_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define LDAP_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define LDAP_TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +#define LDAP_TAILQ_ENTRY_INITIALIZER(entry) \ + { NULL, NULL } + +/* + * Tail queue functions. + */ +#define LDAP_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define LDAP_TAILQ_FOREACH(var, head, field) \ + for (var = LDAP_TAILQ_FIRST(head); var; var = LDAP_TAILQ_NEXT(var, field)) + +#define LDAP_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = LDAP_TAILQ_LAST((head), headname); \ + (var); \ + (var) = LDAP_TAILQ_PREV((var), headname, field)) + +#define LDAP_TAILQ_FIRST(head) ((head)->tqh_first) + +#define LDAP_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define LDAP_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define LDAP_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define LDAP_TAILQ_ENTRY_INIT(var, field) do { \ + (var)->field.tqe_next = NULL; \ + (var)->field.tqe_prev = NULL; \ +} while (0) + +#define LDAP_TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define LDAP_TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define LDAP_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define LDAP_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define LDAP_TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +/* + * Circular queue definitions. + */ +#define LDAP_CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define LDAP_CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&(head), (void *)&(head) } + +#define LDAP_CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define LDAP_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) + +#define LDAP_CIRCLEQ_FIRST(head) ((head)->cqh_first) + +#define LDAP_CIRCLEQ_FOREACH(var, head, field) \ + for((var) = (head)->cqh_first; \ + (var) != (void *)(head); \ + (var) = (var)->field.cqe_next) + +#define LDAP_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = (head)->cqh_last; \ + (var) != (void *)(head); \ + (var) = (var)->field.cqe_prev) + +#define LDAP_CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (0) + +#define LDAP_CIRCLEQ_ENTRY_INIT(var, field) do { \ + (var)->field.cqe_next = NULL; \ + (var)->field.cqe_prev = NULL; \ +} while (0) + +#define LDAP_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define LDAP_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define LDAP_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define LDAP_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define LDAP_CIRCLEQ_LAST(head) ((head)->cqh_last) + +#define LDAP_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) + +#define LDAP_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) + +#define LDAP_CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define LDAP_CIRCLEQ_LOOP_NEXT(head, elm, field) \ + (((elm)->field.cqe_next == (void *)(head)) \ + ? ((head)->cqh_first) \ + : ((elm)->field.cqe_next)) + +#define LDAP_CIRCLEQ_LOOP_PREV(head, elm, field) \ + (((elm)->field.cqe_prev == (void *)(head)) \ + ? ((head)->cqh_last) \ + : ((elm)->field.cqe_prev)) + +#define LDAP_CIRCLEQ_MAKE_HEAD(head, elm, field) do { \ + if ((elm)->field.cqe_prev != (void *)(head)) { \ + (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \ + (head)->cqh_last->field.cqe_next = (head)->cqh_first; \ + (head)->cqh_first = elm; \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + (elm)->field.cqe_prev->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (void *)(head); \ + } \ +} while (0) + +#define LDAP_CIRCLEQ_MAKE_TAIL(head, elm, field) do { \ + if ((elm)->field.cqe_next != (void *)(head)) { \ + (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \ + (head)->cqh_last->field.cqe_next = (head)->cqh_first; \ + (head)->cqh_first = (elm)->field.cqe_next; \ + (head)->cqh_last = elm; \ + (elm)->field.cqe_next->field.cqe_prev = (void *)(head); \ + (elm)->field.cqe_next = (void *)(head); \ + } \ +} while (0) + +#endif /* !_LDAP_QUEUE_H_ */ diff --git a/libs/ldap/include/ldap_rq.h b/libs/ldap/include/ldap_rq.h new file mode 100644 index 00000000000..1050550ba85 --- /dev/null +++ b/libs/ldap/include/ldap_rq.h @@ -0,0 +1,102 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef LDAP_RQ_H +#define LDAP_RQ_H 1 + +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +typedef struct re_s { + struct timeval next_sched; + struct timeval interval; + LDAP_STAILQ_ENTRY(re_s) tnext; /* it includes running */ + LDAP_STAILQ_ENTRY(re_s) rnext; + ldap_pvt_thread_start_t *routine; + void *arg; + char *tname; + char *tspec; + void *pool_cookie; +} re_t; + +typedef struct runqueue_s { + LDAP_STAILQ_HEAD(l, re_s) task_list; + LDAP_STAILQ_HEAD(rl, re_s) run_list; + ldap_pvt_thread_mutex_t rq_mutex; +} runqueue_t; + +LDAP_F( struct re_s* ) +ldap_pvt_runqueue_insert( + struct runqueue_s* rq, + time_t interval, + ldap_pvt_thread_start_t* routine, + void *arg, + char *tname, + char *tspec +); + +LDAP_F( struct re_s* ) +ldap_pvt_runqueue_find( + struct runqueue_s* rq, + ldap_pvt_thread_start_t* routine, + void *arg +); + +LDAP_F( void ) +ldap_pvt_runqueue_remove( + struct runqueue_s* rq, + struct re_s* entry +); + +LDAP_F( struct re_s* ) +ldap_pvt_runqueue_next_sched( + struct runqueue_s* rq, + struct timeval* next_run +); + +LDAP_F( void ) +ldap_pvt_runqueue_runtask( + struct runqueue_s* rq, + struct re_s* entry +); + +LDAP_F( void ) +ldap_pvt_runqueue_stoptask( + struct runqueue_s* rq, + struct re_s* entry +); + +LDAP_F( int ) +ldap_pvt_runqueue_isrunning( + struct runqueue_s* rq, + struct re_s* entry +); + +LDAP_F( void ) +ldap_pvt_runqueue_resched( + struct runqueue_s* rq, + struct re_s* entry, + int defer +); + +LDAP_F( int ) +ldap_pvt_runqueue_persistent_backload( + struct runqueue_s* rq +); + +LDAP_END_DECL + +#endif diff --git a/libs/ldap/include/ldap_schema.h b/libs/ldap/include/ldap_schema.h new file mode 100644 index 00000000000..9a01d2c059b --- /dev/null +++ b/libs/ldap/include/ldap_schema.h @@ -0,0 +1,359 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* ldap-schema.h - Header for basic schema handling functions that can be + * used by both clients and servers. + * these routines should be renamed ldap_x_... + */ + +#ifndef _LDAP_SCHEMA_H +#define _LDAP_SCHEMA_H 1 + +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +/* Codes for parsing errors */ + +#define LDAP_SCHERR_OUTOFMEM 1 +#define LDAP_SCHERR_UNEXPTOKEN 2 +#define LDAP_SCHERR_NOLEFTPAREN 3 +#define LDAP_SCHERR_NORIGHTPAREN 4 +#define LDAP_SCHERR_NODIGIT 5 +#define LDAP_SCHERR_BADNAME 6 +#define LDAP_SCHERR_BADDESC 7 +#define LDAP_SCHERR_BADSUP 8 +#define LDAP_SCHERR_DUPOPT 9 +#define LDAP_SCHERR_EMPTY 10 +#define LDAP_SCHERR_MISSING 11 +#define LDAP_SCHERR_OUT_OF_ORDER 12 + +typedef struct ldap_schema_extension_item { + char *lsei_name; + char **lsei_values; +} LDAPSchemaExtensionItem; + +typedef struct ldap_syntax { + char *syn_oid; /* REQUIRED */ + char **syn_names; /* OPTIONAL */ + char *syn_desc; /* OPTIONAL */ + LDAPSchemaExtensionItem **syn_extensions; /* OPTIONAL */ +} LDAPSyntax; + +typedef struct ldap_matchingrule { + char *mr_oid; /* REQUIRED */ + char **mr_names; /* OPTIONAL */ + char *mr_desc; /* OPTIONAL */ + int mr_obsolete; /* OPTIONAL */ + char *mr_syntax_oid; /* REQUIRED */ + LDAPSchemaExtensionItem **mr_extensions; /* OPTIONAL */ +} LDAPMatchingRule; + +typedef struct ldap_matchingruleuse { + char *mru_oid; /* REQUIRED */ + char **mru_names; /* OPTIONAL */ + char *mru_desc; /* OPTIONAL */ + int mru_obsolete; /* OPTIONAL */ + char **mru_applies_oids; /* REQUIRED */ + LDAPSchemaExtensionItem **mru_extensions; /* OPTIONAL */ +} LDAPMatchingRuleUse; + +typedef struct ldap_attributetype { + char *at_oid; /* REQUIRED */ + char **at_names; /* OPTIONAL */ + char *at_desc; /* OPTIONAL */ + int at_obsolete; /* 0=no, 1=yes */ + char *at_sup_oid; /* OPTIONAL */ + char *at_equality_oid; /* OPTIONAL */ + char *at_ordering_oid; /* OPTIONAL */ + char *at_substr_oid; /* OPTIONAL */ + char *at_syntax_oid; /* OPTIONAL */ + int at_syntax_len; /* OPTIONAL */ + int at_single_value; /* 0=no, 1=yes */ + int at_collective; /* 0=no, 1=yes */ + int at_no_user_mod; /* 0=no, 1=yes */ + int at_usage; /* 0=userApplications, 1=directoryOperation, + 2=distributedOperation, 3=dSAOperation */ + LDAPSchemaExtensionItem **at_extensions; /* OPTIONAL */ +} LDAPAttributeType; + +typedef struct ldap_objectclass { + char *oc_oid; /* REQUIRED */ + char **oc_names; /* OPTIONAL */ + char *oc_desc; /* OPTIONAL */ + int oc_obsolete; /* 0=no, 1=yes */ + char **oc_sup_oids; /* OPTIONAL */ + int oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ + char **oc_at_oids_must; /* OPTIONAL */ + char **oc_at_oids_may; /* OPTIONAL */ + LDAPSchemaExtensionItem **oc_extensions; /* OPTIONAL */ +} LDAPObjectClass; + +typedef struct ldap_contentrule { + char *cr_oid; /* REQUIRED */ + char **cr_names; /* OPTIONAL */ + char *cr_desc; /* OPTIONAL */ + char **cr_sup_oids; /* OPTIONAL */ + int cr_obsolete; /* 0=no, 1=yes */ + char **cr_oc_oids_aux; /* OPTIONAL */ + char **cr_at_oids_must; /* OPTIONAL */ + char **cr_at_oids_may; /* OPTIONAL */ + char **cr_at_oids_not; /* OPTIONAL */ + LDAPSchemaExtensionItem **cr_extensions; /* OPTIONAL */ +} LDAPContentRule; + +typedef struct ldap_nameform { + char *nf_oid; /* REQUIRED */ + char **nf_names; /* OPTIONAL */ + char *nf_desc; /* OPTIONAL */ + int nf_obsolete; /* 0=no, 1=yes */ + char *nf_objectclass; /* REQUIRED */ + char **nf_at_oids_must; /* REQUIRED */ + char **nf_at_oids_may; /* OPTIONAL */ + LDAPSchemaExtensionItem **nf_extensions; /* OPTIONAL */ +} LDAPNameForm; + +typedef struct ldap_structurerule { + int sr_ruleid; /* REQUIRED */ + char **sr_names; /* OPTIONAL */ + char *sr_desc; /* OPTIONAL */ + int sr_obsolete; /* 0=no, 1=yes */ + char *sr_nameform; /* REQUIRED */ + int sr_nsup_ruleids;/* number of sr_sup_ruleids */ + int *sr_sup_ruleids;/* OPTIONAL */ + LDAPSchemaExtensionItem **sr_extensions; /* OPTIONAL */ +} LDAPStructureRule; + +/* + * Misc macros + */ +#define LDAP_SCHEMA_NO 0 +#define LDAP_SCHEMA_YES 1 + +#define LDAP_SCHEMA_USER_APPLICATIONS 0 +#define LDAP_SCHEMA_DIRECTORY_OPERATION 1 +#define LDAP_SCHEMA_DISTRIBUTED_OPERATION 2 +#define LDAP_SCHEMA_DSA_OPERATION 3 + +#define LDAP_SCHEMA_ABSTRACT 0 +#define LDAP_SCHEMA_STRUCTURAL 1 +#define LDAP_SCHEMA_AUXILIARY 2 + + +/* + * Flags that control how liberal the parsing routines are. + */ +#define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ +#define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ +#define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ +#define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ +#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ +#define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ +#define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ +#define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ +#define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ + + +LDAP_F( LDAP_CONST char * ) +ldap_syntax2name LDAP_P(( + LDAPSyntax * syn )); + +LDAP_F( LDAP_CONST char * ) +ldap_matchingrule2name LDAP_P(( + LDAPMatchingRule * mr )); + +LDAP_F( LDAP_CONST char * ) +ldap_matchingruleuse2name LDAP_P(( + LDAPMatchingRuleUse * mru )); + +LDAP_F( LDAP_CONST char * ) +ldap_attributetype2name LDAP_P(( + LDAPAttributeType * at )); + +LDAP_F( LDAP_CONST char * ) +ldap_objectclass2name LDAP_P(( + LDAPObjectClass * oc )); + +LDAP_F( LDAP_CONST char * ) +ldap_contentrule2name LDAP_P(( + LDAPContentRule * cr )); + +LDAP_F( LDAP_CONST char * ) +ldap_nameform2name LDAP_P(( + LDAPNameForm * nf )); + +LDAP_F( LDAP_CONST char * ) +ldap_structurerule2name LDAP_P(( + LDAPStructureRule * sr )); + +LDAP_F( void ) +ldap_syntax_free LDAP_P(( + LDAPSyntax * syn )); + +LDAP_F( void ) +ldap_matchingrule_free LDAP_P(( + LDAPMatchingRule * mr )); + +LDAP_F( void ) +ldap_matchingruleuse_free LDAP_P(( + LDAPMatchingRuleUse * mr )); + +LDAP_F( void ) +ldap_attributetype_free LDAP_P(( + LDAPAttributeType * at )); + +LDAP_F( void ) +ldap_objectclass_free LDAP_P(( + LDAPObjectClass * oc )); + +LDAP_F( void ) +ldap_contentrule_free LDAP_P(( + LDAPContentRule * cr )); + +LDAP_F( void ) +ldap_nameform_free LDAP_P(( + LDAPNameForm * nf )); + +LDAP_F( void ) +ldap_structurerule_free LDAP_P(( + LDAPStructureRule * sr )); + +LDAP_F( LDAPStructureRule * ) +ldap_str2structurerule LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPNameForm * ) +ldap_str2nameform LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPContentRule * ) +ldap_str2contentrule LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPObjectClass * ) +ldap_str2objectclass LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPAttributeType * ) +ldap_str2attributetype LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPSyntax * ) +ldap_str2syntax LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPMatchingRule * ) +ldap_str2matchingrule LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( LDAPMatchingRuleUse * ) +ldap_str2matchingruleuse LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags )); + +LDAP_F( char * ) +ldap_structurerule2str LDAP_P(( + LDAPStructureRule * sr )); + +LDAP_F( struct berval * ) +ldap_structurerule2bv LDAP_P(( + LDAPStructureRule * sr, struct berval *bv )); + +LDAP_F( char * ) +ldap_nameform2str LDAP_P(( + LDAPNameForm * nf )); + +LDAP_F( struct berval * ) +ldap_nameform2bv LDAP_P(( + LDAPNameForm * nf, struct berval *bv )); + +LDAP_F( char * ) +ldap_contentrule2str LDAP_P(( + LDAPContentRule * cr )); + +LDAP_F( struct berval * ) +ldap_contentrule2bv LDAP_P(( + LDAPContentRule * cr, struct berval *bv )); + +LDAP_F( char * ) +ldap_objectclass2str LDAP_P(( + LDAPObjectClass * oc )); + +LDAP_F( struct berval * ) +ldap_objectclass2bv LDAP_P(( + LDAPObjectClass * oc, struct berval *bv )); + +LDAP_F( char * ) +ldap_attributetype2str LDAP_P(( + LDAPAttributeType * at )); + +LDAP_F( struct berval * ) +ldap_attributetype2bv LDAP_P(( + LDAPAttributeType * at, struct berval *bv )); + +LDAP_F( char * ) +ldap_syntax2str LDAP_P(( + LDAPSyntax * syn )); + +LDAP_F( struct berval * ) +ldap_syntax2bv LDAP_P(( + LDAPSyntax * syn, struct berval *bv )); + +LDAP_F( char * ) +ldap_matchingrule2str LDAP_P(( + LDAPMatchingRule * mr )); + +LDAP_F( struct berval * ) +ldap_matchingrule2bv LDAP_P(( + LDAPMatchingRule * mr, struct berval *bv )); + +LDAP_F( char * ) +ldap_matchingruleuse2str LDAP_P(( + LDAPMatchingRuleUse * mru )); + +LDAP_F( struct berval * ) +ldap_matchingruleuse2bv LDAP_P(( + LDAPMatchingRuleUse * mru, struct berval *bv )); + +LDAP_F( char * ) +ldap_scherr2str LDAP_P(( + int code )) LDAP_GCCATTR((const)); + +LDAP_END_DECL + +#endif diff --git a/libs/ldap/include/ldap_utf8.h b/libs/ldap/include/ldap_utf8.h new file mode 100644 index 00000000000..663043a594f --- /dev/null +++ b/libs/ldap/include/ldap_utf8.h @@ -0,0 +1,106 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ +/* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +#ifndef _LDAP_UTF8_H +#define _LDAP_UTF8_H + +#include <lber_types.h> /* get ber_*_t */ + +/* + * UTF-8 Utility Routines + */ + +LDAP_BEGIN_DECL + +#define LDAP_UCS4_INVALID (0x80000000U) +typedef ber_int_t ldap_ucs4_t; + + +/* LDAP_MAX_UTF8_LEN is 3 or 6 depending on size of wchar_t */ +#define LDAP_MAX_UTF8_LEN ( sizeof(wchar_t) * 3/2 ) + +/* Unicode conversion routines */ +LDAP_F( ldap_ucs4_t ) ldap_x_utf8_to_ucs4( LDAP_CONST char * p ); +LDAP_F( int ) ldap_x_ucs4_to_utf8( ldap_ucs4_t c, char *buf ); + + +/* + * Wide Char / UTF-8 Conversion Routines + */ + +/* UTF-8 character to Wide Char */ +LDAP_F(int) ldap_x_utf8_to_wc LDAP_P(( + wchar_t *wchar, LDAP_CONST char *utf8char )); + +/* UTF-8 string to Wide Char string */ +LDAP_F(int) ldap_x_utf8s_to_wcs LDAP_P(( + wchar_t *wcstr, LDAP_CONST char *utf8str, size_t count )); + +/* Wide Char to UTF-8 character */ +LDAP_F(int) ldap_x_wc_to_utf8 LDAP_P(( + char *utf8char, wchar_t wchar, size_t count )); + +/* Wide Char string to UTF-8 string */ +LDAP_F(int) ldap_x_wcs_to_utf8s LDAP_P(( + char *utf8str, LDAP_CONST wchar_t *wcstr, size_t count )); + +/* + * MultiByte Char / UTF-8 Conversion Routines + */ + +/* UTF-8 character to MultiByte character */ +LDAP_F(int) ldap_x_utf8_to_mb LDAP_P(( + char *mbchar, LDAP_CONST char *utf8char, + int (*ldap_f_wctomb)( char *mbchar, wchar_t wchar ))); + +/* UTF-8 string to MultiByte string */ +LDAP_F(int) ldap_x_utf8s_to_mbs LDAP_P(( + char *mbstr, LDAP_CONST char *utf8str, size_t count, + size_t (*ldap_f_wcstombs)( char *mbstr, + LDAP_CONST wchar_t *wcstr, size_t count) )); + +/* MultiByte character to UTF-8 character */ +LDAP_F(int) ldap_x_mb_to_utf8 LDAP_P(( + char *utf8char, LDAP_CONST char *mbchar, size_t mbsize, + int (*ldap_f_mbtowc)( wchar_t *wchar, + LDAP_CONST char *mbchar, size_t count) )); + +/* MultiByte string to UTF-8 string */ +LDAP_F(int) ldap_x_mbs_to_utf8s LDAP_P(( + char *utf8str, LDAP_CONST char *mbstr, size_t count, + size_t (*ldap_f_mbstowcs)( wchar_t *wcstr, + LDAP_CONST char *mbstr, size_t count) )); + +LDAP_END_DECL + +#endif /* _LDAP_UTF8_H */ diff --git a/libs/ldap/include/ldif.h b/libs/ldap/include/ldif.h new file mode 100644 index 00000000000..62cacdc8ee7 --- /dev/null +++ b/libs/ldap/include/ldif.h @@ -0,0 +1,171 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ + +#ifndef _LDIF_H +#define _LDIF_H + +#include <ldap_cdefs.h> + +LDAP_BEGIN_DECL + +/* This is NOT a bogus extern declaration (unlike ldap_debug) */ +LDAP_LDIF_V (int) ldif_debug; + +#define LDIF_LINE_WIDTH 78 /* default maximum length of LDIF lines */ +#define LDIF_LINE_WIDTH_MAX ((ber_len_t)-1) /* maximum length of LDIF lines */ +#define LDIF_LINE_WIDTH_WRAP(wrap) ((wrap) == 0 ? LDIF_LINE_WIDTH : (wrap)) + +/* + * Macro to calculate maximum number of bytes that the base64 equivalent + * of an item that is "len" bytes long will take up. Base64 encoding + * uses one byte for every six bits in the value plus up to two pad bytes. + */ +#define LDIF_BASE64_LEN(len) (((len) * 4 / 3 ) + 3) + +/* + * Macro to calculate maximum size that an LDIF-encoded type (length + * tlen) and value (length vlen) will take up: room for type + ":: " + + * first newline + base64 value + continued lines. Each continued line + * needs room for a newline and a leading space character. + */ +#define LDIF_SIZE_NEEDED(nlen,vlen) LDIF_SIZE_NEEDED_WRAP(nlen, vlen, 0) + +#define LDIF_SIZE_NEEDED_WRAP(nlen,vlen,wrap) \ + ((nlen) + 4 + LDIF_BASE64_LEN(vlen) \ + + ((wrap) == 0 ? ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / ( LDIF_LINE_WIDTH-1 ) * 2 ) : \ + ((wrap) == LDIF_LINE_WIDTH_MAX ? 0 : ((LDIF_BASE64_LEN(vlen) + (nlen) + 3) / (wrap-1) * 2 )))) + +LDAP_LDIF_F( int ) +ldif_parse_line LDAP_P(( + LDAP_CONST char *line, + char **name, + char **value, + ber_len_t *vlen )); + +LDAP_LDIF_F( int ) +ldif_parse_line2 LDAP_P(( + char *line, + struct berval *type, + struct berval *value, + int *freeval )); + +LDAP_LDIF_F( FILE * ) +ldif_open_url LDAP_P(( LDAP_CONST char *urlstr )); + +LDAP_LDIF_F( int ) +ldif_fetch_url LDAP_P(( + LDAP_CONST char *line, + char **value, + ber_len_t *vlen )); + +LDAP_LDIF_F( char * ) +ldif_getline LDAP_P(( char **next )); + +LDAP_LDIF_F( int ) +ldif_countlines LDAP_P(( LDAP_CONST char *line )); + +/* ldif_ropen, rclose, read_record - just for reading LDIF files, + * no special open/close needed to write LDIF files. + */ +typedef struct LDIFFP { + FILE *fp; + struct LDIFFP *prev; +} LDIFFP; + +LDAP_LDIF_F( LDIFFP * ) +ldif_open LDAP_P(( LDAP_CONST char *file, LDAP_CONST char *mode )); + +/* ldif_open equivalent that opens ldif stream in memory rather than from file */ +LDAP_LDIF_F( LDIFFP * ) +ldif_open_mem LDAP_P(( char *ldif, size_t size, LDAP_CONST char *mode )); + +LDAP_LDIF_F( void ) +ldif_close LDAP_P(( LDIFFP * )); + +LDAP_LDIF_F( int ) +ldif_read_record LDAP_P(( + LDIFFP *fp, + unsigned long *lineno, + char **bufp, + int *buflen )); + +LDAP_LDIF_F( int ) +ldif_must_b64_encode_register LDAP_P(( + LDAP_CONST char *name, + LDAP_CONST char *oid )); + +LDAP_LDIF_F( void ) +ldif_must_b64_encode_release LDAP_P(( void )); + +#define LDIF_PUT_NOVALUE 0x0000 /* no value */ +#define LDIF_PUT_VALUE 0x0001 /* value w/ auto detection */ +#define LDIF_PUT_TEXT 0x0002 /* assume text */ +#define LDIF_PUT_BINARY 0x0004 /* assume binary (convert to base64) */ +#define LDIF_PUT_B64 0x0008 /* pre-converted base64 value */ + +#define LDIF_PUT_COMMENT 0x0010 /* comment */ +#define LDIF_PUT_URL 0x0020 /* url */ +#define LDIF_PUT_SEP 0x0040 /* separator */ + +LDAP_LDIF_F( void ) +ldif_sput LDAP_P(( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen )); + +LDAP_LDIF_F( void ) +ldif_sput_wrap LDAP_P(( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap )); + +LDAP_LDIF_F( char * ) +ldif_put LDAP_P(( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen )); + +LDAP_LDIF_F( char * ) +ldif_put_wrap LDAP_P(( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap )); + +LDAP_LDIF_F( int ) +ldif_is_not_printable LDAP_P(( + LDAP_CONST char *val, + ber_len_t vlen )); + +LDAP_END_DECL + +#endif /* _LDIF_H */ diff --git a/libs/ldap/include/lutil.h b/libs/ldap/include/lutil.h new file mode 100644 index 00000000000..8205ed7cbcc --- /dev/null +++ b/libs/ldap/include/lutil.h @@ -0,0 +1,375 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _LUTIL_H +#define _LUTIL_H 1 + +#include <ldap_cdefs.h> +#include <lber_types.h> +#include <ac/socket.h> + +#ifdef HAVE_TCPD +# include <tcpd.h> +# define LUTIL_STRING_UNKNOWN STRING_UNKNOWN +#else /* ! TCP Wrappers */ +# define LUTIL_STRING_UNKNOWN "unknown" +#endif /* ! TCP Wrappers */ + +/* + * Include file for LDAP utility routine + */ + +LDAP_BEGIN_DECL + +/* n octets encode into ceiling(n/3) * 4 bytes */ +/* Avoid floating point math through extra padding */ + +#define LUTIL_BASE64_ENCODE_LEN(n) (((n)+2)/3 * 4) +#define LUTIL_BASE64_DECODE_LEN(n) ((n)/4*3) + +/* ISC Base64 Routines */ +/* base64.c */ + +LDAP_LUTIL_F( int ) +lutil_b64_ntop LDAP_P(( + unsigned char const *, + size_t, + char *, + size_t)); + +LDAP_LUTIL_F( int ) +lutil_b64_pton LDAP_P(( + char const *, + unsigned char *, + size_t)); + +/* detach.c */ +LDAP_LUTIL_F( int ) +lutil_detach LDAP_P(( + int debug, + int do_close)); + +/* entropy.c */ +LDAP_LUTIL_F( int ) +lutil_entropy LDAP_P(( + unsigned char *buf, + ber_len_t nbytes )); + +/* passfile.c */ +struct berval; /* avoid pulling in lber.h */ + +LDAP_LUTIL_F( int ) +lutil_get_filed_password LDAP_P(( + const char *filename, + struct berval * )); + +/* passwd.c */ +struct lutil_pw_scheme; + +#define LUTIL_PASSWD_OK (0) +#define LUTIL_PASSWD_ERR (-1) + +typedef int (LUTIL_PASSWD_CHK_FUNC)( + const struct berval *scheme, + const struct berval *passwd, + const struct berval *cred, + const char **text ); + +typedef int (LUTIL_PASSWD_HASH_FUNC) ( + const struct berval *scheme, + const struct berval *passwd, + struct berval *hash, + const char **text ); + +LDAP_LUTIL_F( int ) +lutil_passwd_add LDAP_P(( + struct berval *scheme, + LUTIL_PASSWD_CHK_FUNC *chk_fn, + LUTIL_PASSWD_HASH_FUNC *hash_fn )); + +LDAP_LUTIL_F( void ) +lutil_passwd_init LDAP_P(( void )); + +LDAP_LUTIL_F( void ) +lutil_passwd_destroy LDAP_P(( void )); + +LDAP_LUTIL_F( int ) +lutil_authpasswd LDAP_P(( + const struct berval *passwd, /* stored password */ + const struct berval *cred, /* user supplied value */ + const char **methods )); + +LDAP_LUTIL_F( int ) +lutil_authpasswd_hash LDAP_P(( + const struct berval *cred, + struct berval **passwd, /* password to store */ + struct berval **salt, /* salt to store */ + const char *method )); + +#ifdef SLAPD_CRYPT +typedef int (lutil_cryptfunc) LDAP_P(( + const char *key, + const char *salt, + char **hash )); +LDAP_LUTIL_V (lutil_cryptfunc *) lutil_cryptptr; +#endif + +LDAP_LUTIL_F( int ) +lutil_passwd LDAP_P(( + const struct berval *passwd, /* stored password */ + const struct berval *cred, /* user supplied value */ + const char **methods, + const char **text )); /* error message */ + +LDAP_LUTIL_F( int ) +lutil_passwd_generate LDAP_P(( struct berval *pw, ber_len_t )); + +LDAP_LUTIL_F( int ) +lutil_passwd_hash LDAP_P(( + const struct berval *passwd, + const char *method, + struct berval *hash, + const char **text )); + +LDAP_LUTIL_F( int ) +lutil_passwd_scheme LDAP_P(( + const char *scheme )); + +LDAP_LUTIL_F( int ) +lutil_salt_format LDAP_P(( + const char *format )); + +LDAP_LUTIL_F( int ) +lutil_passwd_string64 LDAP_P(( + const struct berval *sc, + const struct berval *hash, + struct berval *b64, + const struct berval *salt )); + +/* utils.c */ +LDAP_LUTIL_F( char* ) +lutil_progname LDAP_P(( + const char* name, + int argc, + char *argv[] )); + +typedef struct lutil_tm { + int tm_sec; /* seconds 0-60 (1 leap second) */ + int tm_min; /* minutes 0-59 */ + int tm_hour; /* hours 0-23 */ + int tm_mday; /* day 1-31 */ + int tm_mon; /* month 0-11 */ + int tm_year; /* year - 1900 */ + int tm_nsec; /* nanoseconds */ + int tm_usub; /* submicro */ +} lutil_tm; + +typedef struct lutil_timet { + unsigned int tt_sec; /* seconds since epoch, 0000 or 1970 */ + int tt_gsec; /* seconds since epoch, high 7 bits, maybe sign-flipped */ + /* sign flipped to sort properly as unsigned ints */ + unsigned int tt_nsec; /* nanoseconds */ +} lutil_timet; + +/* Parse a timestamp string into a structure */ +LDAP_LUTIL_F( int ) +lutil_parsetime LDAP_P(( + char *atm, struct lutil_tm * )); + +/* Convert structured time to time in seconds since 1970 (Unix epoch) */ +LDAP_LUTIL_F( int ) +lutil_tm2time LDAP_P(( + struct lutil_tm *, struct lutil_timet * )); + +/* Convert structured time to time in seconds since 0000 (Proleptic Gregorian) */ +LDAP_LUTIL_F( int ) +lutil_tm2gtime LDAP_P(( + struct lutil_tm *, struct lutil_timet * )); + +#ifdef _WIN32 +LDAP_LUTIL_F( void ) +lutil_slashpath LDAP_P(( char* path )); +#define LUTIL_SLASHPATH(p) lutil_slashpath(p) +#else +#define LUTIL_SLASHPATH(p) +#endif + +LDAP_LUTIL_F( char* ) +lutil_strcopy LDAP_P(( char *dst, const char *src )); + +LDAP_LUTIL_F( char* ) +lutil_strncopy LDAP_P(( char *dst, const char *src, size_t n )); + +LDAP_LUTIL_F( char* ) +lutil_memcopy LDAP_P(( char *dst, const char *src, size_t n )); + +#define lutil_strbvcopy(a, bv) lutil_memcopy((a),(bv)->bv_val,(bv)->bv_len) + +struct tm; + +/* use this macro to statically allocate buffer for lutil_gentime */ +#define LDAP_LUTIL_GENTIME_BUFSIZE 22 +#define lutil_gentime(s,m,t) lutil_localtime((s),(m),(t),0) +LDAP_LUTIL_F( size_t ) +lutil_localtime LDAP_P(( char *s, size_t smax, const struct tm *tm, + long delta )); + +#ifndef HAVE_MKSTEMP +LDAP_LUTIL_F( int ) +mkstemp LDAP_P (( char * template )); +#endif + +/* sockpair.c */ +LDAP_LUTIL_F( int ) +lutil_pair( ber_socket_t sd[2] ); + +/* uuid.c */ +/* use this macro to allocate buffer for lutil_uuidstr */ +#define LDAP_LUTIL_UUIDSTR_BUFSIZE 40 +LDAP_LUTIL_F( size_t ) +lutil_uuidstr( char *buf, size_t len ); + +LDAP_LUTIL_F( int ) +lutil_uuidstr_from_normalized( + char *uuid, + size_t uuidlen, + char *buf, + size_t buflen ); + +/* + * Sometimes not all declarations in a header file are needed. + * An indicator to this is whether or not the symbol's type has + * been defined. Thus, we don't need to include a symbol if + * its type has not been defined through another header file. + */ + +#ifdef HAVE_NT_SERVICE_MANAGER +LDAP_LUTIL_V (int) is_NT_Service; + +#ifdef _LDAP_PVT_THREAD_H +LDAP_LUTIL_V (ldap_pvt_thread_cond_t) started_event; +#endif /* _LDAP_PVT_THREAD_H */ + +/* macros are different between Windows and Mingw */ +#if defined(_WINSVC_H) || defined(_WINSVC_) +LDAP_LUTIL_V (SERVICE_STATUS) lutil_ServiceStatus; +LDAP_LUTIL_V (SERVICE_STATUS_HANDLE) hlutil_ServiceStatus; +#endif /* _WINSVC_H */ + +LDAP_LUTIL_F (void) +lutil_CommenceStartupProcessing( char *serverName, void (*stopper)(int)) ; + +LDAP_LUTIL_F (void) +lutil_ReportShutdownComplete( void ); + +LDAP_LUTIL_F (void *) +lutil_getRegParam( char *svc, char *value ); + +LDAP_LUTIL_F (int) +lutil_srv_install( char* service, char * displayName, char* filename, + int auto_start ); +LDAP_LUTIL_F (int) +lutil_srv_remove ( char* service, char* filename ); + +#endif /* HAVE_NT_SERVICE_MANAGER */ + +#ifdef HAVE_NT_EVENT_LOG +LDAP_LUTIL_F (void) +lutil_LogStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ); + +LDAP_LUTIL_F (void) +lutil_LogStoppedEvent( char *svc ); +#endif + +#ifdef HAVE_EBCDIC +/* Generally this has only been used to put '\n' to stdout. We need to + * make sure it is output in EBCDIC. + */ +#undef putchar +#undef putc +#define putchar(c) putc((c), stdout) +#define putc(c,fp) do { char x=(c); __atoe_l(&x,1); putc(x,fp); } while(0) +#endif + +LDAP_LUTIL_F (int) +lutil_atoix( int *v, const char *s, int x ); + +LDAP_LUTIL_F (int) +lutil_atoux( unsigned *v, const char *s, int x ); + +LDAP_LUTIL_F (int) +lutil_atolx( long *v, const char *s, int x ); + +LDAP_LUTIL_F (int) +lutil_atoulx( unsigned long *v, const char *s, int x ); + +#define lutil_atoi(v, s) lutil_atoix((v), (s), 10) +#define lutil_atou(v, s) lutil_atoux((v), (s), 10) +#define lutil_atol(v, s) lutil_atolx((v), (s), 10) +#define lutil_atoul(v, s) lutil_atoulx((v), (s), 10) + +#ifdef HAVE_LONG_LONG +#if defined(HAVE_STRTOLL) || defined(HAVE_STRTOQ) +LDAP_LUTIL_F (int) +lutil_atollx( long long *v, const char *s, int x ); +#define lutil_atoll(v, s) lutil_atollx((v), (s), 10) +#endif /* HAVE_STRTOLL || HAVE_STRTOQ */ + +#if defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ) +LDAP_LUTIL_F (int) +lutil_atoullx( unsigned long long *v, const char *s, int x ); +#define lutil_atoull(v, s) lutil_atoullx((v), (s), 10) +#endif /* HAVE_STRTOULL || HAVE_STRTOUQ */ +#endif /* HAVE_LONG_LONG */ + +LDAP_LUTIL_F (int) +lutil_str2bin( struct berval *in, struct berval *out, void *ctx ); + +/* Parse and unparse time intervals */ +LDAP_LUTIL_F (int) +lutil_parse_time( const char *in, unsigned long *tp ); + +LDAP_LUTIL_F (int) +lutil_unparse_time( char *buf, size_t buflen, unsigned long t ); + +#ifdef timerdiv +#define lutil_timerdiv timerdiv +#else /* ! timerdiv */ +/* works inplace (x == t) */ +#define lutil_timerdiv(t,d,x) \ + do { \ + time_t s = (t)->tv_sec; \ + assert( d > 0 ); \ + (x)->tv_sec = s / d; \ + (x)->tv_usec = ( (t)->tv_usec + 1000000 * ( s % d ) ) / d; \ + } while ( 0 ) +#endif /* ! timerdiv */ + +#ifdef timermul +#define lutil_timermul timermul +#else /* ! timermul */ +/* works inplace (x == t) */ +#define lutil_timermul(t,m,x) \ + do { \ + time_t u = (t)->tv_usec * m; \ + assert( m > 0 ); \ + (x)->tv_sec = (t)->tv_sec * m + u / 1000000; \ + (x)->tv_usec = u % 1000000; \ + } while ( 0 ); +#endif /* ! timermul */ + +LDAP_END_DECL + +#endif /* _LUTIL_H */ diff --git a/libs/ldap/include/lutil_lockf.h b/libs/ldap/include/lutil_lockf.h new file mode 100644 index 00000000000..b24bde881d8 --- /dev/null +++ b/libs/ldap/include/lutil_lockf.h @@ -0,0 +1,34 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* File locking methods + * + * lutil_lockf() will block until an exclusive lock is acquired. + */ + +#ifndef _LUTIL_LOCKF_H_ +#define _LUTIL_LOCKF_H_ + +LDAP_BEGIN_DECL + +LDAP_LUTIL_F( int ) +lutil_lockf LDAP_P(( int fd )); + +LDAP_LUTIL_F( int ) +lutil_unlockf LDAP_P(( int fd )); + +LDAP_END_DECL + +#endif /* _LUTIL_LOCKF_H_ */ diff --git a/libs/ldap/include/openldap.h b/libs/ldap/include/openldap.h new file mode 100644 index 00000000000..70a39c69daf --- /dev/null +++ b/libs/ldap/include/openldap.h @@ -0,0 +1,39 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2019-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* openldap.h - Header for openldap specific interfaces. */ + +#ifndef _OPENLDAP_H +#define _OPENLDAP_H 1 + +#include <ldap.h> + +LDAP_BEGIN_DECL + +#define LDAP_PROTO_TCP 1 /* ldap:// */ +#define LDAP_PROTO_UDP 2 /* reserved */ +#define LDAP_PROTO_IPC 3 /* ldapi:// */ +#define LDAP_PROTO_EXT 4 /* user-defined socket/sockbuf */ + +LDAP_F( int ) +ldap_init_fd LDAP_P(( + ber_socket_t fd, + int proto, + LDAP_CONST char *url, + LDAP **ldp )); + +LDAP_END_DECL + +#endif /* _OPENLDAP_H */ diff --git a/libs/ldap/include/portable.h b/libs/ldap/include/portable.h new file mode 100644 index 00000000000..a8bb8a5d553 --- /dev/null +++ b/libs/ldap/include/portable.h @@ -0,0 +1,1200 @@ +/* include/portable.h. Generated from portable.hin by configure. */ +/* include/portable.hin. Generated from configure.ac by autoheader. */ + + +/* begin of portable.h.pre */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2021 The OpenLDAP Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _LDAP_PORTABLE_H +#define _LDAP_PORTABLE_H + +/* define this if needed to get reentrant functions */ +#ifndef REENTRANT +/* #undef REENTRANT */ +#endif +#ifndef _REENTRANT +/* #undef _REENTRANT */ +#endif + +/* define this if needed to get threadsafe functions */ +#ifndef THREADSAFE +/* #undef THREADSAFE */ +#endif +#ifndef _THREADSAFE +/* #undef _THREADSAFE */ +#endif +#ifndef THREAD_SAFE +/* #undef THREAD_SAFE */ +#endif +#ifndef _THREAD_SAFE +/* #undef _THREAD_SAFE */ +#endif + +#ifndef _SGI_MP_SOURCE +/* #undef _SGI_MP_SOURCE */ +#endif + +/* end of portable.h.pre */ + + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* define to use both <string.h> and <strings.h> */ +/* #undef BOTH_STRINGS_H */ + +/* define if cross compiling */ +#define CROSS_COMPILING 1 + +/* set to the number of arguments ctime_r() expects */ +/* #undef CTIME_R_NARGS */ + +/* define if toupper() requires islower() */ +#define C_UPPER_LOWER 1 + +/* define if sys_errlist is not declared in stdio.h or errno.h */ +/* #undef DECL_SYS_ERRLIST */ + +/* define to enable slapi library */ +/* #undef ENABLE_SLAPI */ + +/* defined to be the EXE extension */ +#define EXEEXT ".exe" + +/* set to the number of arguments gethostbyaddr_r() expects */ +/* #undef GETHOSTBYADDR_R_NARGS */ + +/* set to the number of arguments gethostbyname_r() expects */ +/* #undef GETHOSTBYNAME_R_NARGS */ + +/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */ +/* #undef GWINSZ_IN_SYS_IOCTL */ + +/* define if you have AIX security lib */ +/* #undef HAVE_AIX_SECURITY */ + +/* Define to 1 if you have the <argon2.h> header file. */ +/* #undef HAVE_ARGON2_H */ + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the <arpa/nameser.h> header file. */ +/* #undef HAVE_ARPA_NAMESER_H */ + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `bcopy' function. */ +/* #undef HAVE_BCOPY */ + +/* Define to 1 if you have the <bits/types.h> header file. */ +/* #undef HAVE_BITS_TYPES_H */ + +/* Define to 1 if you have the `chroot' function. */ +/* #undef HAVE_CHROOT */ + +/* Define to 1 if you have the `clock_gettime' function. */ +/* #undef HAVE_CLOCK_GETTIME */ + +/* Define to 1 if you have the `closesocket' function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define to 1 if you have the <conio.h> header file. */ +#define HAVE_CONIO_H 1 + +/* define if crypt(3) is available */ +/* #undef HAVE_CRYPT */ + +/* Define to 1 if you have the <crypt.h> header file. */ +/* #undef HAVE_CRYPT_H */ + +/* define if crypt_r() is also available */ +/* #undef HAVE_CRYPT_R */ + +/* Define to 1 if you have the `ctime_r' function. */ +/* #undef HAVE_CTIME_R */ + +/* define if you have Cyrus SASL */ +/* #undef HAVE_CYRUS_SASL */ +#define HAVE_CYRUS_SASL 1 + +/* define if your system supports /dev/poll */ +/* #undef HAVE_DEVPOLL */ + +/* Define to 1 if you have the <direct.h> header file. */ +#define HAVE_DIRECT_H 1 + +/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* define if system uses EBCDIC instead of ASCII */ +/* #undef HAVE_EBCDIC */ + +/* Define to 1 if you have the `endgrent' function. */ +/* #undef HAVE_ENDGRENT */ + +/* Define to 1 if you have the `endpwent' function. */ +/* #undef HAVE_ENDPWENT */ + +/* define if your system supports epoll */ +/* #undef HAVE_EPOLL */ + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `fcntl' function. */ +/* #undef HAVE_FCNTL */ + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* define if you actually have FreeBSD fetch(3) */ +/* #undef HAVE_FETCH */ + +/* Define to 1 if you have the <filio.h> header file. */ +/* #undef HAVE_FILIO_H */ + +/* Define to 1 if you have the `flock' function. */ +/* #undef HAVE_FLOCK */ + +/* Define to 1 if you have the `fmemopen' function. */ +/* #undef HAVE_FMEMOPEN */ + +/* Define to 1 if you have the `fstat' function. */ +#define HAVE_FSTAT 1 + +/* Define to 1 if you have the `gai_strerror' function. */ +/* #undef HAVE_GAI_STRERROR */ + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getdtablesize' function. */ +/* #undef HAVE_GETDTABLESIZE */ + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the `getgrgid' function. */ +/* #undef HAVE_GETGRGID */ + +/* Define to 1 if you have the `gethostbyaddr_r' function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define to 1 if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getpassphrase' function. */ +/* #undef HAVE_GETPASSPHRASE */ + +/* Define to 1 if you have the `getpeereid' function. */ +/* #undef HAVE_GETPEEREID */ + +/* Define to 1 if you have the `getpeerucred' function. */ +/* #undef HAVE_GETPEERUCRED */ + +/* Define to 1 if you have the `getpwnam' function. */ +/* #undef HAVE_GETPWNAM */ + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getspnam' function. */ +/* #undef HAVE_GETSPNAM */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <gmp.h> header file. */ +/* #undef HAVE_GMP_H */ + +/* Define to 1 if you have the `gmtime_r' function. */ +/* #undef HAVE_GMTIME_R */ + +/* define if you have GNUtls */ +/* #undef HAVE_GNUTLS */ + +/* Define to 1 if you have the <gnutls/gnutls.h> header file. */ +/* #undef HAVE_GNUTLS_GNUTLS_H */ + +/* if you have GNU Pth */ +/* #undef HAVE_GNU_PTH */ + +/* Define to 1 if you have the <grp.h> header file. */ +/* #undef HAVE_GRP_H */ + +/* Define to 1 if you have the `hstrerror' function. */ +/* #undef HAVE_HSTRERROR */ + +/* define to you inet_aton(3) is available */ +/* #undef HAVE_INET_ATON */ + +/* Define to 1 if you have the `inet_ntoa_b' function. */ +/* #undef HAVE_INET_NTOA_B */ + +/* Define to 1 if you have the `inet_ntop' function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `initgroups' function. */ +/* #undef HAVE_INITGROUPS */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `ioctl' function. */ +/* #undef HAVE_IOCTL */ + +/* Define to 1 if you have the <io.h> header file. */ +#define HAVE_IO_H 1 + +/* define if your system supports kqueue */ +/* #undef HAVE_KQUEUE */ + +/* define if you have libargon2 */ +/* #undef HAVE_LIBARGON2 */ + +/* define if you have -levent */ +/* #undef HAVE_LIBEVENT */ + +/* Define to 1 if you have the `gen' library (-lgen). */ +/* #undef HAVE_LIBGEN */ + +/* Define to 1 if you have the `gmp' library (-lgmp). */ +/* #undef HAVE_LIBGMP */ + +/* Define to 1 if you have the `inet' library (-linet). */ +/* #undef HAVE_LIBINET */ + +/* define if you have libtool -ltdl */ +/* #undef HAVE_LIBLTDL */ + +/* Define to 1 if you have the `net' library (-lnet). */ +/* #undef HAVE_LIBNET */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `nsl_s' library (-lnsl_s). */ +/* #undef HAVE_LIBNSL_S */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* define if you have libsodium */ +/* #undef HAVE_LIBSODIUM */ + +/* Define to 1 if you have the <libutil.h> header file. */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define to 1 if you have the `V3' library (-lV3). */ +/* #undef HAVE_LIBV3 */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* if you have LinuxThreads */ +/* #undef HAVE_LINUX_THREADS */ + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +/* #undef HAVE_LOCALTIME_R */ + +/* Define to 1 if you have the `lockf' function. */ +/* #undef HAVE_LOCKF */ + +/* Define to 1 if the system has the type `long long'. */ +#define HAVE_LONG_LONG 1 + +/* Define to 1 if you have the <ltdl.h> header file. */ +/* #undef HAVE_LTDL_H */ + +/* Define to 1 if you have the <malloc.h> header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memrchr' function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have the `mktemp' function. */ +#define HAVE_MKTEMP 1 + +/* define this if you have mkversion */ +#define HAVE_MKVERSION 1 + +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* define if strerror_r returns char* instead of int */ +/* #undef HAVE_NONPOSIX_STRERROR_R */ + +/* if you have NT Event Log */ +#define HAVE_NT_EVENT_LOG 1 + +/* if you have NT Service Manager */ +#define HAVE_NT_SERVICE_MANAGER 1 + +/* if you have NT Threads */ +#define HAVE_NT_THREADS 1 + +/* define if you have OpenSSL */ +/* #undef HAVE_OPENSSL */ + +/* Define to 1 if you have the <openssl/bn.h> header file. */ +/* #undef HAVE_OPENSSL_BN_H */ + +/* Define to 1 if you have the <openssl/crypto.h> header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the <openssl/ssl.h> header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the `pipe' function. */ +/* #undef HAVE_PIPE */ + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* Define to 1 if you have the <poll.h> header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have the <process.h> header file. */ +#define HAVE_PROCESS_H 1 + +/* Define to 1 if you have the <psap.h> header file. */ +/* #undef HAVE_PSAP_H */ + +/* define to pthreads API spec revision */ +/* #undef HAVE_PTHREADS */ + +/* define if you have pthread_detach function */ +/* #undef HAVE_PTHREAD_DETACH */ + +/* Define to 1 if you have the `pthread_getconcurrency' function. */ +/* #undef HAVE_PTHREAD_GETCONCURRENCY */ + +/* Define to 1 if you have the <pthread.h> header file. */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the `pthread_kill' function. */ +/* #undef HAVE_PTHREAD_KILL */ + +/* Define to 1 if you have the `pthread_kill_other_threads_np' function. */ +/* #undef HAVE_PTHREAD_KILL_OTHER_THREADS_NP */ + +/* define if you have pthread_rwlock_destroy function */ +/* #undef HAVE_PTHREAD_RWLOCK_DESTROY */ + +/* Define to 1 if you have the `pthread_setconcurrency' function. */ +/* #undef HAVE_PTHREAD_SETCONCURRENCY */ + +/* Define to 1 if you have the `pthread_yield' function. */ +/* #undef HAVE_PTHREAD_YIELD */ + +/* Define to 1 if you have the <pth.h> header file. */ +/* #undef HAVE_PTH_H */ + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#define HAVE_PTRDIFF_T 1 + +/* Define to 1 if you have the <pwd.h> header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `read' function. */ +#define HAVE_READ 1 + +/* Define to 1 if you have the `recv' function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the `recvfrom' function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the <regex.h> header file. */ +/* #undef HAVE_REGEX_H */ + +/* Define to 1 if you have the <resolv.h> header file. */ +/* #undef HAVE_RESOLV_H */ + +/* define if you have res_query() */ +/* #undef HAVE_RES_QUERY */ + +/* Define to 1 if you have the <sasl.h> header file. */ +/* #undef HAVE_SASL_H */ + +/* Define to 1 if you have the <sasl/sasl.h> header file. */ +/* #undef HAVE_SASL_SASL_H */ + +/* define if your SASL library has sasl_version() */ +/* #undef HAVE_SASL_VERSION */ + +/* Define to 1 if you have the <sched.h> header file. */ +/* #undef HAVE_SCHED_H */ + +/* Define to 1 if you have the `sched_yield' function. */ +/* #undef HAVE_SCHED_YIELD */ + +/* Define to 1 if you have the `send' function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the `sendmsg' function. */ +/* #undef HAVE_SENDMSG */ + +/* Define to 1 if you have the `sendto' function. */ +#define HAVE_SENDTO 1 + +/* Define to 1 if you have the `setegid' function. */ +/* #undef HAVE_SETEGID */ + +/* Define to 1 if you have the `seteuid' function. */ +/* #undef HAVE_SETEUID */ + +/* Define to 1 if you have the `setgid' function. */ +/* #undef HAVE_SETGID */ + +/* Define to 1 if you have the `setpwfile' function. */ +/* #undef HAVE_SETPWFILE */ + +/* Define to 1 if you have the `setsid' function. */ +/* #undef HAVE_SETSID */ + +/* Define to 1 if you have the `setuid' function. */ +/* #undef HAVE_SETUID */ + +/* Define to 1 if you have the <sgtty.h> header file. */ +/* #undef HAVE_SGTTY_H */ + +/* Define to 1 if you have the <shadow.h> header file. */ +/* #undef HAVE_SHADOW_H */ + +/* Define to 1 if you have the `sigaction' function. */ +/* #undef HAVE_SIGACTION */ + +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the `sigset' function. */ +/* #undef HAVE_SIGSET */ + +/* define if you have -lslp */ +/* #undef HAVE_SLP */ + +/* Define to 1 if you have the <slp.h> header file. */ +/* #undef HAVE_SLP_H */ + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the <sodium.h> header file. */ +/* #undef HAVE_SODIUM_H */ + +/* if you have spawnlp() */ +#define HAVE_SPAWNLP 1 + +/* Define to 1 if you have the <sqlext.h> header file. */ +/* #undef HAVE_SQLEXT_H */ + +/* Define to 1 if you have the <sql.h> header file. */ +/* #undef HAVE_SQL_H */ + +/* Define to 1 if you have the <stddef.h> header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdio.h> header file. */ +/* #undef HAVE_STDIO_H */ + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strpbrk' function. */ +#define HAVE_STRPBRK 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strsep' function. */ +/* #undef HAVE_STRSEP */ + +/* Define to 1 if you have the `strspn' function. */ +#define HAVE_STRSPN 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if you have the `strtouq' function. */ +/* #undef HAVE_STRTOUQ */ + +/* Define to 1 if `msg_accrightslen' is a member of `struct msghdr'. */ +/* #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN */ + +/* Define to 1 if `msg_control' is a member of `struct msghdr'. */ +/* #undef HAVE_STRUCT_MSGHDR_MSG_CONTROL */ + +/* Define to 1 if `pw_gecos' is a member of `struct passwd'. */ +/* #undef HAVE_STRUCT_PASSWD_PW_GECOS */ + +/* Define to 1 if `pw_passwd' is a member of `struct passwd'. */ +/* #undef HAVE_STRUCT_PASSWD_PW_PASSWD */ + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ + +/* Define to 1 if `st_fstype' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_FSTYPE */ + +/* define to 1 if st_fstype is char * */ +/* #undef HAVE_STRUCT_STAT_ST_FSTYPE_CHAR */ + +/* define to 1 if st_fstype is int */ +/* #undef HAVE_STRUCT_STAT_ST_FSTYPE_INT */ + +/* Define to 1 if `st_vfstype' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_VFSTYPE */ + +/* Define to 1 if you have the <synch.h> header file. */ +/* #undef HAVE_SYNCH_H */ + +/* Define to 1 if you have the `sysconf' function. */ +/* #undef HAVE_SYSCONF */ + +/* Define to 1 if you have the <sysexits.h> header file. */ +/* #undef HAVE_SYSEXITS_H */ + +/* Define to 1 if you have the <syslog.h> header file. */ +/* #undef HAVE_SYSLOG_H */ + +/* define if you have systemd */ +/* #undef HAVE_SYSTEMD */ + +/* Define to 1 if you have the <systemd/sd-daemon.h> header file. */ +/* #undef HAVE_SYSTEMD_SD_DAEMON_H */ + +/* Define to 1 if you have the <sys/devpoll.h> header file. */ +/* #undef HAVE_SYS_DEVPOLL_H */ + +/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the <sys/epoll.h> header file. */ +/* #undef HAVE_SYS_EPOLL_H */ + +/* define if you actually have sys_errlist in your libs */ +/* #undef HAVE_SYS_ERRLIST */ + +/* Define to 1 if you have the <sys/errno.h> header file. */ +/* #undef HAVE_SYS_ERRNO_H */ + +/* Define to 1 if you have the <sys/event.h> header file. */ +/* #undef HAVE_SYS_EVENT_H */ + +/* Define to 1 if you have the <sys/file.h> header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the <sys/filio.h> header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the <sys/fstyp.h> header file. */ +/* #undef HAVE_SYS_FSTYP_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the <sys/privgrp.h> header file. */ +/* #undef HAVE_SYS_PRIVGRP_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the <sys/select.h> header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the <sys/socket.h> header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/syslog.h> header file. */ +/* #undef HAVE_SYS_SYSLOG_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/ucred.h> header file. */ +/* #undef HAVE_SYS_UCRED_H */ + +/* Define to 1 if you have the <sys/uio.h> header file. */ +/* #undef HAVE_SYS_UIO_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +/* #undef HAVE_SYS_UN_H */ + +/* Define to 1 if you have the <sys/uuid.h> header file. */ +/* #undef HAVE_SYS_UUID_H */ + +/* Define to 1 if you have the <sys/vmount.h> header file. */ +/* #undef HAVE_SYS_VMOUNT_H */ + +/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* define if you have -lwrap */ +/* #undef HAVE_TCPD */ + +/* Define to 1 if you have the <tcpd.h> header file. */ +/* #undef HAVE_TCPD_H */ + +/* Define to 1 if you have the <termios.h> header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* if you have Solaris LWP (thr) package */ +/* #undef HAVE_THR */ + +/* Define to 1 if you have the <thread.h> header file. */ +/* #undef HAVE_THREAD_H */ + +/* Define to 1 if you have the `thr_getconcurrency' function. */ +/* #undef HAVE_THR_GETCONCURRENCY */ + +/* Define to 1 if you have the `thr_setconcurrency' function. */ +/* #undef HAVE_THR_SETCONCURRENCY */ + +/* Define to 1 if you have the `thr_yield' function. */ +/* #undef HAVE_THR_YIELD */ + +/* define if you have TLS */ +#define HAVE_TLS 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* define if you have uuid_generate() */ +/* #undef HAVE_UUID_GENERATE */ + +/* define if you have uuid_to_str() */ +/* #undef HAVE_UUID_TO_STR */ + +/* Define to 1 if you have the <uuid/uuid.h> header file. */ +/* #undef HAVE_UUID_UUID_H */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `wait4' function. */ +/* #undef HAVE_WAIT4 */ + +/* Define to 1 if you have the `waitpid' function. */ +/* #undef HAVE_WAITPID */ + +/* define if you have winsock */ +#define HAVE_WINSOCK 1 + +/* define if you have winsock2 */ +#define HAVE_WINSOCK2 1 + +/* Define to 1 if you have the <winsock2.h> header file. */ +#define HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the <winsock.h> header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define to 1 if you have the `write' function. */ +#define HAVE_WRITE 1 + +/* define if select implicitly yields */ +#define HAVE_YIELDING_SELECT 1 + +/* Define to 1 if you have the `_vsnprintf' function. */ +#define HAVE__VSNPRINTF 1 + +/* define to 32-bit or greater integer type */ +#define LBER_INT_T int + +/* define to large integer type */ +#define LBER_LEN_T long + +/* define to socket descriptor type */ +#define LBER_SOCKET_T int + +/* define to large integer type */ +#define LBER_TAG_T long + +/* define to 1 if library is reentrant */ +#define LDAP_API_FEATURE_X_OPENLDAP_REENTRANT 1 + +/* define to 1 if library is thread safe */ +#define LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE 1 + +/* define to LDAP VENDOR VERSION */ +/* #undef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ + +/* define this to add debugging code */ +/* #undef LDAP_DEBUG */ + +/* define if LDAP libs are dynamic */ +/* #undef LDAP_LIBS_DYNAMIC */ + +/* define to support PF_INET6 */ +/* #undef LDAP_PF_INET6 */ + +/* define to support PF_LOCAL */ +/* #undef LDAP_PF_LOCAL */ + +/* define this to add SLAPI code */ +/* #undef LDAP_SLAPI */ + +/* define this to add syslog code */ +/* #undef LDAP_SYSLOG */ + +/* Version */ +#define LDAP_VENDOR_VERSION 000000 + +/* Major */ +#define LDAP_VENDOR_VERSION_MAJOR 2 + +/* Minor */ +#define LDAP_VENDOR_VERSION_MINOR X + +/* Patch */ +#define LDAP_VENDOR_VERSION_PATCH X + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* define if memcmp is not 8-bit clean or is otherwise broken */ +/* #undef NEED_MEMCMP_REPLACEMENT */ + +/* define if you have (or want) no threads */ +/* #undef NO_THREADS */ + +/* define to use the original debug style */ +/* #undef OLD_DEBUG */ + +/* Package */ +#define OPENLDAP_PACKAGE "OpenLDAP" + +/* Version */ +#define OPENLDAP_VERSION "2.X" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* define if sched_yield yields the entire process */ +/* #undef REPLACE_BROKEN_YIELD */ + +/* Define to the type of arg 1 for `select'. */ +/* #undef SELECT_TYPE_ARG1 */ + +/* Define to the type of args 2, 3 and 4 for `select'. */ +/* #undef SELECT_TYPE_ARG234 */ + +/* Define to the type of arg 5 for `select'. */ +/* #undef SELECT_TYPE_ARG5 */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 2 + +/* define to support per-object ACIs */ +/* #undef SLAPD_ACI_ENABLED */ + +/* define to support LDAP Async Metadirectory backend */ +/* #undef SLAPD_ASYNCMETA */ + +/* define to support cleartext passwords */ +/* #undef SLAPD_CLEARTEXT */ + +/* define to support crypt(3) passwords */ +/* #undef SLAPD_CRYPT */ + +/* define to support DNS SRV backend */ +/* #undef SLAPD_DNSSRV */ + +/* define to support LDAP backend */ +/* #undef SLAPD_LDAP */ + +/* define to support MDB backend */ +/* #undef SLAPD_MDB */ + +/* define to support LDAP Metadirectory backend */ +/* #undef SLAPD_META */ + +/* define to support modules */ +/* #undef SLAPD_MODULES */ + +/* dynamically linked module */ +#define SLAPD_MOD_DYNAMIC 2 + +/* statically linked module */ +#define SLAPD_MOD_STATIC 1 + +/* define to support NDB backend */ +/* #undef SLAPD_NDB */ + +/* define to support NULL backend */ +/* #undef SLAPD_NULL */ + +/* define for In-Directory Access Logging overlay */ +/* #undef SLAPD_OVER_ACCESSLOG */ + +/* define for Audit Logging overlay */ +/* #undef SLAPD_OVER_AUDITLOG */ + +/* define for Automatic Certificate Authority overlay */ +/* #undef SLAPD_OVER_AUTOCA */ + +/* define for Collect overlay */ +/* #undef SLAPD_OVER_COLLECT */ + +/* define for Attribute Constraint overlay */ +/* #undef SLAPD_OVER_CONSTRAINT */ + +/* define for Dynamic Directory Services overlay */ +/* #undef SLAPD_OVER_DDS */ + +/* define for Dynamic Directory Services overlay */ +/* #undef SLAPD_OVER_DEREF */ + +/* define for Dynamic Group overlay */ +/* #undef SLAPD_OVER_DYNGROUP */ + +/* define for Dynamic List overlay */ +/* #undef SLAPD_OVER_DYNLIST */ + +/* define for Home Directory Management overlay */ +/* #undef SLAPD_OVER_HOMEDIR */ + +/* define for Reverse Group Membership overlay */ +/* #undef SLAPD_OVER_MEMBEROF */ + +/* define for OTP 2-factor Authentication overlay */ +/* #undef SLAPD_OVER_OTP */ + +/* define for Password Policy overlay */ +/* #undef SLAPD_OVER_PPOLICY */ + +/* define for Proxy Cache overlay */ +/* #undef SLAPD_OVER_PROXYCACHE */ + +/* define for Referential Integrity overlay */ +/* #undef SLAPD_OVER_REFINT */ + +/* define for Deferred Authentication overlay */ +/* #undef SLAPD_OVER_REMOTEAUTH */ + +/* define for Return Code overlay */ +/* #undef SLAPD_OVER_RETCODE */ + +/* define for Rewrite/Remap overlay */ +/* #undef SLAPD_OVER_RWM */ + +/* define for Sequential Modify overlay */ +/* #undef SLAPD_OVER_SEQMOD */ + +/* define for ServerSideSort/VLV overlay */ +/* #undef SLAPD_OVER_SSSVLV */ + +/* define for Syncrepl Provider overlay */ +/* #undef SLAPD_OVER_SYNCPROV */ + +/* define for Translucent Proxy overlay */ +/* #undef SLAPD_OVER_TRANSLUCENT */ + +/* define for Attribute Uniqueness overlay */ +/* #undef SLAPD_OVER_UNIQUE */ + +/* define for Value Sorting overlay */ +/* #undef SLAPD_OVER_VALSORT */ + +/* define to support PASSWD backend */ +/* #undef SLAPD_PASSWD */ + +/* define to support PERL backend */ +/* #undef SLAPD_PERL */ + +/* define for Argon2 Password hashing module */ +/* #undef SLAPD_PWMOD_PW_ARGON2 */ + +/* define to support relay backend */ +/* #undef SLAPD_RELAY */ + +/* define to support reverse lookups */ +/* #undef SLAPD_RLOOKUPS */ + +/* define to support SHELL backend */ +/* #undef SLAPD_SHELL */ + +/* define to support SOCK backend */ +/* #undef SLAPD_SOCK */ + +/* define to support SASL passwords */ +/* #undef SLAPD_SPASSWD */ + +/* define to support SQL backend */ +/* #undef SLAPD_SQL */ + +/* define to support WiredTiger backend */ +/* #undef SLAPD_WT */ + +/* define to support run-time loadable ACL */ +/* #undef SLAP_DYNACL */ + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* set to urandom device */ +/* #undef URANDOM_DEVICE */ + +/* define to use OpenSSL BIGNUM for MP */ +/* #undef USE_MP_BIGNUM */ + +/* define to use GMP for MP */ +/* #undef USE_MP_GMP */ + +/* define to use 'long' for MP */ +/* #undef USE_MP_LONG */ + +/* define to use 'long long' for MP */ +#define USE_MP_LONG_LONG 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to the type of arg 3 for `accept'. */ +#define ber_socklen_t int + +/* Define to `char *' if <sys/types.h> does not define. */ +#define caddr_t char * + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if <sys/types.h> doesn't define. */ +#define gid_t int + +/* Define to `int' if <sys/types.h> does not define. */ +/* #undef mode_t */ + +/* Define to `long' if <sys/types.h> does not define. */ +/* #undef off_t */ + +/* Define to `int' if <sys/types.h> does not define. */ +/* #undef pid_t */ + +/* Define to `int' if <signal.h> does not define. */ +/* #undef sig_atomic_t */ + +/* Define to `unsigned' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* define to snprintf routine */ +/* #define snprintf _snprintf */ + +/* Define like ber_socklen_t if <sys/socket.h> does not define. */ +/* #undef socklen_t */ + +/* Define to `signed int' if <sys/types.h> does not define. */ +/* #undef ssize_t */ + +/* Define to `int' if <sys/types.h> doesn't define. */ +#define uid_t int + +/* define as empty if volatile is not supported */ +/* #undef volatile */ + +/* define to snprintf routine */ +/* #undef vsnprintf */ + + +/* begin of portable.h.post */ + +#define RETSIGTYPE void + +#ifdef _WIN32 + /* don't suck in all of the win32 api */ +# define WIN32_LEAN_AND_MEAN 1 +#endif + +#ifndef LDAP_NEEDS_PROTOTYPES +/* force LDAP_P to always include prototypes */ +#define LDAP_NEEDS_PROTOTYPES 1 +#endif + +#ifndef LDAP_REL_ENG +#if (LDAP_VENDOR_VERSION == 000000) && !defined(LDAP_DEVEL) +#define LDAP_DEVEL +#endif +#if defined(LDAP_DEVEL) && !defined(LDAP_TEST) +#define LDAP_TEST +#endif +#endif + +#ifdef HAVE_STDDEF_H +# include <stddef.h> +#endif + +#ifdef HAVE_EBCDIC +/* ASCII/EBCDIC converting replacements for stdio funcs + * vsnprintf and snprintf are used too, but they are already + * checked by the configure script + */ +#define fputs ber_pvt_fputs +#define fgets ber_pvt_fgets +#define printf ber_pvt_printf +#define fprintf ber_pvt_fprintf +#define vfprintf ber_pvt_vfprintf +#define vsprintf ber_pvt_vsprintf +#endif + +#include "ac/fdset.h" + +#include "ldap_cdefs.h" +#include "ldap_features.h" + +#include "ac/assert.h" +#include "ac/localize.h" + +#endif /* _LDAP_PORTABLE_H */ +/* end of portable.h.post */ diff --git a/libs/ldap/include/sasl.h b/libs/ldap/include/sasl.h new file mode 100644 index 00000000000..d4d50f5c34f --- /dev/null +++ b/libs/ldap/include/sasl.h @@ -0,0 +1,120 @@ +/* + * Copyright 2022 Hans Leidekker for CodeWeavers + * + * Minimal compatible sasl.h header + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef SASL_H +#define SASL_H 1 + +#define SASL_VERSION_MAJOR 2 +#define SASL_VERSION_MINOR 1 + +#define SASL_CONTINUE 1 +#define SASL_INTERACT 2 +#define SASL_OK 0 +#define SASL_FAIL -1 +#define SASL_NOMEM -2 +#define SASL_BUFOVER -3 +#define SASL_NOMECH -4 +#define SASL_BADPROT -5 +#define SASL_NOTDONE -6 +#define SASL_BADPARAM -7 +#define SASL_TRYAGAIN -8 +#define SASL_BADMAC -9 +#define SASL_BADSERV -10 +#define SASL_WRONGMECH -11 +#define SASL_NOTINIT -12 +#define SASL_BADAUTH -13 +#define SASL_NOAUTHZ -14 +#define SASL_TOOWEAK -15 +#define SASL_ENCRYPT -16 + +typedef unsigned int sasl_ssf_t; + +#define SASL_SEC_NOPLAINTEXT 0x0001 +#define SASL_SEC_NOACTIVE 0x0002 +#define SASL_SEC_NODICTIONARY 0x0004 +#define SASL_SEC_FORWARD_SECRECY 0x0008 +#define SASL_SEC_NOANONYMOUS 0x0010 +#define SASL_SEC_PASS_CREDENTIALS 0x0020 +#define SASL_SEC_MUTUAL_AUTH 0x0040 +#define SASL_SEC_MAXIMUM 0x00FF + +typedef struct sasl_security_properties +{ + sasl_ssf_t min_ssf; + sasl_ssf_t max_ssf; + unsigned int maxbufsize; + unsigned int security_flags; + const char **property_names; + const char **property_values; +} sasl_security_properties_t; + +#define SASL_CB_LIST_END 0 +#define SASL_CB_USER 0x4001 +#define SASL_CB_AUTHNAME 0x4002 +#define SASL_CB_PASS 0x4004 +#define SASL_CB_ECHOPROMPT 0x4005 +#define SASL_CB_NOECHOPROMPT 0x4006 +#define SASL_CB_GETREALM 0x4008 + +typedef struct sasl_callback +{ + unsigned long id; + int (*proc)(void); + void *context; +} sasl_callback_t; + +typedef struct sasl_interact +{ + unsigned long id; + const char *challenge; + const char *prompt; + const char *defresult; + const void *result; + unsigned len; +} sasl_interact_t; + +#define SASL_USERNAME 0 +#define SASL_SSF 1 +#define SASL_MAXOUTBUF 2 + +typedef struct sasl_conn sasl_conn_t; + +#define SASL_SSF_EXTERNAL 100 +#define SASL_SEC_PROPS 101 +#define SASL_AUTH_EXTERNAL 102 + +int sasl_client_init(const sasl_callback_t *); +int sasl_client_new(const char *, const char *, const char *, const char *, const sasl_callback_t *, + unsigned int, sasl_conn_t **); +int sasl_client_start(sasl_conn_t *conn, const char *, sasl_interact_t **, const char **, unsigned int *, + const char **); +int sasl_client_step(sasl_conn_t *conn, const char *, unsigned int, sasl_interact_t **, const char **, + unsigned int *); +int sasl_decode(sasl_conn_t *, const char *, unsigned int, const char **, unsigned int *); +void sasl_dispose(sasl_conn_t **); +int sasl_encode(sasl_conn_t *, const char *, unsigned int, const char **, unsigned int *); +const char *sasl_errdetail(sasl_conn_t *); +const char *sasl_errstring(int, const char *, const char **); +int sasl_getprop(sasl_conn_t *, int, const void **); +const char **sasl_global_listmech(void); +void sasl_set_mutex(void *, void *, void *, void *); +int sasl_setprop(sasl_conn_t *, int, const void *); + +#endif /* SASL_H */ diff --git a/libs/ldap/liblber/bprint.c b/libs/ldap/liblber/bprint.c new file mode 100644 index 00000000000..da5003a82f9 --- /dev/null +++ b/libs/ldap/liblber/bprint.c @@ -0,0 +1,296 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* + * Copyright (c) 1991 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. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/ctype.h> +#include <ac/stdarg.h> +#include <ac/string.h> + +#include "lber-int.h" + +#define ber_log_check(errlvl, loglvl) ((errlvl) & (loglvl)) + +BER_LOG_FN ber_int_log_proc = NULL; + +/* + * We don't just set ber_pvt_err_file to stderr here, because in NT, + * stderr is a symbol imported from a DLL. As such, the compiler + * doesn't recognize the symbol as having a constant address. Thus + * we set ber_pvt_err_file to stderr later, when it first gets + * referenced. + */ +FILE *ber_pvt_err_file = NULL; + +/* + * ber errno + */ +BER_ERRNO_FN ber_int_errno_fn = NULL; + +int * ber_errno_addr(void) +{ + static int ber_int_errno = LBER_ERROR_NONE; + + if( ber_int_errno_fn ) { + return (*ber_int_errno_fn)(); + } + + return &ber_int_errno; +} + +/* + * Print stuff + */ +void ber_error_print( LDAP_CONST char *data ) +{ + assert( data != NULL ); + + if (!ber_pvt_err_file) ber_pvt_err_file = stderr; + + fputs( data, ber_pvt_err_file ); + + /* Print to both streams */ + if (ber_pvt_err_file != stderr) { + fputs( data, stderr ); + fflush( stderr ); + } + + fflush( ber_pvt_err_file ); +} + +BER_LOG_PRINT_FN ber_pvt_log_print = ber_error_print; + +/* + * lber log + */ + +int ber_pvt_log_output( + const char *subsystem, + int level, + const char *fmt, + ... ) +{ + char buf[1024]; + va_list vl; + va_start( vl, fmt ); + + if ( ber_int_log_proc != NULL ) { + ber_int_log_proc( ber_pvt_err_file, subsystem, level, fmt, vl ); + + } else { + int level; + ber_get_option( NULL, LBER_OPT_BER_DEBUG, &level ); + buf[sizeof(buf) - 1] = '\0'; + vsnprintf( buf, sizeof(buf)-1, fmt, vl ); + if ( ber_log_check( LDAP_DEBUG_BER, level ) ) { + (*ber_pvt_log_print)( buf ); + } + } + + va_end(vl); + return 1; +} + +int ber_pvt_log_printf( int errlvl, int loglvl, const char *fmt, ... ) +{ + char buf[1024]; + va_list ap; + + assert( fmt != NULL ); + + if ( !ber_log_check( errlvl, loglvl )) { + return 0; + } + + va_start( ap, fmt ); + + buf[sizeof(buf) - 1] = '\0'; + vsnprintf( buf, sizeof(buf)-1, fmt, ap ); + + va_end(ap); + + (*ber_pvt_log_print)( buf ); + return 1; +} + +#if 0 +static int ber_log_puts(int errlvl, int loglvl, char *buf) +{ + assert( buf != NULL ); + + if ( !ber_log_check( errlvl, loglvl )) { + return 0; + } + + (*ber_pvt_log_print)( buf ); + return 1; +} +#endif + +/* + * Print arbitrary stuff, for debugging. + */ + +int +ber_log_bprint(int errlvl, + int loglvl, + const char *data, + ber_len_t len ) +{ + assert( data != NULL ); + + if ( !ber_log_check( errlvl, loglvl )) { + return 0; + } + + ber_bprint(data, len); + return 1; +} + +void +ber_bprint( + LDAP_CONST char *data, + ber_len_t len ) +{ + static const char hexdig[] = "0123456789abcdef"; +#define BP_OFFSET 9 +#define BP_GRAPH 60 +#define BP_LEN 80 + char line[BP_LEN]; + ber_len_t i; + + assert( data != NULL ); + + /* in case len is zero */ + line[0] = '\n'; + line[1] = '\0'; + + for ( i = 0 ; i < len ; i++ ) { + int n = i % 16; + unsigned off; + + if( !n ) { + if( i ) (*ber_pvt_log_print)( line ); + memset( line, ' ', sizeof(line)-2 ); + line[sizeof(line)-2] = '\n'; + line[sizeof(line)-1] = '\0'; + + off = i % 0x0ffffU; + + line[2] = hexdig[0x0f & (off >> 12)]; + line[3] = hexdig[0x0f & (off >> 8)]; + line[4] = hexdig[0x0f & (off >> 4)]; + line[5] = hexdig[0x0f & off]; + line[6] = ':'; + } + + off = BP_OFFSET + n*3 + ((n >= 8)?1:0); + line[off] = hexdig[0x0f & ( data[i] >> 4 )]; + line[off+1] = hexdig[0x0f & data[i]]; + + off = BP_GRAPH + n + ((n >= 8)?1:0); + + if ( isprint( (unsigned char) data[i] )) { + line[BP_GRAPH + n] = data[i]; + } else { + line[BP_GRAPH + n] = '.'; + } + } + + (*ber_pvt_log_print)( line ); +} + + +int +ber_log_dump( + int errlvl, + int loglvl, + BerElement *ber, + int inout ) +{ + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( !ber_log_check( errlvl, loglvl )) { + return 0; + } + + ber_dump(ber, inout); + return 1; +} + +void +ber_dump( + BerElement *ber, + int inout ) +{ + char buf[132]; + ber_len_t len; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( inout == 1 ) { + len = ber_pvt_ber_remaining(ber); + } else { + len = ber_pvt_ber_write(ber); + } + + sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n", + (void *) ber->ber_buf, + (void *) ber->ber_ptr, + (void *) ber->ber_end, + (long) len ); + + (void) (*ber_pvt_log_print)( buf ); + + ber_bprint( ber->ber_ptr, len ); +} + +typedef struct seqorset Seqorset; + +/* Exists for binary compatibility with OpenLDAP 2.4.17-- */ +int +ber_log_sos_dump( + int errlvl, + int loglvl, + Seqorset *sos ) +{ + return 0; +} + +/* Exists for binary compatibility with OpenLDAP 2.4.17-- */ +void +ber_sos_dump( + Seqorset *sos ) +{ +} diff --git a/libs/ldap/liblber/decode.c b/libs/ldap/liblber/decode.c new file mode 100644 index 00000000000..48696e05101 --- /dev/null +++ b/libs/ldap/liblber/decode.c @@ -0,0 +1,1026 @@ +/* decode.c - ber input decoding routines */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/stdarg.h> +#include <ac/string.h> +#include <ac/socket.h> + +#include "lber-int.h" + + +/* out->bv_len should be the buffer size on input */ +int +ber_decode_oid( BerValue *in, BerValue *out ) +{ + const unsigned char *der; + unsigned long val; + unsigned val1; + ber_len_t i; + char *ptr; + + assert( in != NULL ); + assert( out != NULL ); + + /* need 4 chars/inbyte + \0 for input={7f 7f 7f...} */ + if ( !out->bv_val || (out->bv_len+3)/4 <= in->bv_len ) + return -1; + + ptr = NULL; + der = (unsigned char *) in->bv_val; + val = 0; + for ( i=0; i < in->bv_len; i++ ) { + val |= der[i] & 0x7f; + if ( !( der[i] & 0x80 )) { + if ( ptr == NULL ) { + /* Initial "x.y": val=x*40+y, x<=2, y<40 if x<2 */ + ptr = out->bv_val; + val1 = (val < 80 ? val/40 : 2); + val -= val1*40; + ptr += sprintf( ptr, "%u", val1 ); + } + ptr += sprintf( ptr, ".%lu", val ); + val = 0; + } else if ( val - 1UL < LBER_OID_COMPONENT_MAX >> 7 ) { + val <<= 7; + } else { + /* val would overflow, or is 0 from invalid initial 0x80 octet */ + return -1; + } + } + if ( ptr == NULL || val != 0 ) + return -1; + + out->bv_len = ptr - out->bv_val; + return 0; +} + +/* Return tag, with *bv = rest of element (starting at length octets) */ +static ber_tag_t +ber_tag_and_rest( const BerElement *ber, struct berval *bv ) +{ + ber_tag_t tag; + ptrdiff_t rest; + unsigned char *ptr; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + ptr = (unsigned char *) ber->ber_ptr; + rest = (unsigned char *) ber->ber_end - ptr; + if ( rest <= 0 ) { + goto fail; + } + + tag = ber->ber_tag; + if ( (char *) ptr == ber->ber_buf ) { + tag = *ptr; + } + ptr++; + rest--; + if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { + goto done; + } + + do { + if ( rest <= 0 ) { + break; + } + tag <<= 8; + tag |= *ptr++ & 0xffU; + rest--; + + if ( ! (tag & LBER_MORE_TAG_MASK) ) { + goto done; + } + } while ( tag <= (ber_tag_t)-1 / 256 ); + + fail: + /* Error or unsupported tag size */ + tag = LBER_DEFAULT; + + done: + bv->bv_len = rest; + bv->bv_val = (char *) ptr; + return tag; +} + +/* Return the tag - LBER_DEFAULT returned means trouble */ +ber_tag_t +ber_get_tag( BerElement *ber ) +{ + struct berval bv; + ber_tag_t tag = ber_tag_and_rest( ber, &bv ); + + ber->ber_ptr = bv.bv_val; + return tag; +} + +/* Return next element's tag and point *bv at its contents in-place */ +ber_tag_t +ber_peek_element( const BerElement *ber, struct berval *bv ) +{ + ber_tag_t tag; + ber_len_t len, rest; + unsigned i; + unsigned char *ptr; + + assert( bv != NULL ); + + /* + * Any ber element looks like this: tag length contents. + * Assuming everything's ok, we return the tag, and point + * bv at the contents. + * + * Assumptions: + * 1) definite lengths + * 2) primitive encodings used whenever possible + */ + + len = 0; + + /* + * First, we read the tag. + */ + tag = ber_tag_and_rest( ber, bv ); + + rest = bv->bv_len; + ptr = (unsigned char *) bv->bv_val; + if ( tag == LBER_DEFAULT || rest == 0 ) { + goto fail; + } + + /* + * Next, read the length. The first octet determines the length + * of the length. If bit 8 is 0, the length is the short form, + * otherwise if the octet != 0x80 it's the long form, otherwise + * the ber element has the unsupported indefinite-length format. + * Lengths that do not fit in a ber_len_t are not accepted. + */ + + len = *ptr++; + rest--; + + if ( len & 0x80U ) { + len &= 0x7fU; + if ( len - 1U > sizeof(ber_len_t) - 1U || rest < len ) { + /* Indefinite-length/too long length/not enough data */ + goto fail; + } + + rest -= len; + i = len; + for( len = *ptr++ & 0xffU; --i; len |= *ptr++ & 0xffU ) { + len <<= 8; + } + } + + /* BER element should have enough data left */ + if( len > rest ) { + fail: + tag = LBER_DEFAULT; + } + + bv->bv_len = len; + bv->bv_val = (char *) ptr; + return tag; +} + +/* Move past next element, point *bv at it in-place, and return its tag. + * The caller may \0-terminate *bv, as next octet is saved in ber->ber_tag. + * Similar to ber_get_stringbv(ber, bv, LBER_BV_NOTERM) except on error. + */ +ber_tag_t +ber_skip_element( BerElement *ber, struct berval *bv ) +{ + ber_tag_t tag = ber_peek_element( ber, bv ); + + if ( tag != LBER_DEFAULT ) { + ber->ber_ptr = bv->bv_val + bv->bv_len; + ber->ber_tag = *(unsigned char *) ber->ber_ptr; + } + + return tag; +} + +/* Move past next element, point *bv at the complete element in-place, and + * return its tag. The caller may \0-terminate *bv, as next octet is saved in + * ber->ber_tag. Similar to ber_skip_element(ber, bv) except the tag+length + * header is also included in *bv. + */ +ber_tag_t +ber_skip_raw( BerElement *ber, struct berval *bv ) +{ + char *val = ber->ber_ptr; + ber_tag_t tag = ber_skip_element( ber, bv ); + + if ( tag != LBER_DEFAULT ) { + bv->bv_len += bv->bv_val - val; + bv->bv_val = val; + } + + return tag; +} + +ber_tag_t +ber_peek_tag( + BerElement *ber, + ber_len_t *len ) +{ + struct berval bv; + ber_tag_t tag = ber_peek_element( ber, &bv ); + + *len = bv.bv_len; + return tag; +} + +ber_tag_t +ber_skip_tag( BerElement *ber, ber_len_t *lenp ) +{ + struct berval bv; + ber_tag_t tag = ber_peek_element( ber, &bv ); + + ber->ber_ptr = bv.bv_val; + ber->ber_tag = *(unsigned char *) ber->ber_ptr; + + *lenp = bv.bv_len; + return tag; +} + +ber_tag_t +ber_get_int( + BerElement *ber, + ber_int_t *num ) +{ + struct berval bv; + ber_tag_t tag = ber_skip_element( ber, &bv ); + + if ( tag == LBER_DEFAULT ) { + return tag; + } + + return ber_decode_int( &bv, num ) ? LBER_DEFAULT : tag; +} + +int +ber_decode_int( const struct berval *bv, ber_int_t *num ) +{ + ber_len_t len = bv->bv_len; + if ( len > sizeof(ber_int_t) ) + return -1; + + assert( num != NULL ); + + /* parse two's complement integer */ + if( len ) { + unsigned char *buf = (unsigned char *) bv->bv_val; + ber_len_t i; + ber_int_t netnum = buf[0] & 0xff; + + /* sign extend */ + netnum = (netnum ^ 0x80) - 0x80; + + /* shift in the bytes */ + for( i = 1; i < len; i++ ) { + netnum = (netnum << 8 ) | buf[i]; + } + + *num = netnum; + + } else { + *num = 0; + } + + return 0; +} + +ber_tag_t +ber_get_enum( + BerElement *ber, + ber_int_t *num ) +{ + return ber_get_int( ber, num ); +} + +ber_tag_t +ber_get_stringb( + BerElement *ber, + char *buf, + ber_len_t *len ) +{ + struct berval bv; + ber_tag_t tag; + + if ( (tag = ber_skip_element( ber, &bv )) == LBER_DEFAULT ) { + return LBER_DEFAULT; + } + + /* must fit within allocated space with termination */ + if ( bv.bv_len >= *len ) { + return LBER_DEFAULT; + } + + memcpy( buf, bv.bv_val, bv.bv_len ); + buf[bv.bv_len] = '\0'; + + *len = bv.bv_len; + return tag; +} + +/* Definitions for get_string vector + * + * ChArray, BvArray, and BvVec are self-explanatory. + * BvOff is a struct berval embedded in an array of larger structures + * of siz bytes at off bytes from the beginning of the struct. + */ +enum bgbvc { ChArray, BvArray, BvVec, BvOff }; + +/* Use this single cookie for state, to keep actual + * stack use to the absolute minimum. + */ +typedef struct bgbvr { + const enum bgbvc choice; + const int option; /* (ALLOC unless BvOff) | (STRING if ChArray) */ + ber_len_t siz; /* input array element size, output count */ + ber_len_t off; /* BvOff offset to the struct berval */ + void *result; +} bgbvr; + +static ber_tag_t +ber_get_stringbvl( BerElement *ber, bgbvr *b ) +{ + int i = 0, n; + ber_tag_t tag; + ber_len_t tot_size = 0, siz = b->siz; + char *last, *orig; + struct berval bv, *bvp = NULL; + union stringbvl_u { + char **ca; /* ChArray */ + BerVarray ba; /* BvArray */ + struct berval **bv; /* BvVec */ + char *bo; /* BvOff */ + } res; + + tag = ber_skip_tag( ber, &bv.bv_len ); + + if ( tag != LBER_DEFAULT ) { + tag = 0; + orig = ber->ber_ptr; + last = orig + bv.bv_len; + + for ( ; ber->ber_ptr < last; i++, tot_size += siz ) { + if ( ber_skip_element( ber, &bv ) == LBER_DEFAULT ) + break; + } + if ( ber->ber_ptr != last ) { + i = 0; + tag = LBER_DEFAULT; + } + + ber->ber_ptr = orig; + ber->ber_tag = *(unsigned char *) orig; + } + + b->siz = i; + if ( i == 0 ) { + return tag; + } + + /* Allocate and NULL-terminate the result vector */ + b->result = ber_memalloc_x( tot_size + siz, ber->ber_memctx ); + if ( b->result == NULL ) { + return LBER_DEFAULT; + } + switch (b->choice) { + case ChArray: + res.ca = b->result; + res.ca[i] = NULL; + break; + case BvArray: + res.ba = b->result; + res.ba[i].bv_val = NULL; + break; + case BvVec: + res.bv = b->result; + res.bv[i] = NULL; + break; + case BvOff: + res.bo = (char *) b->result + b->off; + ((struct berval *) (res.bo + tot_size))->bv_val = NULL; + tot_size = 0; + break; + } + + n = 0; + do { + tag = ber_get_stringbv( ber, &bv, b->option ); + if ( tag == LBER_DEFAULT ) { + goto failed; + } + + /* store my result */ + switch (b->choice) { + case ChArray: + res.ca[n] = bv.bv_val; + break; + case BvArray: + res.ba[n] = bv; + break; + case BvVec: + bvp = ber_memalloc_x( sizeof( struct berval ), + ber->ber_memctx ); + if ( !bvp ) { + ber_memfree_x( bv.bv_val, ber->ber_memctx ); + goto failed; + } + res.bv[n] = bvp; + *bvp = bv; + break; + case BvOff: + *(struct berval *)(res.bo + tot_size) = bv; + tot_size += siz; + break; + } + } while (++n < i); + return tag; + +failed: + if (b->choice != BvOff) { /* BvOff does not have LBER_BV_ALLOC set */ + while (--n >= 0) { + switch(b->choice) { + case ChArray: + ber_memfree_x(res.ca[n], ber->ber_memctx); + break; + case BvArray: + ber_memfree_x(res.ba[n].bv_val, ber->ber_memctx); + break; + case BvVec: + ber_memfree_x(res.bv[n]->bv_val, ber->ber_memctx); + ber_memfree_x(res.bv[n], ber->ber_memctx); + break; + default: + break; + } + } + } + ber_memfree_x(b->result, ber->ber_memctx); + b->result = NULL; + return LBER_DEFAULT; +} + +ber_tag_t +ber_get_stringbv( BerElement *ber, struct berval *bv, int option ) +{ + ber_tag_t tag; + char *data; + + tag = ber_skip_element( ber, bv ); + if ( tag == LBER_DEFAULT || + (( option & LBER_BV_STRING ) && + bv->bv_len && memchr( bv->bv_val, 0, bv->bv_len - 1 ))) + { + bv->bv_val = NULL; + return LBER_DEFAULT; + } + + data = bv->bv_val; + if ( option & LBER_BV_ALLOC ) { + bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, + ber->ber_memctx ); + if ( bv->bv_val == NULL ) { + return LBER_DEFAULT; + } + + if ( bv->bv_len != 0 ) { + memcpy( bv->bv_val, data, bv->bv_len ); + } + data = bv->bv_val; + } + if ( !( option & LBER_BV_NOTERM )) + data[bv->bv_len] = '\0'; + + return tag; +} + +ber_tag_t +ber_get_stringbv_null( BerElement *ber, struct berval *bv, int option ) +{ + ber_tag_t tag; + char *data; + + tag = ber_skip_element( ber, bv ); + if ( tag == LBER_DEFAULT || bv->bv_len == 0 ) { + bv->bv_val = NULL; + return tag; + } + + if (( option & LBER_BV_STRING ) && + memchr( bv->bv_val, 0, bv->bv_len - 1 )) + { + bv->bv_val = NULL; + return LBER_DEFAULT; + } + + data = bv->bv_val; + if ( option & LBER_BV_ALLOC ) { + bv->bv_val = (char *) ber_memalloc_x( bv->bv_len + 1, + ber->ber_memctx ); + if ( bv->bv_val == NULL ) { + return LBER_DEFAULT; + } + + memcpy( bv->bv_val, data, bv->bv_len ); + data = bv->bv_val; + } + if ( !( option & LBER_BV_NOTERM )) + data[bv->bv_len] = '\0'; + + return tag; +} + +ber_tag_t +ber_get_stringa( BerElement *ber, char **buf ) +{ + BerValue bv; + ber_tag_t tag; + + assert( buf != NULL ); + + tag = ber_get_stringbv( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING ); + *buf = bv.bv_val; + + return tag; +} + +ber_tag_t +ber_get_stringa_null( BerElement *ber, char **buf ) +{ + BerValue bv; + ber_tag_t tag; + + assert( buf != NULL ); + + tag = ber_get_stringbv_null( ber, &bv, LBER_BV_ALLOC | LBER_BV_STRING ); + *buf = bv.bv_val; + + return tag; +} + +ber_tag_t +ber_get_stringal( BerElement *ber, struct berval **bv ) +{ + ber_tag_t tag; + + assert( ber != NULL ); + assert( bv != NULL ); + + *bv = (struct berval *) ber_memalloc_x( sizeof(struct berval), + ber->ber_memctx ); + if ( *bv == NULL ) { + return LBER_DEFAULT; + } + + tag = ber_get_stringbv( ber, *bv, LBER_BV_ALLOC ); + if ( tag == LBER_DEFAULT ) { + ber_memfree_x( *bv, ber->ber_memctx ); + *bv = NULL; + } + return tag; +} + +ber_tag_t +ber_get_bitstringa( + BerElement *ber, + char **buf, + ber_len_t *blen ) +{ + ber_tag_t tag; + struct berval data; + unsigned char unusedbits; + + assert( buf != NULL ); + assert( blen != NULL ); + + if ( (tag = ber_skip_element( ber, &data )) == LBER_DEFAULT ) { + goto fail; + } + + if ( --data.bv_len > (ber_len_t)-1 / 8 ) { + goto fail; + } + unusedbits = *(unsigned char *) data.bv_val++; + if ( unusedbits > 7 ) { + goto fail; + } + + if ( memchr( data.bv_val, 0, data.bv_len )) { + goto fail; + } + + *buf = (char *) ber_memalloc_x( data.bv_len, ber->ber_memctx ); + if ( *buf == NULL ) { + return LBER_DEFAULT; + } + memcpy( *buf, data.bv_val, data.bv_len ); + + *blen = data.bv_len * 8 - unusedbits; + return tag; + + fail: + *buf = NULL; + return LBER_DEFAULT; +} + +ber_tag_t +ber_get_null( BerElement *ber ) +{ + ber_len_t len; + ber_tag_t tag = ber_skip_tag( ber, &len ); + + return( len == 0 ? tag : LBER_DEFAULT ); +} + +ber_tag_t +ber_get_boolean( + BerElement *ber, + ber_int_t *boolval ) +{ + return ber_get_int( ber, boolval ); +} + +ber_tag_t +ber_first_element( + BerElement *ber, + ber_len_t *len, + char **last ) +{ + assert( last != NULL ); + + /* skip the sequence header, use the len to mark where to stop */ + if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) { + *last = NULL; + return LBER_DEFAULT; + } + + *last = ber->ber_ptr + *len; + + if ( *len == 0 ) { + return LBER_DEFAULT; + } + + return ber_peek_tag( ber, len ); +} + +ber_tag_t +ber_next_element( + BerElement *ber, + ber_len_t *len, + LDAP_CONST char *last ) +{ + assert( ber != NULL ); + assert( last != NULL ); + assert( LBER_VALID( ber ) ); + + if ( ber->ber_ptr >= last ) { + return LBER_DEFAULT; + } + + return ber_peek_tag( ber, len ); +} + +/* VARARGS */ +ber_tag_t +ber_scanf ( BerElement *ber, + LDAP_CONST char *fmt, + ... ) +{ + va_list ap; + LDAP_CONST char *fmt_reset; + char *s, **ss, ***sss; + struct berval data, *bval, **bvp, ***bvpp; + ber_int_t *i; + ber_len_t *l; + ber_tag_t *t; + ber_tag_t rc; + ber_len_t len; + + va_start( ap, fmt ); + + assert( ber != NULL ); + assert( fmt != NULL ); + assert( LBER_VALID( ber ) ); + + fmt_reset = fmt; + + if ( ber->ber_debug & (LDAP_DEBUG_TRACE|LDAP_DEBUG_BER)) { + ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, + "ber_scanf fmt (%s) ber:\n", fmt ); + ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); + } + + for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) { + /* When this is modified, remember to update + * the error-cleanup code below accordingly. */ + switch ( *fmt ) { + case '!': { /* Hook */ + BERDecodeCallback *f; + void *p; + + f = va_arg( ap, BERDecodeCallback * ); + p = va_arg( ap, void * ); + + rc = (*f)( ber, p, 0 ); + } break; + + case 'a': /* octet string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + rc = ber_get_stringa( ber, ss ); + break; + + case 'A': /* octet string - allocate storage as needed, + * but return NULL if len == 0 */ + ss = va_arg( ap, char ** ); + rc = ber_get_stringa_null( ber, ss ); + break; + + case 'b': /* boolean */ + i = va_arg( ap, ber_int_t * ); + rc = ber_get_boolean( ber, i ); + break; + + case 'B': /* bit string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + l = va_arg( ap, ber_len_t * ); /* for length, in bits */ + rc = ber_get_bitstringa( ber, ss, l ); + break; + + case 'e': /* enumerated */ + case 'i': /* integer */ + i = va_arg( ap, ber_int_t * ); + rc = ber_get_int( ber, i ); + break; + + case 'l': /* length of next item */ + l = va_arg( ap, ber_len_t * ); + rc = ber_peek_tag( ber, l ); + break; + + case 'm': /* octet string in berval, in-place */ + bval = va_arg( ap, struct berval * ); + rc = ber_get_stringbv( ber, bval, 0 ); + break; + + case 'M': /* bvoffarray - must include address of + * a record len, and record offset. + * number of records will be returned thru + * len ptr on finish. parsed in-place. + */ + { + bgbvr cookie = { BvOff, 0 }; + bvp = va_arg( ap, struct berval ** ); + l = va_arg( ap, ber_len_t * ); + cookie.siz = *l; + cookie.off = va_arg( ap, ber_len_t ); + rc = ber_get_stringbvl( ber, &cookie ); + *bvp = cookie.result; + *l = cookie.siz; + break; + } + + case 'n': /* null */ + rc = ber_get_null( ber ); + break; + + case 'o': /* octet string in a supplied berval */ + bval = va_arg( ap, struct berval * ); + rc = ber_get_stringbv( ber, bval, LBER_BV_ALLOC ); + break; + + case 'O': /* octet string - allocate & include length */ + bvp = va_arg( ap, struct berval ** ); + rc = ber_get_stringal( ber, bvp ); + break; + + case 's': /* octet string - in a buffer */ + s = va_arg( ap, char * ); + l = va_arg( ap, ber_len_t * ); + rc = ber_get_stringb( ber, s, 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 */ + { + bgbvr cookie = { + ChArray, LBER_BV_ALLOC | LBER_BV_STRING, sizeof( char * ) + }; + rc = ber_get_stringbvl( ber, &cookie ); + *(va_arg( ap, char *** )) = cookie.result; + break; + } + + case 'V': /* sequence of strings + lengths */ + { + bgbvr cookie = { + BvVec, LBER_BV_ALLOC, sizeof( struct berval * ) + }; + rc = ber_get_stringbvl( ber, &cookie ); + *(va_arg( ap, struct berval *** )) = cookie.result; + break; + } + + case 'W': /* bvarray */ + { + bgbvr cookie = { + BvArray, LBER_BV_ALLOC, sizeof( struct berval ) + }; + rc = ber_get_stringbvl( ber, &cookie ); + *(va_arg( ap, struct berval ** )) = cookie.result; + break; + } + + case 'x': /* skip the next element - whatever it is */ + rc = ber_skip_element( ber, &data ); + break; + + case '{': /* begin sequence */ + case '[': /* begin set */ + switch ( fmt[1] ) { + case 'v': case 'V': case 'W': case 'M': + break; + default: + rc = ber_skip_tag( ber, &len ); + break; + } + break; + + case '}': /* end sequence */ + case ']': /* end set */ + break; + + default: + if( ber->ber_debug ) { + ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, + "ber_scanf: unknown fmt %c\n", *fmt ); + } + rc = LBER_DEFAULT; + break; + } + } + + va_end( ap ); + + if ( rc == LBER_DEFAULT ) { + /* + * Error. Reclaim malloced memory that was given to the caller. + * Set allocated pointers to NULL, "data length" outvalues to 0. + */ + va_start( ap, fmt ); + + for ( ; fmt_reset < fmt; fmt_reset++ ) { + switch ( *fmt_reset ) { + case '!': { /* Hook */ + BERDecodeCallback *f; + void *p; + + f = va_arg( ap, BERDecodeCallback * ); + p = va_arg( ap, void * ); + + (void) (*f)( ber, p, 1 ); + } break; + + case 'a': /* octet string - allocate storage as needed */ + case 'A': + ss = va_arg( ap, char ** ); + ber_memfree_x( *ss, ber->ber_memctx ); + *ss = NULL; + break; + + case 'b': /* boolean */ + case 'e': /* enumerated */ + case 'i': /* integer */ + (void) va_arg( ap, ber_int_t * ); + break; + + case 'l': /* length of next item */ + *(va_arg( ap, ber_len_t * )) = 0; + break; + + case 'm': /* berval in-place */ + bval = va_arg( ap, struct berval * ); + BER_BVZERO( bval ); + break; + + case 'M': /* BVoff array in-place */ + bvp = va_arg( ap, struct berval ** ); + ber_memfree_x( *bvp, ber->ber_memctx ); + *bvp = NULL; + *(va_arg( ap, ber_len_t * )) = 0; + (void) va_arg( ap, ber_len_t ); + break; + + case 'o': /* octet string in a supplied berval */ + bval = va_arg( ap, struct berval * ); + ber_memfree_x( bval->bv_val, ber->ber_memctx ); + BER_BVZERO( bval ); + break; + + case 'O': /* octet string - allocate & include length */ + bvp = va_arg( ap, struct berval ** ); + ber_bvfree_x( *bvp, ber->ber_memctx ); + *bvp = NULL; + break; + + case 's': /* octet string - in a buffer */ + (void) va_arg( ap, char * ); + *(va_arg( ap, ber_len_t * )) = 0; + break; + + case 't': /* tag of next item */ + case 'T': /* skip tag of next item */ + (void) va_arg( ap, ber_tag_t * ); + break; + + case 'B': /* bit string - allocate storage as needed */ + ss = va_arg( ap, char ** ); + ber_memfree_x( *ss, ber->ber_memctx ); + *ss = NULL; + *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */ + break; + + case 'v': /* sequence of strings */ + sss = va_arg( ap, char *** ); + ber_memvfree_x( (void **) *sss, ber->ber_memctx ); + *sss = NULL; + break; + + case 'V': /* sequence of strings + lengths */ + bvpp = va_arg( ap, struct berval *** ); + ber_bvecfree_x( *bvpp, ber->ber_memctx ); + *bvpp = NULL; + break; + + case 'W': /* BerVarray */ + bvp = va_arg( ap, struct berval ** ); + ber_bvarray_free_x( *bvp, ber->ber_memctx ); + *bvp = NULL; + break; + + case 'n': /* null */ + case 'x': /* skip the next element - whatever it is */ + case '{': /* begin sequence */ + case '[': /* begin set */ + case '}': /* end sequence */ + case ']': /* end set */ + break; + + default: + /* format should be good */ + assert( 0 ); + } + } + + va_end( ap ); + } + + return rc; +} diff --git a/libs/ldap/liblber/encode.c b/libs/ldap/liblber/encode.c new file mode 100644 index 00000000000..30d28eb6038 --- /dev/null +++ b/libs/ldap/liblber/encode.c @@ -0,0 +1,651 @@ +/* encode.c - ber output encoding routines */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + +#include "portable.h" + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/stdarg.h> +#include <ac/socket.h> +#include <ac/string.h> + +#include "lber-int.h" + + +#define OCTET_SIZE(type) ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8) +#define TAGBUF_SIZE OCTET_SIZE(ber_tag_t) +#define LENBUF_SIZE (1 + OCTET_SIZE(ber_len_t)) +#define HEADER_SIZE (TAGBUF_SIZE + LENBUF_SIZE) + +/* + * BER element size constrains: + * + * - We traditionally support a length of max 0xffffffff. However + * some functions return an int length so that is their max. + * MAXINT_BERSIZE is the max for those functions. + * + * - MAXINT_BERSIZE must fit in MAXINT_BERSIZE_OCTETS octets. + * + * - sizeof(ber_elem_size_t) is normally MAXINT_BERSIZE_OCTETS: + * Big enough for MAXINT_BERSIZE, but not more. (Larger wastes + * space in the working encoding and DER encoding of a sequence + * or set. Smaller further limits sizes near a sequence/set.) + * + * ber_len_t is mostly unrelated to this. Which may be for the best, + * since it is also used for lengths of data that are never encoded. + */ +#define MAXINT_BERSIZE \ + (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE) +#define MAXINT_BERSIZE_OCTETS 4 +typedef ber_uint_t ber_elem_size_t; /* normally 32 bits */ + + +/* Prepend tag to ptr, which points to the end of a tag buffer */ +static unsigned char * +ber_prepend_tag( unsigned char *ptr, ber_tag_t tag ) +{ + do { + *--ptr = (unsigned char) tag & 0xffU; + } while ( (tag >>= 8) != 0 ); + + return ptr; +} + +/* Prepend ber length to ptr, which points to the end of a length buffer */ +static unsigned char * +ber_prepend_len( unsigned char *ptr, ber_len_t len ) +{ + /* + * short len if it's less than 128 - one byte giving the len, + * with bit 8 0. + * long len otherwise - one byte with bit 8 set, giving the + * length of the length, followed by the length itself. + */ + + *--ptr = (unsigned char) len & 0xffU; + + if ( len >= 0x80 ) { + unsigned char *endptr = ptr--; + + while ( (len >>= 8) != 0 ) { + *ptr-- = (unsigned char) len & 0xffU; + } + *ptr = (unsigned char) (endptr - ptr) + 0x80U; + } + + return ptr; +} + +/* out->bv_len should be the buffer size on input */ +int +ber_encode_oid( BerValue *in, BerValue *out ) +{ + unsigned char *der; + unsigned long val1, val; + int i, j, len; + char *ptr, *end, *inend; + + assert( in != NULL ); + assert( out != NULL ); + + if ( !out->bv_val || out->bv_len < in->bv_len/2 ) + return -1; + + der = (unsigned char *) out->bv_val; + ptr = in->bv_val; + inend = ptr + in->bv_len; + + /* OIDs start with <0-1>.<0-39> or 2.<any>, DER-encoded 40*val1+val2 */ + if ( !isdigit( (unsigned char) *ptr )) return -1; + val1 = strtoul( ptr, &end, 10 ); + if ( end == ptr || val1 > 2 ) return -1; + if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1; + val = strtoul( end, &ptr, 10 ); + if ( ptr == end ) return -1; + if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1; + val += val1 * 40; + + for (;;) { + if ( ptr > inend ) return -1; + + /* Write the OID component little-endian, then reverse it */ + len = 0; + do { + der[len++] = (val & 0xff) | 0x80; + } while ( (val >>= 7) != 0 ); + der[0] &= 0x7f; + for ( i = 0, j = len; i < --j; i++ ) { + unsigned char tmp = der[i]; + der[i] = der[j]; + der[j] = tmp; + } + der += len; + + if ( ptr == inend ) + break; + + if ( *ptr++ != '.' ) return -1; + if ( !isdigit( (unsigned char) *ptr )) return -1; + val = strtoul( ptr, &end, 10 ); + if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1; + ptr = end; + } + + out->bv_len = (char *)der - out->bv_val; + return 0; +} + +static int +ber_put_int_or_enum( + BerElement *ber, + ber_int_t num, + ber_tag_t tag ) +{ + ber_uint_t unum; + unsigned char sign, data[TAGBUF_SIZE+1 + OCTET_SIZE(ber_int_t)], *ptr; + + sign = 0; + unum = num; /* Bit fiddling should be done with unsigned values */ + if ( num < 0 ) { + sign = 0xffU; + unum = ~unum; + } + for ( ptr = &data[sizeof(data) - 1] ;; unum >>= 8 ) { + *ptr-- = (sign ^ (unsigned char) unum) & 0xffU; + if ( unum < 0x80 ) /* top bit at *ptr is sign bit */ + break; + } + + *ptr = (unsigned char) (&data[sizeof(data) - 1] - ptr); /* length */ + ptr = ber_prepend_tag( ptr, tag ); + + return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); +} + +int +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 +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 +ber_put_ostring( + BerElement *ber, + LDAP_CONST char *str, + ber_len_t len, + ber_tag_t tag ) +{ + int rc; + unsigned char header[HEADER_SIZE], *ptr; + + if ( tag == LBER_DEFAULT ) { + tag = LBER_OCTETSTRING; + } + + if ( len > MAXINT_BERSIZE ) { + return -1; + } + + ptr = ber_prepend_len( &header[sizeof(header)], len ); + ptr = ber_prepend_tag( ptr, tag ); + + rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 ); + if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) { + /* length(tag + length + contents) */ + return rc + (int) len; + } + + return -1; +} + +int +ber_put_berval( + BerElement *ber, + struct berval *bv, + ber_tag_t tag ) +{ + if( bv == NULL || bv->bv_len == 0 ) { + return ber_put_ostring( ber, "", (ber_len_t) 0, tag ); + } + + return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag ); +} + +int +ber_put_string( + BerElement *ber, + LDAP_CONST char *str, + ber_tag_t tag ) +{ + assert( str != NULL ); + + return ber_put_ostring( ber, str, strlen( str ), tag ); +} + +int +ber_put_bitstring( + BerElement *ber, + LDAP_CONST char *str, + ber_len_t blen /* in bits */, + ber_tag_t tag ) +{ + int rc; + ber_len_t len; + unsigned char unusedbits, header[HEADER_SIZE + 1], *ptr; + + if ( tag == LBER_DEFAULT ) { + tag = LBER_BITSTRING; + } + + unusedbits = (unsigned char) -blen & 7; + len = blen / 8 + (unusedbits != 0); /* (blen+7)/8 without overflow */ + if ( len >= MAXINT_BERSIZE ) { + return -1; + } + + header[sizeof(header) - 1] = unusedbits; + ptr = ber_prepend_len( &header[sizeof(header) - 1], len + 1 ); + ptr = ber_prepend_tag( ptr, tag ); + + rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 ); + if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) { + /* length(tag + length + unused bit count + bitstring) */ + return rc + (int) len; + } + + return -1; +} + +int +ber_put_null( BerElement *ber, ber_tag_t tag ) +{ + unsigned char data[TAGBUF_SIZE + 1], *ptr; + + if ( tag == LBER_DEFAULT ) { + tag = LBER_NULL; + } + + data[sizeof(data) - 1] = 0; /* length */ + ptr = ber_prepend_tag( &data[sizeof(data) - 1], tag ); + + return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); +} + +int +ber_put_boolean( + BerElement *ber, + ber_int_t boolval, + ber_tag_t tag ) +{ + unsigned char data[TAGBUF_SIZE + 2], *ptr; + + if ( tag == LBER_DEFAULT ) + tag = LBER_BOOLEAN; + + data[sizeof(data) - 1] = boolval ? 0xff : 0; + data[sizeof(data) - 2] = 1; /* length */ + ptr = ber_prepend_tag( &data[sizeof(data) - 2], tag ); + + return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 ); +} + + +/* Max number of length octets in a sequence or set, normally 5 */ +#define SOS_LENLEN (1 + (sizeof(ber_elem_size_t) > MAXINT_BERSIZE_OCTETS ? \ + (ber_len_t) sizeof(ber_elem_size_t) : MAXINT_BERSIZE_OCTETS)) + +/* Header of incomplete sequence or set */ +typedef struct seqorset_header { + char xtagbuf[TAGBUF_SIZE + 1]; /* room for tag + len(tag or len) */ + union { + ber_elem_size_t offset; /* enclosing sequence/set */ + char padding[SOS_LENLEN-1]; /* for final length encoding */ + } next_sos; +# define SOS_TAG_END(header) ((unsigned char *) &(header).next_sos - 1) +} Seqorset_header; + +/* Start a sequence or set */ +static int +ber_start_seqorset( + BerElement *ber, + ber_tag_t tag ) +{ + /* + * Write the tag and SOS_LENLEN octets reserved for length, to ber. + * For now, length octets = (tag length, previous ber_sos_inner). + * + * Update ber_sos_inner and the write-cursor ber_sos_ptr. ber_ptr + * will not move until the outermost sequence or set is complete. + */ + + Seqorset_header header; + unsigned char *headptr; + ber_len_t taglen, headlen; + char *dest, **p; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( ber->ber_sos_ptr == NULL ) { /* outermost sequence/set? */ + header.next_sos.offset = 0; + p = &ber->ber_ptr; + } else { + if ( (ber_len_t) -1 > (ber_elem_size_t) -1 ) { + if ( ber->ber_sos_inner > (ber_elem_size_t) -1 ) + return -1; + } + header.next_sos.offset = ber->ber_sos_inner; + p = &ber->ber_sos_ptr; + } + headptr = ber_prepend_tag( SOS_TAG_END(header), tag ); + *SOS_TAG_END(header) = taglen = SOS_TAG_END(header) - headptr; + headlen = taglen + SOS_LENLEN; + + /* As ber_write(,headptr,headlen,) except update ber_sos_ptr, not *p */ + if ( headlen > (ber_len_t) (ber->ber_end - *p) ) { + if ( ber_realloc( ber, headlen ) != 0 ) + return -1; + } + dest = *p; + AC_MEMCPY( dest, headptr, headlen ); + ber->ber_sos_ptr = dest + headlen; + + ber->ber_sos_inner = dest + taglen - ber->ber_buf; + + /* + * Do not return taglen + SOS_LENLEN here - then ber_put_seqorset() + * should return lenlen - SOS_LENLEN + len, which can be < 0. + */ + return 0; +} + +int +ber_start_seq( BerElement *ber, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) { + tag = LBER_SEQUENCE; + } + + return ber_start_seqorset( ber, tag ); +} + +int +ber_start_set( BerElement *ber, ber_tag_t tag ) +{ + if ( tag == LBER_DEFAULT ) { + tag = LBER_SET; + } + + return ber_start_seqorset( ber, tag ); +} + +/* End a sequence or set */ +static int +ber_put_seqorset( BerElement *ber ) +{ + Seqorset_header header; + unsigned char *lenptr; /* length octets in the sequence/set */ + ber_len_t len; /* length(contents) */ + ber_len_t xlen; /* len + length(length) */ + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( ber->ber_sos_ptr == NULL ) return -1; + + lenptr = (unsigned char *) ber->ber_buf + ber->ber_sos_inner; + xlen = ber->ber_sos_ptr - (char *) lenptr; + if ( xlen > MAXINT_BERSIZE + SOS_LENLEN ) { + return -1; + } + + /* Extract sequence/set information from length octets */ + memcpy( SOS_TAG_END(header), lenptr, SOS_LENLEN ); + + /* Store length, and close gap of leftover reserved length octets */ + len = xlen - SOS_LENLEN; + if ( !(ber->ber_options & LBER_USE_DER) ) { + int i; + lenptr[0] = SOS_LENLEN - 1 + 0x80; /* length(length)-1 */ + for( i = SOS_LENLEN; --i > 0; len >>= 8 ) { + lenptr[i] = len & 0xffU; + } + } else { + unsigned char *p = ber_prepend_len( lenptr + SOS_LENLEN, len ); + ber_len_t unused = p - lenptr; + if ( unused != 0 ) { + /* length(length) < the reserved SOS_LENLEN bytes */ + xlen -= unused; + AC_MEMCPY( lenptr, p, xlen ); + ber->ber_sos_ptr = (char *) lenptr + xlen; + } + } + + ber->ber_sos_inner = header.next_sos.offset; + if ( header.next_sos.offset == 0 ) { /* outermost sequence/set? */ + /* The ber_ptr is at the set/seq start - move it to the end */ + ber->ber_ptr = ber->ber_sos_ptr; + ber->ber_sos_ptr = NULL; + } + + return xlen + *SOS_TAG_END(header); /* lenlen + len + taglen */ +} + +int +ber_put_seq( BerElement *ber ) +{ + return ber_put_seqorset( ber ); +} + +int +ber_put_set( BerElement *ber ) +{ + return ber_put_seqorset( ber ); +} + +/* N tag */ +static ber_tag_t lber_int_null = 0; + +/* VARARGS */ +int +ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... ) +{ + va_list ap; + char *s, **ss; + struct berval *bv, **bvp; + int rc; + ber_int_t i; + ber_len_t len; + + assert( ber != NULL ); + assert( fmt != NULL ); + assert( LBER_VALID( ber ) ); + + va_start( ap, fmt ); + + for ( rc = 0; *fmt && rc != -1; fmt++ ) { + switch ( *fmt ) { + case '!': { /* hook */ + BEREncodeCallback *f; + void *p; + + ber->ber_usertag = 0; + + f = va_arg( ap, BEREncodeCallback * ); + p = va_arg( ap, void * ); + rc = (*f)( ber, p ); + + if ( ber->ber_usertag ) { + goto next; + } + } break; + + case 'b': /* boolean */ + i = va_arg( ap, ber_int_t ); + rc = ber_put_boolean( ber, i, ber->ber_tag ); + break; + + case 'i': /* int */ + i = va_arg( ap, ber_int_t ); + rc = ber_put_int( ber, i, ber->ber_tag ); + break; + + case 'e': /* enumeration */ + i = va_arg( ap, ber_int_t ); + rc = ber_put_enum( ber, i, ber->ber_tag ); + break; + + case 'n': /* null */ + rc = ber_put_null( ber, ber->ber_tag ); + break; + + case 'N': /* Debug NULL */ + rc = 0; + if( lber_int_null != 0 ) { + /* Insert NULL to ensure peer ignores unknown tags */ + rc = ber_put_null( ber, lber_int_null ); + } + break; + + case 'o': /* octet string (non-null terminated) */ + s = va_arg( ap, char * ); + len = va_arg( ap, ber_len_t ); + rc = ber_put_ostring( ber, s, len, ber->ber_tag ); + break; + + case 'O': /* berval octet string */ + bv = va_arg( ap, struct berval * ); + if( bv == NULL ) break; + rc = ber_put_berval( ber, bv, 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 */ + case 'X': /* bit string (deprecated) */ + s = va_arg( ap, char * ); + len = va_arg( ap, ber_len_t ); /* 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 ); + goto next; + + 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 ( (bvp = va_arg( ap, struct berval ** )) == NULL ) + break; + for ( i = 0; bvp[i] != NULL; i++ ) { + if ( (rc = ber_put_berval( ber, bvp[i], + ber->ber_tag )) == -1 ) + break; + } + break; + + case 'W': /* BerVarray */ + if ( (bv = va_arg( ap, BerVarray )) == NULL ) + break; + for ( i = 0; bv[i].bv_val != NULL; i++ ) { + if ( (rc = ber_put_berval( ber, &bv[i], + 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: + if( ber->ber_debug ) { + ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, + "ber_printf: unknown fmt %c\n", *fmt ); + } + rc = -1; + break; + } + + ber->ber_tag = LBER_DEFAULT; + next:; + } + + va_end( ap ); + + return rc; +} diff --git a/libs/ldap/liblber/io.c b/libs/ldap/liblber/io.c new file mode 100644 index 00000000000..d1234c49b16 --- /dev/null +++ b/libs/ldap/liblber/io.c @@ -0,0 +1,725 @@ +/* io.c - ber general i/o routines */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/ctype.h> +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +#include "lber-int.h" +#include "ldap_log.h" + +ber_slen_t +ber_skip_data( + BerElement *ber, + ber_len_t len ) +{ + ber_len_t actuallen, nleft; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + nleft = ber_pvt_ber_remaining( ber ); + actuallen = nleft < len ? nleft : len; + ber->ber_ptr += actuallen; + ber->ber_tag = *(unsigned char *)ber->ber_ptr; + + return( (ber_slen_t) actuallen ); +} + +/* + * Read from the ber buffer. The caller must maintain ber->ber_tag. + * Do not use to read whole tags. See ber_get_tag() and ber_skip_data(). + */ +ber_slen_t +ber_read( + BerElement *ber, + char *buf, + ber_len_t len ) +{ + ber_len_t actuallen, nleft; + + assert( ber != NULL ); + assert( buf != NULL ); + assert( LBER_VALID( ber ) ); + + nleft = ber_pvt_ber_remaining( ber ); + actuallen = nleft < len ? nleft : len; + + AC_MEMCPY( buf, ber->ber_ptr, actuallen ); + + ber->ber_ptr += actuallen; + + return( (ber_slen_t) actuallen ); +} + +/* + * Write to the ber buffer. + * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write(). + */ +ber_slen_t +ber_write( + BerElement *ber, + LDAP_CONST char *buf, + ber_len_t len, + int zero ) /* nonzero is unsupported from OpenLDAP 2.4.18 */ +{ + char **p; + + assert( ber != NULL ); + assert( buf != NULL ); + assert( LBER_VALID( ber ) ); + + if ( zero != 0 ) { + ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s", + "ber_write: nonzero 4th argument not supported\n" ); + return( -1 ); + } + + p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr; + if ( len > (ber_len_t) (ber->ber_end - *p) ) { + if ( ber_realloc( ber, len ) != 0 ) return( -1 ); + } + AC_MEMCPY( *p, buf, len ); + *p += len; + + return( (ber_slen_t) len ); +} + +/* Resize the ber buffer */ +int +ber_realloc( BerElement *ber, ber_len_t len ) +{ + ber_len_t total, offset, sos_offset, rw_offset; + char *buf; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + /* leave room for ber_flatten() to \0-terminate ber_buf */ + if ( ++len == 0 ) { + return( -1 ); + } + + total = ber_pvt_ber_total( ber ); + +#define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ +#if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0 +# ifndef notdef + /* don't realloc by small amounts */ + total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; +# else + { /* not sure what value this adds. reduce fragmentation? */ + ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; + ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; + total = ( have + need ) * LBER_EXBUFSIZ; + } +# endif +#else + total += len; /* realloc just what's needed */ +#endif + + if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) { + return( -1 ); + } + + buf = ber->ber_buf; + offset = ber->ber_ptr - buf; + sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0; + /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */ + rw_offset = ber->ber_rwptr ? ber->ber_rwptr - buf : 0; + + buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx ); + if ( buf == NULL ) { + return( -1 ); + } + + ber->ber_buf = buf; + ber->ber_end = buf + total; + ber->ber_ptr = buf + offset; + if ( sos_offset ) + ber->ber_sos_ptr = buf + sos_offset; + if ( ber->ber_rwptr ) + ber->ber_rwptr = buf + rw_offset; + + return( 0 ); +} + +void +ber_free_buf( BerElement *ber ) +{ + assert( LBER_VALID( ber ) ); + + if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx ); + + ber->ber_buf = NULL; + ber->ber_sos_ptr = NULL; + ber->ber_valid = LBER_UNINITIALIZED; +} + +void +ber_free( BerElement *ber, int freebuf ) +{ + if( ber == NULL ) { + LDAP_MEMORY_DEBUG_ASSERT( ber != NULL ); + return; + } + + if( freebuf ) ber_free_buf( ber ); + + ber_memfree_x( (char *) ber, ber->ber_memctx ); +} + +int +ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) +{ + return ber_flush2( sb, ber, + freeit ? LBER_FLUSH_FREE_ON_SUCCESS + : LBER_FLUSH_FREE_NEVER ); +} + +int +ber_flush2( Sockbuf *sb, BerElement *ber, int freeit ) +{ + ber_len_t towrite; + ber_slen_t rc; + + assert( sb != NULL ); + assert( ber != NULL ); + assert( SOCKBUF_VALID( sb ) ); + assert( LBER_VALID( ber ) ); + + if ( ber->ber_rwptr == NULL ) { + ber->ber_rwptr = ber->ber_buf; + } + towrite = ber->ber_ptr - ber->ber_rwptr; + + if ( sb->sb_debug ) { + ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug, + "ber_flush2: %ld bytes to sd %ld%s\n", + towrite, (long) sb->sb_fd, + ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); + ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug, + ber->ber_rwptr, towrite ); + } + + while ( towrite > 0 ) { +#ifdef LBER_TRICKLE + sleep(1); + rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 ); +#else + rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite ); +#endif + if ( rc <= 0 ) { + if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 ); + return -1; + } + towrite -= rc; + ber->ber_rwptr += rc; + } + + if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 ); + + return 0; +} + +BerElement * +ber_alloc_t( int options ) +{ + BerElement *ber; + + ber = (BerElement *) LBER_CALLOC( 1, sizeof(BerElement) ); + + if ( ber == NULL ) { + return NULL; + } + + ber->ber_valid = LBER_VALID_BERELEMENT; + ber->ber_tag = LBER_DEFAULT; + ber->ber_options = options; + ber->ber_debug = ber_int_debug; + + assert( LBER_VALID( ber ) ); + return ber; +} + +BerElement * +ber_alloc( void ) /* deprecated */ +{ + return ber_alloc_t( 0 ); +} + +BerElement * +der_alloc( void ) /* deprecated */ +{ + return ber_alloc_t( LBER_USE_DER ); +} + +BerElement * +ber_dup( BerElement *ber ) +{ + BerElement *new; + + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + if ( (new = ber_alloc_t( ber->ber_options )) == NULL ) { + return NULL; + } + + *new = *ber; + + assert( LBER_VALID( new ) ); + return( new ); +} + + +void +ber_init2( BerElement *ber, struct berval *bv, int options ) +{ + assert( ber != NULL ); + + (void) memset( (char *)ber, '\0', sizeof( BerElement )); + ber->ber_valid = LBER_VALID_BERELEMENT; + ber->ber_tag = LBER_DEFAULT; + ber->ber_options = (char) options; + ber->ber_debug = ber_int_debug; + + if ( bv != NULL ) { + ber->ber_buf = bv->bv_val; + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + bv->bv_len; + } + + assert( LBER_VALID( ber ) ); +} + +/* OLD U-Mich ber_init() */ +void +ber_init_w_nullc( BerElement *ber, int options ) +{ + ber_init2( ber, NULL, options ); +} + +/* New C-API ber_init() */ +/* This function constructs a BerElement containing a copy +** of the data in the bv argument. +*/ +BerElement * +ber_init( struct berval *bv ) +{ + BerElement *ber; + + assert( bv != NULL ); + + if ( bv == NULL ) { + return NULL; + } + + ber = ber_alloc_t( 0 ); + + if( ber == NULL ) { + /* allocation failed */ + return NULL; + } + + /* copy the data */ + if ( ((ber_len_t) ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) + != bv->bv_len ) + { + /* write failed, so free and return NULL */ + ber_free( ber, 1 ); + return NULL; + } + + ber_reset( ber, 1 ); /* reset the pointer to the start of the buffer */ + return ber; +} + +/* New C-API ber_flatten routine */ +/* This routine allocates a struct berval whose contents are a BER +** encoding taken from the ber argument. The bvPtr pointer points to +** the returned berval. +** +** ber_flatten2 is the same, but uses a struct berval passed by +** the caller. If alloc is 0 the returned bv uses the ber buf directly. +*/ +int ber_flatten2( + BerElement *ber, + struct berval *bv, + int alloc ) +{ + assert( bv != NULL ); + + if ( bv == NULL ) { + return -1; + } + + if ( ber == NULL ) { + /* ber is null, create an empty berval */ + bv->bv_val = NULL; + bv->bv_len = 0; + + } else if ( ber->ber_sos_ptr != NULL ) { + /* unmatched "{" and "}" */ + return -1; + + } else { + /* copy the berval */ + ber_len_t len = ber_pvt_ber_write( ber ); + + if ( alloc ) { + bv->bv_val = (char *) ber_memalloc_x( len + 1, ber->ber_memctx ); + if ( bv->bv_val == NULL ) { + return -1; + } + AC_MEMCPY( bv->bv_val, ber->ber_buf, len ); + bv->bv_val[len] = '\0'; + } else if ( ber->ber_buf != NULL ) { + bv->bv_val = ber->ber_buf; + bv->bv_val[len] = '\0'; + } else { + bv->bv_val = ""; + } + bv->bv_len = len; + } + return 0; +} + +int ber_flatten( + BerElement *ber, + struct berval **bvPtr) +{ + struct berval *bv; + int rc; + + assert( bvPtr != NULL ); + + if(bvPtr == NULL) { + return -1; + } + + bv = ber_memalloc_x( sizeof(struct berval), ber->ber_memctx ); + if ( bv == NULL ) { + return -1; + } + rc = ber_flatten2(ber, bv, 1); + if (rc == -1) { + ber_memfree_x(bv, ber->ber_memctx); + } else { + *bvPtr = bv; + } + return rc; +} + +void +ber_reset( BerElement *ber, int was_writing ) +{ + assert( ber != NULL ); + assert( LBER_VALID( ber ) ); + + 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; +} + +/* + * A rewrite of ber_get_next that can safely be called multiple times + * for the same packet. It will simply continue where it stopped until + * a full packet is read. + */ + +#define LENSIZE 4 + +ber_tag_t +ber_get_next( + Sockbuf *sb, + ber_len_t *len, + BerElement *ber ) +{ + assert( sb != NULL ); + assert( len != NULL ); + assert( ber != NULL ); + assert( SOCKBUF_VALID( sb ) ); + assert( LBER_VALID( ber ) ); + + if ( ber->ber_debug & LDAP_DEBUG_TRACE ) { + ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, + "ber_get_next\n" ); + } + + /* + * 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 + * + * The code also handles multi-byte tags. The first few bytes + * of the message are read to check for multi-byte tags and + * lengths. These bytes are temporarily stored in the ber_tag, + * ber_len, and ber_usertag fields of the berelement until + * tag/len parsing is complete. After this parsing, any leftover + * bytes and the rest of the message are copied into the ber_buf. + * + * We expect tag and len to be at most 32 bits wide. + */ + + if (ber->ber_rwptr == NULL) { + assert( ber->ber_buf == NULL ); + ber->ber_rwptr = (char *) &ber->ber_len-1; + ber->ber_ptr = ber->ber_rwptr; + ber->ber_tag = 0; + } + + while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr < + (char *)&ber->ber_len + LENSIZE*2) { + ber_slen_t sblen; + char buf[sizeof(ber->ber_len)-1]; + ber_len_t tlen = 0; + + /* The tag & len can be at most 9 bytes; we try to read up to 8 here */ + sock_errset(0); + sblen=((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr; + /* Trying to read the last len byte of a 9 byte tag+len */ + if (sblen<1) + sblen = 1; + sblen=ber_int_sb_read( sb, ber->ber_rwptr, sblen ); + if (sblen<=0) return LBER_DEFAULT; + ber->ber_rwptr += sblen; + + /* We got at least one byte, try to parse the tag. */ + if (ber->ber_ptr == (char *)&ber->ber_len-1) { + ber_tag_t tag; + unsigned char *p = (unsigned char *)ber->ber_ptr; + tag = *p++; + if ((tag & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK) { + ber_len_t i; + for (i=1; (char *)p<ber->ber_rwptr; i++) { + tag <<= 8; + tag |= *p++; + if (!(tag & LBER_MORE_TAG_MASK)) + break; + /* Is the tag too big? */ + if (i == sizeof(ber_tag_t)-1) { + sock_errset(ERANGE); + return LBER_DEFAULT; + } + } + /* Did we run out of bytes? */ + if ((char *)p == ber->ber_rwptr) { + sock_errset(EWOULDBLOCK); + return LBER_DEFAULT; + } + } + ber->ber_tag = tag; + ber->ber_ptr = (char *)p; + } + + if ( ber->ber_ptr == ber->ber_rwptr ) { + sock_errset(EWOULDBLOCK); + return LBER_DEFAULT; + } + + /* Now look for the length */ + if (*ber->ber_ptr & 0x80) { /* multi-byte */ + int i; + unsigned char *p = (unsigned char *)ber->ber_ptr; + int llen = *p++ & 0x7f; + if (llen > LENSIZE) { + sock_errset(ERANGE); + return LBER_DEFAULT; + } + /* Not enough bytes? */ + if (ber->ber_rwptr - (char *)p < llen) { + sock_errset(EWOULDBLOCK); + return LBER_DEFAULT; + } + for (i=0; i<llen; i++) { + tlen <<=8; + tlen |= *p++; + } + ber->ber_ptr = (char *)p; + } else { + tlen = *(unsigned char *)ber->ber_ptr++; + } + + /* Are there leftover data bytes inside ber->ber_len? */ + if (ber->ber_ptr < (char *)&ber->ber_usertag) { + if (ber->ber_rwptr < (char *)&ber->ber_usertag) { + sblen = ber->ber_rwptr - ber->ber_ptr; + } else { + sblen = (char *)&ber->ber_usertag - ber->ber_ptr; + } + AC_MEMCPY(buf, ber->ber_ptr, sblen); + ber->ber_ptr += sblen; + } else { + sblen = 0; + } + ber->ber_len = tlen; + + /* now fill the buffer. */ + + /* make sure length is reasonable */ + if ( ber->ber_len == 0 ) { + sock_errset(ERANGE); + return LBER_DEFAULT; + } + + if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) { + ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug, + "ber_get_next: sockbuf_max_incoming exceeded " + "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming ); + sock_errset(ERANGE); + return LBER_DEFAULT; + } + + if (ber->ber_buf==NULL) { + ber_len_t l = ber->ber_rwptr - ber->ber_ptr; + /* ber->ber_ptr is always <= ber->ber->ber_rwptr. + * make sure ber->ber_len agrees with what we've + * already read. + */ + if ( ber->ber_len < sblen + l ) { + sock_errset(ERANGE); + return LBER_DEFAULT; + } + ber->ber_buf = (char *) ber_memalloc_x( ber->ber_len + 1, ber->ber_memctx ); + if (ber->ber_buf==NULL) { + return LBER_DEFAULT; + } + ber->ber_end = ber->ber_buf + ber->ber_len; + if (sblen) { + AC_MEMCPY(ber->ber_buf, buf, sblen); + } + if (l > 0) { + AC_MEMCPY(ber->ber_buf + sblen, ber->ber_ptr, l); + sblen += l; + } + *ber->ber_end = '\0'; + ber->ber_ptr = ber->ber_buf; + ber->ber_usertag = 0; + if ((ber_len_t)sblen == ber->ber_len) { + goto done; + } + ber->ber_rwptr = ber->ber_buf + sblen; + } + } + + if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptr<ber->ber_end)) { + ber_slen_t res; + ber_slen_t to_go; + + to_go = ber->ber_end - ber->ber_rwptr; + /* unsigned/signed overflow */ + if (to_go<0) return LBER_DEFAULT; + + sock_errset(0); + res = ber_int_sb_read( sb, ber->ber_rwptr, to_go ); + if (res<=0) return LBER_DEFAULT; + ber->ber_rwptr+=res; + + if (res<to_go) { + sock_errset(EWOULDBLOCK); + return LBER_DEFAULT; + } +done: + ber->ber_rwptr = NULL; + *len = ber->ber_len; + if ( ber->ber_debug ) { + ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, + "ber_get_next: tag 0x%lx len %ld contents:\n", + ber->ber_tag, ber->ber_len ); + ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); + } + return (ber->ber_tag); + } + + /* invalid input */ + return LBER_DEFAULT; +} + +char * +ber_start( BerElement* ber ) +{ + return ber->ber_buf; +} + +int +ber_len( BerElement* ber ) +{ + return ( ber->ber_end - ber->ber_buf ); +} + +int +ber_ptrlen( BerElement* ber ) +{ + return ( ber->ber_ptr - ber->ber_buf ); +} + +void +ber_rewind ( BerElement * ber ) +{ + ber->ber_rwptr = NULL; + ber->ber_sos_ptr = NULL; + ber->ber_end = ber->ber_ptr; + ber->ber_ptr = ber->ber_buf; +#if 0 /* TODO: Should we add this? */ + ber->ber_tag = LBER_DEFAULT; + ber->ber_usertag = 0; +#endif +} + +int +ber_remaining( BerElement * ber ) +{ + return ber_pvt_ber_remaining( ber ); +} diff --git a/libs/ldap/liblber/lber-int.h b/libs/ldap/liblber/lber-int.h new file mode 100644 index 00000000000..1d8c5cb0b50 --- /dev/null +++ b/libs/ldap/liblber/lber-int.h @@ -0,0 +1,225 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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. + */ + +#ifndef _LBER_INT_H +#define _LBER_INT_H + +#include "lber.h" +#define LDAP_INT_DEBUG +#include "ldap_log.h" +#include "lber_pvt.h" +#include "ldap_queue.h" + +LDAP_BEGIN_DECL + +typedef void (*BER_LOG_FN)(FILE *file, + const char *subsys, int level, const char *fmt, ... ); + +LBER_V (BER_ERRNO_FN) ber_int_errno_fn; + +#ifdef LDAP_MEMORY_TRACE +# ifndef LDAP_MEMORY_DEBUG +# define LDAP_MEMORY_DEBUG 1 +# endif +#endif + +#ifdef LDAP_MEMORY_DEBUG +LBER_V (long) ber_int_meminuse; +#endif +#if defined(LDAP_MEMORY_DEBUG) && ((LDAP_MEMORY_DEBUG +0) & 2) +# define LDAP_MEMORY_DEBUG_ASSERT assert +#else +# define LDAP_MEMORY_DEBUG_ASSERT(expr) ((void) 0) +#endif + +struct lber_options { + short lbo_valid; + unsigned short lbo_options; + int lbo_debug; +}; + +LBER_F( int ) ber_pvt_log_output( + const char *subsystem, + int level, + const char *fmt, ... ); + +#define LBER_UNINITIALIZED 0x0 +#define LBER_INITIALIZED 0x1 +#define LBER_VALID_BERELEMENT 0x2 +#define LBER_VALID_SOCKBUF 0x3 + +LBER_V (struct lber_options) ber_int_options; +#define ber_int_debug ber_int_options.lbo_debug + +/* Data encoded in ASN.1 BER format */ +struct berelement { + struct lber_options ber_opts; +#define ber_valid ber_opts.lbo_valid +#define ber_options ber_opts.lbo_options +#define ber_debug ber_opts.lbo_debug + + /* + * The members below, when not NULL/LBER_DEFAULT/etc, are: + * ber_buf Data buffer. Other pointers normally point into it. + * ber_rwptr Read/write cursor for Sockbuf I/O. + * ber_memctx Context passed to ber_memalloc() & co. + * When decoding data (reading it from the BerElement): + * ber_end End of BER data. + * ber_ptr Read cursor, except for 1st octet of tags. + * ber_tag 1st octet of next tag, saved from *ber_ptr when + * ber_ptr may be pointing at a tag and is >ber_buf. + * The octet *ber_ptr itself may get overwritten with + * a \0, to terminate the preceding element. + * When encoding data (writing it to the BerElement): + * ber_end End of allocated buffer - 1 (allowing a final \0). + * ber_ptr Last complete BER element (normally write cursor). + * ber_sos_ptr NULL or write cursor for incomplete sequence or set. + * ber_sos_inner offset(seq/set length octets) if ber_sos_ptr!=NULL. + * ber_tag Default tag for next ber_printf() element. + * ber_usertag Boolean set by ber_printf "!" if it sets ber_tag. + * ber_len Reused for ber_sos_inner. + * When output to a Sockbuf: + * ber_ptr End of encoded data to write. + * When input from a Sockbuf: + * See ber_get_next(). + */ + + /* Do not change the order of these 3 fields! see ber_get_next */ + ber_tag_t ber_tag; + ber_len_t ber_len; + ber_tag_t ber_usertag; + + char *ber_buf; + char *ber_ptr; + char *ber_end; + + char *ber_sos_ptr; +# define ber_sos_inner ber_len /* reused for binary compat */ + + char *ber_rwptr; + void *ber_memctx; +}; +#define LBER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT) + +#define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr) +#define ber_pvt_ber_total(ber) ((ber)->ber_end - (ber)->ber_buf) +#define ber_pvt_ber_write(ber) ((ber)->ber_ptr - (ber)->ber_buf) + +struct sockbuf { + struct lber_options sb_opts; + Sockbuf_IO_Desc *sb_iod; /* I/O functions */ +#define sb_valid sb_opts.lbo_valid +#define sb_options sb_opts.lbo_options +#define sb_debug sb_opts.lbo_debug + ber_socket_t sb_fd; + ber_len_t sb_max_incoming; + unsigned int sb_trans_needs_read:1; + unsigned int sb_trans_needs_write:1; +#ifdef LDAP_PF_LOCAL_SENDMSG + char sb_ungetlen; + char sb_ungetbuf[8]; +#endif +}; + +#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF ) + + +/* + * decode.c, encode.c + */ + +/* Simplest OID max-DER-component to implement in both decode and encode */ +#define LBER_OID_COMPONENT_MAX ((unsigned long)-1 - 128) + + +/* + * io.c + */ +LBER_F( int ) +ber_realloc LDAP_P(( + BerElement *ber, + ber_len_t len )); + +LBER_F (char *) ber_start LDAP_P(( BerElement * )); +LBER_F (int) ber_len LDAP_P(( BerElement * )); +LBER_F (int) ber_ptrlen LDAP_P(( BerElement * )); +LBER_F (void) ber_rewind LDAP_P(( BerElement * )); + +/* + * bprint.c + */ +#define ber_log_printf ber_pvt_log_printf + +LBER_F( int ) +ber_log_bprint LDAP_P(( + int errlvl, + int loglvl, + const char *data, + ber_len_t len )); + +LBER_F( int ) +ber_log_dump LDAP_P(( + int errlvl, + int loglvl, + BerElement *ber, + int inout )); + +LBER_V (BER_LOG_FN) ber_int_log_proc; +LBER_V (FILE *) ber_pvt_err_file; + +/* memory.c */ + /* simple macros to realloc for now */ +LBER_V (BerMemoryFunctions *) ber_int_memory_fns; +LBER_F (char *) ber_strndup( LDAP_CONST char *, ber_len_t ); +LBER_F (char *) ber_strndup_x( LDAP_CONST char *, ber_len_t, void *ctx ); + +#define LBER_MALLOC(s) ber_memalloc((s)) +#define LBER_CALLOC(n,s) ber_memcalloc((n),(s)) +#define LBER_REALLOC(p,s) ber_memrealloc((p),(s)) +#define LBER_FREE(p) ber_memfree((p)) +#define LBER_VFREE(v) ber_memvfree((void**)(v)) +#define LBER_STRDUP(s) ber_strdup((s)) +#define LBER_STRNDUP(s,l) ber_strndup((s),(l)) + +/* sockbuf.c */ + +LBER_F( int ) +ber_int_sb_init LDAP_P(( Sockbuf *sb )); + +LBER_F( int ) +ber_int_sb_close LDAP_P(( Sockbuf *sb )); + +LBER_F( int ) +ber_int_sb_destroy LDAP_P(( Sockbuf *sb )); + +LBER_F( ber_slen_t ) +ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); + +LBER_F( ber_slen_t ) +ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len )); + +LDAP_END_DECL + +#endif /* _LBER_INT_H */ diff --git a/libs/ldap/liblber/memory.c b/libs/ldap/liblber/memory.c new file mode 100644 index 00000000000..ef2ac095f4f --- /dev/null +++ b/libs/ldap/liblber/memory.c @@ -0,0 +1,831 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <ac/stdlib.h> +#include <ac/string.h> + +#include "lber-int.h" + +#ifdef LDAP_MEMORY_TRACE +#include <stdio.h> +#endif + +#ifdef LDAP_MEMORY_DEBUG +/* + * LDAP_MEMORY_DEBUG should only be enabled for the purposes of + * debugging memory management within OpenLDAP libraries and slapd. + * + * It should only be enabled by an experienced developer as it causes + * the inclusion of numerous assert()'s, many of which may be triggered + * by a perfectly valid program. If LDAP_MEMORY_DEBUG & 2 is true, + * that includes asserts known to break both slapd and current clients. + * + * The code behind this macro is subject to change as needed to + * support this testing. + */ + +struct ber_mem_hdr { + ber_int_t bm_top; /* Pattern to detect buf overrun from prev buffer */ + ber_int_t bm_length; /* Length of user allocated area */ +#ifdef LDAP_MEMORY_TRACE + ber_int_t bm_sequence; /* Allocation sequence number */ +#endif + union bmu_align_u { /* Force alignment, pattern to detect back clobber */ + ber_len_t bmu_len_t; + ber_tag_t bmu_tag_t; + ber_int_t bmu_int_t; + + size_t bmu_size_t; + void * bmu_voidp; + double bmu_double; + long bmu_long; + long (*bmu_funcp)( double ); + unsigned char bmu_char[4]; + } ber_align; +#define bm_junk ber_align.bmu_len_t +#define bm_data ber_align.bmu_char[1] +#define bm_char ber_align.bmu_char +}; + +/* Pattern at top of allocated space */ +#define LBER_MEM_JUNK ((ber_int_t) 0xdeaddada) + +static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK }; + +/* Note sequence and ber_int_meminuse are counters, but are not + * thread safe. If you want to use these values for multithreaded applications, + * you must put mutexes around them, otherwise they will have incorrect values. + * When debugging, if you sort the debug output, the sequence number will + * put allocations/frees together. It is then a simple matter to write a script + * to find any allocations that don't have a buffer free function. + */ +long ber_int_meminuse = 0; +#ifdef LDAP_MEMORY_TRACE +static ber_int_t sequence = 0; +#endif + +/* Pattern placed just before user data */ +static unsigned char toppattern[4] = { 0xde, 0xad, 0xba, 0xde }; +/* Pattern placed just after user data */ +static unsigned char endpattern[4] = { 0xd1, 0xed, 0xde, 0xca }; + +#define mbu_len sizeof(ber_int_mem_hdr.ber_align) + +/* Test if pattern placed just before user data is good */ +#define testdatatop(val) ( \ + *(val->bm_char+mbu_len-4)==toppattern[0] && \ + *(val->bm_char+mbu_len-3)==toppattern[1] && \ + *(val->bm_char+mbu_len-2)==toppattern[2] && \ + *(val->bm_char+mbu_len-1)==toppattern[3] ) + +/* Place pattern just before user data */ +#define setdatatop(val) *(val->bm_char+mbu_len-4)=toppattern[0]; \ + *(val->bm_char+mbu_len-3)=toppattern[1]; \ + *(val->bm_char+mbu_len-2)=toppattern[2]; \ + *(val->bm_char+mbu_len-1)=toppattern[3]; + +/* Test if pattern placed just after user data is good */ +#define testend(val) ( *((unsigned char *)val+0)==endpattern[0] && \ + *((unsigned char *)val+1)==endpattern[1] && \ + *((unsigned char *)val+2)==endpattern[2] && \ + *((unsigned char *)val+3)==endpattern[3] ) + +/* Place pattern just after user data */ +#define setend(val) *((unsigned char *)val+0)=endpattern[0]; \ + *((unsigned char *)val+1)=endpattern[1]; \ + *((unsigned char *)val+2)=endpattern[2]; \ + *((unsigned char *)val+3)=endpattern[3]; + +#define BER_MEM_BADADDR ((void *) &ber_int_mem_hdr.bm_data) +#define BER_MEM_VALID(p) do { \ + assert( (p) != BER_MEM_BADADDR ); \ + assert( (p) != (void *) &ber_int_mem_hdr ); \ + } while(0) + +#else +#define BER_MEM_VALID(p) /* no-op */ +#endif + +BerMemoryFunctions *ber_int_memory_fns = NULL; + +void +ber_memfree_x( void *p, void *ctx ) +{ + if( p == NULL ) { + return; + } + + BER_MEM_VALID( p ); + + if( ber_int_memory_fns == NULL || ctx == NULL ) { +#ifdef LDAP_MEMORY_DEBUG + struct ber_mem_hdr *mh = (struct ber_mem_hdr *) + ((char *)p - sizeof(struct ber_mem_hdr)); + assert( mh->bm_top == LBER_MEM_JUNK); + assert( testdatatop( mh)); + assert( testend( (char *)&mh[1] + mh->bm_length) ); + ber_int_meminuse -= mh->bm_length; + +#ifdef LDAP_MEMORY_TRACE + fprintf(stderr, "0x%08lx 0x%08lx -f- %ld ber_memfree %ld\n", + (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, + ber_int_meminuse); +#endif + /* Fill the free space with poison */ + memset( mh, 0xff, mh->bm_length + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t)); + free( mh ); +#else + free( p ); +#endif + return; + } + + assert( ber_int_memory_fns->bmf_free != 0 ); + + (*ber_int_memory_fns->bmf_free)( p, ctx ); +} + +void +ber_memfree( void *p ) +{ + ber_memfree_x(p, NULL); +} + +void +ber_memvfree_x( void **vec, void *ctx ) +{ + int i; + + if( vec == NULL ) { + return; + } + + BER_MEM_VALID( vec ); + + for ( i = 0; vec[i] != NULL; i++ ) { + ber_memfree_x( vec[i], ctx ); + } + + ber_memfree_x( vec, ctx ); +} + +void +ber_memvfree( void **vec ) +{ + ber_memvfree_x( vec, NULL ); +} + +void * +ber_memalloc_x( ber_len_t s, void *ctx ) +{ + void *new; + + if( s == 0 ) { + LDAP_MEMORY_DEBUG_ASSERT( s != 0 ); + return NULL; + } + + if( ber_int_memory_fns == NULL || ctx == NULL ) { +#ifdef LDAP_MEMORY_DEBUG + new = malloc(s + sizeof(struct ber_mem_hdr) + sizeof( ber_int_t)); + if( new ) + { + struct ber_mem_hdr *mh = new; + mh->bm_top = LBER_MEM_JUNK; + mh->bm_length = s; + setdatatop( mh); + setend( (char *)&mh[1] + mh->bm_length ); + + ber_int_meminuse += mh->bm_length; /* Count mem inuse */ + +#ifdef LDAP_MEMORY_TRACE + mh->bm_sequence = sequence++; + fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memalloc %ld\n", + (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, + ber_int_meminuse); +#endif + /* poison new memory */ + memset( (char *)&mh[1], 0xff, s); + + BER_MEM_VALID( &mh[1] ); + new = &mh[1]; + } +#else + new = malloc( s ); +#endif + } else { + new = (*ber_int_memory_fns->bmf_malloc)( s, ctx ); + } + + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } + + return new; +} + +void * +ber_memalloc( ber_len_t s ) +{ + return ber_memalloc_x( s, NULL ); +} + +void * +ber_memcalloc_x( ber_len_t n, ber_len_t s, void *ctx ) +{ + void *new; + + if( n == 0 || s == 0 ) { + LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0); + return NULL; + } + + if( ber_int_memory_fns == NULL || ctx == NULL ) { +#ifdef LDAP_MEMORY_DEBUG + new = n < (-sizeof(struct ber_mem_hdr) - sizeof(ber_int_t)) / s + ? calloc(1, n*s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t)) + : NULL; + if( new ) + { + struct ber_mem_hdr *mh = new; + + mh->bm_top = LBER_MEM_JUNK; + mh->bm_length = n*s; + setdatatop( mh); + setend( (char *)&mh[1] + mh->bm_length ); + + ber_int_meminuse += mh->bm_length; + +#ifdef LDAP_MEMORY_TRACE + mh->bm_sequence = sequence++; + fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memcalloc %ld\n", + (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, + ber_int_meminuse); +#endif + BER_MEM_VALID( &mh[1] ); + new = &mh[1]; + } +#else + new = calloc( n, s ); +#endif + + } else { + new = (*ber_int_memory_fns->bmf_calloc)( n, s, ctx ); + } + + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } + + return new; +} + +void * +ber_memcalloc( ber_len_t n, ber_len_t s ) +{ + return ber_memcalloc_x( n, s, NULL ); +} + +void * +ber_memrealloc_x( void* p, ber_len_t s, void *ctx ) +{ + void *new = NULL; + + /* realloc(NULL,s) -> malloc(s) */ + if( p == NULL ) { + return ber_memalloc_x( s, ctx ); + } + + /* realloc(p,0) -> free(p) */ + if( s == 0 ) { + ber_memfree_x( p, ctx ); + return NULL; + } + + BER_MEM_VALID( p ); + + if( ber_int_memory_fns == NULL || ctx == NULL ) { +#ifdef LDAP_MEMORY_DEBUG + ber_int_t oldlen; + struct ber_mem_hdr *mh = (struct ber_mem_hdr *) + ((char *)p - sizeof(struct ber_mem_hdr)); + assert( mh->bm_top == LBER_MEM_JUNK); + assert( testdatatop( mh)); + assert( testend( (char *)&mh[1] + mh->bm_length) ); + oldlen = mh->bm_length; + + p = realloc( mh, s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) ); + if( p == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + return NULL; + } + + mh = p; + mh->bm_length = s; + setend( (char *)&mh[1] + mh->bm_length ); + if( s > oldlen ) { + /* poison any new memory */ + memset( (char *)&mh[1] + oldlen, 0xff, s - oldlen); + } + + assert( mh->bm_top == LBER_MEM_JUNK); + assert( testdatatop( mh)); + + ber_int_meminuse += s - oldlen; +#ifdef LDAP_MEMORY_TRACE + fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memrealloc %ld\n", + (long)mh->bm_sequence, (long)mh, (long)mh->bm_length, + ber_int_meminuse); +#endif + BER_MEM_VALID( &mh[1] ); + return &mh[1]; +#else + new = realloc( p, s ); +#endif + } else { + new = (*ber_int_memory_fns->bmf_realloc)( p, s, ctx ); + } + + if( new == NULL ) { + ber_errno = LBER_ERROR_MEMORY; + } + + return new; +} + +void * +ber_memrealloc( void* p, ber_len_t s ) +{ + return ber_memrealloc_x( p, s, NULL ); +} + +void +ber_bvfree_x( struct berval *bv, void *ctx ) +{ + if( bv == NULL ) { + return; + } + + BER_MEM_VALID( bv ); + + if ( bv->bv_val != NULL ) { + ber_memfree_x( bv->bv_val, ctx ); + } + + ber_memfree_x( (char *) bv, ctx ); +} + +void +ber_bvfree( struct berval *bv ) +{ + ber_bvfree_x( bv, NULL ); +} + +void +ber_bvecfree_x( struct berval **bv, void *ctx ) +{ + int i; + + if( bv == NULL ) { + return; + } + + BER_MEM_VALID( bv ); + + /* count elements */ + for ( i = 0; bv[i] != NULL; i++ ) ; + + /* free in reverse order */ + for ( i--; i >= 0; i-- ) { + ber_bvfree_x( bv[i], ctx ); + } + + ber_memfree_x( (char *) bv, ctx ); +} + +void +ber_bvecfree( struct berval **bv ) +{ + ber_bvecfree_x( bv, NULL ); +} + +int +ber_bvecadd_x( struct berval ***bvec, struct berval *bv, void *ctx ) +{ + ber_len_t i; + struct berval **new; + + if( *bvec == NULL ) { + if( bv == NULL ) { + /* nothing to add */ + return 0; + } + + *bvec = ber_memalloc_x( 2 * sizeof(struct berval *), ctx ); + + if( *bvec == NULL ) { + return -1; + } + + (*bvec)[0] = bv; + (*bvec)[1] = NULL; + + return 1; + } + + BER_MEM_VALID( bvec ); + + /* count entries */ + for ( i = 0; (*bvec)[i] != NULL; i++ ) { + /* EMPTY */; + } + + if( bv == NULL ) { + return i; + } + + new = ber_memrealloc_x( *bvec, (i+2) * sizeof(struct berval *), ctx); + + if( new == NULL ) { + return -1; + } + + *bvec = new; + + (*bvec)[i++] = bv; + (*bvec)[i] = NULL; + + return i; +} + +int +ber_bvecadd( struct berval ***bvec, struct berval *bv ) +{ + return ber_bvecadd_x( bvec, bv, NULL ); +} + +struct berval * +ber_dupbv_x( + struct berval *dst, struct berval *src, void *ctx ) +{ + struct berval *new, tmp; + + if( src == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + if ( dst ) { + if ( src->bv_val == NULL ) { + tmp.bv_val = NULL; + tmp.bv_len = 0; + } else { + + if(( tmp.bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) { + return NULL; + } + + AC_MEMCPY( tmp.bv_val, src->bv_val, src->bv_len ); + tmp.bv_val[src->bv_len] = '\0'; + tmp.bv_len = src->bv_len; + } + *dst = tmp; + return dst; + } else { + if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { + return NULL; + } + + if ( src->bv_val == NULL ) { + new->bv_val = NULL; + new->bv_len = 0; + } else { + + if(( new->bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) { + return NULL; + } + + AC_MEMCPY( new->bv_val, src->bv_val, src->bv_len ); + new->bv_val[src->bv_len] = '\0'; + new->bv_len = src->bv_len; + } + return new; + } +} + +struct berval * +ber_dupbv( + struct berval *dst, struct berval *src ) +{ + return ber_dupbv_x( dst, src, NULL ); +} + +struct berval * +ber_bvdup( + struct berval *src ) +{ + return ber_dupbv_x( NULL, src, NULL ); +} + +struct berval * +ber_str2bv_x( + LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv, + void *ctx) +{ + struct berval *new; + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + if( bv ) { + new = bv; + } else { + if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { + return NULL; + } + } + + new->bv_len = len ? len : strlen( s ); + if ( dup ) { + if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) { + if ( !bv ) + ber_memfree_x( new, ctx ); + return NULL; + } + + AC_MEMCPY( new->bv_val, s, new->bv_len ); + new->bv_val[new->bv_len] = '\0'; + } else { + new->bv_val = (char *) s; + } + + return( new ); +} + +struct berval * +ber_str2bv( + LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv) +{ + return ber_str2bv_x( s, len, dup, bv, NULL ); +} + +struct berval * +ber_mem2bv_x( + LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv, + void *ctx) +{ + struct berval *new; + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + if( bv ) { + new = bv; + } else { + if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) { + return NULL; + } + } + + new->bv_len = len; + if ( dup ) { + if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) { + if ( !bv ) { + ber_memfree_x( new, ctx ); + } + return NULL; + } + + AC_MEMCPY( new->bv_val, s, new->bv_len ); + new->bv_val[new->bv_len] = '\0'; + } else { + new->bv_val = (char *) s; + } + + return( new ); +} + +struct berval * +ber_mem2bv( + LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv) +{ + return ber_mem2bv_x( s, len, dup, bv, NULL ); +} + +char * +ber_strdup_x( LDAP_CONST char *s, void *ctx ) +{ + char *p; + size_t len; + +#ifdef LDAP_MEMORY_DEBUG + assert(s != NULL); /* bv damn better point to something */ +#endif + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + len = strlen( s ) + 1; + if ( (p = ber_memalloc_x( len, ctx )) != NULL ) { + AC_MEMCPY( p, s, len ); + } + + return p; +} + +char * +ber_strdup( LDAP_CONST char *s ) +{ + return ber_strdup_x( s, NULL ); +} + +ber_len_t +ber_strnlen( LDAP_CONST char *s, ber_len_t len ) +{ + ber_len_t l; + + for ( l = 0; l < len && s[l] != '\0'; l++ ) ; + + return l; +} + +char * +ber_strndup_x( LDAP_CONST char *s, ber_len_t l, void *ctx ) +{ + char *p; + size_t len; + +#ifdef LDAP_MEMORY_DEBUG + assert(s != NULL); /* bv damn better point to something */ +#endif + + if( s == NULL ) { + ber_errno = LBER_ERROR_PARAM; + return NULL; + } + + len = ber_strnlen( s, l ); + if ( (p = ber_memalloc_x( len + 1, ctx )) != NULL ) { + AC_MEMCPY( p, s, len ); + p[len] = '\0'; + } + + return p; +} + +char * +ber_strndup( LDAP_CONST char *s, ber_len_t l ) +{ + return ber_strndup_x( s, l, NULL ); +} + +/* + * dst is resized as required by src and the value of src is copied into dst + * dst->bv_val must be NULL (and dst->bv_len must be 0), or it must be + * alloc'ed with the context ctx + */ +struct berval * +ber_bvreplace_x( struct berval *dst, LDAP_CONST struct berval *src, void *ctx ) +{ + assert( dst != NULL ); + assert( !BER_BVISNULL( src ) ); + + if ( BER_BVISNULL( dst ) || dst->bv_len < src->bv_len ) { + dst->bv_val = ber_memrealloc_x( dst->bv_val, src->bv_len + 1, ctx ); + } + + AC_MEMCPY( dst->bv_val, src->bv_val, src->bv_len + 1 ); + dst->bv_len = src->bv_len; + + return dst; +} + +struct berval * +ber_bvreplace( struct berval *dst, LDAP_CONST struct berval *src ) +{ + return ber_bvreplace_x( dst, src, NULL ); +} + +void +ber_bvarray_free_x( BerVarray a, void *ctx ) +{ + int i; + + if (a) { + BER_MEM_VALID( a ); + + /* count elements */ + for (i=0; a[i].bv_val; i++) ; + + /* free in reverse order */ + for (i--; i>=0; i--) { + ber_memfree_x(a[i].bv_val, ctx); + } + + ber_memfree_x(a, ctx); + } +} + +void +ber_bvarray_free( BerVarray a ) +{ + ber_bvarray_free_x(a, NULL); +} + +int +ber_bvarray_dup_x( BerVarray *dst, BerVarray src, void *ctx ) +{ + int i, j; + BerVarray new; + + if ( !src ) { + *dst = NULL; + return 0; + } + + for (i=0; !BER_BVISNULL( &src[i] ); i++) ; + new = ber_memalloc_x(( i+1 ) * sizeof(BerValue), ctx ); + if ( !new ) + return -1; + for (j=0; j<i; j++) { + ber_dupbv_x( &new[j], &src[j], ctx ); + if ( BER_BVISNULL( &new[j] )) { + ber_bvarray_free_x( new, ctx ); + return -1; + } + } + BER_BVZERO( &new[j] ); + *dst = new; + return 0; +} + +int +ber_bvarray_add_x( BerVarray *a, BerValue *bv, void *ctx ) +{ + int n; + + if ( *a == NULL ) { + if (bv == NULL) { + return 0; + } + n = 0; + + *a = (BerValue *) ber_memalloc_x( 2 * sizeof(BerValue), ctx ); + if ( *a == NULL ) { + return -1; + } + + } else { + BerVarray atmp; + BER_MEM_VALID( a ); + + for ( n = 0; *a != NULL && (*a)[n].bv_val != NULL; n++ ) { + ; /* just count them */ + } + + if (bv == NULL) { + return n; + } + + atmp = (BerValue *) ber_memrealloc_x( (char *) *a, + (n + 2) * sizeof(BerValue), ctx ); + + if( atmp == NULL ) { + return -1; + } + + *a = atmp; + } + + (*a)[n++] = *bv; + (*a)[n].bv_val = NULL; + (*a)[n].bv_len = 0; + + return n; +} + +int +ber_bvarray_add( BerVarray *a, BerValue *bv ) +{ + return ber_bvarray_add_x( a, bv, NULL ); +} diff --git a/libs/ldap/liblber/nt_err.c b/libs/ldap/liblber/nt_err.c new file mode 100644 index 00000000000..54253564fd7 --- /dev/null +++ b/libs/ldap/liblber/nt_err.c @@ -0,0 +1,96 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#ifdef HAVE_WINSOCK2 +#include <winsock2.h> +#elif defined(HAVE_WINSOCK) +#include <winsock.h> +#endif /* HAVE_WINSOCK(2) */ + +#define LBER_RETSTR( x ) case x: return #x; + +char *ber_pvt_wsa_err2string( int err ) +{ + switch( err ) { + LBER_RETSTR( WSAEINTR ) + LBER_RETSTR( WSAEBADF ) + LBER_RETSTR( WSAEACCES ) + LBER_RETSTR( WSAEFAULT ) + LBER_RETSTR( WSAEINVAL ) + LBER_RETSTR( WSAEMFILE ) + LBER_RETSTR( WSAEWOULDBLOCK ) + LBER_RETSTR( WSAEINPROGRESS ) + LBER_RETSTR( WSAEALREADY ) + LBER_RETSTR( WSAENOTSOCK ) + LBER_RETSTR( WSAEDESTADDRREQ ) + LBER_RETSTR( WSAEMSGSIZE ) + LBER_RETSTR( WSAEPROTOTYPE ) + LBER_RETSTR( WSAENOPROTOOPT ) + LBER_RETSTR( WSAEPROTONOSUPPORT ) + LBER_RETSTR( WSAESOCKTNOSUPPORT ) + LBER_RETSTR( WSAEOPNOTSUPP ) + LBER_RETSTR( WSAEPFNOSUPPORT ) + LBER_RETSTR( WSAEAFNOSUPPORT ) + LBER_RETSTR( WSAEADDRINUSE ) + LBER_RETSTR( WSAEADDRNOTAVAIL ) + LBER_RETSTR( WSAENETDOWN ) + LBER_RETSTR( WSAENETUNREACH ) + LBER_RETSTR( WSAENETRESET ) + LBER_RETSTR( WSAECONNABORTED ) + LBER_RETSTR( WSAECONNRESET ) + LBER_RETSTR( WSAENOBUFS ) + LBER_RETSTR( WSAEISCONN ) + LBER_RETSTR( WSAENOTCONN ) + LBER_RETSTR( WSAESHUTDOWN ) + LBER_RETSTR( WSAETOOMANYREFS ) + LBER_RETSTR( WSAETIMEDOUT ) + LBER_RETSTR( WSAECONNREFUSED ) + LBER_RETSTR( WSAELOOP ) + LBER_RETSTR( WSAENAMETOOLONG ) + LBER_RETSTR( WSAEHOSTDOWN ) + LBER_RETSTR( WSAEHOSTUNREACH ) + LBER_RETSTR( WSAENOTEMPTY ) + LBER_RETSTR( WSAEPROCLIM ) + LBER_RETSTR( WSAEUSERS ) + LBER_RETSTR( WSAEDQUOT ) + LBER_RETSTR( WSAESTALE ) + LBER_RETSTR( WSAEREMOTE ) + LBER_RETSTR( WSASYSNOTREADY ) + LBER_RETSTR( WSAVERNOTSUPPORTED ) + LBER_RETSTR( WSANOTINITIALISED ) + LBER_RETSTR( WSAEDISCON ) + +#ifdef HAVE_WINSOCK2 + LBER_RETSTR( WSAENOMORE ) + LBER_RETSTR( WSAECANCELLED ) + LBER_RETSTR( WSAEINVALIDPROCTABLE ) + LBER_RETSTR( WSAEINVALIDPROVIDER ) + LBER_RETSTR( WSASYSCALLFAILURE ) + LBER_RETSTR( WSASERVICE_NOT_FOUND ) + LBER_RETSTR( WSATYPE_NOT_FOUND ) + LBER_RETSTR( WSA_E_NO_MORE ) + LBER_RETSTR( WSA_E_CANCELLED ) + LBER_RETSTR( WSAEREFUSED ) +#endif /* HAVE_WINSOCK2 */ + + LBER_RETSTR( WSAHOST_NOT_FOUND ) + LBER_RETSTR( WSATRY_AGAIN ) + LBER_RETSTR( WSANO_RECOVERY ) + LBER_RETSTR( WSANO_DATA ) + } + return "unknown WSA error"; +} diff --git a/libs/ldap/liblber/options.c b/libs/ldap/liblber/options.c new file mode 100644 index 00000000000..a51e16c8f9d --- /dev/null +++ b/libs/ldap/liblber/options.c @@ -0,0 +1,237 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/stdarg.h> +#include "lber-int.h" + +char ber_pvt_opt_on; /* used to get a non-NULL address for *_OPT_ON */ + +struct lber_options ber_int_options = { + LBER_UNINITIALIZED, 0, 0 }; + +static BerMemoryFunctions ber_int_memory_fns_datum; + +int +ber_get_option( + void *item, + int option, + void *outvalue) +{ + const BerElement *ber; + const Sockbuf *sb; + + if(outvalue == NULL) { + /* no place to get to */ + ber_errno = LBER_ERROR_PARAM; + return LBER_OPT_ERROR; + } + + if(item == NULL) { + switch ( option ) { + case LBER_OPT_BER_DEBUG: + * (int *) outvalue = ber_int_debug; + return LBER_OPT_SUCCESS; + + case LBER_OPT_MEMORY_INUSE: + /* The memory inuse is a global variable on kernel implementations. + * This means that memory debug is shared by all LDAP processes + * so for this variable to have much meaning, only one LDAP process + * should be running and memory inuse should be initialized to zero + * using the lber_set_option() function during startup. + * The counter is not accurate for multithreaded ldap applications. + */ +#ifdef LDAP_MEMORY_DEBUG + * (int *) outvalue = ber_int_meminuse; + return LBER_OPT_SUCCESS; +#else + return LBER_OPT_ERROR; +#endif + + case LBER_OPT_LOG_PRINT_FILE: + *((FILE**)outvalue) = (FILE*)ber_pvt_err_file; + return LBER_OPT_SUCCESS; + + case LBER_OPT_LOG_PRINT_FN: + *(BER_LOG_PRINT_FN *)outvalue = ber_pvt_log_print; + return LBER_OPT_SUCCESS; + } + + ber_errno = LBER_ERROR_PARAM; + return LBER_OPT_ERROR; + } + + ber = item; + sb = item; + + switch(option) { + case LBER_OPT_BER_OPTIONS: + assert( LBER_VALID( ber ) ); + * (int *) outvalue = ber->ber_options; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_DEBUG: + assert( LBER_VALID( ber ) ); + * (int *) outvalue = ber->ber_debug; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_REMAINING_BYTES: + assert( LBER_VALID( ber ) ); + *((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber); + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_TOTAL_BYTES: + assert( LBER_VALID( ber ) ); + *((ber_len_t *) outvalue) = ber_pvt_ber_total(ber); + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_BYTES_TO_WRITE: + assert( LBER_VALID( ber ) ); + *((ber_len_t *) outvalue) = ber_pvt_ber_write(ber); + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_MEMCTX: + assert( LBER_VALID( ber ) ); + *((void **) outvalue) = ber->ber_memctx; + return LBER_OPT_SUCCESS; + + default: + /* bad param */ + ber_errno = LBER_ERROR_PARAM; + break; + } + + return LBER_OPT_ERROR; +} + +int +ber_set_option( + void *item, + int option, + LDAP_CONST void *invalue) +{ + BerElement *ber; + Sockbuf *sb; + + if(invalue == NULL) { + /* no place to set from */ + ber_errno = LBER_ERROR_PARAM; + return LBER_OPT_ERROR; + } + + if(item == NULL) { + switch ( option ) { + case LBER_OPT_BER_DEBUG: + ber_int_debug = * (const int *) invalue; + return LBER_OPT_SUCCESS; + + case LBER_OPT_LOG_PRINT_FN: + ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue; + return LBER_OPT_SUCCESS; + + case LBER_OPT_LOG_PRINT_FILE: + ber_pvt_err_file = (void *) invalue; + return LBER_OPT_SUCCESS; + + case LBER_OPT_MEMORY_INUSE: + /* The memory inuse is a global variable on kernel implementations. + * This means that memory debug is shared by all LDAP processes + * so for this variable to have much meaning, only one LDAP process + * should be running and memory inuse should be initialized to zero + * using the lber_set_option() function during startup. + * The counter is not accurate for multithreaded applications. + */ +#ifdef LDAP_MEMORY_DEBUG + ber_int_meminuse = * (int *) invalue; + return LBER_OPT_SUCCESS; +#else + return LBER_OPT_ERROR; +#endif + case LBER_OPT_MEMORY_FNS: + if ( ber_int_memory_fns == NULL ) + { + const BerMemoryFunctions *f = + (const BerMemoryFunctions *) invalue; + /* make sure all functions are provided */ + if(!( f->bmf_malloc && f->bmf_calloc + && f->bmf_realloc && f->bmf_free )) + { + ber_errno = LBER_ERROR_PARAM; + return LBER_OPT_ERROR; + } + + ber_int_memory_fns = &ber_int_memory_fns_datum; + + AC_MEMCPY(ber_int_memory_fns, f, + sizeof(BerMemoryFunctions)); + + return LBER_OPT_SUCCESS; + } + break; + + case LBER_OPT_LOG_PROC: + ber_int_log_proc = (BER_LOG_FN)invalue; + return LBER_OPT_SUCCESS; + } + + ber_errno = LBER_ERROR_PARAM; + return LBER_OPT_ERROR; + } + + ber = item; + sb = item; + + switch(option) { + case LBER_OPT_BER_OPTIONS: + assert( LBER_VALID( ber ) ); + ber->ber_options = * (const int *) invalue; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_DEBUG: + assert( LBER_VALID( ber ) ); + ber->ber_debug = * (const int *) invalue; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_REMAINING_BYTES: + assert( LBER_VALID( ber ) ); + ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_TOTAL_BYTES: + assert( LBER_VALID( ber ) ); + ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_BYTES_TO_WRITE: + assert( LBER_VALID( ber ) ); + ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue]; + return LBER_OPT_SUCCESS; + + case LBER_OPT_BER_MEMCTX: + assert( LBER_VALID( ber ) ); + ber->ber_memctx = *(void **)invalue; + return LBER_OPT_SUCCESS; + + default: + /* bad param */ + ber_errno = LBER_ERROR_PARAM; + break; + } + + return LBER_OPT_ERROR; +} diff --git a/libs/ldap/liblber/sockbuf.c b/libs/ldap/liblber/sockbuf.c new file mode 100644 index 00000000000..915941a5d09 --- /dev/null +++ b/libs/ldap/liblber/sockbuf.c @@ -0,0 +1,988 @@ +/* sockbuf.c - i/o routines with support for adding i/o layers. */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/ctype.h> +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif /* HAVE_IO_H */ + +#if defined( HAVE_FCNTL_H ) +#include <fcntl.h> +#endif + +#if defined( HAVE_SYS_FILIO_H ) +#include <sys/filio.h> +#elif defined( HAVE_SYS_IOCTL_H ) +#include <sys/ioctl.h> +#endif + +#include "lber-int.h" + +#ifndef LBER_MIN_BUFF_SIZE +#define LBER_MIN_BUFF_SIZE 4096 +#endif +#ifndef LBER_MAX_BUFF_SIZE +#define LBER_MAX_BUFF_SIZE (65536*256) +#endif +#ifndef LBER_DEFAULT_READAHEAD +#define LBER_DEFAULT_READAHEAD 16384 +#endif + +Sockbuf * +ber_sockbuf_alloc( void ) +{ + Sockbuf *sb; + + sb = LBER_CALLOC( 1, sizeof( Sockbuf ) ); + + if( sb == NULL ) return NULL; + + ber_int_sb_init( sb ); + return sb; +} + +void +ber_sockbuf_free( Sockbuf *sb ) +{ + assert( sb != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + ber_int_sb_close( sb ); + ber_int_sb_destroy( sb ); + LBER_FREE( sb ); +} + +/* Return values: -1: error, 0: no operation performed or the answer is false, + * 1: successful operation or the answer is true + */ +int +ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg ) +{ + Sockbuf_IO_Desc *p; + int ret = 0; + + assert( sb != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + switch ( opt ) { + case LBER_SB_OPT_HAS_IO: + p = sb->sb_iod; + while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) { + p = p->sbiod_next; + } + + if ( p ) { + ret = 1; + } + break; + + case LBER_SB_OPT_GET_FD: + if ( arg != NULL ) { + *((ber_socket_t *)arg) = sb->sb_fd; + } + ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1); + break; + + case LBER_SB_OPT_SET_FD: + sb->sb_fd = *((ber_socket_t *)arg); + ret = 1; + break; + + case LBER_SB_OPT_SET_NONBLOCK: + ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL) + ? -1 : 1; + break; + + case LBER_SB_OPT_DRAIN: { + /* Drain the data source to enable possible errors (e.g. + * TLS) to be propagated to the upper layers + */ + char buf[LBER_MIN_BUFF_SIZE]; + + do { + ret = ber_int_sb_read( sb, buf, sizeof( buf ) ); + } while ( ret == sizeof( buf ) ); + + ret = 1; + } break; + + case LBER_SB_OPT_NEEDS_READ: + ret = ( sb->sb_trans_needs_read ? 1 : 0 ); + break; + + case LBER_SB_OPT_NEEDS_WRITE: + ret = ( sb->sb_trans_needs_write ? 1 : 0 ); + break; + + case LBER_SB_OPT_GET_MAX_INCOMING: + if ( arg != NULL ) { + *((ber_len_t *)arg) = sb->sb_max_incoming; + } + ret = 1; + break; + + case LBER_SB_OPT_SET_MAX_INCOMING: + sb->sb_max_incoming = *((ber_len_t *)arg); + ret = 1; + break; + + case LBER_SB_OPT_UNGET_BUF: +#ifdef LDAP_PF_LOCAL_SENDMSG + sb->sb_ungetlen = ((struct berval *)arg)->bv_len; + if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) { + AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val, + sb->sb_ungetlen ); + ret = 1; + } else { + sb->sb_ungetlen = 0; + ret = -1; + } +#endif + break; + + default: + ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg ); + break; + } + + return ret; +} + +int +ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg ) +{ + Sockbuf_IO_Desc *d, *p, **q; + + assert( sb != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + if ( sbio == NULL ) { + return -1; + } + + q = &sb->sb_iod; + p = *q; + while ( p && p->sbiod_level > layer ) { + q = &p->sbiod_next; + p = *q; + } + + d = LBER_MALLOC( sizeof( *d ) ); + if ( d == NULL ) { + return -1; + } + + d->sbiod_level = layer; + d->sbiod_sb = sb; + d->sbiod_io = sbio; + memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) ); + d->sbiod_next = p; + *q = d; + + if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) { + return -1; + } + + return 0; +} + +int +ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer ) +{ + Sockbuf_IO_Desc *p, **q; + + assert( sb != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + if ( sb->sb_iod == NULL ) { + return -1; + } + + q = &sb->sb_iod; + while ( *q != NULL ) { + p = *q; + if ( layer == p->sbiod_level && p->sbiod_io == sbio ) { + if ( p->sbiod_io->sbi_remove != NULL && + p->sbiod_io->sbi_remove( p ) < 0 ) + { + return -1; + } + *q = p->sbiod_next; + LBER_FREE( p ); + break; + } + q = &p->sbiod_next; + } + + return 0; +} + +void +ber_pvt_sb_buf_init( Sockbuf_Buf *buf ) +{ + buf->buf_base = NULL; + buf->buf_ptr = 0; + buf->buf_end = 0; + buf->buf_size = 0; +} + +void +ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf ) +{ + assert( buf != NULL); + + if (buf->buf_base) { + LBER_FREE( buf->buf_base ); + } + ber_pvt_sb_buf_init( buf ); +} + +int +ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize ) +{ + ber_len_t pw; + char *p; + + assert( buf != NULL ); + + for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) { + if (pw > LBER_MAX_BUFF_SIZE) return -1; + } + + if ( buf->buf_size < pw ) { + p = LBER_REALLOC( buf->buf_base, pw ); + if ( p == NULL ) return -1; + buf->buf_base = p; + buf->buf_size = pw; + } + return 0; +} + +ber_len_t +ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len ) +{ + ber_len_t max; + + assert( buf != NULL ); + assert( sbb != NULL ); +#if 0 + assert( sbb->buf_size > 0 ); +#endif + + max = sbb->buf_end - sbb->buf_ptr; + max = ( max < len) ? max : len; + if ( max ) { + AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max ); + sbb->buf_ptr += max; + if ( sbb->buf_ptr >= sbb->buf_end ) { + sbb->buf_ptr = sbb->buf_end = 0; + } + } + return max; +} + +ber_slen_t +ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ) +{ + ber_len_t to_go; + ber_slen_t ret; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + to_go = buf_out->buf_end - buf_out->buf_ptr; + assert( to_go > 0 ); + + for(;;) { + ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base + + buf_out->buf_ptr, to_go ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) continue; +#endif + break; + } + + if ( ret <= 0 ) return ret; + + buf_out->buf_ptr += ret; + if (buf_out->buf_ptr == buf_out->buf_end) { + buf_out->buf_end = buf_out->buf_ptr = 0; + } + + return ret; +} + +int +ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) +{ +#ifdef HAVE_FCNTL + int flags = fcntl( sd, F_GETFL); + if( nb ) { + flags |= O_NONBLOCK; + } else { + flags &= ~O_NONBLOCK; + } + return fcntl( sd, F_SETFL, flags ); + +#elif defined( FIONBIO ) + ioctl_t status = nb ? 1 : 0; + return ioctl( sd, FIONBIO, &status ); +#endif +} + +int +ber_int_sb_init( Sockbuf *sb ) +{ + assert( sb != NULL); + + sb->sb_valid=LBER_VALID_SOCKBUF; + sb->sb_options = 0; + sb->sb_debug = ber_int_debug; + sb->sb_fd = AC_SOCKET_INVALID; + sb->sb_iod = NULL; + sb->sb_trans_needs_read = 0; + sb->sb_trans_needs_write = 0; + + assert( SOCKBUF_VALID( sb ) ); + return 0; +} + +int +ber_int_sb_close( Sockbuf *sb ) +{ + Sockbuf_IO_Desc *p; + + assert( sb != NULL); + + p = sb->sb_iod; + while ( p ) { + if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) { + return -1; + } + p = p->sbiod_next; + } + + sb->sb_fd = AC_SOCKET_INVALID; + + return 0; +} + +int +ber_int_sb_destroy( Sockbuf *sb ) +{ + Sockbuf_IO_Desc *p; + + assert( sb != NULL); + assert( SOCKBUF_VALID( sb ) ); + + while ( sb->sb_iod ) { + p = sb->sb_iod->sbiod_next; + ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io, + sb->sb_iod->sbiod_level ); + sb->sb_iod = p; + } + + return ber_int_sb_init( sb ); +} + +ber_slen_t +ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + + assert( buf != NULL ); + assert( sb != NULL); + assert( sb->sb_iod != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + for (;;) { + ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len ); + +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; +#endif + break; + } + + return ret; +} + +ber_slen_t +ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + + assert( buf != NULL ); + assert( sb != NULL); + assert( sb->sb_iod != NULL ); + assert( SOCKBUF_VALID( sb ) ); + + for (;;) { + ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len ); + +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; +#endif + break; + } + + return ret; +} + +/* + * Support for TCP + */ + +static ber_slen_t +sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + +#if defined(MACOS) +/* + * MacTCP/OpenTransport + */ + return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf, + len, NULL ); + +#elif defined( HAVE_PCNFS ) || \ + defined( HAVE_WINSOCK ) || defined ( __BEOS__ ) +/* + * PCNFS (under DOS) + */ +/* + * Windows Socket API (under DOS/Windows 3.x) + */ +/* + * 32-bit Windows Socket API (under Windows NT or Windows 95) + */ + return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); + +#elif defined( HAVE_NCSA ) +/* + * NCSA Telnet TCP/IP stack (under DOS) + */ + return nread( sbiod->sbiod_sb->sb_fd, buf, len ); + +#else + return read( sbiod->sbiod_sb->sb_fd, buf, len ); +#endif +} + +static ber_slen_t +sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + +#if defined(MACOS) +/* + * MacTCP/OpenTransport + */ +#define MAX_WRITE 65535 + return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf, + (len<MAX_WRITE) ? len : MAX_WRITE ); + +#elif defined( HAVE_PCNFS) \ + || defined( HAVE_WINSOCK) || defined ( __BEOS__ ) +/* + * PCNFS (under DOS) + */ +/* + * Windows Socket API (under DOS/Windows 3.x) + */ +/* + * 32-bit Windows Socket API (under Windows NT or Windows 95) + */ + return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); + +#elif defined(HAVE_NCSA) + return netwrite( sbiod->sbiod_sb->sb_fd, buf, len ); + +#elif defined(VMS) +/* + * VMS -- each write must be 64K or smaller + */ +#define MAX_WRITE 65535 + return write( sbiod->sbiod_sb->sb_fd, buf, + (len<MAX_WRITE) ? len : MAX_WRITE); +#else + return write( sbiod->sbiod_sb->sb_fd, buf, len ); +#endif +} + +static int +sb_stream_close( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) + tcp_close( sbiod->sbiod_sb->sb_fd ); + return 0; +} + +/* The argument is a pointer to the socket descriptor */ +static int +sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { + assert( sbiod != NULL ); + + if ( arg != NULL ) { + sbiod->sbiod_sb->sb_fd = *((int *)arg); + } + return 0; +} + +static int +sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { + /* This is an end IO descriptor */ + return 0; +} + +Sockbuf_IO ber_sockbuf_io_tcp = { + sb_stream_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + sb_stream_ctrl, /* sbi_ctrl */ + sb_stream_read, /* sbi_read */ + sb_stream_write, /* sbi_write */ + sb_stream_close /* sbi_close */ +}; + + +/* + * Support for readahead (UDP needs it) + */ + +static int +sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + Sockbuf_Buf *p; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) return -1; + + ber_pvt_sb_buf_init( p ); + + if ( arg == NULL ) { + ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD ); + } else { + ber_pvt_sb_grow_buffer( p, *((int *)arg) ); + } + + sbiod->sbiod_pvt = p; + return 0; +} + +static int +sb_rdahead_remove( Sockbuf_IO_Desc *sbiod ) +{ + Sockbuf_Buf *p; + + assert( sbiod != NULL ); + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + if ( p->buf_ptr != p->buf_end ) return -1; + + ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) ); + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + + return 0; +} + +static ber_slen_t +sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + Sockbuf_Buf *p; + ber_slen_t bufptr = 0, ret, max; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + assert( sbiod->sbiod_next != NULL ); + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + assert( p->buf_size > 0 ); + + /* Are there anything left in the buffer? */ + ret = ber_pvt_sb_copy_out( p, buf, len ); + bufptr += ret; + len -= ret; + + if ( len == 0 ) return bufptr; + + max = p->buf_size - p->buf_end; + ret = 0; + while ( max > 0 ) { + ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end, + max ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; +#endif + break; + } + + if ( ret < 0 ) { + return ( bufptr ? bufptr : ret ); + } + + p->buf_end += ret; + bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len ); + return bufptr; +} + +static ber_slen_t +sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL ); + assert( sbiod->sbiod_next != NULL ); + + return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); +} + +static int +sb_rdahead_close( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + + /* Just erase the buffer */ + ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt); + return 0; +} + +static int +sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + Sockbuf_Buf *p; + + p = (Sockbuf_Buf *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( p->buf_ptr != p->buf_end ) { + return 1; + } + + } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) { + if ( p->buf_size >= *((ber_len_t *)arg) ) { + return 0; + } + return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ? + -1 : 1 ); + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +Sockbuf_IO ber_sockbuf_io_readahead = { + sb_rdahead_setup, /* sbi_setup */ + sb_rdahead_remove, /* sbi_remove */ + sb_rdahead_ctrl, /* sbi_ctrl */ + sb_rdahead_read, /* sbi_read */ + sb_rdahead_write, /* sbi_write */ + sb_rdahead_close /* sbi_close */ +}; + +/* + * Support for simple file IO + */ + +static ber_slen_t +sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + +#ifdef LDAP_PF_LOCAL_SENDMSG + if ( sbiod->sbiod_sb->sb_ungetlen ) { + ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen; + if ( blen > len ) + blen = len; + AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen ); + buf = (char *) buf + blen; + len -= blen; + sbiod->sbiod_sb->sb_ungetlen -= blen; + if ( sbiod->sbiod_sb->sb_ungetlen ) { + AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf, + sbiod->sbiod_sb->sb_ungetbuf+blen, + sbiod->sbiod_sb->sb_ungetlen ); + } + if ( len == 0 ) + return blen; + } +#endif + return read( sbiod->sbiod_sb->sb_fd, buf, len ); +} + +static ber_slen_t +sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + return write( sbiod->sbiod_sb->sb_fd, buf, len ); +} + +static int +sb_fd_close( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) + close( sbiod->sbiod_sb->sb_fd ); + return 0; +} + +/* The argument is a pointer to the file descriptor */ +static int +sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { + assert( sbiod != NULL ); + + if ( arg != NULL ) + sbiod->sbiod_sb->sb_fd = *((int *)arg); + return 0; +} + +static int +sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { + /* This is an end IO descriptor */ + return 0; +} + +Sockbuf_IO ber_sockbuf_io_fd = { + sb_fd_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + sb_fd_ctrl, /* sbi_ctrl */ + sb_fd_read, /* sbi_read */ + sb_fd_write, /* sbi_write */ + sb_fd_close /* sbi_close */ +}; + +/* + * Debugging layer + */ + +static int +sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + assert( sbiod != NULL ); + + if ( arg == NULL ) arg = "sockbuf_"; + + sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 ); + if ( sbiod->sbiod_pvt == NULL ) return -1; + + strcpy( (char *)sbiod->sbiod_pvt, (char *)arg ); + return 0; +} + +static int +sb_debug_remove( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static int +sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +static ber_slen_t +sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + char ebuf[128]; + + ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len ); + if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { + int err = sock_errno(); + if ( ret < 0 ) { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, + (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); + } else { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt, + (long)len, (long)ret ); + ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + (const char *)buf, ret ); + } + sock_errset(err); + } + return ret; +} + +static ber_slen_t +sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t ret; + char ebuf[128]; + + ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); + if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { + int err = sock_errno(); + if ( ret < 0 ) { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%swrite: want=%ld error=%s\n", + (char *)sbiod->sbiod_pvt, (long)len, + AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); + } else { + ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + "%swrite: want=%ld, written=%ld\n", + (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); + ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, + (const char *)buf, ret ); + } + sock_errset(err); + } + + return ret; +} + +Sockbuf_IO ber_sockbuf_io_debug = { + sb_debug_setup, /* sbi_setup */ + sb_debug_remove, /* sbi_remove */ + sb_debug_ctrl, /* sbi_ctrl */ + sb_debug_read, /* sbi_read */ + sb_debug_write, /* sbi_write */ + NULL /* sbi_close */ +}; + +#ifdef LDAP_CONNECTIONLESS + +/* + * Support for UDP (CLDAP) + * + * All I/O at this level must be atomic. For ease of use, the sb_readahead + * must be used above this module. All data reads and writes are prefixed + * with a sockaddr_storage containing the address of the remote entity. Upper levels + * must read and write this sockaddr_storage before doing the usual ber_printf/scanf + * operations on LDAP messages. + */ + +static int +sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + assert( sbiod != NULL); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg); + return 0; +} + +static ber_slen_t +sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t rc; + ber_socklen_t addrlen; + struct sockaddr *src; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + assert( buf != NULL ); + + addrlen = sizeof( struct sockaddr_storage ); + src = buf; + buf = (char *) buf + addrlen; + len -= addrlen; + rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen ); + + return rc > 0 ? rc+sizeof(struct sockaddr_storage) : rc; +} + +static ber_slen_t +sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) +{ + ber_slen_t rc; + struct sockaddr *dst; + socklen_t dstsize; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + assert( buf != NULL ); + + dst = buf; + buf = (char *) buf + sizeof( struct sockaddr_storage ); + len -= sizeof( struct sockaddr_storage ); + dstsize = dst->sa_family == AF_INET ? sizeof( struct sockaddr_in ) +#ifdef LDAP_PF_INET6 + : dst->sa_family == AF_INET6 ? sizeof( struct sockaddr_in6 ) +#endif + : sizeof( struct sockaddr_storage ); + rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst, dstsize ); + + if ( rc < 0 ) return -1; + + /* fake error if write was not atomic */ + if (rc < len) { +# ifdef EMSGSIZE + errno = EMSGSIZE; +# endif + return -1; + } + rc = len + sizeof(struct sockaddr_storage); + return rc; +} + +static int +sb_dgram_close( Sockbuf_IO_Desc *sbiod ) +{ + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) + tcp_close( sbiod->sbiod_sb->sb_fd ); + return 0; +} + +static int +sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + /* This is an end IO descriptor */ + return 0; +} + +Sockbuf_IO ber_sockbuf_io_udp = +{ + sb_dgram_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + sb_dgram_ctrl, /* sbi_ctrl */ + sb_dgram_read, /* sbi_read */ + sb_dgram_write, /* sbi_write */ + sb_dgram_close /* sbi_close */ +}; + +#endif /* LDAP_CONNECTIONLESS */ diff --git a/libs/ldap/libldap/abandon.c b/libs/ldap/libldap/abandon.c new file mode 100644 index 00000000000..35e81a7e3ed --- /dev/null +++ b/libs/ldap/libldap/abandon.c @@ -0,0 +1,458 @@ +/* abandon.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* + * An abandon request looks like this: + * AbandonRequest ::= [APPLICATION 16] MessageID + * and has no response. (Source: RFC 4511) + */ +#include "lutil.h" + +static int +do_abandon( + LDAP *ld, + ber_int_t origid, + LDAPRequest *lr, + LDAPControl **sctrls, + int sendabandon ); + +/* + * ldap_abandon_ext - perform an ldap extended abandon operation. + * + * Parameters: + * ld LDAP descriptor + * msgid The message id of the operation to abandon + * scntrls Server Controls + * ccntrls Client Controls + * + * ldap_abandon_ext returns a LDAP error code. + * (LDAP_SUCCESS if everything went ok) + * + * Example: + * ldap_abandon_ext( ld, msgid, scntrls, ccntrls ); + */ +int +ldap_abandon_ext( + LDAP *ld, + int msgid, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int rc; + + Debug1( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid ); + + /* check client controls */ + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + + rc = ldap_int_client_controls( ld, cctrls ); + if ( rc == LDAP_SUCCESS ) { + rc = do_abandon( ld, msgid, NULL, sctrls, 1 ); + } + + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + + return rc; +} + + +/* + * 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_abandon( LDAP *ld, int msgid ) +{ + Debug1( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid ); + return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS + ? 0 : -1; +} + + +int +ldap_pvt_discard( + LDAP *ld, + ber_int_t msgid ) +{ + int rc; + + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + rc = do_abandon( ld, msgid, NULL, NULL, 0 ); + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + return rc; +} + +static int +do_abandon( + LDAP *ld, + ber_int_t origid, + LDAPRequest *lr, + LDAPControl **sctrls, + int sendabandon ) +{ + BerElement *ber; + int i, err; + ber_int_t msgid = origid; + Sockbuf *sb; + LDAPRequest needle = {0}; + + needle.lr_msgid = origid; + + if ( lr != NULL ) { + msgid = lr->lr_msgid; + Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", + origid, msgid ); + } else if ( (lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp )) != NULL ) { + Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", + origid, msgid ); + if ( lr->lr_parent != NULL ) { + /* don't let caller abandon child requests! */ + ld->ld_errno = LDAP_PARAM_ERROR; + return( LDAP_PARAM_ERROR ); + } + msgid = lr->lr_msgid; + } + + if ( lr != NULL ) { + LDAPRequest **childp = &lr->lr_child; + + needle.lr_msgid = lr->lr_msgid; + + if ( lr->lr_status != LDAP_REQST_INPROGRESS ) { + /* no need to send abandon message */ + sendabandon = 0; + } + + while ( *childp ) { + /* Abandon children */ + LDAPRequest *child = *childp; + + (void)do_abandon( ld, lr->lr_origid, child, sctrls, sendabandon ); + if ( *childp == child ) { + childp = &child->lr_refnext; + } + } + } + + /* ldap_msgdelete locks the res_mutex. Give up the req_mutex + * while we're in there. + */ + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + err = ldap_msgdelete( ld, msgid ); + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + if ( err == 0 ) { + ld->ld_errno = LDAP_SUCCESS; + return LDAP_SUCCESS; + } + + /* fetch again the request that we are abandoning */ + if ( lr != NULL ) { + lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp ); + } + + err = 0; + if ( sendabandon ) { + if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) { + /* not connected */ + err = -1; + ld->ld_errno = LDAP_SERVER_DOWN; + + } else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) { + /* BER element allocation failed */ + err = -1; + ld->ld_errno = LDAP_NO_MEMORY; + + } else { + /* + * We already have the mutex in LDAP_R_COMPILE, so + * don't try to get it again. + * LDAP_NEXT_MSGID(ld, i); + */ + + LDAP_NEXT_MSGID(ld, i); +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP(ld) ) { + struct sockaddr_storage sa = {0}; + /* dummy, filled with ldo_peer in request.c */ + err = ber_write( ber, (char *) &sa, sizeof(sa), 0 ); + } + if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == + LDAP_VERSION2 ) + { + char *dn; + LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); + dn = ld->ld_options.ldo_cldapdn; + if (!dn) dn = ""; + err = ber_printf( ber, "{isti", /* '}' */ + i, dn, + LDAP_REQ_ABANDON, msgid ); + LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); + } else +#endif + { + /* create a message to send */ + err = ber_printf( ber, "{iti", /* '}' */ + i, + LDAP_REQ_ABANDON, msgid ); + } + + if ( err == -1 ) { + /* encoding error */ + ld->ld_errno = LDAP_ENCODING_ERROR; + + } else { + /* Put Server Controls */ + if ( ldap_int_put_controls( ld, sctrls, ber ) + != LDAP_SUCCESS ) + { + err = -1; + + } else { + /* close '{' */ + err = ber_printf( ber, /*{*/ "N}" ); + + if ( err == -1 ) { + /* encoding error */ + ld->ld_errno = LDAP_ENCODING_ERROR; + } + } + } + + if ( err == -1 ) { + ber_free( ber, 1 ); + + } else { + /* send the message */ + if ( lr != NULL ) { + assert( lr->lr_conn != NULL ); + sb = lr->lr_conn->lconn_sb; + } else { + sb = ld->ld_sb; + } + + if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) { + ld->ld_errno = LDAP_SERVER_DOWN; + err = -1; + } else { + err = 0; + } + } + } + } + + if ( lr != NULL ) { + LDAPConn *lc; + int freeconn = 0; + if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) { + freeconn = 1; + lc = lr->lr_conn; + } + if ( origid == msgid ) { + ldap_free_request( ld, lr ); + + } else { + lr->lr_abandoned = 1; + } + + if ( freeconn ) { + /* release ld_req_mutex while grabbing ld_conn_mutex to + * prevent deadlock. + */ + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + ldap_free_connection( ld, lc, 0, 1 ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + } + } + + LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); + + /* use bisection */ + i = 0; + if ( ld->ld_nabandoned == 0 || + ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 ) + { + ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i ); + } + + if ( err != -1 ) { + ld->ld_errno = LDAP_SUCCESS; + } + + LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); + return( ld->ld_errno ); +} + +/* + * ldap_int_bisect_find + * + * args: + * v: array of length n (in) + * n: length of array v (in) + * id: value to look for (in) + * idxp: pointer to location of value/insert point + * + * return: + * 0: not found + * 1: found + * -1: error + */ +int +ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp ) +{ + int begin, + end, + rc = 0; + + assert( id >= 0 ); + + begin = 0; + end = n - 1; + + if ( n <= 0 || id < v[ begin ] ) { + *idxp = 0; + + } else if ( id > v[ end ] ) { + *idxp = n; + + } else { + int pos; + ber_int_t curid; + + do { + pos = (begin + end)/2; + curid = v[ pos ]; + + if ( id < curid ) { + end = pos - 1; + + } else if ( id > curid ) { + begin = ++pos; + + } else { + /* already abandoned? */ + rc = 1; + break; + } + } while ( end >= begin ); + + *idxp = pos; + } + + return rc; +} + +/* + * ldap_int_bisect_insert + * + * args: + * vp: pointer to array of length *np (in/out) + * np: pointer to length of array *vp (in/out) + * id: value to insert (in) + * idx: location of insert point (as computed by ldap_int_bisect_find()) + * + * return: + * 0: inserted + * -1: error + */ +int +ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx ) +{ + ber_int_t *v; + ber_len_t n; + int i; + + assert( vp != NULL ); + assert( np != NULL ); + assert( idx >= 0 ); + assert( (unsigned) idx <= *np ); + + n = *np; + + v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) ); + if ( v == NULL ) { + return -1; + } + *vp = v; + + for ( i = n; i > idx; i-- ) { + v[ i ] = v[ i - 1 ]; + } + v[ idx ] = id; + ++(*np); + + return 0; +} + +/* + * ldap_int_bisect_delete + * + * args: + * vp: pointer to array of length *np (in/out) + * np: pointer to length of array *vp (in/out) + * id: value to delete (in) + * idx: location of value to delete (as computed by ldap_int_bisect_find()) + * + * return: + * 0: deleted + */ +int +ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx ) +{ + ber_int_t *v; + ber_len_t i, n; + + assert( vp != NULL ); + assert( np != NULL ); + assert( idx >= 0 ); + assert( (unsigned) idx < *np ); + + v = *vp; + + assert( v[ idx ] == id ); + + --(*np); + n = *np; + + for ( i = idx; i < n; i++ ) { + v[ i ] = v[ i + 1 ]; + } + + return 0; +} diff --git a/libs/ldap/libldap/add.c b/libs/ldap/libldap/add.c new file mode 100644 index 00000000000..57de453d159 --- /dev/null +++ b/libs/ldap/libldap/add.c @@ -0,0 +1,262 @@ +/* add.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* An LDAP Add Request/Response looks like this: + * AddRequest ::= [APPLICATION 8] SEQUENCE { + * entry LDAPDN, + * attributes AttributeList } + * + * AttributeList ::= SEQUENCE OF attribute Attribute + * + * Attribute ::= PartialAttribute(WITH COMPONENTS { + * ..., + * vals (SIZE(1..MAX))}) + * + * PartialAttribute ::= SEQUENCE { + * type AttributeDescription, + * vals SET OF value AttributeValue } + * + * AttributeDescription ::= LDAPString + * -- Constrained to <attributedescription> [RFC4512] + * + * AttributeValue ::= OCTET STRING + * + * AddResponse ::= [APPLICATION 9] LDAPResult + * (Source: RFC 4511) + */ + +/* + * 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_add( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs ) +{ + int rc; + int msgid; + + rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); + + if ( rc != LDAP_SUCCESS ) + return -1; + + return msgid; +} + + +BerElement * +ldap_build_add_req( + LDAP *ld, + const char *dn, + LDAPMod **attrs, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp ) +{ + BerElement *ber; + int i, rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID(ld, *msgidp); + rc = ber_printf( ber, "{it{s{", /* '}}}' */ + *msgidp, LDAP_REQ_ADD, dn ); + + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* allow attrs to be NULL ("touch"; should fail...) */ + if ( attrs ) { + /* for each attribute in the entry... */ + for ( i = 0; attrs[i] != NULL; i++ ) { + if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { + int j; + + if ( attrs[i]->mod_bvalues == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) { + if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + } + + rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type, + attrs[i]->mod_bvalues ); + + } else { + if ( attrs[i]->mod_values == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type, + attrs[i]->mod_values ); + } + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + } + } + + if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_add_ext - initiate an ldap extended 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. + * sctrl Server Controls + * cctrl Client Controls + * msgidp Message ID pointer + * + * Example: + * LDAPMod *attrs[] = { + * { 0, "cn", { "babs jensen", "babs", 0 } }, + * { 0, "sn", { "jensen", 0 } }, + * { 0, "objectClass", { "person", 0 } }, + * 0 + * } + * rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); + */ +int +ldap_add_ext( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_add_ext\n" ); + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( dn != NULL ); + assert( msgidp != NULL ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_add_req( ld, dn, attrs, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id ); + + if(*msgidp < 0) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + +int +ldap_add_ext_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **attrs, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int msgid, rc; + LDAPMessage *res; + + rc = ldap_add_ext( ld, dn, attrs, sctrls, cctrls, &msgid ); + + if ( rc != LDAP_SUCCESS ) + return( rc ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, res, 1 ) ); +} + +int +ldap_add_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs ) +{ + return ldap_add_ext_s( ld, dn, attrs, NULL, NULL ); +} diff --git a/libs/ldap/libldap/avl.c b/libs/ldap/libldap/avl.c new file mode 100644 index 00000000000..fd22c7f0de6 --- /dev/null +++ b/libs/ldap/libldap/avl.c @@ -0,0 +1,671 @@ +/* avl.c - routines to implement an avl tree */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1993 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. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by the University of Michigan + * (as part of U-MICH LDAP). Additional significant contributors + * include: + * Howard Y. Chu + * Hallvard B. Furuseth + * Kurt D. Zeilenga + */ + +#include "portable.h" + +#include <limits.h> +#include <stdio.h> +#include <ac/stdlib.h> + +#ifdef CSRIMALLOC +#define ber_memalloc malloc +#define ber_memrealloc realloc +#define ber_memfree free +#else +#include "lber.h" +#endif + +#define AVL_INTERNAL +#include "ldap_avl.h" + +/* Maximum tree depth this host's address space could support */ +#define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT) + +static const int avl_bfs[] = {LH, RH}; + +/* + * ldap_avl_insert -- insert a node containing data data into the avl tree + * with root root. fcmp is a function to call to compare the data portion + * of two nodes. it should take two arguments and return <, >, or == 0, + * depending on whether its first argument is <, >, or == its second + * argument (like strcmp, e.g.). fdup is a function to call when a duplicate + * node is inserted. it should return 0, or -1 and its return value + * will be the return value from ldap_avl_insert in the case of a duplicate node. + * the function will be called with the original node's data as its first + * argument and with the incoming duplicate node's data as its second + * argument. this could be used, for example, to keep a count with each + * node. + * + * NOTE: this routine may malloc memory + */ +int +ldap_avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup ) +{ + Avlnode *t, *p, *s, *q, *r; + int a, cmp, ncmp; + + if ( *root == NULL ) { + if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { + return( -1 ); + } + r->avl_link[0] = r->avl_link[1] = NULL; + r->avl_data = data; + r->avl_bits[0] = r->avl_bits[1] = AVL_CHILD; + r->avl_bf = EH; + *root = r; + + return( 0 ); + } + + t = NULL; + s = p = *root; + + /* find insertion point */ + while (1) { + cmp = fcmp( data, p->avl_data ); + if ( cmp == 0 ) + return (*fdup)( p->avl_data, data ); + + cmp = (cmp > 0); + q = p->avl_link[cmp]; + if (q == NULL) { + /* insert */ + if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) { + return( -1 ); + } + q->avl_link[0] = q->avl_link[1] = NULL; + q->avl_data = data; + q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD; + q->avl_bf = EH; + + p->avl_link[cmp] = q; + break; + } else if ( q->avl_bf ) { + t = p; + s = q; + } + p = q; + } + + /* adjust balance factors */ + cmp = fcmp( data, s->avl_data ) > 0; + r = p = s->avl_link[cmp]; + a = avl_bfs[cmp]; + + while ( p != q ) { + cmp = fcmp( data, p->avl_data ) > 0; + p->avl_bf = avl_bfs[cmp]; + p = p->avl_link[cmp]; + } + + /* checks and balances */ + + if ( s->avl_bf == EH ) { + s->avl_bf = a; + return 0; + } else if ( s->avl_bf == -a ) { + s->avl_bf = EH; + return 0; + } else if ( s->avl_bf == a ) { + cmp = (a > 0); + ncmp = !cmp; + if ( r->avl_bf == a ) { + /* single rotation */ + p = r; + s->avl_link[cmp] = r->avl_link[ncmp]; + r->avl_link[ncmp] = s; + s->avl_bf = 0; + r->avl_bf = 0; + } else if ( r->avl_bf == -a ) { + /* double rotation */ + p = r->avl_link[ncmp]; + r->avl_link[ncmp] = p->avl_link[cmp]; + p->avl_link[cmp] = r; + s->avl_link[cmp] = p->avl_link[ncmp]; + p->avl_link[ncmp] = s; + + if ( p->avl_bf == a ) { + s->avl_bf = -a; + r->avl_bf = 0; + } else if ( p->avl_bf == -a ) { + s->avl_bf = 0; + r->avl_bf = a; + } else { + s->avl_bf = 0; + r->avl_bf = 0; + } + p->avl_bf = 0; + } + /* Update parent */ + if ( t == NULL ) + *root = p; + else if ( s == t->avl_right ) + t->avl_right = p; + else + t->avl_left = p; + } + + return 0; +} + +void* +ldap_avl_delete( Avlnode **root, void* data, AVL_CMP fcmp ) +{ + Avlnode *p, *q, *r, *top; + int side, side_bf, shorter, nside; + + /* parent stack */ + Avlnode *pptr[MAX_TREE_DEPTH]; + unsigned char pdir[MAX_TREE_DEPTH]; + int depth = 0; + + if ( *root == NULL ) + return NULL; + + p = *root; + + while (1) { + side = fcmp( data, p->avl_data ); + if ( !side ) + break; + side = ( side > 0 ); + pdir[depth] = side; + pptr[depth++] = p; + + p = p->avl_link[side]; + if ( p == NULL ) + return p; + } + data = p->avl_data; + + /* If this node has two children, swap so we are deleting a node with + * at most one child. + */ + if ( p->avl_link[0] && p->avl_link[1] ) { + + /* find the immediate predecessor <q> */ + q = p->avl_link[0]; + side = depth; + pdir[depth++] = 0; + while (q->avl_link[1]) { + pdir[depth] = 1; + pptr[depth++] = q; + q = q->avl_link[1]; + } + /* swap links */ + r = p->avl_link[0]; + p->avl_link[0] = q->avl_link[0]; + q->avl_link[0] = r; + + q->avl_link[1] = p->avl_link[1]; + p->avl_link[1] = NULL; + + q->avl_bf = p->avl_bf; + + /* fix stack positions: old parent of p points to q */ + pptr[side] = q; + if ( side ) { + r = pptr[side-1]; + r->avl_link[pdir[side-1]] = q; + } else { + *root = q; + } + /* new parent of p points to p */ + if ( depth-side > 1 ) { + r = pptr[depth-1]; + r->avl_link[1] = p; + } else { + q->avl_link[0] = p; + } + } + + /* now <p> has at most one child, get it */ + q = p->avl_link[0] ? p->avl_link[0] : p->avl_link[1]; + + ber_memfree( p ); + + if ( !depth ) { + *root = q; + return data; + } + + /* set the child into p's parent */ + depth--; + p = pptr[depth]; + side = pdir[depth]; + p->avl_link[side] = q; + + top = NULL; + shorter = 1; + + while ( shorter ) { + p = pptr[depth]; + side = pdir[depth]; + nside = !side; + side_bf = avl_bfs[side]; + + /* case 1: height unchanged */ + if ( p->avl_bf == EH ) { + /* Tree is now heavier on opposite side */ + p->avl_bf = avl_bfs[nside]; + shorter = 0; + + } else if ( p->avl_bf == side_bf ) { + /* case 2: taller subtree shortened, height reduced */ + p->avl_bf = EH; + } else { + /* case 3: shorter subtree shortened */ + if ( depth ) + top = pptr[depth-1]; /* p->parent; */ + else + top = NULL; + /* set <q> to the taller of the two subtrees of <p> */ + q = p->avl_link[nside]; + if ( q->avl_bf == EH ) { + /* case 3a: height unchanged, single rotate */ + p->avl_link[nside] = q->avl_link[side]; + q->avl_link[side] = p; + shorter = 0; + q->avl_bf = side_bf; + p->avl_bf = (- side_bf); + + } else if ( q->avl_bf == p->avl_bf ) { + /* case 3b: height reduced, single rotate */ + p->avl_link[nside] = q->avl_link[side]; + q->avl_link[side] = p; + shorter = 1; + q->avl_bf = EH; + p->avl_bf = EH; + + } else { + /* case 3c: height reduced, balance factors opposite */ + r = q->avl_link[side]; + q->avl_link[side] = r->avl_link[nside]; + r->avl_link[nside] = q; + + p->avl_link[nside] = r->avl_link[side]; + r->avl_link[side] = p; + + if ( r->avl_bf == side_bf ) { + q->avl_bf = (- side_bf); + p->avl_bf = EH; + } else if ( r->avl_bf == (- side_bf)) { + q->avl_bf = EH; + p->avl_bf = side_bf; + } else { + q->avl_bf = EH; + p->avl_bf = EH; + } + r->avl_bf = EH; + q = r; + } + /* a rotation has caused <q> (or <r> in case 3c) to become + * the root. let <p>'s former parent know this. + */ + if ( top == NULL ) { + *root = q; + } else if (top->avl_link[0] == p) { + top->avl_link[0] = q; + } else { + top->avl_link[1] = q; + } + /* end case 3 */ + p = q; + } + if ( !depth ) + break; + depth--; + } /* end while(shorter) */ + + return data; +} + +static int +avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) +{ + if ( root == 0 ) + return( AVL_NOMORE ); + + if ( root->avl_left != 0 ) + if ( avl_inapply( root->avl_left, fn, arg, stopflag ) + == stopflag ) + return( stopflag ); + + if ( (*fn)( root->avl_data, arg ) == stopflag ) + return( stopflag ); + + if ( root->avl_right == 0 ) + return( AVL_NOMORE ); + else + return( avl_inapply( root->avl_right, fn, arg, stopflag ) ); +} + +static int +avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) +{ + if ( root == 0 ) + return( AVL_NOMORE ); + + if ( root->avl_left != 0 ) + if ( avl_postapply( root->avl_left, fn, arg, stopflag ) + == stopflag ) + return( stopflag ); + + if ( root->avl_right != 0 ) + if ( avl_postapply( root->avl_right, fn, arg, stopflag ) + == stopflag ) + return( stopflag ); + + return( (*fn)( root->avl_data, arg ) ); +} + +static int +avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag ) +{ + if ( root == 0 ) + return( AVL_NOMORE ); + + if ( (*fn)( root->avl_data, arg ) == stopflag ) + return( stopflag ); + + if ( root->avl_left != 0 ) + if ( avl_preapply( root->avl_left, fn, arg, stopflag ) + == stopflag ) + return( stopflag ); + + if ( root->avl_right == 0 ) + return( AVL_NOMORE ); + else + return( avl_preapply( root->avl_right, fn, arg, stopflag ) ); +} + +/* + * ldap_avl_apply -- avl tree root is traversed, function fn is called with + * arguments arg and the data portion of each node. if fn returns stopflag, + * the traversal is cut short, otherwise it continues. Do not use -6 as + * a stopflag, as this is what is used to indicate the traversal ran out + * of nodes. + */ + +int +ldap_avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type ) +{ + switch ( type ) { + case AVL_INORDER: + return( avl_inapply( root, fn, arg, stopflag ) ); + case AVL_PREORDER: + return( avl_preapply( root, fn, arg, stopflag ) ); + case AVL_POSTORDER: + return( avl_postapply( root, fn, arg, stopflag ) ); + default: + fprintf( stderr, "Invalid traversal type %d\n", type ); + return( -1 ); + } + + /* NOTREACHED */ +} + +/* + * ldap_avl_prefixapply - traverse avl tree root, applying function fprefix + * to any nodes that match. fcmp is called with data as its first arg + * and the current node's data as its second arg. it should return + * 0 if they match, < 0 if data is less, and > 0 if data is greater. + * the idea is to efficiently find all nodes that are prefixes of + * some key... Like ldap_avl_apply, this routine also takes a stopflag + * and will return prematurely if fmatch returns this value. Otherwise, + * AVL_NOMORE is returned. + */ + +int +ldap_avl_prefixapply( + Avlnode *root, + void* data, + AVL_CMP fmatch, + void* marg, + AVL_CMP fcmp, + void* carg, + int stopflag +) +{ + int cmp; + + if ( root == 0 ) + return( AVL_NOMORE ); + + cmp = (*fcmp)( data, root->avl_data /* , carg */); + if ( cmp == 0 ) { + if ( (*fmatch)( root->avl_data, marg ) == stopflag ) + return( stopflag ); + + if ( root->avl_left != 0 ) + if ( ldap_avl_prefixapply( root->avl_left, data, fmatch, + marg, fcmp, carg, stopflag ) == stopflag ) + return( stopflag ); + + if ( root->avl_right != 0 ) + return( ldap_avl_prefixapply( root->avl_right, data, fmatch, + marg, fcmp, carg, stopflag ) ); + else + return( AVL_NOMORE ); + + } else if ( cmp < 0 ) { + if ( root->avl_left != 0 ) + return( ldap_avl_prefixapply( root->avl_left, data, fmatch, + marg, fcmp, carg, stopflag ) ); + } else { + if ( root->avl_right != 0 ) + return( ldap_avl_prefixapply( root->avl_right, data, fmatch, + marg, fcmp, carg, stopflag ) ); + } + + return( AVL_NOMORE ); +} + +/* + * ldap_avl_free -- traverse avltree root, freeing the memory it is using. + * the dfree() is called to free the data portion of each node. The + * number of items actually freed is returned. + */ + +int +ldap_avl_free( Avlnode *root, AVL_FREE dfree ) +{ + int nleft, nright; + + if ( root == 0 ) + return( 0 ); + + nleft = nright = 0; + if ( root->avl_left != 0 ) + nleft = ldap_avl_free( root->avl_left, dfree ); + + if ( root->avl_right != 0 ) + nright = ldap_avl_free( root->avl_right, dfree ); + + if ( dfree ) + (*dfree)( root->avl_data ); + ber_memfree( root ); + + return( nleft + nright + 1 ); +} + +/* + * ldap_avl_find -- search avltree root for a node with data data. the function + * cmp is used to compare things. it is called with data as its first arg + * and the current node data as its second. it should return 0 if they match, + * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2. + */ + +Avlnode * +ldap_avl_find2( Avlnode *root, const void *data, AVL_CMP fcmp ) +{ + int cmp; + + while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { + cmp = cmp > 0; + root = root->avl_link[cmp]; + } + return root; +} + +void* +ldap_avl_find( Avlnode *root, const void* data, AVL_CMP fcmp ) +{ + int cmp; + + while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { + cmp = cmp > 0; + root = root->avl_link[cmp]; + } + + return( root ? root->avl_data : 0 ); +} + +/* + * ldap_avl_find_lin -- search avltree root linearly for a node with data data. + * the function cmp is used to compare things. it is called with data as its + * first arg and the current node data as its second. it should return 0 if + * they match, non-zero otherwise. + */ + +void* +ldap_avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp ) +{ + void* res; + + if ( root == 0 ) + return( NULL ); + + if ( (*fcmp)( data, root->avl_data ) == 0 ) + return( root->avl_data ); + + if ( root->avl_left != 0 ) + if ( (res = ldap_avl_find_lin( root->avl_left, data, fcmp )) + != NULL ) + return( res ); + + if ( root->avl_right == 0 ) + return( NULL ); + else + return( ldap_avl_find_lin( root->avl_right, data, fcmp ) ); +} + +/* NON-REENTRANT INTERFACE */ + +static void* *avl_list; +static int avl_maxlist; +static int ldap_avl_nextlist; + +#define AVL_GRABSIZE 100 + +/* ARGSUSED */ +static int +avl_buildlist( void* data, void* arg ) +{ + static int slots; + + if ( avl_list == (void* *) 0 ) { + avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*)); + slots = AVL_GRABSIZE; + avl_maxlist = 0; + } else if ( avl_maxlist == slots ) { + slots += AVL_GRABSIZE; + avl_list = (void* *) ber_memrealloc( (char *) avl_list, + (unsigned) slots * sizeof(void*)); + } + + avl_list[ avl_maxlist++ ] = data; + + return( 0 ); +} + +/* + * ldap_avl_getfirst() and ldap_avl_getnext() are provided as alternate tree + * traversal methods, to be used when a single function cannot be + * provided to be called with every node in the tree. ldap_avl_getfirst() + * traverses the tree and builds a linear list of all the nodes, + * returning the first node. ldap_avl_getnext() returns the next thing + * on the list built by ldap_avl_getfirst(). This means that ldap_avl_getfirst() + * can take a while, and that the tree should not be messed with while + * being traversed in this way, and that multiple traversals (even of + * different trees) cannot be active at once. + */ + +void* +ldap_avl_getfirst( Avlnode *root ) +{ + if ( avl_list ) { + ber_memfree( (char *) avl_list); + avl_list = (void* *) 0; + } + avl_maxlist = 0; + ldap_avl_nextlist = 0; + + if ( root == 0 ) + return( 0 ); + + (void) ldap_avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER ); + + return( avl_list[ ldap_avl_nextlist++ ] ); +} + +void* +ldap_avl_getnext( void ) +{ + if ( avl_list == 0 ) + return( 0 ); + + if ( ldap_avl_nextlist == avl_maxlist ) { + ber_memfree( (void*) avl_list); + avl_list = (void* *) 0; + return( 0 ); + } + + return( avl_list[ ldap_avl_nextlist++ ] ); +} + +/* end non-reentrant code */ + + +int +ldap_avl_dup_error( void* left, void* right ) +{ + return( -1 ); +} + +int +ldap_avl_dup_ok( void* left, void* right ) +{ + return( 0 ); +} diff --git a/libs/ldap/libldap/bind.c b/libs/ldap/libldap/bind.c new file mode 100644 index 00000000000..ea6fe5ca6bb --- /dev/null +++ b/libs/ldap/libldap/bind.c @@ -0,0 +1,117 @@ +/* bind.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" +#include "ldap_log.h" + +/* + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING -- passwd + * krbv42ldap [1] OCTET STRING -- OBSOLETE + * krbv42dsa [2] OCTET STRING -- OBSOLETE + * sasl [3] SaslCredentials -- LDAPv3 + * } + * } + * + * BindResponse ::= SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 + * } + * + * (Source: RFC 2251) + */ + +/* + * ldap_bind - bind to the ldap server (and X.500). 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. 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_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmethod ) +{ + Debug0( LDAP_DEBUG_TRACE, "ldap_bind\n" ); + + switch ( authmethod ) { + case LDAP_AUTH_SIMPLE: + return( ldap_simple_bind( ld, dn, passwd ) ); + + case LDAP_AUTH_SASL: + /* user must use ldap_sasl_bind */ + /* FALL-THRU */ + + default: + ld->ld_errno = LDAP_AUTH_UNKNOWN; + return( -1 ); + } +} + +/* + * ldap_bind_s - bind to the ldap server (and X.500). 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). + * + * 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_bind_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *passwd, + int authmethod ) +{ + Debug0( LDAP_DEBUG_TRACE, "ldap_bind_s\n" ); + + switch ( authmethod ) { + case LDAP_AUTH_SIMPLE: + return( ldap_simple_bind_s( ld, dn, passwd ) ); + + case LDAP_AUTH_SASL: + /* user must use ldap_sasl_bind */ + /* FALL-THRU */ + + default: + return( ld->ld_errno = LDAP_AUTH_UNKNOWN ); + } +} diff --git a/libs/ldap/libldap/charray.c b/libs/ldap/libldap/charray.c new file mode 100644 index 00000000000..cd83290c86d --- /dev/null +++ b/libs/ldap/libldap/charray.c @@ -0,0 +1,275 @@ +/* charray.c - routines for dealing with char * arrays */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/string.h> +#include <ac/socket.h> + +#include "ldap-int.h" + +int +ldap_charray_add( + char ***a, + const char *s +) +{ + int n; + + if ( *a == NULL ) { + *a = (char **) LDAP_MALLOC( 2 * sizeof(char *) ); + n = 0; + + if( *a == NULL ) { + return -1; + } + + } else { + char **new; + + for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { + ; /* NULL */ + } + + new = (char **) LDAP_REALLOC( (char *) *a, + (n + 2) * sizeof(char *) ); + + if( new == NULL ) { + /* caller is required to call ldap_charray_free(*a) */ + return -1; + } + + *a = new; + } + + (*a)[n] = LDAP_STRDUP(s); + + if( (*a)[n] == NULL ) { + return 1; + } + + (*a)[++n] = NULL; + + return 0; +} + +int +ldap_charray_merge( + char ***a, + char **s +) +{ + int i, n, nn; + char **aa; + + for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { + ; /* NULL */ + } + for ( nn = 0; s[nn] != NULL; nn++ ) { + ; /* NULL */ + } + + aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) ); + + if( aa == NULL ) { + return -1; + } + + *a = aa; + + for ( i = 0; i < nn; i++ ) { + (*a)[n + i] = LDAP_STRDUP(s[i]); + + if( (*a)[n + i] == NULL ) { + for( --i ; i >= 0 ; i-- ) { + LDAP_FREE( (*a)[n + i] ); + (*a)[n + i] = NULL; + } + return -1; + } + } + + (*a)[n + nn] = NULL; + return 0; +} + +void +ldap_charray_free( char **a ) +{ + char **p; + + if ( a == NULL ) { + return; + } + + for ( p = a; *p != NULL; p++ ) { + if ( *p != NULL ) { + LDAP_FREE( *p ); + } + } + + LDAP_FREE( (char *) a ); +} + +int +ldap_charray_inlist( + char **a, + const 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; +} + +char ** +ldap_charray_dup( char **a ) +{ + int i; + char **new; + + for ( i = 0; a[i] != NULL; i++ ) + ; /* NULL */ + + new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) ); + + if( new == NULL ) { + return NULL; + } + + for ( i = 0; a[i] != NULL; i++ ) { + new[i] = LDAP_STRDUP( a[i] ); + + if( new[i] == NULL ) { + for( --i ; i >= 0 ; i-- ) { + LDAP_FREE( new[i] ); + } + LDAP_FREE( new ); + return NULL; + } + } + new[i] = NULL; + + return( new ); +} + +char ** +ldap_str2charray( const char *str_in, const char *brkstr ) +{ + char **res; + char *str, *s; + char *lasts; + int i; + + /* protect the input string from strtok */ + str = LDAP_STRDUP( str_in ); + if( str == NULL ) { + return NULL; + } + + i = 1; + for ( s = str; ; LDAP_UTF8_INCR(s) ) { + s = ldap_utf8_strpbrk( s, brkstr ); + if ( !s ) break; + i++; + } + + res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) ); + + if( res == NULL ) { + LDAP_FREE( str ); + return NULL; + } + + i = 0; + + for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); + s != NULL; + s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) + { + res[i] = LDAP_STRDUP( s ); + + if(res[i] == NULL) { + for( --i ; i >= 0 ; i-- ) { + LDAP_FREE( res[i] ); + } + LDAP_FREE( res ); + LDAP_FREE( str ); + return NULL; + } + + i++; + } + + res[i] = NULL; + + LDAP_FREE( str ); + return( res ); +} + +char * ldap_charray2str( char **a, const char *sep ) +{ + char *s, **v, *p; + int len; + int slen; + + if( sep == NULL ) sep = " "; + + slen = strlen( sep ); + len = 0; + + for ( v = a; *v != NULL; v++ ) { + len += strlen( *v ) + slen; + } + + if ( len == 0 ) { + return NULL; + } + + /* trim extra sep len */ + len -= slen; + + s = LDAP_MALLOC ( len + 1 ); + + if ( s == NULL ) { + return NULL; + } + + p = s; + for ( v = a; *v != NULL; v++ ) { + if ( v != a ) { + strncpy( p, sep, slen ); + p += slen; + } + + len = strlen( *v ); + memcpy( p, *v, len ); + p += len; + } + + *p = '\0'; + return s; +} diff --git a/libs/ldap/libldap/compare.c b/libs/ldap/libldap/compare.c new file mode 100644 index 00000000000..86285c685ac --- /dev/null +++ b/libs/ldap/libldap/compare.c @@ -0,0 +1,197 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" +#include "ldap_log.h" + +/* The compare request looks like this: + * CompareRequest ::= SEQUENCE { + * entry DistinguishedName, + * ava SEQUENCE { + * type AttributeType, + * value AttributeValue + * } + * } + */ + +BerElement * +ldap_build_compare_req( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + struct berval *bvalue, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID(ld, *msgidp); + rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */ + *msgidp, + LDAP_REQ_COMPARE, dn, attr, bvalue ); + if ( rc == -1 ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_compare_ext - perform an ldap extended 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: + * struct berval bvalue = { "secret", sizeof("secret")-1 }; + * rc = ldap_compare( ld, "c=us@cn=bob", + * "userPassword", &bvalue, + * sctrl, cctrl, &msgid ) + */ +int +ldap_compare_ext( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + struct berval *bvalue, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + int rc; + BerElement *ber; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_compare\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( dn != NULL ); + assert( attr != NULL ); + assert( msgidp != NULL ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_compare_req( + ld, dn, attr, bvalue, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber, id ); + return ( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); +} + +/* + * ldap_compare_ext - perform an ldap extended 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: + * msgid = ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) + */ +int +ldap_compare( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + LDAP_CONST char *value ) +{ + int msgid; + struct berval bvalue; + + assert( value != NULL ); + + bvalue.bv_val = (char *) value; + bvalue.bv_len = (value == NULL) ? 0 : strlen( value ); + + return ldap_compare_ext( ld, dn, attr, &bvalue, NULL, NULL, &msgid ) == LDAP_SUCCESS + ? msgid : -1; +} + +int +ldap_compare_ext_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + struct berval *bvalue, + LDAPControl **sctrl, + LDAPControl **cctrl ) +{ + int rc; + int msgid; + LDAPMessage *res; + + rc = ldap_compare_ext( ld, dn, attr, bvalue, sctrl, cctrl, &msgid ); + + if ( rc != LDAP_SUCCESS ) + return( rc ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, res, 1 ) ); +} + +int +ldap_compare_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *attr, + LDAP_CONST char *value ) +{ + struct berval bvalue; + + assert( value != NULL ); + + bvalue.bv_val = (char *) value; + bvalue.bv_len = (value == NULL) ? 0 : strlen( value ); + + return ldap_compare_ext_s( ld, dn, attr, &bvalue, NULL, NULL ); +} diff --git a/libs/ldap/libldap/controls.c b/libs/ldap/libldap/controls.c new file mode 100644 index 00000000000..1485346416d --- /dev/null +++ b/libs/ldap/libldap/controls.c @@ -0,0 +1,552 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +#include "portable.h" + +#include <ac/stdlib.h> + +#include <ac/time.h> +#include <ac/string.h> + +#include "ldap-int.h" + +/* LDAPv3 Controls (RFC 4511) + * + * Controls ::= SEQUENCE OF control Control + * + * Control ::= SEQUENCE { + * controlType LDAPOID, + * criticality BOOLEAN DEFAULT FALSE, + * controlValue OCTET STRING OPTIONAL + * } + */ + +int +ldap_pvt_put_control( + const LDAPControl *c, + BerElement *ber ) +{ + if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) { + return LDAP_ENCODING_ERROR; + } + + if ( c->ldctl_iscritical /* only if true */ + && ( ber_printf( ber, "b", + (ber_int_t) c->ldctl_iscritical ) == -1 ) ) + { + return LDAP_ENCODING_ERROR; + } + + if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */ + && ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) ) + { + return LDAP_ENCODING_ERROR; + } + + if ( ber_printf( ber, /*{*/"N}" ) == -1 ) { + return LDAP_ENCODING_ERROR; + } + + return LDAP_SUCCESS; +} + + +/* + * ldap_int_put_controls + */ + +int +ldap_int_put_controls( + LDAP *ld, + LDAPControl *const *ctrls, + BerElement *ber ) +{ + LDAPControl *const *c; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( ber != NULL ); + + if( ctrls == NULL ) { + /* use default server controls */ + ctrls = ld->ld_sctrls; + } + + if( ctrls == NULL || *ctrls == NULL ) { + return LDAP_SUCCESS; + } + + if ( ld->ld_version < LDAP_VERSION3 ) { + /* LDAPv2 doesn't support controls, + * error if any control is critical + */ + for( c = ctrls ; *c != NULL; c++ ) { + if( (*c)->ldctl_iscritical ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + } + + return LDAP_SUCCESS; + } + + /* Controls are encoded as a sequence of sequences */ + if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + for( c = ctrls ; *c != NULL; c++ ) { + ld->ld_errno = ldap_pvt_put_control( *c, ber ); + if ( ld->ld_errno != LDAP_SUCCESS ) { + return ld->ld_errno; + } + } + + + if( ber_printf( ber, /*{*/ "}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + return ld->ld_errno; + } + + return LDAP_SUCCESS; +} + +int ldap_pvt_get_controls( + BerElement *ber, + LDAPControl ***ctrls ) +{ + int nctrls; + ber_tag_t tag; + ber_len_t len; + char *opaque; + + assert( ber != NULL ); + + if( ctrls == NULL ) { + return LDAP_SUCCESS; + } + *ctrls = NULL; + + len = ber_pvt_ber_remaining( ber ); + + if( len == 0) { + /* no controls */ + return LDAP_SUCCESS; + } + + if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { + if( tag == LBER_ERROR ) { + /* decoding error */ + return LDAP_DECODING_ERROR; + } + + /* ignore unexpected input */ + return LDAP_SUCCESS; + } + + /* set through each element */ + nctrls = 0; + *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) ); + + if( *ctrls == NULL ) { + return LDAP_NO_MEMORY; + } + + *ctrls[nctrls] = NULL; + + for( tag = ber_first_element( ber, &len, &opaque ); + tag != LBER_ERROR; + tag = ber_next_element( ber, &len, opaque ) ) + { + LDAPControl *tctrl; + LDAPControl **tctrls; + + tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) ); + + /* allocate pointer space for current controls (nctrls) + * + this control + extra NULL + */ + tctrls = (tctrl == NULL) ? NULL : + LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *)); + + if( tctrls == NULL ) { + /* one of the above allocation failed */ + + if( tctrl != NULL ) { + LDAP_FREE( tctrl ); + } + + ldap_controls_free(*ctrls); + *ctrls = NULL; + + return LDAP_NO_MEMORY; + } + + + tctrls[nctrls++] = tctrl; + tctrls[nctrls] = NULL; + + tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid ); + + if( tag == LBER_ERROR ) { + *ctrls = NULL; + ldap_controls_free( tctrls ); + return LDAP_DECODING_ERROR; + } + + tag = ber_peek_tag( ber, &len ); + + if( tag == LBER_BOOLEAN ) { + ber_int_t crit; + tag = ber_scanf( ber, "b", &crit ); + tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0; + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LBER_OCTETSTRING ) { + tag = ber_scanf( ber, "o", &tctrl->ldctl_value ); + } else { + BER_BVZERO( &tctrl->ldctl_value ); + } + + *ctrls = tctrls; + } + + return LDAP_SUCCESS; +} + +/* + * Free a LDAPControl + */ +void +ldap_control_free( LDAPControl *c ) +{ + LDAP_MEMORY_DEBUG_ASSERT( c != NULL ); + + if ( c != NULL ) { + if( c->ldctl_oid != NULL) { + LDAP_FREE( c->ldctl_oid ); + } + + if( c->ldctl_value.bv_val != NULL ) { + LDAP_FREE( c->ldctl_value.bv_val ); + } + + LDAP_FREE( c ); + } +} + +/* + * Free an array of LDAPControl's + */ +void +ldap_controls_free( LDAPControl **controls ) +{ + LDAP_MEMORY_DEBUG_ASSERT( controls != NULL ); + + if ( controls != NULL ) { + int i; + + for( i=0; controls[i] != NULL; i++) { + ldap_control_free( controls[i] ); + } + + LDAP_FREE( controls ); + } +} + +/* + * Duplicate an array of LDAPControl + */ +LDAPControl ** +ldap_controls_dup( LDAPControl *const *controls ) +{ + LDAPControl **new; + int i; + + if ( controls == NULL ) { + return NULL; + } + + /* count the controls */ + for(i=0; controls[i] != NULL; i++) /* empty */ ; + + if( i < 1 ) { + /* no controls to duplicate */ + return NULL; + } + + new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) ); + + if( new == NULL ) { + /* memory allocation failure */ + return NULL; + } + + /* duplicate the controls */ + for(i=0; controls[i] != NULL; i++) { + new[i] = ldap_control_dup( controls[i] ); + + if( new[i] == NULL ) { + ldap_controls_free( new ); + return NULL; + } + } + + new[i] = NULL; + + return new; +} + +/* + * Duplicate a LDAPControl + */ +LDAPControl * +ldap_control_dup( const LDAPControl *c ) +{ + LDAPControl *new; + + if ( c == NULL || c->ldctl_oid == NULL ) { + return NULL; + } + + new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); + + if( new == NULL ) { + return NULL; + } + + new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid ); + + if(new->ldctl_oid == NULL) { + LDAP_FREE( new ); + return NULL; + } + + if( c->ldctl_value.bv_val != NULL ) { + new->ldctl_value.bv_val = + (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 ); + + if(new->ldctl_value.bv_val == NULL) { + if(new->ldctl_oid != NULL) { + LDAP_FREE( new->ldctl_oid ); + } + LDAP_FREE( new ); + return NULL; + } + + new->ldctl_value.bv_len = c->ldctl_value.bv_len; + + AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, + c->ldctl_value.bv_len ); + + new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0'; + + } else { + new->ldctl_value.bv_len = 0; + new->ldctl_value.bv_val = NULL; + } + + new->ldctl_iscritical = c->ldctl_iscritical; + return new; +} + +/* + * Find a LDAPControl - deprecated + */ +LDAPControl * +ldap_find_control( + LDAP_CONST char *oid, + LDAPControl **ctrls ) +{ + if( ctrls == NULL || *ctrls == NULL ) { + return NULL; + } + + for( ; *ctrls != NULL; ctrls++ ) { + if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { + return *ctrls; + } + } + + return NULL; +} + +/* + * Find a LDAPControl + */ +LDAPControl * +ldap_control_find( + LDAP_CONST char *oid, + LDAPControl **ctrls, + LDAPControl ***nextctrlp ) +{ + if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) { + return NULL; + } + + for( ; *ctrls != NULL; ctrls++ ) { + if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) { + if ( nextctrlp != NULL ) { + *nextctrlp = ctrls + 1; + } + + return *ctrls; + } + } + + if ( nextctrlp != NULL ) { + *nextctrlp = NULL; + } + + return NULL; +} + +/* + * Create a LDAPControl, optionally from ber - deprecated + */ +int +ldap_create_control( + LDAP_CONST char *requestOID, + BerElement *ber, + int iscritical, + LDAPControl **ctrlp ) +{ + LDAPControl *ctrl; + + assert( requestOID != NULL ); + assert( ctrlp != NULL ); + + ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) ); + if ( ctrl == NULL ) { + return LDAP_NO_MEMORY; + } + + BER_BVZERO(&ctrl->ldctl_value); + if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) { + LDAP_FREE( ctrl ); + return LDAP_NO_MEMORY; + } + + ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); + ctrl->ldctl_iscritical = iscritical; + + if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) { + ldap_control_free( ctrl ); + return LDAP_NO_MEMORY; + } + + *ctrlp = ctrl; + return LDAP_SUCCESS; +} + +/* + * Create a LDAPControl, optionally from value + */ +int +ldap_control_create( + LDAP_CONST char *requestOID, + int iscritical, + struct berval *value, + int dupval, + LDAPControl **ctrlp ) +{ + LDAPControl *ctrl; + + assert( requestOID != NULL ); + assert( ctrlp != NULL ); + + ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 ); + if ( ctrl == NULL ) { + return LDAP_NO_MEMORY; + } + + ctrl->ldctl_iscritical = iscritical; + if ( requestOID != NULL ) { + ctrl->ldctl_oid = LDAP_STRDUP( requestOID ); + if ( ctrl->ldctl_oid == NULL ) { + ldap_control_free( ctrl ); + return LDAP_NO_MEMORY; + } + } + + if ( value && !BER_BVISNULL( value ) ) { + if ( dupval ) { + ber_dupbv( &ctrl->ldctl_value, value ); + if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { + ldap_control_free( ctrl ); + return LDAP_NO_MEMORY; + } + + } else { + ctrl->ldctl_value = *value; + } + } + + *ctrlp = ctrl; + + return LDAP_SUCCESS; +} + +/* + * check for critical client controls and bitch if present + * if we ever support critical controls, we'll have to + * find a means for maintaining per API call control + * information. + */ +int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls ) +{ + LDAPControl *const *c; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + if( ctrls == NULL ) { + /* use default client controls */ + ctrls = ld->ld_cctrls; + } + + if( ctrls == NULL || *ctrls == NULL ) { + return LDAP_SUCCESS; + } + + for( c = ctrls ; *c != NULL; c++ ) { + if( (*c)->ldctl_iscritical ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + } + + return LDAP_SUCCESS; +} diff --git a/libs/ldap/libldap/cyrus.c b/libs/ldap/libldap/cyrus.c new file mode 100644 index 00000000000..d7111ace6f9 --- /dev/null +++ b/libs/ldap/libldap/cyrus.c @@ -0,0 +1,1335 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <ac/errno.h> +#include "ldap-int.h" + +#ifdef HAVE_CYRUS_SASL + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/ctype.h> +#include <ac/unistd.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef INT_MAX +#define INT_MAX 2147483647 /* 32 bit signed max */ +#endif + +#if !defined(HOST_NAME_MAX) && defined(_POSIX_HOST_NAME_MAX) +#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +#endif + +#ifdef HAVE_SASL_SASL_H +#include <sasl/sasl.h> +#else +#include <sasl.h> +#endif + +#if SASL_VERSION_MAJOR >= 2 +#define SASL_CONST const +#else +#define SASL_CONST +#endif + +/* +* Various Cyrus SASL related stuff. +*/ + +static const sasl_callback_t client_callbacks[] = { +#ifdef SASL_CB_GETREALM + { SASL_CB_GETREALM, NULL, NULL }, +#endif + { SASL_CB_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 } +}; + +/* + * ldap_int_initialize is responsible for calling this only once. + */ +int ldap_int_sasl_init( void ) +{ +#ifdef HAVE_SASL_VERSION + /* stringify the version number, sasl.h doesn't do it for us */ +#define VSTR0(maj, min, pat) #maj "." #min "." #pat +#define VSTR(maj, min, pat) VSTR0(maj, min, pat) +#define SASL_VERSION_STRING VSTR(SASL_VERSION_MAJOR, SASL_VERSION_MINOR, \ + SASL_VERSION_STEP) + { int rc; + sasl_version( NULL, &rc ); + if ( ((rc >> 16) != ((SASL_VERSION_MAJOR << 8)|SASL_VERSION_MINOR)) || + (rc & 0xffff) < SASL_VERSION_STEP) { + char version[sizeof("xxx.xxx.xxxxx")]; + sprintf( version, "%u.%d.%d", (unsigned)rc >> 24, (rc >> 16) & 0xff, + rc & 0xffff ); + + Debug1( LDAP_DEBUG_ANY, + "ldap_int_sasl_init: SASL library version mismatch:" + " expected " SASL_VERSION_STRING "," + " got %s\n", version ); + return -1; + } + } +#endif + +/* SASL 2 takes care of its own memory completely internally */ +#if SASL_VERSION_MAJOR < 2 && !defined(CSRIMALLOC) + sasl_set_alloc( + ber_memalloc, + ber_memcalloc, + ber_memrealloc, + ber_memfree ); +#endif /* CSRIMALLOC */ + +#ifdef LDAP_R_COMPILE + sasl_set_mutex( + ldap_pvt_sasl_mutex_new, + ldap_pvt_sasl_mutex_lock, + ldap_pvt_sasl_mutex_unlock, + ldap_pvt_sasl_mutex_dispose ); +#endif + + if ( sasl_client_init( NULL ) == SASL_OK ) { + return 0; + } + +#if SASL_VERSION_MAJOR < 2 + /* A no-op to make sure we link with Cyrus 1.5 */ + sasl_client_auth( NULL, NULL, NULL, 0, NULL, NULL ); +#endif + return -1; +} + +static void +sb_sasl_cyrus_init( + struct sb_sasl_generic_data *p, + ber_len_t *min_send, + ber_len_t *max_send, + ber_len_t *max_recv) +{ + sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; + ber_len_t maxbuf; + + sasl_getprop( sasl_context, SASL_MAXOUTBUF, + (SASL_CONST void **)(char *) &maxbuf ); + + *min_send = SASL_MIN_BUFF_SIZE; + *max_send = maxbuf; + *max_recv = SASL_MAX_BUFF_SIZE; +} + +static ber_int_t +sb_sasl_cyrus_encode( + struct sb_sasl_generic_data *p, + unsigned char *buf, + ber_len_t len, + Sockbuf_Buf *dst) +{ + sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; + ber_int_t ret; + unsigned tmpsize = dst->buf_size; + + ret = sasl_encode( sasl_context, (char *)buf, len, + (SASL_CONST char **)&dst->buf_base, + &tmpsize ); + + dst->buf_size = tmpsize; + dst->buf_end = dst->buf_size; + + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, + "sb_sasl_cyrus_encode: failed to encode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + return -1; + } + + return 0; +} + +static ber_int_t +sb_sasl_cyrus_decode( + struct sb_sasl_generic_data *p, + const Sockbuf_Buf *src, + Sockbuf_Buf *dst) +{ + sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private; + ber_int_t ret; + unsigned tmpsize = dst->buf_size; + + ret = sasl_decode( sasl_context, + src->buf_base, src->buf_end, + (SASL_CONST char **)&dst->buf_base, + (unsigned *)&tmpsize ); + + + dst->buf_size = tmpsize; + dst->buf_end = dst->buf_size; + + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug, + "sb_sasl_cyrus_decode: failed to decode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + return -1; + } + + return 0; +} + +static void +sb_sasl_cyrus_reset_buf( + struct sb_sasl_generic_data *p, + Sockbuf_Buf *buf) +{ +#if SASL_VERSION_MAJOR >= 2 + ber_pvt_sb_buf_init( buf ); +#else + ber_pvt_sb_buf_destroy( buf ); +#endif +} + +static void +sb_sasl_cyrus_fini( + struct sb_sasl_generic_data *p) +{ +#if SASL_VERSION_MAJOR >= 2 + /* + * SASLv2 encode/decode buffers are managed by + * libsasl2. Ensure they are not freed by liblber. + */ + p->buf_in.buf_base = NULL; + p->buf_out.buf_base = NULL; +#endif +} + +static const struct sb_sasl_generic_ops sb_sasl_cyrus_ops = { + sb_sasl_cyrus_init, + sb_sasl_cyrus_encode, + sb_sasl_cyrus_decode, + sb_sasl_cyrus_reset_buf, + sb_sasl_cyrus_fini + }; + +int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg ) +{ + struct sb_sasl_generic_install install_arg; + + install_arg.ops = &sb_sasl_cyrus_ops; + install_arg.ops_private = ctx_arg; + + return ldap_pvt_sasl_generic_install( sb, &install_arg ); +} + +void ldap_pvt_sasl_remove( Sockbuf *sb ) +{ + ldap_pvt_sasl_generic_remove( sb ); +} + +static int +sasl_err2ldap( int saslerr ) +{ + int rc; + + /* map SASL errors to LDAP API errors returned by: + * sasl_client_new() + * SASL_OK, SASL_NOMECH, SASL_NOMEM + * sasl_client_start() + * SASL_OK, SASL_NOMECH, SASL_NOMEM, SASL_INTERACT + * sasl_client_step() + * SASL_OK, SASL_INTERACT, SASL_BADPROT, SASL_BADSERV + */ + + switch (saslerr) { + case SASL_CONTINUE: + rc = LDAP_MORE_RESULTS_TO_RETURN; + break; + case SASL_INTERACT: + rc = LDAP_LOCAL_ERROR; + break; + case SASL_OK: + rc = LDAP_SUCCESS; + break; + case SASL_NOMEM: + rc = LDAP_NO_MEMORY; + break; + case SASL_NOMECH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_BADPROT: + rc = LDAP_DECODING_ERROR; + break; + case SASL_BADSERV: + rc = LDAP_AUTH_UNKNOWN; + break; + + /* other codes */ + case SASL_BADAUTH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_NOAUTHZ: + rc = LDAP_PARAM_ERROR; + break; + case SASL_FAIL: + rc = LDAP_LOCAL_ERROR; + break; + case SASL_TOOWEAK: + case SASL_ENCRYPT: + rc = LDAP_AUTH_UNKNOWN; + break; + default: + rc = LDAP_LOCAL_ERROR; + break; + } + + assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); + return rc; +} + +int +ldap_int_sasl_open( + LDAP *ld, + LDAPConn *lc, + const char * host ) +{ + int rc; + sasl_conn_t *ctx; + + assert( lc->lconn_sasl_authctx == NULL ); + + if ( host == NULL ) { + ld->ld_errno = LDAP_LOCAL_ERROR; + return ld->ld_errno; + } + +#if SASL_VERSION_MAJOR >= 2 + rc = sasl_client_new( "ldap", host, NULL, NULL, + client_callbacks, 0, &ctx ); +#else + rc = sasl_client_new( "ldap", host, client_callbacks, + SASL_SECURITY_LAYER, &ctx ); +#endif + + if ( rc != SASL_OK ) { + ld->ld_errno = sasl_err2ldap( rc ); + return ld->ld_errno; + } + + Debug1( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: host=%s\n", + host ); + + lc->lconn_sasl_authctx = ctx; + + return LDAP_SUCCESS; +} + +int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) +{ + sasl_conn_t *ctx = lc->lconn_sasl_authctx; + + if( ctx != NULL ) { + sasl_dispose( &ctx ); + if ( lc->lconn_sasl_sockctx && + lc->lconn_sasl_authctx != lc->lconn_sasl_sockctx ) { + ctx = lc->lconn_sasl_sockctx; + sasl_dispose( &ctx ); + } + lc->lconn_sasl_sockctx = NULL; + lc->lconn_sasl_authctx = NULL; + } + if( lc->lconn_sasl_cbind ) { + ldap_memfree( lc->lconn_sasl_cbind ); + lc->lconn_sasl_cbind = NULL; + } + + return LDAP_SUCCESS; +} + +int ldap_pvt_sasl_cbinding_parse( const char *arg ) +{ + int i = -1; + + if ( strcasecmp(arg, "none") == 0 ) + i = LDAP_OPT_X_SASL_CBINDING_NONE; + else if ( strcasecmp(arg, "tls-unique") == 0 ) + i = LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE; + else if ( strcasecmp(arg, "tls-endpoint") == 0 ) + i = LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT; + + return i; +} + +void *ldap_pvt_sasl_cbinding( void *ssl, int type, int is_server ) +{ +#if defined(SASL_CHANNEL_BINDING) && defined(HAVE_TLS) + char unique_prefix[] = "tls-unique:"; + char endpoint_prefix[] = "tls-server-end-point:"; + char cbinding[ 64 ]; + struct berval cbv = { 64, cbinding }; + unsigned char *cb_data; /* used since cb->data is const* */ + sasl_channel_binding_t *cb; + char *prefix; + int plen; + + switch (type) { + case LDAP_OPT_X_SASL_CBINDING_NONE: + return NULL; + case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE: + if ( !ldap_pvt_tls_get_unique( ssl, &cbv, is_server )) + return NULL; + prefix = unique_prefix; + plen = sizeof(unique_prefix) -1; + break; + case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT: + if ( !ldap_pvt_tls_get_endpoint( ssl, &cbv, is_server )) + return NULL; + prefix = endpoint_prefix; + plen = sizeof(endpoint_prefix) -1; + break; + default: + return NULL; + } + + cb = ldap_memalloc( sizeof(*cb) + plen + cbv.bv_len ); + cb->len = plen + cbv.bv_len; + cb->data = cb_data = (unsigned char *)(cb+1); + memcpy( cb_data, prefix, plen ); + memcpy( cb_data + plen, cbv.bv_val, cbv.bv_len ); + cb->name = "ldap"; + cb->critical = 0; + + return cb; +#else + return NULL; +#endif +} + +int +ldap_int_sasl_bind( + LDAP *ld, + const char *dn, + const char *mechs, + LDAPControl **sctrls, + LDAPControl **cctrls, + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults, + LDAPMessage *result, + const char **rmech, + int *msgid ) +{ + const char *mech; + sasl_ssf_t *ssf; + sasl_conn_t *ctx; + sasl_interact_t *prompts = NULL; + struct berval ccred = BER_BVNULL; + int saslrc, rc; + unsigned credlen; +#if !defined(_WIN32) + char my_hostname[HOST_NAME_MAX + 1]; +#endif + int free_saslhost = 0; + + Debug1( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n", + mechs ? mechs : "<null>" ); + + /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ + if (ld->ld_version < LDAP_VERSION3) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + /* Starting a Bind */ + if ( !result ) { + const char *pmech = NULL; + sasl_conn_t *oldctx; + ber_socket_t sd; + void *ssl; + + rc = 0; + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + + if ( sd == AC_SOCKET_INVALID || !ld->ld_defconn ) { + /* not connected yet */ + + rc = ldap_open_defconn( ld ); + + if ( rc == 0 ) { + ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb, + LBER_SB_OPT_GET_FD, &sd ); + + if( sd == AC_SOCKET_INVALID ) { + ld->ld_errno = LDAP_LOCAL_ERROR; + rc = ld->ld_errno; + } + } + } + if ( rc == 0 && ld->ld_defconn && + ld->ld_defconn->lconn_status == LDAP_CONNST_CONNECTING ) { + rc = ldap_int_check_async_open( ld, sd ); + } + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + if( rc != 0 ) return ld->ld_errno; + + oldctx = ld->ld_defconn->lconn_sasl_authctx; + + /* If we already have an authentication context, clear it out */ + if( oldctx ) { + if ( oldctx != ld->ld_defconn->lconn_sasl_sockctx ) { + sasl_dispose( &oldctx ); + } + ld->ld_defconn->lconn_sasl_authctx = NULL; + } + + { + char *saslhost; + int nocanon = (int)LDAP_BOOL_GET( &ld->ld_options, + LDAP_BOOL_SASL_NOCANON ); + + /* If we don't need to canonicalize just use the host + * from the LDAP URI. + * Always use the result of gethostname() for LDAPI. + * Skip for Windows which doesn't support LDAPI. + */ +#if !defined(_WIN32) + if (ld->ld_defconn->lconn_server->lud_scheme != NULL && + strcmp("ldapi", ld->ld_defconn->lconn_server->lud_scheme) == 0) { + rc = gethostname(my_hostname, HOST_NAME_MAX + 1); + if (rc == 0) { + saslhost = my_hostname; + } else { + saslhost = "localhost"; + } + } else +#endif + if ( nocanon ) + saslhost = ld->ld_defconn->lconn_server->lud_host; + else { + saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb, + "localhost" ); + free_saslhost = 1; + } + rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost ); + if ( free_saslhost ) + LDAP_FREE( saslhost ); + } + + if ( rc != LDAP_SUCCESS ) return rc; + + ctx = ld->ld_defconn->lconn_sasl_authctx; + +#ifdef HAVE_TLS + /* Check for TLS */ + ssl = ldap_pvt_tls_sb_ctx( ld->ld_defconn->lconn_sb ); + if ( ssl ) { + struct berval authid = BER_BVNULL; + ber_len_t fac; + + fac = ldap_pvt_tls_get_strength( ssl ); + /* failure is OK, we just can't use SASL EXTERNAL */ + (void) ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 ); + + (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac ); + LDAP_FREE( authid.bv_val ); +#ifdef SASL_CHANNEL_BINDING /* 2.1.25+ */ + if ( ld->ld_defconn->lconn_sasl_cbind == NULL ) { + void *cb; + cb = ldap_pvt_sasl_cbinding( ssl, + ld->ld_options.ldo_sasl_cbinding, + 0 ); + if ( cb != NULL ) { + sasl_setprop( ld->ld_defconn->lconn_sasl_authctx, + SASL_CHANNEL_BINDING, cb ); + ld->ld_defconn->lconn_sasl_cbind = cb; + } + } +#endif + } +#endif + +#if !defined(_WIN32) + /* Check for local */ + if ( ldap_pvt_url_scheme2proto( + ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC ) + { + char authid[sizeof("gidNumber=4294967295+uidNumber=4294967295," + "cn=peercred,cn=external,cn=auth")]; + sprintf( authid, "gidNumber=%u+uidNumber=%u," + "cn=peercred,cn=external,cn=auth", + getegid(), geteuid() ); + (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid, + LDAP_PVT_SASL_LOCAL_SSF ); + } +#endif + + /* (re)set security properties */ + sasl_setprop( ctx, SASL_SEC_PROPS, + &ld->ld_options.ldo_sasl_secprops ); + + mech = NULL; + + do { + saslrc = sasl_client_start( ctx, + mechs, +#if SASL_VERSION_MAJOR < 2 + NULL, +#endif + &prompts, + (SASL_CONST char **)&ccred.bv_val, + &credlen, + &mech ); + + if( pmech == NULL && mech != NULL ) { + pmech = mech; + *rmech = mech; + + if( flags != LDAP_SASL_QUIET ) { + fprintf(stderr, + "SASL/%s authentication started\n", + pmech ); + } + } + + if( saslrc == SASL_INTERACT ) { + int res; + if( !interact ) break; + res = (interact)( ld, flags, defaults, prompts ); + + if( res != LDAP_SUCCESS ) break; + } + } while ( saslrc == SASL_INTERACT ); + rc = LDAP_SASL_BIND_IN_PROGRESS; + + } else { + /* continuing an in-progress Bind */ + struct berval *scred = NULL; + + ctx = ld->ld_defconn->lconn_sasl_authctx; + + rc = ldap_parse_sasl_bind_result( ld, result, &scred, 0 ); + if ( rc != LDAP_SUCCESS ) { + if ( scred ) + ber_bvfree( scred ); + goto done; + } + + rc = ldap_result2error( ld, result, 0 ); + if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { + if( scred ) { + /* and server provided us with data? */ + Debug2( LDAP_DEBUG_TRACE, + "ldap_int_sasl_bind: rc=%d len=%ld\n", + rc, scred ? (long) scred->bv_len : -1L ); + ber_bvfree( scred ); + scred = NULL; + } + goto done; + } + + mech = *rmech; + if ( rc == LDAP_SUCCESS && mech == NULL ) { + if ( scred ) + ber_bvfree( scred ); + goto success; + } + + do { + if( ! scred ) { + /* no data! */ + Debug0( LDAP_DEBUG_TRACE, + "ldap_int_sasl_bind: no data in step!\n" ); + } + + saslrc = sasl_client_step( ctx, + (scred == NULL) ? NULL : scred->bv_val, + (scred == NULL) ? 0 : scred->bv_len, + &prompts, + (SASL_CONST char **)&ccred.bv_val, + &credlen ); + + Debug1( LDAP_DEBUG_TRACE, "sasl_client_step: %d\n", + saslrc ); + + if( saslrc == SASL_INTERACT ) { + int res; + if( !interact ) break; + res = (interact)( ld, flags, defaults, prompts ); + if( res != LDAP_SUCCESS ) break; + } + } while ( saslrc == SASL_INTERACT ); + + ber_bvfree( scred ); + } + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + rc = ld->ld_errno = sasl_err2ldap( saslrc ); +#if SASL_VERSION_MAJOR >= 2 + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + } + ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) ); +#endif + goto done; + } + + if ( saslrc == SASL_OK ) + *rmech = NULL; + + ccred.bv_len = credlen; + + if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) { + rc = ldap_sasl_bind( ld, dn, mech, &ccred, sctrls, cctrls, msgid ); + + if ( ccred.bv_val != NULL ) { +#if SASL_VERSION_MAJOR < 2 + LDAP_FREE( ccred.bv_val ); +#endif + ccred.bv_val = NULL; + } + if ( rc == LDAP_SUCCESS ) + rc = LDAP_SASL_BIND_IN_PROGRESS; + goto done; + } + +success: + /* Conversation was completed successfully by now */ + if( flags != LDAP_SASL_QUIET ) { + char *data; + saslrc = sasl_getprop( ctx, SASL_USERNAME, + (SASL_CONST void **)(char *) &data ); + if( saslrc == SASL_OK && data && *data ) { + fprintf( stderr, "SASL username: %s\n", data ); + } + +#if SASL_VERSION_MAJOR < 2 + saslrc = sasl_getprop( ctx, SASL_REALM, + (SASL_CONST void **) &data ); + if( saslrc == SASL_OK && data && *data ) { + fprintf( stderr, "SASL realm: %s\n", data ); + } +#endif + } + + ssf = NULL; + saslrc = sasl_getprop( ctx, SASL_SSF, (SASL_CONST void **)(char *) &ssf ); + if( saslrc == SASL_OK ) { + if( flags != LDAP_SASL_QUIET ) { + fprintf( stderr, "SASL SSF: %lu\n", + (unsigned long) *ssf ); + } + + if( ssf && *ssf ) { + if ( ld->ld_defconn->lconn_sasl_sockctx ) { + sasl_conn_t *oldctx = ld->ld_defconn->lconn_sasl_sockctx; + sasl_dispose( &oldctx ); + ldap_pvt_sasl_remove( ld->ld_defconn->lconn_sb ); + } + ldap_pvt_sasl_install( ld->ld_defconn->lconn_sb, ctx ); + ld->ld_defconn->lconn_sasl_sockctx = ctx; + + if( flags != LDAP_SASL_QUIET ) { + fprintf( stderr, "SASL data security layer installed.\n" ); + } + } + } + ld->ld_defconn->lconn_sasl_authctx = ctx; + +done: + return rc; +} + +int +ldap_int_sasl_external( + LDAP *ld, + LDAPConn *conn, + const char * authid, + ber_len_t ssf ) +{ + int sc; + sasl_conn_t *ctx; +#if SASL_VERSION_MAJOR < 2 + sasl_external_properties_t extprops; +#else + sasl_ssf_t sasl_ssf = ssf; +#endif + + ctx = conn->lconn_sasl_authctx; + + if ( ctx == NULL ) { + return LDAP_LOCAL_ERROR; + } + +#if SASL_VERSION_MAJOR >= 2 + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, &sasl_ssf ); + if ( sc == SASL_OK ) + sc = sasl_setprop( ctx, SASL_AUTH_EXTERNAL, authid ); +#else + memset( &extprops, '\0', sizeof(extprops) ); + extprops.ssf = ssf; + extprops.auth_id = (char *) authid; + + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); +#endif + + if ( sc != SASL_OK ) { + return LDAP_LOCAL_ERROR; + } + + return LDAP_SUCCESS; +} + + +#define GOT_MINSSF 1 +#define GOT_MAXSSF 2 +#define GOT_MAXBUF 4 + +static struct { + struct berval key; + int sflag; + int ival; + int idef; +} sprops[] = { + { BER_BVC("none"), 0, 0, 0 }, + { BER_BVC("nodict"), SASL_SEC_NODICTIONARY, 0, 0 }, + { BER_BVC("noplain"), SASL_SEC_NOPLAINTEXT, 0, 0 }, + { BER_BVC("noactive"), SASL_SEC_NOACTIVE, 0, 0 }, + { BER_BVC("passcred"), SASL_SEC_PASS_CREDENTIALS, 0, 0 }, + { BER_BVC("forwardsec"), SASL_SEC_FORWARD_SECRECY, 0, 0 }, + { BER_BVC("noanonymous"), SASL_SEC_NOANONYMOUS, 0, 0 }, + { BER_BVC("minssf="), 0, GOT_MINSSF, 0 }, + { BER_BVC("maxssf="), 0, GOT_MAXSSF, INT_MAX }, + { BER_BVC("maxbufsize="), 0, GOT_MAXBUF, 65536 }, + { BER_BVNULL, 0, 0, 0 } +}; + +void ldap_pvt_sasl_secprops_unparse( + sasl_security_properties_t *secprops, + struct berval *out ) +{ + int i, l = 0; + int comma; + char *ptr; + + if ( secprops == NULL || out == NULL ) { + return; + } + + comma = 0; + for ( i=0; !BER_BVISNULL( &sprops[i].key ); i++ ) { + if ( sprops[i].ival ) { + int v = 0; + + switch( sprops[i].ival ) { + case GOT_MINSSF: v = secprops->min_ssf; break; + case GOT_MAXSSF: v = secprops->max_ssf; break; + case GOT_MAXBUF: v = secprops->maxbufsize; break; + } + /* It is the default, ignore it */ + if ( v == sprops[i].idef ) continue; + + l += sprops[i].key.bv_len + 24; + } else if ( sprops[i].sflag ) { + if ( sprops[i].sflag & secprops->security_flags ) { + l += sprops[i].key.bv_len; + } + } else if ( secprops->security_flags == 0 ) { + l += sprops[i].key.bv_len; + } + if ( comma ) l++; + comma = 1; + } + l++; + + out->bv_val = LDAP_MALLOC( l ); + if ( out->bv_val == NULL ) { + out->bv_len = 0; + return; + } + + ptr = out->bv_val; + comma = 0; + for ( i=0; !BER_BVISNULL( &sprops[i].key ); i++ ) { + if ( sprops[i].ival ) { + int v = 0; + + switch( sprops[i].ival ) { + case GOT_MINSSF: v = secprops->min_ssf; break; + case GOT_MAXSSF: v = secprops->max_ssf; break; + case GOT_MAXBUF: v = secprops->maxbufsize; break; + } + /* It is the default, ignore it */ + if ( v == sprops[i].idef ) continue; + + if ( comma ) *ptr++ = ','; + ptr += sprintf(ptr, "%s%d", sprops[i].key.bv_val, v ); + comma = 1; + } else if ( sprops[i].sflag ) { + if ( sprops[i].sflag & secprops->security_flags ) { + if ( comma ) *ptr++ = ','; + ptr += sprintf(ptr, "%s", sprops[i].key.bv_val ); + comma = 1; + } + } else if ( secprops->security_flags == 0 ) { + if ( comma ) *ptr++ = ','; + ptr += sprintf(ptr, "%s", sprops[i].key.bv_val ); + comma = 1; + } + } + out->bv_len = ptr - out->bv_val; +} + +int ldap_pvt_sasl_secprops( + const char *in, + sasl_security_properties_t *secprops ) +{ + unsigned i, j, l; + char **props; + unsigned sflags = 0; + int got_sflags = 0; + sasl_ssf_t max_ssf = 0; + int got_max_ssf = 0; + sasl_ssf_t min_ssf = 0; + int got_min_ssf = 0; + unsigned maxbufsize = 0; + int got_maxbufsize = 0; + + if( secprops == NULL ) { + return LDAP_PARAM_ERROR; + } + props = ldap_str2charray( in, "," ); + if( props == NULL ) { + return LDAP_PARAM_ERROR; + } + + for( i=0; props[i]; i++ ) { + l = strlen( props[i] ); + for ( j=0; !BER_BVISNULL( &sprops[j].key ); j++ ) { + if ( l < sprops[j].key.bv_len ) continue; + if ( strncasecmp( props[i], sprops[j].key.bv_val, + sprops[j].key.bv_len )) continue; + if ( sprops[j].ival ) { + unsigned v; + char *next = NULL; + if ( !isdigit( (unsigned char)props[i][sprops[j].key.bv_len] )) + continue; + v = strtoul( &props[i][sprops[j].key.bv_len], &next, 10 ); + if ( next == &props[i][sprops[j].key.bv_len] || next[0] != '\0' ) continue; + switch( sprops[j].ival ) { + case GOT_MINSSF: + min_ssf = v; got_min_ssf++; break; + case GOT_MAXSSF: + max_ssf = v; got_max_ssf++; break; + case GOT_MAXBUF: + maxbufsize = v; got_maxbufsize++; break; + } + } else { + if ( props[i][sprops[j].key.bv_len] ) continue; + if ( sprops[j].sflag ) + sflags |= sprops[j].sflag; + else + sflags = 0; + got_sflags++; + } + break; + } + if ( BER_BVISNULL( &sprops[j].key )) { + ldap_charray_free( props ); + 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; +} + +int +ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg ) +{ + int rc, i; + + switch( option ) { + case LDAP_OPT_X_SASL_SECPROPS: + rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops ); + if( rc == LDAP_SUCCESS ) return 0; + break; + case LDAP_OPT_X_SASL_CBINDING: + i = ldap_pvt_sasl_cbinding_parse( arg ); + if ( i >= 0 ) { + lo->ldo_sasl_cbinding = i; + return 0; + } + break; + } + + return -1; +} + +int +ldap_int_sasl_get_option( LDAP *ld, int option, void *arg ) +{ + if ( option == LDAP_OPT_X_SASL_MECHLIST ) { + *(char ***)arg = (char **)sasl_global_listmech(); + return 0; + } + + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_MECH: { + *(char **)arg = ld->ld_options.ldo_def_sasl_mech + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_mech ) : NULL; + } break; + case LDAP_OPT_X_SASL_REALM: { + *(char **)arg = ld->ld_options.ldo_def_sasl_realm + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_realm ) : NULL; + } break; + case LDAP_OPT_X_SASL_AUTHCID: { + *(char **)arg = ld->ld_options.ldo_def_sasl_authcid + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authcid ) : NULL; + } break; + case LDAP_OPT_X_SASL_AUTHZID: { + *(char **)arg = ld->ld_options.ldo_def_sasl_authzid + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL; + } 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 = ld->ld_defconn->lconn_sasl_sockctx; + + if ( ctx == NULL ) { + return -1; + } + + sc = sasl_getprop( ctx, SASL_SSF, + (SASL_CONST void **)(char *) &ssf ); + + if ( sc != SASL_OK ) { + return -1; + } + + *(ber_len_t *)arg = *ssf; + } break; + + case LDAP_OPT_X_SASL_SSF_EXTERNAL: + /* this option is write only */ + return -1; + + case LDAP_OPT_X_SASL_SSF_MIN: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.min_ssf; + break; + case LDAP_OPT_X_SASL_SSF_MAX: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.max_ssf; + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.maxbufsize; + break; + case LDAP_OPT_X_SASL_NOCANON: + *(int *)arg = (int) LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); + break; + + case LDAP_OPT_X_SASL_USERNAME: { + int sc; + char *username; + sasl_conn_t *ctx; + + if( ld->ld_defconn == NULL ) { + return -1; + } + + ctx = ld->ld_defconn->lconn_sasl_authctx; + + if ( ctx == NULL ) { + return -1; + } + + sc = sasl_getprop( ctx, SASL_USERNAME, + (SASL_CONST void **)(char **) &username ); + + if ( sc != SASL_OK ) { + return -1; + } + + *(char **)arg = username ? LDAP_STRDUP( username ) : NULL; + } break; + + case LDAP_OPT_X_SASL_SECPROPS: + /* this option is write only */ + return -1; + + case LDAP_OPT_X_SASL_CBINDING: + *(int *)arg = ld->ld_options.ldo_sasl_cbinding; + break; + +#ifdef SASL_GSS_CREDS + case LDAP_OPT_X_SASL_GSS_CREDS: { + sasl_conn_t *ctx; + int sc; + + if ( ld->ld_defconn == NULL ) + return -1; + + ctx = ld->ld_defconn->lconn_sasl_authctx; + if ( ctx == NULL ) + return -1; + + sc = sasl_getprop( ctx, SASL_GSS_CREDS, arg ); + if ( sc != SASL_OK ) + return -1; + } + break; +#endif + + default: + return -1; + } + return 0; +} + +int +ldap_int_sasl_set_option( LDAP *ld, int option, void *arg ) +{ + if ( ld == NULL ) + return -1; + + if ( arg == NULL && option != LDAP_OPT_X_SASL_NOCANON ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_SSF: + case LDAP_OPT_X_SASL_USERNAME: + /* This option is read-only */ + return -1; + + case LDAP_OPT_X_SASL_SSF_EXTERNAL: { + int sc; +#if SASL_VERSION_MAJOR < 2 + sasl_external_properties_t extprops; +#else + sasl_ssf_t sasl_ssf; +#endif + sasl_conn_t *ctx; + + if( ld->ld_defconn == NULL ) { + return -1; + } + + ctx = ld->ld_defconn->lconn_sasl_authctx; + + if ( ctx == NULL ) { + return -1; + } + +#if SASL_VERSION_MAJOR >= 2 + sasl_ssf = * (ber_len_t *)arg; + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, &sasl_ssf); +#else + memset(&extprops, 0L, sizeof(extprops)); + + extprops.ssf = * (ber_len_t *) arg; + + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); +#endif + + if ( sc != SASL_OK ) { + return -1; + } + } break; + + case LDAP_OPT_X_SASL_SSF_MIN: + ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg; + break; + case LDAP_OPT_X_SASL_SSF_MAX: + ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg; + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg; + break; + case LDAP_OPT_X_SASL_NOCANON: + if ( arg == LDAP_OPT_OFF ) { + LDAP_BOOL_CLR(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); + } else { + LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_SASL_NOCANON ); + } + break; + + case LDAP_OPT_X_SASL_SECPROPS: { + int sc; + sc = ldap_pvt_sasl_secprops( (char *) arg, + &ld->ld_options.ldo_sasl_secprops ); + + return sc == LDAP_SUCCESS ? 0 : -1; + } + + case LDAP_OPT_X_SASL_CBINDING: + if ( !arg ) return -1; + switch( *(int *) arg ) { + case LDAP_OPT_X_SASL_CBINDING_NONE: + case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE: + case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT: + ld->ld_options.ldo_sasl_cbinding = *(int *) arg; + return 0; + } + return -1; + +#ifdef SASL_GSS_CREDS + case LDAP_OPT_X_SASL_GSS_CREDS: { + sasl_conn_t *ctx; + int sc; + + if ( ld->ld_defconn == NULL ) + return -1; + + ctx = ld->ld_defconn->lconn_sasl_authctx; + if ( ctx == NULL ) + return -1; + + sc = sasl_setprop( ctx, SASL_GSS_CREDS, arg ); + if ( sc != SASL_OK ) + return -1; + } + break; +#endif + + default: + return -1; + } + return 0; +} + +#ifdef LDAP_R_COMPILE +#define LDAP_DEBUG_R_SASL +void *ldap_pvt_sasl_mutex_new(void) +{ + ldap_pvt_thread_mutex_t *mutex; + + mutex = (ldap_pvt_thread_mutex_t *) LDAP_CALLOC( 1, + sizeof(ldap_pvt_thread_mutex_t) ); + + if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) { + return mutex; + } + LDAP_FREE( mutex ); +#ifndef LDAP_DEBUG_R_SASL + assert( 0 ); +#endif /* !LDAP_DEBUG_R_SASL */ + return NULL; +} + +int ldap_pvt_sasl_mutex_lock(void *mutex) +{ +#ifdef LDAP_DEBUG_R_SASL + if ( mutex == NULL ) { + return SASL_OK; + } +#else /* !LDAP_DEBUG_R_SASL */ + assert( mutex != NULL ); +#endif /* !LDAP_DEBUG_R_SASL */ + return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex ) + ? SASL_FAIL : SASL_OK; +} + +int ldap_pvt_sasl_mutex_unlock(void *mutex) +{ +#ifdef LDAP_DEBUG_R_SASL + if ( mutex == NULL ) { + return SASL_OK; + } +#else /* !LDAP_DEBUG_R_SASL */ + assert( mutex != NULL ); +#endif /* !LDAP_DEBUG_R_SASL */ + return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex ) + ? SASL_FAIL : SASL_OK; +} + +void ldap_pvt_sasl_mutex_dispose(void *mutex) +{ +#ifdef LDAP_DEBUG_R_SASL + if ( mutex == NULL ) { + return; + } +#else /* !LDAP_DEBUG_R_SASL */ + assert( mutex != NULL ); +#endif /* !LDAP_DEBUG_R_SASL */ + (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex ); + LDAP_FREE( mutex ); +} +#endif + +#else +int ldap_int_sasl_init( void ) +{ return LDAP_SUCCESS; } + +int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) +{ return LDAP_SUCCESS; } + +int +ldap_int_sasl_bind( + LDAP *ld, + const char *dn, + const char *mechs, + LDAPControl **sctrls, + LDAPControl **cctrls, + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults, + LDAPMessage *result, + const char **rmech, + int *msgid ) +{ return LDAP_NOT_SUPPORTED; } + +int +ldap_int_sasl_external( + LDAP *ld, + LDAPConn *conn, + const char * authid, + ber_len_t ssf ) +{ return LDAP_SUCCESS; } + +#endif /* HAVE_CYRUS_SASL */ diff --git a/libs/ldap/libldap/delete.c b/libs/ldap/libldap/delete.c new file mode 100644 index 00000000000..4201b724690 --- /dev/null +++ b/libs/ldap/libldap/delete.c @@ -0,0 +1,174 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* + * A delete request looks like this: + * DelRequest ::= DistinguishedName, + */ + +BerElement * +ldap_build_delete_req( + LDAP *ld, + LDAP_CONST char *dn, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID( ld, *msgidp ); + rc = ber_printf( ber, "{its", /* '}' */ + *msgidp, LDAP_REQ_DELETE, dn ); + if ( rc == -1 ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_delete_ext - initiate an ldap extended delete operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to delete + * sctrls Server Controls + * cctrls Client Controls + * msgidp Message Id Pointer + * + * Example: + * rc = ldap_delete( ld, dn, sctrls, cctrls, msgidp ); + */ +int +ldap_delete_ext( + LDAP *ld, + LDAP_CONST char* dn, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + int rc; + BerElement *ber; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_delete_ext\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( dn != NULL ); + assert( msgidp != NULL ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_delete_req( ld, dn, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_DELETE, dn, ber, id ); + + if(*msgidp < 0) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + +int +ldap_delete_ext_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int msgid; + int rc; + LDAPMessage *res; + + rc = ldap_delete_ext( ld, dn, sctrls, cctrls, &msgid ); + + if( rc != LDAP_SUCCESS ) + return( ld->ld_errno ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, res, 1 ) ); +} +/* + * ldap_delete - initiate an ldap (and X.500) delete operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to delete + * + * Example: + * msgid = ldap_delete( ld, dn ); + */ +int +ldap_delete( LDAP *ld, LDAP_CONST char *dn ) +{ + int msgid; + + /* + * A delete request looks like this: + * DelRequest ::= DistinguishedName, + */ + + Debug0( LDAP_DEBUG_TRACE, "ldap_delete\n" ); + + return ldap_delete_ext( ld, dn, NULL, NULL, &msgid ) == LDAP_SUCCESS + ? msgid : -1 ; +} + + +int +ldap_delete_s( LDAP *ld, LDAP_CONST char *dn ) +{ + return ldap_delete_ext_s( ld, dn, NULL, NULL ); +} diff --git a/libs/ldap/libldap/error.c b/libs/ldap/libldap/error.c new file mode 100644 index 00000000000..444a0244bf3 --- /dev/null +++ b/libs/ldap/libldap/error.c @@ -0,0 +1,395 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +void ldap_int_error_init( void ) { +} + +char * +ldap_err2string( int err ) +{ + char *m; + + Debug0( LDAP_DEBUG_TRACE, "ldap_err2string\n" ); + + switch ( err ) { +# define C(code, message) case code: m = message; break + + /* LDAPv3 (RFC 4511) codes */ + C(LDAP_SUCCESS, N_("Success")); + C(LDAP_OPERATIONS_ERROR, N_("Operations error")); + C(LDAP_PROTOCOL_ERROR, N_("Protocol error")); + C(LDAP_TIMELIMIT_EXCEEDED, N_("Time limit exceeded")); + C(LDAP_SIZELIMIT_EXCEEDED, N_("Size limit exceeded")); + C(LDAP_COMPARE_FALSE, N_("Compare False")); + C(LDAP_COMPARE_TRUE, N_("Compare True")); + C(LDAP_STRONG_AUTH_NOT_SUPPORTED,N_("Authentication method not supported")); + C(LDAP_STRONG_AUTH_REQUIRED, N_("Strong(er) authentication required")); + + C(LDAP_REFERRAL, N_("Referral")); + C(LDAP_ADMINLIMIT_EXCEEDED, N_("Administrative limit exceeded")); + C(LDAP_UNAVAILABLE_CRITICAL_EXTENSION, + N_("Critical extension is unavailable")); + C(LDAP_CONFIDENTIALITY_REQUIRED,N_("Confidentiality required")); + C(LDAP_SASL_BIND_IN_PROGRESS, N_("SASL bind in progress")); + + C(LDAP_NO_SUCH_ATTRIBUTE, N_("No such attribute")); + C(LDAP_UNDEFINED_TYPE, N_("Undefined attribute type")); + C(LDAP_INAPPROPRIATE_MATCHING, N_("Inappropriate matching")); + C(LDAP_CONSTRAINT_VIOLATION, N_("Constraint violation")); + C(LDAP_TYPE_OR_VALUE_EXISTS, N_("Type or value exists")); + C(LDAP_INVALID_SYNTAX, N_("Invalid syntax")); + + C(LDAP_NO_SUCH_OBJECT, N_("No such object")); + C(LDAP_ALIAS_PROBLEM, N_("Alias problem")); + C(LDAP_INVALID_DN_SYNTAX, N_("Invalid DN syntax")); + + C(LDAP_ALIAS_DEREF_PROBLEM, N_("Alias dereferencing problem")); + + C(LDAP_INAPPROPRIATE_AUTH, N_("Inappropriate authentication")); + C(LDAP_INVALID_CREDENTIALS, N_("Invalid credentials")); + C(LDAP_INSUFFICIENT_ACCESS, N_("Insufficient access")); + C(LDAP_BUSY, N_("Server is busy")); + C(LDAP_UNAVAILABLE, N_("Server is unavailable")); + C(LDAP_UNWILLING_TO_PERFORM, N_("Server is unwilling to perform")); + C(LDAP_LOOP_DETECT, N_("Loop detected")); + + C(LDAP_NAMING_VIOLATION, N_("Naming violation")); + C(LDAP_OBJECT_CLASS_VIOLATION, N_("Object class violation")); + C(LDAP_NOT_ALLOWED_ON_NONLEAF, N_("Operation not allowed on non-leaf")); + C(LDAP_NOT_ALLOWED_ON_RDN, N_("Operation not allowed on RDN")); + C(LDAP_ALREADY_EXISTS, N_("Already exists")); + C(LDAP_NO_OBJECT_CLASS_MODS, N_("Cannot modify object class")); + + C(LDAP_AFFECTS_MULTIPLE_DSAS, N_("Operation affects multiple DSAs")); + + /* Virtual List View draft */ + C(LDAP_VLV_ERROR, N_("Virtual List View error")); + + C(LDAP_OTHER, N_("Other (e.g., implementation specific) error")); + + /* LDAPv2 (RFC 1777) codes */ + C(LDAP_PARTIAL_RESULTS, N_("Partial results and referral received")); + C(LDAP_IS_LEAF, N_("Entry is a leaf")); + + /* Connection-less LDAP (CLDAP - RFC 1798) code */ + C(LDAP_RESULTS_TOO_LARGE, N_("Results too large")); + + /* Cancel Operation (RFC 3909) codes */ + C(LDAP_CANCELLED, N_("Cancelled")); + C(LDAP_NO_SUCH_OPERATION, N_("No Operation to Cancel")); + C(LDAP_TOO_LATE, N_("Too Late to Cancel")); + C(LDAP_CANNOT_CANCEL, N_("Cannot Cancel")); + + /* Assert Control (RFC 4528 and old internet-draft) codes */ + C(LDAP_ASSERTION_FAILED, N_("Assertion Failed")); + C(LDAP_X_ASSERTION_FAILED, N_("Assertion Failed (X)")); + + /* Proxied Authorization Control (RFC 4370 and I-D) codes */ + C(LDAP_PROXIED_AUTHORIZATION_DENIED, N_("Proxied Authorization Denied")); + C(LDAP_X_PROXY_AUTHZ_FAILURE, N_("Proxy Authorization Failure (X)")); + + /* Content Sync Operation (RFC 4533 and I-D) codes */ + C(LDAP_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required")); + C(LDAP_X_SYNC_REFRESH_REQUIRED, N_("Content Sync Refresh Required (X)")); + + /* No-Op Control (draft-zeilenga-ldap-noop) code */ + C(LDAP_X_NO_OPERATION, N_("No Operation (X)")); + + /* Client Update Protocol (RFC 3928) codes */ + C(LDAP_CUP_RESOURCES_EXHAUSTED, N_("LCUP Resources Exhausted")); + C(LDAP_CUP_SECURITY_VIOLATION, N_("LCUP Security Violation")); + C(LDAP_CUP_INVALID_DATA, N_("LCUP Invalid Data")); + C(LDAP_CUP_UNSUPPORTED_SCHEME, N_("LCUP Unsupported Scheme")); + C(LDAP_CUP_RELOAD_REQUIRED, N_("LCUP Reload Required")); + + C(LDAP_TXN_SPECIFY_OKAY, N_("TXN specify okay")); + C(LDAP_TXN_ID_INVALID, N_("TXN ID is invalid")); + + /* API codes - renumbered since draft-ietf-ldapext-ldap-c-api */ + C(LDAP_SERVER_DOWN, N_("Can't contact LDAP server")); + C(LDAP_LOCAL_ERROR, N_("Local error")); + C(LDAP_ENCODING_ERROR, N_("Encoding error")); + C(LDAP_DECODING_ERROR, N_("Decoding error")); + C(LDAP_TIMEOUT, N_("Timed out")); + C(LDAP_AUTH_UNKNOWN, N_("Unknown authentication method")); + C(LDAP_FILTER_ERROR, N_("Bad search filter")); + C(LDAP_USER_CANCELLED, N_("User cancelled operation")); + C(LDAP_PARAM_ERROR, N_("Bad parameter to an ldap routine")); + C(LDAP_NO_MEMORY, N_("Out of memory")); + C(LDAP_CONNECT_ERROR, N_("Connect error")); + C(LDAP_NOT_SUPPORTED, N_("Not Supported")); + C(LDAP_CONTROL_NOT_FOUND, N_("Control not found")); + C(LDAP_NO_RESULTS_RETURNED, N_("No results returned")); + C(LDAP_MORE_RESULTS_TO_RETURN, N_("More results to return")); + C(LDAP_CLIENT_LOOP, N_("Client Loop")); + C(LDAP_REFERRAL_LIMIT_EXCEEDED, N_("Referral Limit Exceeded")); + C(LDAP_X_CONNECTING, N_("Connecting (X)")); +# undef C + + default: + m = (LDAP_API_ERROR(err) ? N_("Unknown API error") + : LDAP_E_ERROR(err) ? N_("Unknown (extension) error") + : LDAP_X_ERROR(err) ? N_("Unknown (private extension) error") + : N_("Unknown error")); + break; + } + + return _(m); +} + +/* deprecated */ +void +ldap_perror( LDAP *ld, LDAP_CONST char *str ) +{ + int i; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( str != NULL ); + + fprintf( stderr, "%s: %s (%d)\n", + str ? str : "ldap_perror", + ldap_err2string( ld->ld_errno ), + ld->ld_errno ); + + if ( ld->ld_matched != NULL && ld->ld_matched[0] != '\0' ) { + fprintf( stderr, _("\tmatched DN: %s\n"), ld->ld_matched ); + } + + if ( ld->ld_error != NULL && ld->ld_error[0] != '\0' ) { + fprintf( stderr, _("\tadditional info: %s\n"), ld->ld_error ); + } + + if ( ld->ld_referrals != NULL && ld->ld_referrals[0] != NULL) { + fprintf( stderr, _("\treferrals:\n") ); + for (i=0; ld->ld_referrals[i]; i++) { + fprintf( stderr, _("\t\t%s\n"), ld->ld_referrals[i] ); + } + } + + fflush( stderr ); +} + +/* deprecated */ +int +ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) +{ + int rc, err; + + rc = ldap_parse_result( ld, r, &err, + NULL, NULL, NULL, NULL, freeit ); + + return err != LDAP_SUCCESS ? err : rc; +} + +/* + * Parse LDAPResult Messages: + * + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED, + * matchedDN LDAPDN, + * errorMessage LDAPString, + * referral [3] Referral OPTIONAL } + * + * including Bind results: + * + * BindResponse ::= [APPLICATION 1] SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds [7] OCTET STRING OPTIONAL } + * + * and ExtendedOp results: + * + * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + * COMPONENTS OF LDAPResult, + * responseName [10] LDAPOID OPTIONAL, + * response [11] OCTET STRING OPTIONAL } + * + */ +int +ldap_parse_result( + LDAP *ld, + LDAPMessage *r, + int *errcodep, + char **matcheddnp, + char **errmsgp, + char ***referralsp, + LDAPControl ***serverctrls, + int freeit ) +{ + LDAPMessage *lm; + ber_int_t errcode = LDAP_SUCCESS; + + ber_tag_t tag; + BerElement *ber; + + Debug0( LDAP_DEBUG_TRACE, "ldap_parse_result\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( r != NULL ); + + if(errcodep != NULL) *errcodep = LDAP_SUCCESS; + if(matcheddnp != NULL) *matcheddnp = NULL; + if(errmsgp != NULL) *errmsgp = NULL; + if(referralsp != NULL) *referralsp = NULL; + if(serverctrls != NULL) *serverctrls = NULL; + + LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); + /* Find the result, last msg in chain... */ + lm = r->lm_chain_tail; + /* FIXME: either this is not possible (assert?) + * or it should be handled */ + if ( lm != NULL ) { + switch ( lm->lm_msgtype ) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_REFERENCE: + case LDAP_RES_INTERMEDIATE: + lm = NULL; + break; + + default: + break; + } + } + + if( lm == NULL ) { + errcode = ld->ld_errno = LDAP_NO_RESULTS_RETURNED; + LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); + goto done; + } + + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + if ( ld->ld_matched ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + if ( ld->ld_referrals ) { + LDAP_VFREE( ld->ld_referrals ); + ld->ld_referrals = NULL; + } + + /* parse results */ + + ber = ber_dup( lm->lm_ber ); + + if ( ld->ld_version < LDAP_VERSION2 ) { + tag = ber_scanf( ber, "{iA}", + &ld->ld_errno, &ld->ld_error ); + + } else { + ber_len_t len; + + tag = ber_scanf( ber, "{iAA" /*}*/, + &ld->ld_errno, &ld->ld_matched, &ld->ld_error ); + + if( tag != LBER_ERROR ) { + /* peek for referrals */ + if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) { + tag = ber_scanf( ber, "v", &ld->ld_referrals ); + } + } + + /* need to clean out misc items */ + if( tag != LBER_ERROR ) { + if( lm->lm_msgtype == LDAP_RES_BIND ) { + /* look for sasl result credentials */ + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { + /* skip 'em */ + tag = ber_scanf( ber, "x" ); + } + + } else if( lm->lm_msgtype == LDAP_RES_EXTENDED ) { + /* look for exop result oid or value */ + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { + /* skip 'em */ + tag = ber_scanf( ber, "x" ); + } + + if ( tag != LBER_ERROR && + ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) + { + /* skip 'em */ + tag = ber_scanf( ber, "x" ); + } + } + } + + if( tag != LBER_ERROR ) { + int rc = ldap_pvt_get_controls( ber, serverctrls ); + + if( rc != LDAP_SUCCESS ) { + tag = LBER_ERROR; + } + } + + if( tag != LBER_ERROR ) { + tag = ber_scanf( ber, /*{*/"}" ); + } + } + + if ( tag == LBER_ERROR ) { + ld->ld_errno = errcode = LDAP_DECODING_ERROR; + } + + if( ber != NULL ) { + ber_free( ber, 0 ); + } + + /* return */ + if( errcodep != NULL ) { + *errcodep = ld->ld_errno; + } + if ( errcode == LDAP_SUCCESS ) { + if( matcheddnp != NULL ) { + if ( ld->ld_matched ) + { + *matcheddnp = LDAP_STRDUP( ld->ld_matched ); + } + } + if( errmsgp != NULL ) { + if ( ld->ld_error ) + { + *errmsgp = LDAP_STRDUP( ld->ld_error ); + } + } + + if( referralsp != NULL) { + *referralsp = ldap_value_dup( ld->ld_referrals ); + } + } + LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); + +done: + if ( freeit ) { + ldap_msgfree( r ); + } + + return errcode; +} diff --git a/libs/ldap/libldap/extended.c b/libs/ldap/libldap/extended.c new file mode 100644 index 00000000000..c9f3e716697 --- /dev/null +++ b/libs/ldap/libldap/extended.c @@ -0,0 +1,418 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" +#include "ldap_log.h" + +BerElement * +ldap_build_extended_req( + LDAP *ld, + LDAP_CONST char *reqoid, + struct berval *reqdata, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp ) +{ + BerElement *ber; + int rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID( ld, *msgidp ); + if ( reqdata != NULL ) { + rc = ber_printf( ber, "{it{tstON}", /* '}' */ + *msgidp, LDAP_REQ_EXTENDED, + LDAP_TAG_EXOP_REQ_OID, reqoid, + LDAP_TAG_EXOP_REQ_VALUE, reqdata ); + + } else { + rc = ber_printf( ber, "{it{tsN}", /* '}' */ + *msgidp, LDAP_REQ_EXTENDED, + LDAP_TAG_EXOP_REQ_OID, reqoid ); + } + + if( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * LDAPv3 Extended Operation Request + * ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + * requestName [0] LDAPOID, + * requestValue [1] OCTET STRING OPTIONAL + * } + * + * LDAPv3 Extended Operation Response + * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + * COMPONENTS OF LDAPResult, + * responseName [10] LDAPOID OPTIONAL, + * response [11] OCTET STRING OPTIONAL + * } + * + * (Source RFC 4511) + */ + +int +ldap_extended_operation( + LDAP *ld, + LDAP_CONST char *reqoid, + struct berval *reqdata, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( reqoid != NULL && *reqoid != '\0' ); + assert( msgidp != NULL ); + + /* must be version 3 (or greater) */ + if ( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return( ld->ld_errno ); + } + + ber = ldap_build_extended_req( ld, reqoid, reqdata, + sctrls, cctrls, &id ); + if ( !ber ) + return( ld->ld_errno ); + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id ); + + return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); +} + +int +ldap_extended_operation_s( + LDAP *ld, + LDAP_CONST char *reqoid, + struct berval *reqdata, + LDAPControl **sctrls, + LDAPControl **cctrls, + char **retoidp, + struct berval **retdatap ) +{ + int rc; + int msgid; + LDAPMessage *res; + + Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( reqoid != NULL && *reqoid != '\0' ); + + rc = ldap_extended_operation( ld, reqoid, reqdata, + sctrls, cctrls, &msgid ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) { + return( ld->ld_errno ); + } + + if ( retoidp != NULL ) *retoidp = NULL; + if ( retdatap != NULL ) *retdatap = NULL; + + rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 ); + + if( rc != LDAP_SUCCESS ) { + ldap_msgfree( res ); + return rc; + } + + return( ldap_result2error( ld, res, 1 ) ); +} + +/* Parse an extended result */ +int +ldap_parse_extended_result ( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + int freeit ) +{ + BerElement *ber; + ber_tag_t rc; + ber_tag_t tag; + ber_len_t len; + struct berval *resdata; + ber_int_t errcode; + char *resoid; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( res != NULL ); + + Debug0( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n" ); + + if( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + if( res->lm_msgtype != LDAP_RES_EXTENDED ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + if( retoidp != NULL ) *retoidp = NULL; + if( retdatap != NULL ) *retdatap = NULL; + + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + + if ( ld->ld_matched ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + ber = ber_dup( res->lm_ber ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + rc = ber_scanf( ber, "{eAA" /*}*/, &errcode, + &ld->ld_matched, &ld->ld_error ); + + if( rc == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + resoid = NULL; + resdata = NULL; + + tag = ber_peek_tag( ber, &len ); + + if( tag == LDAP_TAG_REFERRAL ) { + /* skip over referral */ + if( ber_scanf( ber, "x" ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LDAP_TAG_EXOP_RES_OID ) { + /* we have a resoid */ + if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + assert( resoid[ 0 ] != '\0' ); + + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LDAP_TAG_EXOP_RES_VALUE ) { + /* we have a resdata */ + if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + if( resoid != NULL ) LDAP_FREE( resoid ); + return ld->ld_errno; + } + } + + ber_free( ber, 0 ); + + if( retoidp != NULL ) { + *retoidp = resoid; + } else { + LDAP_FREE( resoid ); + } + + if( retdatap != NULL ) { + *retdatap = resdata; + } else { + ber_bvfree( resdata ); + } + + ld->ld_errno = errcode; + + if( freeit ) { + ldap_msgfree( res ); + } + + return LDAP_SUCCESS; +} + + +/* Parse an extended partial */ +int +ldap_parse_intermediate ( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + LDAPControl ***serverctrls, + int freeit ) +{ + BerElement *ber; + ber_tag_t tag; + ber_len_t len; + struct berval *resdata; + char *resoid; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( res != NULL ); + + Debug0( LDAP_DEBUG_TRACE, "ldap_parse_intermediate\n" ); + + if( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + if( res->lm_msgtype != LDAP_RES_INTERMEDIATE ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + if( retoidp != NULL ) *retoidp = NULL; + if( retdatap != NULL ) *retdatap = NULL; + if( serverctrls != NULL ) *serverctrls = NULL; + + ber = ber_dup( res->lm_ber ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_scanf( ber, "{" /*}*/ ); + + if( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + resoid = NULL; + resdata = NULL; + + tag = ber_peek_tag( ber, &len ); + + /* + * NOTE: accept intermediate and extended response tag values + * as older versions of slapd(8) incorrectly used extended + * response tags. + * Should be removed when 2.2 is moved to Historic. + */ + if( tag == LDAP_TAG_IM_RES_OID || tag == LDAP_TAG_EXOP_RES_OID ) { + /* we have a resoid */ + if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + assert( resoid[ 0 ] != '\0' ); + + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LDAP_TAG_IM_RES_VALUE || tag == LDAP_TAG_EXOP_RES_VALUE ) { + /* we have a resdata */ + if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + if( resoid != NULL ) LDAP_FREE( resoid ); + return ld->ld_errno; + } + } + + if ( serverctrls == NULL ) { + ld->ld_errno = LDAP_SUCCESS; + goto free_and_return; + } + + if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + goto free_and_return; + } + + ld->ld_errno = ldap_pvt_get_controls( ber, serverctrls ); + +free_and_return: + ber_free( ber, 0 ); + + if( retoidp != NULL ) { + *retoidp = resoid; + } else { + LDAP_FREE( resoid ); + } + + if( retdatap != NULL ) { + *retdatap = resdata; + } else { + ber_bvfree( resdata ); + } + + if( freeit ) { + ldap_msgfree( res ); + } + + return ld->ld_errno; +} diff --git a/libs/ldap/libldap/fetch.c b/libs/ldap/libldap/fetch.c new file mode 100644 index 00000000000..536871bcfe3 --- /dev/null +++ b/libs/ldap/libldap/fetch.c @@ -0,0 +1,148 @@ +/* fetch.c - routines for fetching data at URLs */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1999-2022 The OpenLDAP Foundation. + * Portions Copyright 1999-2003 Kurt D. Zeilenga. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* This work was initially developed by Kurt D. Zeilenga for + * inclusion in OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/string.h> +#include <ac/socket.h> +#include <ac/time.h> + +#ifdef HAVE_FETCH +#include <fetch.h> +#endif + +#include "lber_pvt.h" +#include "ldap_pvt.h" +#include "ldap_config.h" +#include "ldif.h" + +FILE * +ldif_open_url( + LDAP_CONST char *urlstr ) +{ + FILE *url; + + if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) { + char *p; + urlstr += sizeof("file:")-1; + + /* we don't check for LDAP_DIRSEP since URLs should contain '/' */ + if ( urlstr[0] == '/' && urlstr[1] == '/' ) { + urlstr += 2; + /* path must be absolute if authority is present + * technically, file://hostname/path is also legal but we don't + * accept a non-empty hostname + */ + if ( urlstr[0] != '/' ) { +#ifdef _WIN32 + /* An absolute path in improper file://C:/foo/bar format */ + if ( urlstr[1] != ':' ) +#endif + return NULL; + } +#ifdef _WIN32 + /* An absolute path in proper file:///C:/foo/bar format */ + if ( urlstr[2] == ':' ) + urlstr++; +#endif + } + + p = ber_strdup( urlstr ); + if ( p == NULL ) + return NULL; + + /* But we should convert to LDAP_DIRSEP before use */ + if ( LDAP_DIRSEP[0] != '/' ) { + char *s = p; + while (( s = strchr( s, '/' ))) + *s++ = LDAP_DIRSEP[0]; + } + + ldap_pvt_hex_unescape( p ); + + url = fopen( p, "rb" ); + + ber_memfree( p ); + } else { +#ifdef HAVE_FETCH + url = fetchGetURL( (char*) urlstr, "" ); +#else + url = NULL; +#endif + } + return url; +} + +int +ldif_fetch_url( + LDAP_CONST char *urlstr, + char **valuep, + ber_len_t *vlenp ) +{ + FILE *url; + char buffer[1024]; + char *p = NULL; + size_t total; + size_t bytes; + + *valuep = NULL; + *vlenp = 0; + + url = ldif_open_url( urlstr ); + + if( url == NULL ) { + return -1; + } + + total = 0; + + while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) { + char *newp = ber_memrealloc( p, total + bytes + 1 ); + if( newp == NULL ) { + ber_memfree( p ); + fclose( url ); + return -1; + } + p = newp; + AC_MEMCPY( &p[total], buffer, bytes ); + total += bytes; + } + + fclose( url ); + + if( total == 0 ) { + char *newp = ber_memrealloc( p, 1 ); + if( newp == NULL ) { + ber_memfree( p ); + return -1; + } + p = newp; + } + + p[total] = '\0'; + *valuep = p; + *vlenp = total; + + return 0; +} diff --git a/libs/ldap/libldap/filter.c b/libs/ldap/libldap/filter.c new file mode 100644 index 00000000000..5eb54583b58 --- /dev/null +++ b/libs/ldap/libldap/filter.c @@ -0,0 +1,1114 @@ +/* search.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +static int put_simple_vrFilter LDAP_P(( + BerElement *ber, + char *str )); + +static int put_vrFilter_list LDAP_P(( + BerElement *ber, + char *str )); + +static char *put_complex_filter LDAP_P(( + BerElement *ber, + char *str, + ber_tag_t tag, + int not )); + +static int put_simple_filter LDAP_P(( + BerElement *ber, + char *str )); + +static int put_substring_filter LDAP_P(( + BerElement *ber, + char *type, + char *str, + char *nextstar )); + +static int put_filter_list LDAP_P(( + BerElement *ber, + char *str, + ber_tag_t tag )); + +static int ldap_is_oid ( const char *str ) +{ + int i; + + if( LDAP_ALPHA( str[0] )) { + for( i=1; str[i]; i++ ) { + if( !LDAP_LDH( str[i] )) { + return 0; + } + } + return 1; + + } else if LDAP_DIGIT( str[0] ) { + int dot=0; + for( i=1; str[i]; i++ ) { + if( LDAP_DIGIT( str[i] )) { + dot=0; + + } else if ( str[i] == '.' ) { + if( ++dot > 1 ) return 0; + + } else { + return 0; + } + } + return !dot; + } + + return 0; +} + +static int ldap_is_desc ( const char *str ) +{ + int i; + + if( LDAP_ALPHA( str[0] )) { + for( i=1; str[i]; i++ ) { + if( str[i] == ';' ) { + str = &str[i+1]; + goto options; + } + + if( !LDAP_LDH( str[i] )) { + return 0; + } + } + return 1; + + } else if LDAP_DIGIT( str[0] ) { + int dot=0; + for( i=1; str[i]; i++ ) { + if( str[i] == ';' ) { + if( dot ) return 0; + str = &str[i+1]; + goto options; + } + + if( LDAP_DIGIT( str[i] )) { + dot=0; + + } else if ( str[i] == '.' ) { + if( ++dot > 1 ) return 0; + + } else { + return 0; + } + } + return !dot; + } + + return 0; + +options: + if( !LDAP_LDH( str[0] )) { + return 0; + } + for( i=1; str[i]; i++ ) { + if( str[i] == ';' ) { + str = &str[i+1]; + goto options; + } + if( !LDAP_LDH( str[i] )) { + return 0; + } + } + return 1; +} + +static char * +find_right_paren( char *s ) +{ + int balance, escape; + + balance = 1; + escape = 0; + while ( *s && balance ) { + if ( !escape ) { + if ( *s == '(' ) { + balance++; + } else if ( *s == ')' ) { + balance--; + } + } + + escape = ( *s == '\' && !escape ); + + if ( balance ) s++; + } + + return *s ? s : NULL; +} + +static int hex2value( int c ) +{ + if( c >= '0' && c <= '9' ) { + return c - '0'; + } + + if( c >= 'A' && c <= 'F' ) { + return c + (10 - (int) 'A'); + } + + if( c >= 'a' && c <= 'f' ) { + return c + (10 - (int) 'a'); + } + + return -1; +} + +char * +ldap_pvt_find_wildcard( const char *s ) +{ + for( ; *s; s++ ) { + switch( *s ) { + case '*': /* found wildcard */ + return (char *) s; + + case '(': + case ')': + return NULL; + + case '\': + if( s[1] == '\0' ) return NULL; + + if( LDAP_HEX( s[1] ) && LDAP_HEX( s[2] ) ) { + s+=2; + + } else switch( s[1] ) { + default: + return NULL; + + /* allow RFC 1960 escapes */ + case '*': + case '(': + case ')': + case '\': + s++; + } + } + } + + return (char *) s; +} + +/* unescape filter value */ +/* support both LDAP v2 and v3 escapes */ +/* output can include nul characters! */ +ber_slen_t +ldap_pvt_filter_value_unescape( char *fval ) +{ + ber_slen_t r, v; + int v1, v2; + + for( r=v=0; fval[v] != '\0'; v++ ) { + switch( fval[v] ) { + case '(': + case ')': + case '*': + return -1; + + case '\': + /* escape */ + v++; + + if ( fval[v] == '\0' ) { + /* escape at end of string */ + return -1; + } + + if (( v1 = hex2value( fval[v] )) >= 0 ) { + /* LDAPv3 escape */ + if (( v2 = hex2value( fval[v+1] )) < 0 ) { + /* must be two digit code */ + return -1; + } + + fval[r++] = v1 * 16 + v2; + v++; + + } else { + /* LDAPv2 escape */ + switch( fval[v] ) { + case '(': + case ')': + case '*': + case '\': + fval[r++] = fval[v]; + break; + default: + /* illegal escape */ + return -1; + } + } + break; + + default: + fval[r++] = fval[v]; + } + } + + fval[r] = '\0'; + return r; +} + +static char * +put_complex_filter( BerElement *ber, char *str, ber_tag_t 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, tag ) == -1 ) { + return NULL; + } + + /* close the '(' */ + *next++ = ')'; + + /* flush explicit tagged thang */ + if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) { + return NULL; + } + + return next; +} + +int +ldap_pvt_put_filter( BerElement *ber, const char *str_in ) +{ + int rc; + char *freeme; + char *str; + char *next; + int parens, balance, escape; + + /* + * A Filter looks like this (RFC 4511 as extended by RFC 4526): + * Filter ::= CHOICE { + * and [0] SET SIZE (0..MAX) OF filter Filter, + * or [1] SET SIZE (0..MAX) OF filter Filter, + * not [2] Filter, + * equalityMatch [3] AttributeValueAssertion, + * substrings [4] SubstringFilter, + * greaterOrEqual [5] AttributeValueAssertion, + * lessOrEqual [6] AttributeValueAssertion, + * present [7] AttributeDescription, + * approxMatch [8] AttributeValueAssertion, + * extensibleMatch [9] MatchingRuleAssertion, + * ... } + * + * SubstringFilter ::= SEQUENCE { + * type AttributeDescription, + * substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE { + * initial [0] AssertionValue, -- only once + * any [1] AssertionValue, + * final [2] AssertionValue -- only once + * } + * } + * + * MatchingRuleAssertion ::= SEQUENCE { + * matchingRule [1] MatchingRuleId OPTIONAL, + * type [2] AttributeDescription OPTIONAL, + * matchValue [3] AssertionValue, + * dnAttributes [4] BOOLEAN DEFAULT FALSE } + * + * Note: tags in a CHOICE are always explicit + */ + + Debug1( LDAP_DEBUG_TRACE, "put_filter: "%s"\n", str_in ); + + freeme = LDAP_STRDUP( str_in ); + if( freeme == NULL ) return LDAP_NO_MEMORY; + str = freeme; + + parens = 0; + while ( *str ) { + switch ( *str ) { + case '(': /*')'*/ + str++; + parens++; + + /* skip spaces */ + while( LDAP_SPACE( *str ) ) str++; + + switch ( *str ) { + case '&': + Debug0( LDAP_DEBUG_TRACE, "put_filter: AND\n" ); + + str = put_complex_filter( ber, str, + LDAP_FILTER_AND, 0 ); + if( str == NULL ) { + rc = -1; + goto done; + } + + parens--; + break; + + case '|': + Debug0( LDAP_DEBUG_TRACE, "put_filter: OR\n" ); + + str = put_complex_filter( ber, str, + LDAP_FILTER_OR, 0 ); + if( str == NULL ) { + rc = -1; + goto done; + } + + parens--; + break; + + case '!': + Debug0( LDAP_DEBUG_TRACE, "put_filter: NOT\n" ); + + str = put_complex_filter( ber, str, + LDAP_FILTER_NOT, 0 ); + if( str == NULL ) { + rc = -1; + goto done; + } + + parens--; + break; + + case '(': + rc = -1; + goto done; + + default: + Debug0( LDAP_DEBUG_TRACE, "put_filter: simple\n" ); + + 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 ) { + rc = -1; + goto done; + } + + *next = '\0'; + + if ( put_simple_filter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + + *next++ = /*'('*/ ')'; + + str = next; + parens--; + break; + } + break; + + case /*'('*/ ')': + Debug0( LDAP_DEBUG_TRACE, "put_filter: end\n" ); + if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { + rc = -1; + goto done; + } + str++; + parens--; + break; + + case ' ': + str++; + break; + + default: /* assume it's a simple type=value filter */ + Debug0( LDAP_DEBUG_TRACE, "put_filter: default\n" ); + next = strchr( str, '\0' ); + if ( put_simple_filter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + str = next; + break; + } + if ( !parens ) + break; + } + + rc = ( parens || *str ) ? -1 : 0; + +done: + LDAP_FREE( freeme ); + return rc; +} + +/* + * Put a list of filters like this "(filter1)(filter2)..." + */ + +static int +put_filter_list( BerElement *ber, char *str, ber_tag_t tag ) +{ + char *next = NULL; + char save; + + Debug1( LDAP_DEBUG_TRACE, "put_filter_list "%s"\n", + str ); + + while ( *str ) { + while ( *str && LDAP_SPACE( (unsigned char) *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 ( ldap_pvt_put_filter( ber, str ) == -1 ) return -1; + *next = save; + str = next; + + if( tag == LDAP_FILTER_NOT ) break; + } + + if( tag == LDAP_FILTER_NOT && ( next == NULL || *str )) { + return -1; + } + + return 0; +} + +static int +put_simple_filter( + BerElement *ber, + char *str ) +{ + char *s; + char *value; + ber_tag_t ftype; + int rc = -1; + + Debug1( LDAP_DEBUG_TRACE, "put_simple_filter: "%s"\n", + str ); + + str = LDAP_STRDUP( str ); + if( str == NULL ) return -1; + + if ( (s = strchr( str, '=' )) == NULL ) { + goto done; + } + + value = s + 1; + *s-- = '\0'; + + switch ( *s ) { + case '<': + ftype = LDAP_FILTER_LE; + *s = '\0'; + break; + + case '>': + ftype = LDAP_FILTER_GE; + *s = '\0'; + break; + + case '~': + ftype = LDAP_FILTER_APPROX; + *s = '\0'; + break; + + case ':': + /* RFC 4515 extensible filters are off the form: + * type [:dn] [:rule] := value + * or [:dn]:rule := value + */ + ftype = LDAP_FILTER_EXT; + *s = '\0'; + + { + char *dn = strchr( str, ':' ); + char *rule = NULL; + + if( dn != NULL ) { + *dn++ = '\0'; + rule = strchr( dn, ':' ); + + if( rule == NULL ) { + /* one colon */ + if ( strcasecmp(dn, "dn") == 0 ) { + /* must have attribute */ + if( !ldap_is_desc( str ) ) { + goto done; + } + + rule = ""; + + } else { + rule = dn; + dn = NULL; + } + + } else { + /* two colons */ + *rule++ = '\0'; + + if ( strcasecmp(dn, "dn") != 0 ) { + /* must have "dn" */ + goto done; + } + } + + } + + if ( *str == '\0' && ( !rule || *rule == '\0' ) ) { + /* must have either type or rule */ + goto done; + } + + if ( *str != '\0' && !ldap_is_desc( str ) ) { + goto done; + } + + if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) { + goto done; + } + + rc = ber_printf( ber, "t{" /*"}"*/, ftype ); + + if( rc != -1 && rule && *rule != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule ); + } + + if( rc != -1 && *str != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str ); + } + + if( rc != -1 ) { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "to", + LDAP_FILTER_EXT_VALUE, value, len ); + } else { + rc = -1; + } + } + + if( rc != -1 && dn ) { + rc = ber_printf( ber, "tb", + LDAP_FILTER_EXT_DNATTRS, (ber_int_t) 1 ); + } + + if( rc != -1 ) { + rc = ber_printf( ber, /*"{"*/ "N}" ); + } + } + goto done; + + default: + if( !ldap_is_desc( str ) ) { + goto done; + + } else { + char *nextstar = ldap_pvt_find_wildcard( value ); + + if ( nextstar == NULL ) { + goto done; + + } else if ( *nextstar == '\0' ) { + ftype = LDAP_FILTER_EQUALITY; + + } else if ( strcmp( value, "*" ) == 0 ) { + ftype = LDAP_FILTER_PRESENT; + + } else { + rc = put_substring_filter( ber, str, value, nextstar ); + goto done; + } + } break; + } + + if( !ldap_is_desc( str ) ) goto done; + + if ( ftype == LDAP_FILTER_PRESENT ) { + rc = ber_printf( ber, "ts", ftype, str ); + + } else { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "t{soN}", + ftype, str, value, len ); + } + } + +done: + if( rc != -1 ) rc = 0; + LDAP_FREE( str ); + return rc; +} + +static int +put_substring_filter( BerElement *ber, char *type, char *val, char *nextstar ) +{ + int gotstar = 0; + ber_tag_t ftype = LDAP_FILTER_SUBSTRINGS; + + Debug2( LDAP_DEBUG_TRACE, "put_substring_filter "%s=%s"\n", + type, val ); + + if ( ber_printf( ber, "t{s{" /*"}}"*/, ftype, type ) == -1 ) { + return -1; + } + + for( ; *val; val=nextstar ) { + if ( gotstar ) + nextstar = ldap_pvt_find_wildcard( val ); + + if ( nextstar == NULL ) { + return -1; + } + + if ( *nextstar == '\0' ) { + ftype = LDAP_SUBSTRING_FINAL; + } else { + *nextstar++ = '\0'; + if ( gotstar++ == 0 ) { + ftype = LDAP_SUBSTRING_INITIAL; + } else { + ftype = LDAP_SUBSTRING_ANY; + } + } + + if ( *val != '\0' || ftype == LDAP_SUBSTRING_ANY ) { + ber_slen_t len = ldap_pvt_filter_value_unescape( val ); + + if ( len <= 0 ) { + return -1; + } + + if ( ber_printf( ber, "to", ftype, val, len ) == -1 ) { + return -1; + } + } + } + + if ( ber_printf( ber, /*"{{"*/ "N}N}" ) == -1 ) { + return -1; + } + + return 0; +} + +static int +put_vrFilter( BerElement *ber, const char *str_in ) +{ + int rc; + char *freeme; + char *str; + char *next; + int parens, balance, escape; + + /* + * A ValuesReturnFilter looks like this: + * + * ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem + * SimpleFilterItem ::= CHOICE { + * equalityMatch [3] AttributeValueAssertion, + * substrings [4] SubstringFilter, + * greaterOrEqual [5] AttributeValueAssertion, + * lessOrEqual [6] AttributeValueAssertion, + * present [7] AttributeType, + * approxMatch [8] AttributeValueAssertion, + * extensibleMatch [9] SimpleMatchingAssertion -- LDAPv3 + * } + * + * SubstringFilter ::= SEQUENCE { + * type AttributeType, + * SEQUENCE OF CHOICE { + * initial [0] IA5String, + * any [1] IA5String, + * final [2] IA5String + * } + * } + * + * SimpleMatchingAssertion ::= SEQUENCE { -- LDAPv3 + * matchingRule [1] MatchingRuleId OPTIONAL, + * type [2] AttributeDescription OPTIONAL, + * matchValue [3] AssertionValue } + * + * (Source: RFC 3876) + */ + + Debug1( LDAP_DEBUG_TRACE, "put_vrFilter: "%s"\n", str_in ); + + freeme = LDAP_STRDUP( str_in ); + if( freeme == NULL ) return LDAP_NO_MEMORY; + str = freeme; + + parens = 0; + while ( *str ) { + switch ( *str ) { + case '(': /*')'*/ + str++; + parens++; + + /* skip spaces */ + while( LDAP_SPACE( *str ) ) str++; + + switch ( *str ) { + case '(': + if ( (next = find_right_paren( str )) == NULL ) { + rc = -1; + goto done; + } + + *next = '\0'; + + if ( put_vrFilter_list( ber, str ) == -1 ) { + rc = -1; + goto done; + } + + /* close the '(' */ + *next++ = ')'; + + str = next; + + parens--; + break; + + + default: + Debug0( LDAP_DEBUG_TRACE, "put_vrFilter: simple\n" ); + + 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 ) { + rc = -1; + goto done; + } + + *next = '\0'; + + if ( put_simple_vrFilter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + + *next++ = /*'('*/ ')'; + + str = next; + parens--; + break; + } + break; + + case /*'('*/ ')': + Debug0( LDAP_DEBUG_TRACE, "put_vrFilter: end\n" ); + if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { + rc = -1; + goto done; + } + str++; + parens--; + break; + + case ' ': + str++; + break; + + default: /* assume it's a simple type=value filter */ + Debug0( LDAP_DEBUG_TRACE, "put_vrFilter: default\n" ); + next = strchr( str, '\0' ); + if ( put_simple_vrFilter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + str = next; + break; + } + } + + rc = parens ? -1 : 0; + +done: + LDAP_FREE( freeme ); + return rc; +} + +int +ldap_put_vrFilter( BerElement *ber, const char *str_in ) +{ + int rc =0; + + if ( ber_printf( ber, "{" /*"}"*/ ) == -1 ) { + return -1; + } + + rc = put_vrFilter( ber, str_in ); + + if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) { + rc = -1; + } + + return rc; +} + +static int +put_vrFilter_list( BerElement *ber, char *str ) +{ + char *next = NULL; + char save; + + Debug1( LDAP_DEBUG_TRACE, "put_vrFilter_list "%s"\n", + str ); + + while ( *str ) { + while ( *str && LDAP_SPACE( (unsigned char) *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_vrFilter( ber, str ) == -1 ) return -1; + *next = save; + str = next; + } + + return 0; +} + +static int +put_simple_vrFilter( + BerElement *ber, + char *str ) +{ + char *s; + char *value; + ber_tag_t ftype; + int rc = -1; + + Debug1( LDAP_DEBUG_TRACE, "put_simple_vrFilter: "%s"\n", + str ); + + str = LDAP_STRDUP( str ); + if( str == NULL ) return -1; + + if ( (s = strchr( str, '=' )) == NULL ) { + goto done; + } + + value = s + 1; + *s-- = '\0'; + + switch ( *s ) { + case '<': + ftype = LDAP_FILTER_LE; + *s = '\0'; + break; + + case '>': + ftype = LDAP_FILTER_GE; + *s = '\0'; + break; + + case '~': + ftype = LDAP_FILTER_APPROX; + *s = '\0'; + break; + + case ':': + /* According to ValuesReturnFilter control definition + * extensible filters are off the form: + * type [:rule] := value + * or :rule := value + */ + ftype = LDAP_FILTER_EXT; + *s = '\0'; + + { + char *rule = strchr( str, ':' ); + + if( rule == NULL ) { + /* must have attribute */ + if( !ldap_is_desc( str ) ) { + goto done; + } + rule = ""; + } else { + *rule++ = '\0'; + } + + if ( *str == '\0' && ( !rule || *rule == '\0' ) ) { + /* must have either type or rule */ + goto done; + } + + if ( *str != '\0' && !ldap_is_desc( str ) ) { + goto done; + } + + if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) { + goto done; + } + + rc = ber_printf( ber, "t{" /*"}"*/, ftype ); + + if( rc != -1 && rule && *rule != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule ); + } + + if( rc != -1 && *str != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str ); + } + + if( rc != -1 ) { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "to", + LDAP_FILTER_EXT_VALUE, value, len ); + } else { + rc = -1; + } + } + + if( rc != -1 ) { + rc = ber_printf( ber, /*"{"*/ "N}" ); + } + } + goto done; + + default: + if( !ldap_is_desc( str ) ) { + goto done; + + } else { + char *nextstar = ldap_pvt_find_wildcard( value ); + + if ( nextstar == NULL ) { + goto done; + + } else if ( *nextstar == '\0' ) { + ftype = LDAP_FILTER_EQUALITY; + + } else if ( strcmp( value, "*" ) == 0 ) { + ftype = LDAP_FILTER_PRESENT; + + } else { + rc = put_substring_filter( ber, str, value, nextstar ); + goto done; + } + } break; + } + + if( !ldap_is_desc( str ) ) goto done; + + if ( ftype == LDAP_FILTER_PRESENT ) { + rc = ber_printf( ber, "ts", ftype, str ); + + } else { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "t{soN}", + ftype, str, value, len ); + } + } + +done: + if( rc != -1 ) rc = 0; + LDAP_FREE( str ); + return rc; +} diff --git a/libs/ldap/libldap/free.c b/libs/ldap/libldap/free.c new file mode 100644 index 00000000000..4d09eeef452 --- /dev/null +++ b/libs/ldap/libldap/free.c @@ -0,0 +1,107 @@ +/* free.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions 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 + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* + * C-API deallocator + */ +void +ldap_memfree( void *p ) +{ + LDAP_FREE( p ); +} + +void +ldap_memvfree( void **v ) +{ + LDAP_VFREE( v ); +} + +void * +ldap_memalloc( ber_len_t s ) +{ + return LDAP_MALLOC( s ); +} + +void * +ldap_memcalloc( ber_len_t n, ber_len_t s ) +{ + return LDAP_CALLOC( n, s ); +} + +void * +ldap_memrealloc( void* p, ber_len_t s ) +{ + return LDAP_REALLOC( p, s ); +} + +char * +ldap_strdup( LDAP_CONST char *p ) +{ + return LDAP_STRDUP( p ); +} + +/* + * 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_mods_free( LDAPMod **mods, int freemods ) +{ + int i; + + if ( mods == NULL ) + 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_VFREE( mods[i]->mod_values ); + } + + if ( mods[i]->mod_type != NULL ) { + LDAP_FREE( mods[i]->mod_type ); + } + + LDAP_FREE( (char *) mods[i] ); + } + + if ( freemods ) { + LDAP_FREE( (char *) mods ); + } +} diff --git a/libs/ldap/libldap/getattr.c b/libs/ldap/libldap/getattr.c new file mode 100644 index 00000000000..0306e8b5a28 --- /dev/null +++ b/libs/ldap/libldap/getattr.c @@ -0,0 +1,157 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +char * +ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berout ) +{ + int rc; + ber_tag_t tag; + ber_len_t len = 0; + char *attr; + BerElement *ber; + + Debug0( LDAP_DEBUG_TRACE, "ldap_first_attribute\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( berout != NULL ); + + *berout = NULL; + + ber = ldap_alloc_ber_with_options( ld ); + if( ber == NULL ) { + return NULL; + } + + *ber = *entry->lm_ber; + + /* + * Skip past the sequence, dn, sequence of sequence leaving + * us at the first attribute. + */ + + tag = ber_scanf( ber, "{xl{" /*}}*/, &len ); + if( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return NULL; + } + + /* set the length to avoid overrun */ + rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); + if( rc != LBER_OPT_SUCCESS ) { + ld->ld_errno = LDAP_LOCAL_ERROR; + ber_free( ber, 0 ); + return NULL; + } + + if ( ber_pvt_ber_remaining( ber ) == 0 ) { + assert( len == 0 ); + ber_free( ber, 0 ); + return NULL; + } + assert( len != 0 ); + + /* snatch the first attribute */ + tag = ber_scanf( ber, "{ax}", &attr ); + if( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return NULL; + } + + *berout = ber; + return attr; +} + +/* ARGSUSED */ +char * +ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) +{ + ber_tag_t tag; + char *attr; + + Debug0( LDAP_DEBUG_TRACE, "ldap_next_attribute\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( ber != NULL ); + + if ( ber_pvt_ber_remaining( ber ) == 0 ) { + return NULL; + } + + /* skip sequence, snarf attribute type, skip values */ + tag = ber_scanf( ber, "{ax}", &attr ); + if( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return NULL; + } + + return attr; +} + +/* Fetch attribute type and optionally fetch values. The type + * and values are referenced in-place from the BerElement, they are + * not dup'd into malloc'd memory. + */ +/* ARGSUSED */ +int +ldap_get_attribute_ber( LDAP *ld, LDAPMessage *entry, BerElement *ber, + BerValue *attr, BerVarray *vals ) +{ + ber_tag_t tag; + int rc = LDAP_SUCCESS; + + Debug0( LDAP_DEBUG_TRACE, "ldap_get_attribute_ber\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( ber != NULL ); + assert( attr != NULL ); + + attr->bv_val = NULL; + attr->bv_len = 0; + + if ( ber_pvt_ber_remaining( ber ) ) { + ber_len_t siz = sizeof( BerValue ); + + /* skip sequence, snarf attribute type */ + tag = ber_scanf( ber, vals ? "{mM}" : "{mx}", attr, vals, + &siz, (ber_len_t)0 ); + if( tag == LBER_ERROR ) { + rc = ld->ld_errno = LDAP_DECODING_ERROR; + } + } + + return rc; +} diff --git a/libs/ldap/libldap/getdn.c b/libs/ldap/libldap/getdn.c new file mode 100644 index 00000000000..671371f86f2 --- /dev/null +++ b/libs/ldap/libldap/getdn.c @@ -0,0 +1,3333 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1994 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" +#include "ldap_schema.h" +#include "ldif.h" + +/* extension to UFN that turns trailing "dc=value" rdns in DNS style, + * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */ +#define DC_IN_UFN + +/* parsing/printing routines */ +static int str2strval( const char *str, ber_len_t stoplen, struct berval *val, + const char **next, unsigned flags, int *retFlags, void *ctx ); +static int DCE2strval( const char *str, struct berval *val, + const char **next, unsigned flags, void *ctx ); +static int IA52strval( const char *str, struct berval *val, + const char **next, unsigned flags, void *ctx ); +static int quotedIA52strval( const char *str, struct berval *val, + const char **next, unsigned flags, void *ctx ); +static int hexstr2binval( const char *str, struct berval *val, + const char **next, unsigned flags, void *ctx ); +static int hexstr2bin( const char *str, char *c ); +static int byte2hexpair( const char *val, char *pair ); +static int binval2hexstr( struct berval *val, char *str ); +static int strval2strlen( struct berval *val, unsigned flags, + ber_len_t *len ); +static int strval2str( struct berval *val, char *str, unsigned flags, + ber_len_t *len ); +static int strval2IA5strlen( struct berval *val, unsigned flags, + ber_len_t *len ); +static int strval2IA5str( struct berval *val, char *str, unsigned flags, + ber_len_t *len ); +static int strval2DCEstrlen( struct berval *val, unsigned flags, + ber_len_t *len ); +static int strval2DCEstr( struct berval *val, char *str, unsigned flags, + ber_len_t *len ); +static int strval2ADstrlen( struct berval *val, unsigned flags, + ber_len_t *len ); +static int strval2ADstr( struct berval *val, char *str, unsigned flags, + ber_len_t *len ); +static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ); + +/* AVA helpers */ +static LDAPAVA * ldapava_new( + const struct berval *attr, const struct berval *val, unsigned flags, void *ctx ); + +/* Higher level helpers */ +static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, + int ( *s2l )( struct berval *, unsigned, ber_len_t * ) ); +static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, + int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * )); +static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ); +static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first ); +static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ); + +/* + * RFC 1823 ldap_get_dn + */ +char * +ldap_get_dn( LDAP *ld, LDAPMessage *entry ) +{ + char *dn; + BerElement tmp; + + Debug0( LDAP_DEBUG_TRACE, "ldap_get_dn\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID(ld) ); + assert( entry != NULL ); + + tmp = *entry->lm_ber; /* struct copy */ + if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + return( dn ); +} + +int +ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout, + BerValue *dn ) +{ + BerElement tmp, *ber; + ber_len_t len = 0; + int rc = LDAP_SUCCESS; + + Debug0( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID(ld) ); + assert( entry != NULL ); + assert( dn != NULL ); + + dn->bv_val = NULL; + dn->bv_len = 0; + + if ( berout ) { + *berout = NULL; + ber = ldap_alloc_ber_with_options( ld ); + if( ber == NULL ) { + return LDAP_NO_MEMORY; + } + *berout = ber; + } else { + ber = &tmp; + } + + *ber = *entry->lm_ber; /* struct copy */ + if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) { + rc = ld->ld_errno = LDAP_DECODING_ERROR; + } + if ( rc == LDAP_SUCCESS ) { + /* set the length to avoid overrun */ + rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); + if( rc != LBER_OPT_SUCCESS ) { + rc = ld->ld_errno = LDAP_LOCAL_ERROR; + } + } + if ( rc != LDAP_SUCCESS && berout ) { + ber_free( ber, 0 ); + *berout = NULL; + } + return rc; +} + +/* + * RFC 1823 ldap_dn2ufn + */ +char * +ldap_dn2ufn( LDAP_CONST char *dn ) +{ + char *out = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n" ); + + ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, + &out, LDAP_DN_FORMAT_UFN ); + + return( out ); +} + +/* + * RFC 1823 ldap_explode_dn + */ +char ** +ldap_explode_dn( LDAP_CONST char *dn, int notypes ) +{ + LDAPDN tmpDN; + char **values = NULL; + int iRDN; + unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3; + + Debug0( LDAP_DEBUG_TRACE, "ldap_explode_dn\n" ); + + if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP ) + != LDAP_SUCCESS ) { + return NULL; + } + + if( tmpDN == NULL ) { + values = LDAP_MALLOC( sizeof( char * ) ); + if( values == NULL ) return NULL; + + values[0] = NULL; + return values; + } + + for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ); + + values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) ); + if ( values == NULL ) { + ldap_dnfree( tmpDN ); + return NULL; + } + + for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) { + ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag ); + } + ldap_dnfree( tmpDN ); + values[ iRDN ] = NULL; + + return values; +} + +char ** +ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) +{ + LDAPRDN tmpRDN; + char **values = NULL; + const char *p; + int iAVA; + + Debug0( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n" ); + + /* + * we only parse the first rdn + * FIXME: we prefer efficiency over checking if the _ENTIRE_ + * dn can be parsed + */ + if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP ) + != LDAP_SUCCESS ) { + return( NULL ); + } + + for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ; + values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) ); + if ( values == NULL ) { + ldap_rdnfree( tmpRDN ); + return( NULL ); + } + + for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) { + ber_len_t l = 0, vl, al = 0; + char *str; + LDAPAVA *ava = tmpRDN[ iAVA ]; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + vl = 1 + 2 * ava->la_value.bv_len; + + } else { + if ( strval2strlen( &ava->la_value, + ava->la_flags, &vl ) ) { + goto error_return; + } + } + + if ( !notypes ) { + al = ava->la_attr.bv_len; + l = vl + ava->la_attr.bv_len + 1; + + str = LDAP_MALLOC( l + 1 ); + if ( str == NULL ) { + goto error_return; + } + AC_MEMCPY( str, ava->la_attr.bv_val, + ava->la_attr.bv_len ); + str[ al++ ] = '='; + + } else { + l = vl; + str = LDAP_MALLOC( l + 1 ); + if ( str == NULL ) { + goto error_return; + } + } + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + str[ al++ ] = '#'; + if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) { + goto error_return; + } + + } else { + if ( strval2str( &ava->la_value, &str[ al ], + ava->la_flags, &vl ) ) { + goto error_return; + } + } + + str[ l ] = '\0'; + values[ iAVA ] = str; + } + values[ iAVA ] = NULL; + + ldap_rdnfree( tmpRDN ); + + return( values ); + +error_return:; + LBER_VFREE( values ); + ldap_rdnfree( tmpRDN ); + return( NULL ); +} + +char * +ldap_dn2dcedn( LDAP_CONST char *dn ) +{ + char *out = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n" ); + + ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, + &out, LDAP_DN_FORMAT_DCE ); + + return( out ); +} + +char * +ldap_dcedn2dn( LDAP_CONST char *dce ) +{ + char *out = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n" ); + + ( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 ); + + return( out ); +} + +char * +ldap_dn2ad_canonical( LDAP_CONST char *dn ) +{ + char *out = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n" ); + + ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, + &out, LDAP_DN_FORMAT_AD_CANONICAL ); + + return( out ); +} + +/* + * function that changes the string representation of dnin + * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK ) + * + * fin can be one of: + * LDAP_DN_FORMAT_LDAP (RFC 4514 liberal, plus some RFC 1779) + * LDAP_DN_FORMAT_LDAPV3 (RFC 4514) + * LDAP_DN_FORMAT_LDAPV2 (RFC 1779) + * LDAP_DN_FORMAT_DCE (?) + * + * fout can be any of the above except + * LDAP_DN_FORMAT_LDAP + * plus: + * LDAP_DN_FORMAT_UFN (RFC 1781, partial and with extensions) + * LDAP_DN_FORMAT_AD_CANONICAL (?) + */ +int +ldap_dn_normalize( LDAP_CONST char *dnin, + unsigned fin, char **dnout, unsigned fout ) +{ + int rc; + LDAPDN tmpDN = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n" ); + + assert( dnout != NULL ); + + *dnout = NULL; + + if ( dnin == NULL ) { + return( LDAP_SUCCESS ); + } + + rc = ldap_str2dn( dnin , &tmpDN, fin ); + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + rc = ldap_dn2str( tmpDN, dnout, fout ); + + ldap_dnfree( tmpDN ); + + return( rc ); +} + +/* States */ +#define B4AVA 0x0000 + +/* #define B4ATTRTYPE 0x0001 */ +#define B4OIDATTRTYPE 0x0002 +#define B4STRINGATTRTYPE 0x0003 + +#define B4AVAEQUALS 0x0100 +#define B4AVASEP 0x0200 +#define B4RDNSEP 0x0300 +#define GOTAVA 0x0400 + +#define B4ATTRVALUE 0x0010 +#define B4STRINGVALUE 0x0020 +#define B4IA5VALUEQUOTED 0x0030 +#define B4IA5VALUE 0x0040 +#define B4BINARYVALUE 0x0050 + +/* + * Helpers (mostly from slap.h) + * c is assumed to Unicode in an ASCII compatible format (UTF-8) + * Macros assume "C" Locale (ASCII) + */ +#define LDAP_DN_ASCII_SPACE(c) \ + ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' ) +#define LDAP_DN_ASCII_LOWER(c) LDAP_LOWER(c) +#define LDAP_DN_ASCII_UPPER(c) LDAP_UPPER(c) +#define LDAP_DN_ASCII_ALPHA(c) LDAP_ALPHA(c) + +#define LDAP_DN_ASCII_DIGIT(c) LDAP_DIGIT(c) +#define LDAP_DN_ASCII_LCASE_HEXALPHA(c) LDAP_HEXLOWER(c) +#define LDAP_DN_ASCII_UCASE_HEXALPHA(c) LDAP_HEXUPPER(c) +#define LDAP_DN_ASCII_HEXDIGIT(c) LDAP_HEX(c) +#define LDAP_DN_ASCII_ALNUM(c) LDAP_ALNUM(c) +#define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' ) + +/* attribute type */ +#define LDAP_DN_OID_LEADCHAR(c) LDAP_DIGIT(c) +#define LDAP_DN_DESC_LEADCHAR(c) LDAP_ALPHA(c) +#define LDAP_DN_DESC_CHAR(c) LDAP_LDH(c) +#define LDAP_DN_LANG_SEP(c) ( (c) == ';' ) +#define LDAP_DN_ATTRDESC_CHAR(c) \ + ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) ) + +/* special symbols */ +#define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' ) +#define LDAP_DN_AVA_SEP(c) ( (c) == '+' ) +#define LDAP_DN_RDN_SEP(c) ( (c) == ',' ) +#define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' ) +#define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' ) +#define LDAP_DN_QUOTES(c) ( (c) == '"' ) +#define LDAP_DN_ESCAPE(c) ( (c) == '\' ) +#define LDAP_DN_VALUE_END(c) \ + ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) ) + +/* NOTE: according to RFC 4514, '=' can be escaped and treated as special, + * i.e. escaped both as "<hexpair>" and * as "=", but it is treated as + * a regular char, i.e. it can also appear as '='. + * + * As such, in 2.2 we used to allow reading unescaped '=', but we always + * produced escaped '\3D'; this changes since 2.3, if compatibility issues + * do not arise + */ +#define LDAP_DN_NE(c) \ + ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \ + || LDAP_DN_QUOTES(c) \ + || (c) == '<' || (c) == '>' ) +#define LDAP_DN_MAYESCAPE(c) \ + ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \ + || LDAP_DN_AVA_EQUALS(c) \ + || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) ) +#define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) ) + +#define LDAP_DN_NEEDESCAPE(c) \ + ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) ) +#define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c) +#define LDAP_DN_NEEDESCAPE_TRAIL(c) \ + ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) ) +#define LDAP_DN_WILLESCAPE_CHAR(c) \ + ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) || LDAP_DN_ESCAPE(c) ) +#define LDAP_DN_IS_PRETTY(f) ( (f) & LDAP_DN_PRETTY ) +#define LDAP_DN_WILLESCAPE_HEX(f, c) \ + ( ( !LDAP_DN_IS_PRETTY( f ) ) && LDAP_DN_WILLESCAPE_CHAR(c) ) + +/* LDAPv2 */ +#define LDAP_DN_VALUE_END_V2(c) \ + ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) ) +/* RFC 1779 */ +#define LDAP_DN_V2_SPECIAL(c) \ + ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \ + || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \ + || LDAP_DN_OCTOTHORPE(c) ) +#define LDAP_DN_V2_PAIR(c) \ + ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) ) + +/* + * DCE (mostly from Luke Howard and IBM implementation for AIX) + * + * From: "Application Development Guide - Directory Services" (FIXME: add link?) + * Here escapes and valid chars for GDS are considered; as soon as more + * specific info is found, the macros will be updated. + * + * Chars: 'a'-'z', 'A'-'Z', '0'-'9', + * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '. + * + * Metachars: '/', ',', '=', ''. + * + * the '' is used to escape other metachars. + * + * Assertion: '=' + * RDN separator: '/' + * AVA separator: ',' + * + * Attribute types must start with alphabetic chars and can contain + * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed. + */ +#define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' ) +#define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' ) +#define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) ) +#define LDAP_DN_VALUE_END_DCE(c) \ + ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) ) +#define LDAP_DN_NEEDESCAPE_DCE(c) \ + ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) ) + +/* AD Canonical */ +#define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' ) +#define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) ) +#define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */ +#define LDAP_DN_VALUE_END_AD(c) \ + ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) ) +#define LDAP_DN_NEEDESCAPE_AD(c) \ + ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) ) + +/* generics */ +#define LDAP_DN_HEXPAIR(s) \ + ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) ) +/* better look at the AttributeDescription? */ + +/* FIXME: no composite rdn or non-"dc" types, right? + * (what about "dc" in OID form?) */ +/* FIXME: we do not allow binary values in domain, right? */ +/* NOTE: use this macro only when ABSOLUTELY SURE rdn IS VALID! */ +/* NOTE: don't use strcasecmp() as it is locale specific! */ +#define LDAP_DC_ATTR "dc" +#define LDAP_DC_ATTRU "DC" +#define LDAP_DN_IS_RDN_DC( r ) \ + ( (r) && (r)[0] && !(r)[1] \ + && ((r)[0]->la_flags & LDAP_AVA_STRING) \ + && ((r)[0]->la_attr.bv_len == 2) \ + && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \ + || ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \ + && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \ + || ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1]))) + +/* Composite rules */ +#define LDAP_DN_ALLOW_ONE_SPACE(f) \ + ( LDAP_DN_LDAPV2(f) \ + || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) ) +#define LDAP_DN_ALLOW_SPACES(f) \ + ( LDAP_DN_LDAPV2(f) \ + || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) ) +#define LDAP_DN_LDAP(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAP ) +#define LDAP_DN_LDAPV3(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 ) +#define LDAP_DN_LDAPV2(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 ) +#define LDAP_DN_DCE(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE ) +#define LDAP_DN_UFN(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN ) +#define LDAP_DN_ADC(f) \ + ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL ) +#define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK ) + +/* + * LDAPAVA helpers (will become part of the API for operations + * on structural representations of DNs). + */ +static LDAPAVA * +ldapava_new( const struct berval *attr, const struct berval *val, + unsigned flags, void *ctx ) +{ + LDAPAVA *ava; + + assert( attr != NULL ); + assert( val != NULL ); + + ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx ); + + if ( ava ) { + ava->la_attr.bv_len = attr->bv_len; + ava->la_attr.bv_val = (char *)(ava+1); + AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len ); + ava->la_attr.bv_val[attr->bv_len] = '\0'; + + ava->la_value = *val; + ava->la_flags = flags | LDAP_AVA_FREE_VALUE; + + ava->la_private = NULL; + } + + return( ava ); +} + +static void +ldapava_free( LDAPAVA *ava, void *ctx ) +{ + assert( ava != NULL ); + +#if 0 + /* ava's private must be freed by caller + * (at present let's skip this check because la_private + * basically holds static data) */ + assert( ava->la_private == NULL ); +#endif + + if (ava->la_flags & LDAP_AVA_FREE_VALUE) + LDAP_FREEX( ava->la_value.bv_val, ctx ); + + LDAP_FREEX( ava, ctx ); +} + +void +ldap_rdnfree( LDAPRDN rdn ) +{ + ldap_rdnfree_x( rdn, NULL ); +} + +void +ldap_rdnfree_x( LDAPRDN rdn, void *ctx ) +{ + int iAVA; + + if ( rdn == NULL ) { + return; + } + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + ldapava_free( rdn[ iAVA ], ctx ); + } + + LDAP_FREEX( rdn, ctx ); +} + +void +ldap_dnfree( LDAPDN dn ) +{ + ldap_dnfree_x( dn, NULL ); +} + +void +ldap_dnfree_x( LDAPDN dn, void *ctx ) +{ + int iRDN; + + if ( dn == NULL ) { + return; + } + + for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { + ldap_rdnfree_x( dn[ iRDN ], ctx ); + } + + LDAP_FREEX( dn, ctx ); +} + +/* + * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE) + * into a structural representation of the DN, by separating attribute + * types and values encoded in the more appropriate form, which is + * string or OID for attribute types and binary form of the BER encoded + * value or Unicode string. Formats different from LDAPv3 are parsed + * according to their own rules and turned into the more appropriate + * form according to LDAPv3. + * + * NOTE: I realize the code is getting spaghettish; it is rather + * experimental and will hopefully turn into something more simple + * and readable as soon as it works as expected. + */ + +/* + * Default sizes of AVA and RDN static working arrays; if required + * the are dynamically resized. The values can be tuned in case + * of special requirements (e.g. very deep DN trees or high number + * of AVAs per RDN). + */ +#define TMP_AVA_SLOTS 8 +#define TMP_RDN_SLOTS 32 + +int +ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags ) +{ + struct berval bv; + + assert( str != NULL ); + + bv.bv_len = strlen( str ); + bv.bv_val = (char *) str; + + return ldap_bv2dn_x( &bv, dn, flags, NULL ); +} + +int +ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags ) +{ + return ldap_bv2dn_x( bv, dn, flags, NULL ); +} + +int +ldap_bv2dn_x( struct berval *bvin, LDAPDN *dn, unsigned flags, void *ctx ) +{ + const char *p; + int rc = LDAP_DECODING_ERROR; + int nrdns = 0; + + LDAPDN newDN = NULL; + LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_; + int num_slots = TMP_RDN_SLOTS; + char *str, *end; + struct berval bvtmp, *bv = &bvtmp; + + assert( bvin != NULL ); + assert( bvin->bv_val != NULL ); + assert( dn != NULL ); + + *bv = *bvin; + str = bv->bv_val; + end = str + bv->bv_len; + + Debug2( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags ); + + *dn = NULL; + + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV3: + case LDAP_DN_FORMAT_DCE: + break; + + /* allow DN enclosed in brackets */ + case LDAP_DN_FORMAT_LDAPV2: + if ( str[0] == '<' ) { + if ( bv->bv_len < 2 || end[ -1 ] != '>' ) { + rc = LDAP_DECODING_ERROR; + goto parsing_error; + } + bv->bv_val++; + bv->bv_len -= 2; + str++; + end--; + } + break; + + /* unsupported in str2dn */ + case LDAP_DN_FORMAT_UFN: + case LDAP_DN_FORMAT_AD_CANONICAL: + return LDAP_PARAM_ERROR; + + case LDAP_DN_FORMAT_LBER: + default: + return LDAP_PARAM_ERROR; + } + + if ( bv->bv_len == 0 ) { + return LDAP_SUCCESS; + } + + if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { + /* value must have embedded NULs */ + return LDAP_DECODING_ERROR; + } + + p = str; + if ( LDAP_DN_DCE( flags ) ) { + + /* + * (from Luke Howard: thnx) A RDN separator is required + * at the beginning of an (absolute) DN. + */ + if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { + goto parsing_error; + } + p++; + + /* + * actually we do not want to accept by default the DCE form, + * we do not want to auto-detect it + */ +#if 0 + } else if ( LDAP_DN_LDAP( flags ) ) { + /* + * if dn starts with '/' let's make it a DCE dn + */ + if ( LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { + flags |= LDAP_DN_FORMAT_DCE; + p++; + } +#endif + } + + for ( ; p < end; p++ ) { + int err; + struct berval tmpbv; + tmpbv.bv_len = bv->bv_len - ( p - str ); + tmpbv.bv_val = (char *)p; + + err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx); + if ( err != LDAP_SUCCESS ) { + goto parsing_error; + } + + /* + * We expect a rdn separator + */ + if ( p < end && p[ 0 ] ) { + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) { + rc = LDAP_DECODING_ERROR; + goto parsing_error; + } + break; + + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV2: + if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) { + rc = LDAP_DECODING_ERROR; + goto parsing_error; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) { + rc = LDAP_DECODING_ERROR; + goto parsing_error; + } + break; + } + } + + + tmpDN[nrdns++] = newRDN; + newRDN = NULL; + + /* + * make the static RDN array dynamically rescalable + */ + if ( nrdns == num_slots ) { + LDAPRDN *tmp; + + if ( tmpDN == tmpDN_ ) { + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) ); + + } else { + tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + } + + tmpDN = tmp; + num_slots *= 2; + } + + if ( p >= end || p[ 0 ] == '\0' ) { + /* + * the DN is over, phew + */ + newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx ); + if ( newDN == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } else { + int i; + + if ( LDAP_DN_DCE( flags ) ) { + /* add in reversed order */ + for ( i=0; i<nrdns; i++ ) + newDN[i] = tmpDN[nrdns-1-i]; + } else { + for ( i=0; i<nrdns; i++ ) + newDN[i] = tmpDN[i]; + } + newDN[nrdns] = NULL; + rc = LDAP_SUCCESS; + } + goto return_result; + } + } + +parsing_error:; + if ( newRDN ) { + ldap_rdnfree_x( newRDN, ctx ); + } + + for ( nrdns-- ;nrdns >= 0; nrdns-- ) { + ldap_rdnfree_x( tmpDN[nrdns], ctx ); + } + +return_result:; + + if ( tmpDN != tmpDN_ ) { + LDAP_FREEX( tmpDN, ctx ); + } + + Debug3( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc, + rc ? ldap_err2string( rc ) : "" ); + *dn = newDN; + + return( rc ); +} + +/* + * ldap_str2rdn + * + * Parses a relative DN according to flags up to a rdn separator + * or to the end of str. + * Returns the rdn and a pointer to the string continuation, which + * corresponds to the rdn separator or to '\0' in case the string is over. + */ +int +ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn, + char **n_in, unsigned flags ) +{ + struct berval bv; + + assert( str != NULL ); + assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */ + + bv.bv_len = strlen( str ); + bv.bv_val = (char *) str; + + return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL ); +} + +int +ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn, + char **n_in, unsigned flags ) +{ + return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL ); +} + +int +ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn, + char **n_in, unsigned flags, void *ctx ) +{ + const char **n = (const char **) n_in; + const char *p; + int navas = 0; + int state = B4AVA; + int rc = LDAP_DECODING_ERROR; + int attrTypeEncoding = LDAP_AVA_STRING, + attrValueEncoding = LDAP_AVA_STRING; + + struct berval attrType = BER_BVNULL; + struct berval attrValue = BER_BVNULL; + + LDAPRDN newRDN = NULL; + LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_; + int num_slots = TMP_AVA_SLOTS; + + char *str; + ber_len_t stoplen; + + assert( bv != NULL ); + assert( bv->bv_len != 0 ); + assert( bv->bv_val != NULL ); + assert( rdn || flags & LDAP_DN_SKIP ); + assert( n != NULL ); + + str = bv->bv_val; + stoplen = bv->bv_len; + + if ( rdn ) { + *rdn = NULL; + } + *n = NULL; + + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV3: + case LDAP_DN_FORMAT_LDAPV2: + case LDAP_DN_FORMAT_DCE: + break; + + /* unsupported in str2dn */ + case LDAP_DN_FORMAT_UFN: + case LDAP_DN_FORMAT_AD_CANONICAL: + return LDAP_PARAM_ERROR; + + case LDAP_DN_FORMAT_LBER: + default: + return LDAP_PARAM_ERROR; + } + + if ( bv->bv_len == 0 ) { + return LDAP_SUCCESS; + + } + + if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { + /* value must have embedded NULs */ + return LDAP_DECODING_ERROR; + } + + p = str; + for ( ; p[ 0 ] || state == GOTAVA; ) { + + /* + * The parser in principle advances one token a time, + * or toggles state if preferable. + */ + switch (state) { + + /* + * an AttributeType can be encoded as: + * - its string representation; in detail, implementations + * MUST recognize AttributeType string type names listed + * in Section 3 of RFC 4514, and MAY recognize other names. + * - its numeric OID (a dotted decimal string) + */ + case B4AVA: + if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) { + /* error */ + goto parsing_error; + } + p++; + } + + if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { + /* error */ + goto parsing_error; + } + + /* whitespace is allowed (and trimmed) */ + p++; + while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + p++; + } + + if ( !p[ 0 ] ) { + /* error: we expected an AVA */ + goto parsing_error; + } + } + + /* oid */ + if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) { + state = B4OIDATTRTYPE; + break; + } + + /* else must be alpha */ + if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) { + goto parsing_error; + } + + /* LDAPv2 "oid." prefix */ + if ( LDAP_DN_LDAPV2( flags ) ) { + /* + * to be overly pedantic, we only accept + * "OID." or "oid." + */ + if ( flags & LDAP_DN_PEDANTIC ) { + if ( !strncmp( p, "OID.", 4 ) + || !strncmp( p, "oid.", 4 ) ) { + p += 4; + state = B4OIDATTRTYPE; + break; + } + } else { + if ( !strncasecmp( p, "oid.", 4 ) ) { + p += 4; + state = B4OIDATTRTYPE; + break; + } + } + } + + state = B4STRINGATTRTYPE; + break; + + case B4OIDATTRTYPE: { + int err = LDAP_SUCCESS; + + attrType.bv_val = ldap_int_parse_numericoid( &p, &err, + LDAP_SCHEMA_SKIP); + + if ( err != LDAP_SUCCESS ) { + goto parsing_error; + } + attrType.bv_len = p - attrType.bv_val; + + attrTypeEncoding = LDAP_AVA_BINARY; + + state = B4AVAEQUALS; + break; + } + + case B4STRINGATTRTYPE: { + const char *startPos, *endPos = NULL; + ber_len_t len; + + /* + * the starting char has been found to be + * a LDAP_DN_DESC_LEADCHAR so we don't re-check it + * FIXME: DCE attr types seem to have a more + * restrictive syntax (no '-' ...) + */ + for ( startPos = p++; p[ 0 ]; p++ ) { + if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) { + continue; + } + + if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) { + + /* + * RFC 4514 explicitly does not allow attribute + * description options, such as language tags. + */ + if ( flags & LDAP_DN_PEDANTIC ) { + goto parsing_error; + } + + /* + * we trim ';' and following lang + * and so from attribute types + */ + endPos = p; + for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] ) + || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) { + /* no op */ ; + } + break; + } + break; + } + + len = ( endPos ? endPos : p ) - startPos; + if ( len == 0 ) { + goto parsing_error; + } + + attrTypeEncoding = LDAP_AVA_STRING; + + /* + * here we need to decide whether to use it as is + * or turn it in OID form; as a consequence, we + * need to decide whether to binary encode the value + */ + + state = B4AVAEQUALS; + + if ( flags & LDAP_DN_SKIP ) { + break; + } + + attrType.bv_val = (char *)startPos; + attrType.bv_len = len; + + break; + } + + case B4AVAEQUALS: + /* spaces may not be allowed */ + if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { + goto parsing_error; + } + + /* trim spaces */ + for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { + /* no op */ + } + } + + /* need equal sign */ + if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) { + goto parsing_error; + } + p++; + + /* spaces may not be allowed */ + if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + if ( !LDAP_DN_ALLOW_SPACES( flags ) ) { + goto parsing_error; + } + + /* trim spaces */ + for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { + /* no op */ + } + } + + /* + * octothorpe means a BER encoded value will follow + * FIXME: I don't think DCE will allow it + */ + if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) { + p++; + attrValueEncoding = LDAP_AVA_BINARY; + state = B4BINARYVALUE; + break; + } + + /* STRING value expected */ + + /* + * if we're pedantic, an attribute type in OID form + * SHOULD imply a BER encoded attribute value; we + * should at least issue a warning + */ + if ( ( flags & LDAP_DN_PEDANTIC ) + && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) { + /* OID attrType SHOULD use binary encoding */ + goto parsing_error; + } + + attrValueEncoding = LDAP_AVA_STRING; + + /* + * LDAPv2 allows the attribute value to be quoted; + * also, IA5 values are expected, in principle + */ + if ( LDAP_DN_LDAPV2( flags ) || LDAP_DN_LDAP( flags ) ) { + if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { + p++; + state = B4IA5VALUEQUOTED; + break; + } + + if ( LDAP_DN_LDAPV2( flags ) ) { + state = B4IA5VALUE; + break; + } + } + + /* + * here STRING means RFC 4514 string + * FIXME: what about DCE strings? + */ + if ( !p[ 0 ] ) { + /* empty value */ + state = GOTAVA; + } else { + state = B4STRINGVALUE; + } + break; + + case B4BINARYVALUE: + if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) { + goto parsing_error; + } + + state = GOTAVA; + break; + + case B4STRINGVALUE: + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV3: + if ( str2strval( p, stoplen - ( p - str ), + &attrValue, &p, flags, + &attrValueEncoding, ctx ) ) { + goto parsing_error; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) { + goto parsing_error; + } + break; + + default: + assert( 0 ); + } + + state = GOTAVA; + break; + + case B4IA5VALUE: + if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) { + goto parsing_error; + } + + state = GOTAVA; + break; + + case B4IA5VALUEQUOTED: + + /* lead quote already stripped */ + if ( quotedIA52strval( p, &attrValue, + &p, flags, ctx ) ) { + goto parsing_error; + } + + state = GOTAVA; + break; + + case GOTAVA: { + int rdnsep = 0; + + if ( !( flags & LDAP_DN_SKIP ) ) { + LDAPAVA *ava; + + /* + * we accept empty values + */ + ava = ldapava_new( &attrType, &attrValue, + attrValueEncoding, ctx ); + if ( ava == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + tmpRDN[navas++] = ava; + + attrValue.bv_val = NULL; + attrValue.bv_len = 0; + + /* + * prepare room for new AVAs if needed + */ + if (navas == num_slots) { + LDAPAVA **tmp; + + if ( tmpRDN == tmpRDN_ ) { + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) ); + + } else { + tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + } + + tmpRDN = tmp; + num_slots *= 2; + } + } + + /* + * if we got an AVA separator ('+', or ',' for DCE ) + * we expect a new AVA for this RDN; otherwise + * we add the RDN to the DN + */ + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV3: + case LDAP_DN_FORMAT_LDAPV2: + if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) { + rdnsep = 1; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) { + rdnsep = 1; + } + break; + } + + if ( rdnsep ) { + /* + * the RDN is over, phew + */ + *n = p; + if ( !( flags & LDAP_DN_SKIP ) ) { + newRDN = (LDAPRDN)LDAP_MALLOCX( + sizeof(LDAPAVA) * (navas+1), ctx ); + if ( newRDN == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } else { + AC_MEMCPY( newRDN, tmpRDN, sizeof(LDAPAVA *) * navas); + newRDN[navas] = NULL; + } + + } + rc = LDAP_SUCCESS; + goto return_result; + } + + /* they should have been used in an AVA */ + attrType.bv_val = NULL; + attrValue.bv_val = NULL; + + p++; + state = B4AVA; + break; + } + + default: + assert( 0 ); + goto parsing_error; + } + } + *n = p; + +parsing_error:; + /* They are set to NULL after they're used in an AVA */ + + if ( attrValue.bv_val ) { + LDAP_FREEX( attrValue.bv_val, ctx ); + } + + for ( navas-- ; navas >= 0; navas-- ) { + ldapava_free( tmpRDN[navas], ctx ); + } + +return_result:; + + if ( tmpRDN != tmpRDN_ ) { + LDAP_FREEX( tmpRDN, ctx ); + } + + if ( rdn ) { + *rdn = newRDN; + } + + return( rc ); +} + +/* + * reads in a UTF-8 string value, unescaping stuff: + * '' + LDAP_DN_NEEDESCAPE(c) -> 'c' + * '' + HEXPAIR(p) -> unhex(p) + */ +static int +str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx ) +{ + const char *p, *end, *startPos, *endPos = NULL; + ber_len_t len, escapes; + + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); + + *next = NULL; + end = str + stoplen; + for ( startPos = p = str, escapes = 0; p < end; p++ ) { + if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { + p++; + if ( p[ 0 ] == '\0' ) { + return( 1 ); + } + if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) { + escapes++; + continue; + } + + if ( LDAP_DN_HEXPAIR( p ) ) { + char c; + + hexstr2bin( p, &c ); + escapes += 2; + + if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) { + + /* + * we assume the string is UTF-8 + */ + *retFlags = LDAP_AVA_NONPRINTABLE; + } + p++; + + continue; + } + + if ( LDAP_DN_PEDANTIC & flags ) { + return( 1 ); + } + /* + * we do not allow escaping + * of chars that don't need + * to and do not belong to + * HEXDIGITS + */ + return( 1 ); + + } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { + if ( p[ 0 ] == '\0' ) { + return( 1 ); + } + *retFlags = LDAP_AVA_NONPRINTABLE; + + } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) + || ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) { + break; + + } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) { + /* + * FIXME: maybe we can add + * escapes if not pedantic? + */ + return( 1 ); + } + } + + /* + * we do allow unescaped spaces at the end + * of the value only in non-pedantic mode + */ + if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && + !LDAP_DN_ESCAPE( p[ -2 ] ) ) { + if ( flags & LDAP_DN_PEDANTIC ) { + return( 1 ); + } + + /* strip trailing (unescaped) spaces */ + for ( endPos = p - 1; + endPos > startPos + 1 && + LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && + !LDAP_DN_ESCAPE( endPos[ -2 ] ); + endPos-- ) { + /* no op */ + } + } + + *next = p; + if ( flags & LDAP_DN_SKIP ) { + return( 0 ); + } + + /* + * FIXME: test memory? + */ + len = ( endPos ? endPos : p ) - startPos - escapes; + val->bv_len = len; + + if ( escapes == 0 ) { + if ( *retFlags & LDAP_AVA_NONPRINTABLE ) { + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( 1 ); + } + + AC_MEMCPY( val->bv_val, startPos, len ); + val->bv_val[ len ] = '\0'; + } else { + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); + } + + } else { + ber_len_t s, d; + + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( 1 ); + } + + for ( s = 0, d = 0; d < len; ) { + if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { + s++; + if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) { + val->bv_val[ d++ ] = + startPos[ s++ ]; + + } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) { + char c; + + hexstr2bin( &startPos[ s ], &c ); + val->bv_val[ d++ ] = c; + s += 2; + + } else { + /* we should never get here */ + assert( 0 ); + } + + } else { + val->bv_val[ d++ ] = startPos[ s++ ]; + } + } + + val->bv_val[ d ] = '\0'; + assert( d == len ); + } + + return( 0 ); +} + +static int +DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) +{ + const char *p, *startPos, *endPos = NULL; + ber_len_t len, escapes; + + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); + + *next = NULL; + + for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { + if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) { + p++; + if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { + escapes++; + + } else { + return( 1 ); + } + + } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { + break; + } + + /* + * FIXME: can we accept anything else? I guess we need + * to stop if a value is not legal + */ + } + + /* + * (unescaped) trailing spaces are trimmed must be silently ignored; + * so we eat them + */ + if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) && + !LDAP_DN_ESCAPE( p[ -2 ] ) ) { + if ( flags & LDAP_DN_PEDANTIC ) { + return( 1 ); + } + + /* strip trailing (unescaped) spaces */ + for ( endPos = p - 1; + endPos > startPos + 1 && + LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && + !LDAP_DN_ESCAPE( endPos[ -2 ] ); + endPos-- ) { + /* no op */ + } + } + + *next = p; + if ( flags & LDAP_DN_SKIP ) { + return( 0 ); + } + + len = ( endPos ? endPos : p ) - startPos - escapes; + val->bv_len = len; + if ( escapes == 0 ){ + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); + + } else { + ber_len_t s, d; + + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( 1 ); + } + + for ( s = 0, d = 0; d < len; ) { + /* + * This point is reached only if escapes + * are properly used, so all we need to + * do is eat them + */ + if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) { + s++; + + } + val->bv_val[ d++ ] = startPos[ s++ ]; + } + val->bv_val[ d ] = '\0'; + assert( strlen( val->bv_val ) == len ); + } + + return( 0 ); +} + +static int +IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) +{ + const char *p, *startPos, *endPos = NULL; + ber_len_t len, escapes; + + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); + + *next = NULL; + + /* + * LDAPv2 (RFC 1779) + */ + + for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) { + if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { + p++; + if ( p[ 0 ] == '\0' ) { + return( 1 ); + } + + if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] ) + && ( LDAP_DN_PEDANTIC & flags ) ) { + return( 1 ); + } + escapes++; + + } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { + break; + } + + /* + * FIXME: can we accept anything else? I guess we need + * to stop if a value is not legal + */ + } + + /* strip trailing (unescaped) spaces */ + for ( endPos = p; + endPos > startPos + 1 && + LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) && + !LDAP_DN_ESCAPE( endPos[ -2 ] ); + endPos-- ) { + /* no op */ + } + + *next = p; + if ( flags & LDAP_DN_SKIP ) { + return( 0 ); + } + + len = ( endPos ? endPos : p ) - startPos - escapes; + val->bv_len = len; + if ( escapes == 0 ) { + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); + + } else { + ber_len_t s, d; + + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( 1 ); + } + + for ( s = 0, d = 0; d < len; ) { + if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { + s++; + } + val->bv_val[ d++ ] = startPos[ s++ ]; + } + val->bv_val[ d ] = '\0'; + assert( strlen( val->bv_val ) == len ); + } + + return( 0 ); +} + +static int +quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) +{ + const char *p, *startPos, *endPos = NULL; + ber_len_t len; + unsigned escapes = 0; + + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); + + *next = NULL; + + /* initial quote already eaten */ + for ( startPos = p = str; p[ 0 ]; p++ ) { + /* + * According to RFC 1779, the quoted value can + * contain escaped as well as unescaped special values; + * as a consequence we tolerate escaped values + * (e.g. '","' -> ',') and escape unescaped specials + * (e.g. '","' -> ','). + */ + if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { + if ( p[ 1 ] == '\0' ) { + return( 1 ); + } + p++; + + if ( !LDAP_DN_V2_PAIR( p[ 0 ] ) + && ( LDAP_DN_PEDANTIC & flags ) ) { + /* + * do we allow to escape normal chars? + * LDAPv2 does not allow any mechanism + * for escaping chars with '' and hex + * pair + */ + return( 1 ); + } + escapes++; + + } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) { + endPos = p; + /* eat closing quotes */ + p++; + break; + } + + /* + * FIXME: can we accept anything else? I guess we need + * to stop if a value is not legal + */ + } + + if ( endPos == NULL ) { + return( 1 ); + } + + /* Strip trailing (unescaped) spaces */ + for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) { + /* no op */ + } + + *next = p; + if ( flags & LDAP_DN_SKIP ) { + return( 0 ); + } + + len = endPos - startPos - escapes; + assert( endPos >= startPos + escapes ); + val->bv_len = len; + if ( escapes == 0 ) { + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); + + } else { + ber_len_t s, d; + + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( 1 ); + } + + val->bv_len = len; + + for ( s = d = 0; d < len; ) { + if ( LDAP_DN_ESCAPE( str[ s ] ) ) { + s++; + } + val->bv_val[ d++ ] = str[ s++ ]; + } + val->bv_val[ d ] = '\0'; + assert( strlen( val->bv_val ) == len ); + } + + return( 0 ); +} + +static int +hexstr2bin( const char *str, char *c ) +{ + char c1, c2; + + assert( str != NULL ); + assert( c != NULL ); + + c1 = str[ 0 ]; + c2 = str[ 1 ]; + + if ( LDAP_DN_ASCII_DIGIT( c1 ) ) { + *c = c1 - '0'; + + } else { + if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c1 ) ) { + *c = c1 - 'A' + 10; + } else { + assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) ); + *c = c1 - 'a' + 10; + } + } + + *c <<= 4; + + if ( LDAP_DN_ASCII_DIGIT( c2 ) ) { + *c += c2 - '0'; + + } else { + if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c2 ) ) { + *c += c2 - 'A' + 10; + } else { + assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) ); + *c += c2 - 'a' + 10; + } + } + + return( 0 ); +} + +static int +hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) +{ + const char *p, *startPos, *endPos = NULL; + ber_len_t len; + ber_len_t s, d; + + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); + + *next = NULL; + + for ( startPos = p = str; p[ 0 ]; p += 2 ) { + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { + goto end_of_value; + } + break; + + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV2: + if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { + goto end_of_value; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { + goto end_of_value; + } + break; + } + + if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { + if ( flags & LDAP_DN_PEDANTIC ) { + return( 1 ); + } + endPos = p; + + for ( ; p[ 0 ]; p++ ) { + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) { + goto end_of_value; + } + break; + + case LDAP_DN_FORMAT_LDAP: + case LDAP_DN_FORMAT_LDAPV2: + if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) { + goto end_of_value; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) { + goto end_of_value; + } + break; + } + } + break; + } + + if ( !LDAP_DN_HEXPAIR( p ) ) { + return( 1 ); + } + } + +end_of_value:; + + *next = p; + if ( flags & LDAP_DN_SKIP ) { + return( 0 ); + } + + len = ( ( endPos ? endPos : p ) - startPos ) / 2; + /* must be even! */ + assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos )); + + val->bv_len = len; + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + if ( val->bv_val == NULL ) { + return( LDAP_NO_MEMORY ); + } + + for ( s = 0, d = 0; d < len; s += 2, d++ ) { + char c; + + hexstr2bin( &startPos[ s ], &c ); + + val->bv_val[ d ] = c; + } + + val->bv_val[ d ] = '\0'; + + return( 0 ); +} + +/* + * convert a byte in a hexadecimal pair + */ +static int +byte2hexpair( const char *val, char *pair ) +{ + static const char hexdig[] = "0123456789ABCDEF"; + + assert( val != NULL ); + assert( pair != NULL ); + + /* + * we assume the string has enough room for the hex encoding + * of the value + */ + + pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ]; + pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ]; + + return( 0 ); +} + +/* + * convert a binary value in hexadecimal pairs + */ +static int +binval2hexstr( struct berval *val, char *str ) +{ + ber_len_t s, d; + + assert( val != NULL ); + assert( str != NULL ); + + if ( val->bv_len == 0 ) { + return( 0 ); + } + + /* + * we assume the string has enough room for the hex encoding + * of the value + */ + + for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) { + byte2hexpair( &val->bv_val[ s ], &str[ d ] ); + } + + return( 0 ); +} + +/* + * Length of the string representation, accounting for escaped hex + * of UTF-8 chars + */ +static int +strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) +{ + ber_len_t l, cl = 1; + char *p, *end; + int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3; +#ifdef PRETTY_ESCAPE + int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3; +#endif /* PRETTY_ESCAPE */ + + assert( val != NULL ); + assert( len != NULL ); + + *len = 0; + if ( val->bv_len == 0 ) { + return( 0 ); + } + + end = val->bv_val + val->bv_len - 1; + for ( l = 0, p = val->bv_val; p <= end; p += cl ) { + + /* + * escape '%x00' + */ + if ( p[ 0 ] == '\0' ) { + cl = 1; + l += 3; + continue; + } + + cl = LDAP_UTF8_CHARLEN2( p, cl ); + if ( cl == 0 ) { + /* illegal utf-8 char! */ + return( -1 ); + + } else if ( cl > 1 ) { + ber_len_t cnt; + + for ( cnt = 1; cnt < cl; cnt++ ) { + if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) { + return( -1 ); + } + } + l += escaped_byte_len * cl; + + } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) + || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) + || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) + || ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { +#ifdef PRETTY_ESCAPE +#if 0 + if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) { +#else + if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) { +#endif + + /* + * there might be some chars we want + * to escape in form of a couple + * of hexdigits for optimization purposes + */ + l += 3; + + } else { + l += escaped_ascii_len; + } +#else /* ! PRETTY_ESCAPE */ + l += 3; +#endif /* ! PRETTY_ESCAPE */ + + } else { + l++; + } + } + + *len = l; + + return( 0 ); +} + +/* + * convert to string representation, escaping with hex the UTF-8 stuff; + * assume the destination has enough room for escaping + */ +static int +strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) +{ + ber_len_t s, d, end; + + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); + + if ( val->bv_len == 0 ) { + *len = 0; + return( 0 ); + } + + /* + * we assume the string has enough room for the hex encoding + * of the value + */ + for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { + ber_len_t cl; + + /* + * escape '%x00' + */ + if ( val->bv_val[ s ] == '\0' ) { + cl = 1; + str[ d++ ] = '\'; + str[ d++ ] = '0'; + str[ d++ ] = '0'; + s++; + continue; + } + + /* + * The length was checked in strval2strlen(); + */ + cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] ); + + /* + * there might be some chars we want to escape in form + * of a couple of hexdigits for optimization purposes + */ + if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) ) +#ifdef PRETTY_ESCAPE +#if 0 + || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] ) +#else + || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] ) +#endif +#else /* ! PRETTY_ESCAPE */ + || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) + || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) + || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) + +#endif /* ! PRETTY_ESCAPE */ + ) { + for ( ; cl--; ) { + str[ d++ ] = '\'; + byte2hexpair( &val->bv_val[ s ], &str[ d ] ); + s++; + d += 2; + } + + } else if ( cl > 1 ) { + for ( ; cl--; ) { + str[ d++ ] = val->bv_val[ s++ ]; + } + + } else { +#ifdef PRETTY_ESCAPE + if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) + || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) + || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { + str[ d++ ] = '\'; + if ( !LDAP_DN_IS_PRETTY( flags ) ) { + byte2hexpair( &val->bv_val[ s ], &str[ d ] ); + s++; + d += 2; + continue; + } + } +#endif /* PRETTY_ESCAPE */ + str[ d++ ] = val->bv_val[ s++ ]; + } + } + + *len = d; + + return( 0 ); +} + +/* + * Length of the IA5 string representation (no UTF-8 allowed) + */ +static int +strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ) +{ + ber_len_t l; + char *p; + + assert( val != NULL ); + assert( len != NULL ); + + *len = 0; + if ( val->bv_len == 0 ) { + return( 0 ); + } + + if ( flags & LDAP_AVA_NONPRINTABLE ) { + /* + * Turn value into a binary encoded BER + */ + return( -1 ); + + } else { + for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { + if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) + || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) + || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) + || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { + l += 2; + + } else { + l++; + } + } + } + + *len = l; + + return( 0 ); +} + +/* + * convert to string representation (np UTF-8) + * assume the destination has enough room for escaping + */ +static int +strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) +{ + ber_len_t s, d, end; + + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); + + if ( val->bv_len == 0 ) { + *len = 0; + return( 0 ); + } + + if ( flags & LDAP_AVA_NONPRINTABLE ) { + /* + * Turn value into a binary encoded BER + */ + *len = 0; + return( -1 ); + + } else { + /* + * we assume the string has enough room for the hex encoding + * of the value + */ + + for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { + if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) + || ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) + || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { + str[ d++ ] = '\'; + } + str[ d++ ] = val->bv_val[ s++ ]; + } + } + + *len = d; + + return( 0 ); +} + +/* + * Length of the (supposedly) DCE string representation, + * accounting for escaped hex of UTF-8 chars + */ +static int +strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len ) +{ + ber_len_t l; + char *p; + + assert( val != NULL ); + assert( len != NULL ); + + *len = 0; + if ( val->bv_len == 0 ) { + return( 0 ); + } + + if ( flags & LDAP_AVA_NONPRINTABLE ) { + /* + * FIXME: Turn the value into a binary encoded BER? + */ + return( -1 ); + + } else { + for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { + if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) { + l += 2; + + } else { + l++; + } + } + } + + *len = l; + + return( 0 ); +} + +/* + * convert to (supposedly) DCE string representation, + * escaping with hex the UTF-8 stuff; + * assume the destination has enough room for escaping + */ +static int +strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) +{ + ber_len_t s, d; + + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); + + if ( val->bv_len == 0 ) { + *len = 0; + return( 0 ); + } + + if ( flags & LDAP_AVA_NONPRINTABLE ) { + /* + * FIXME: Turn the value into a binary encoded BER? + */ + *len = 0; + return( -1 ); + + } else { + + /* + * we assume the string has enough room for the hex encoding + * of the value + */ + + for ( s = 0, d = 0; s < val->bv_len; ) { + if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) { + str[ d++ ] = '\'; + } + str[ d++ ] = val->bv_val[ s++ ]; + } + } + + *len = d; + + return( 0 ); +} + +/* + * Length of the (supposedly) AD canonical string representation, + * accounting for chars that need to be escaped + */ +static int +strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ) +{ + ber_len_t l, cl; + char *p; + + assert( val != NULL ); + assert( len != NULL ); + + *len = 0; + if ( val->bv_len == 0 ) { + return( 0 ); + } + + for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) { + cl = LDAP_UTF8_CHARLEN2( p, cl ); + if ( cl == 0 ) { + /* illegal utf-8 char */ + return -1; + } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) { + l += 2; + } else { + l += cl; + } + } + + *len = l; + + return( 0 ); +} + +/* + * convert to (supposedly) AD string representation, + * assume the destination has enough room for escaping + */ +static int +strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) +{ + ber_len_t s, d, cl; + + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); + + if ( val->bv_len == 0 ) { + *len = 0; + return( 0 ); + } + + /* + * we assume the string has enough room for the escaping + * of the value + */ + + for ( s = 0, d = 0; s < val->bv_len; ) { + cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl ); + if ( cl == 0 ) { + /* illegal utf-8 char */ + return -1; + } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) { + str[ d++ ] = '\'; + } + for (; cl--;) { + str[ d++ ] = val->bv_val[ s++ ]; + } + } + + *len = d; + + return( 0 ); +} + +/* + * If the DN is terminated by single-AVA RDNs with attribute type of "dc", + * the first part of the AD representation of the DN is written in DNS + * form, i.e. dot separated domain name components (as suggested + * by Luke Howard, http://www.padl.com/~lukeh) + */ +static int +dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ) +{ + int i; + int domain = 0, first = 1; + ber_len_t l = 1; /* we move the null also */ + char *str; + + /* we are guaranteed there's enough memory in str */ + + /* sanity */ + assert( dn != NULL ); + assert( bv != NULL ); + assert( iRDN != NULL ); + assert( *iRDN >= 0 ); + + str = bv->bv_val + pos; + + for ( i = *iRDN; i >= 0; i-- ) { + LDAPRDN rdn; + LDAPAVA *ava; + + assert( dn[ i ] != NULL ); + rdn = dn[ i ]; + + assert( rdn[ 0 ] != NULL ); + ava = rdn[ 0 ]; + + if ( !LDAP_DN_IS_RDN_DC( rdn ) ) { + break; + } + + if ( ldif_is_not_printable( ava->la_value.bv_val, ava->la_value.bv_len ) ) { + domain = 0; + break; + } + + domain = 1; + + if ( first ) { + first = 0; + AC_MEMCPY( str, ava->la_value.bv_val, + ava->la_value.bv_len + 1); + l += ava->la_value.bv_len; + + } else { + AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l); + AC_MEMCPY( str, ava->la_value.bv_val, + ava->la_value.bv_len ); + str[ ava->la_value.bv_len ] = '.'; + l += ava->la_value.bv_len + 1; + } + } + + *iRDN = i; + bv->bv_len = pos + l - 1; + + return( domain ); +} + +static int +rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, + int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) ) +{ + int iAVA; + ber_len_t l = 0; + + *len = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + /* len(type) + '=' + '+' | ',' */ + l += ava->la_attr.bv_len + 2; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + /* octothorpe + twice the length */ + l += 1 + 2 * ava->la_value.bv_len; + + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( ( *s2l )( &ava->la_value, f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, + int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) ) +{ + int iAVA; + ber_len_t l = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, + ava->la_attr.bv_len ); + l += ava->la_attr.bv_len; + + str[ l++ ] = '='; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + str[ l++ ] = '#'; + if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { + return( -1 ); + } + l += 2 * ava->la_value.bv_len; + + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( ( *s2s )( &ava->la_value, &str[ l ], f, &vl ) ) { + return( -1 ); + } + l += vl; + } + str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' ); + } + + *len = l; + + return( 0 ); +} + +static int +rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) +{ + int iAVA; + ber_len_t l = 0; + + *len = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + /* len(type) + '=' + ',' | '/' */ + l += ava->la_attr.bv_len + 2; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + /* octothorpe + twice the length */ + l += 1 + 2 * ava->la_value.bv_len; + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2DCEstrlen( &ava->la_value, f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) +{ + int iAVA; + ber_len_t l = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + if ( first ) { + first = 0; + } else { + str[ l++ ] = ( iAVA ? ',' : '/' ); + } + + AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, + ava->la_attr.bv_len ); + l += ava->la_attr.bv_len; + + str[ l++ ] = '='; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + str[ l++ ] = '#'; + if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { + return( -1 ); + } + l += 2 * ava->la_value.bv_len; + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2DCEstr( &ava->la_value, &str[ l ], f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) +{ + int iAVA; + ber_len_t l = 0; + + assert( rdn != NULL ); + assert( len != NULL ); + + *len = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + /* ' + ' | ', ' */ + l += ( rdn[ iAVA + 1 ] ? 3 : 2 ); + + /* FIXME: are binary values allowed in UFN? */ + if ( ava->la_flags & LDAP_AVA_BINARY ) { + /* octothorpe + twice the value */ + l += 1 + 2 * ava->la_value.bv_len; + + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2strlen( &ava->la_value, f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ) +{ + int iAVA; + ber_len_t l = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + str[ l++ ] = '#'; + if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { + return( -1 ); + } + l += 2 * ava->la_value.bv_len; + + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2str( &ava->la_value, &str[ l ], f, &vl ) ) { + return( -1 ); + } + l += vl; + } + + if ( rdn[ iAVA + 1 ] ) { + AC_MEMCPY( &str[ l ], " + ", 3 ); + l += 3; + + } else { + AC_MEMCPY( &str[ l ], ", ", 2 ); + l += 2; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) +{ + int iAVA; + ber_len_t l = 0; + + assert( rdn != NULL ); + assert( len != NULL ); + + *len = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + /* ',' | '/' */ + l++; + + /* FIXME: are binary values allowed in UFN? */ + if ( ava->la_flags & LDAP_AVA_BINARY ) { + /* octothorpe + twice the value */ + l += 1 + 2 * ava->la_value.bv_len; + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2ADstrlen( &ava->la_value, f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +static int +rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) +{ + int iAVA; + ber_len_t l = 0; + + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; + + if ( first ) { + first = 0; + } else { + str[ l++ ] = ( iAVA ? ',' : '/' ); + } + + if ( ava->la_flags & LDAP_AVA_BINARY ) { + str[ l++ ] = '#'; + if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { + return( -1 ); + } + l += 2 * ava->la_value.bv_len; + } else { + ber_len_t vl; + unsigned f = flags | ava->la_flags; + + if ( strval2ADstr( &ava->la_value, &str[ l ], f, &vl ) ) { + return( -1 ); + } + l += vl; + } + } + + *len = l; + + return( 0 ); +} + +/* + * ldap_rdn2str + * + * Returns in str a string representation of rdn based on flags. + * There is some duplication of code between this and ldap_dn2str; + * this is wanted to reduce the allocation of temporary buffers. + */ +int +ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags ) +{ + struct berval bv; + int rc; + + assert( str != NULL ); + + if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { + return LDAP_PARAM_ERROR; + } + + rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL ); + *str = bv.bv_val; + return rc; +} + +int +ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags ) +{ + return ldap_rdn2bv_x( rdn, bv, flags, NULL ); +} + +int +ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx ) +{ + int rc, back; + ber_len_t l; + + assert( bv != NULL ); + + bv->bv_len = 0; + bv->bv_val = NULL; + + if ( rdn == NULL ) { + bv->bv_val = LDAP_STRDUPX( "", ctx ); + return( LDAP_SUCCESS ); + } + + /* + * This routine wastes "back" bytes at the end of the string + */ + + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) { + return LDAP_DECODING_ERROR; + } + break; + + case LDAP_DN_FORMAT_LDAPV2: + if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) { + return LDAP_DECODING_ERROR; + } + break; + + case LDAP_DN_FORMAT_UFN: + if ( rdn2UFNstrlen( rdn, flags, &l ) ) { + return LDAP_DECODING_ERROR; + } + break; + + case LDAP_DN_FORMAT_DCE: + if ( rdn2DCEstrlen( rdn, flags, &l ) ) { + return LDAP_DECODING_ERROR; + } + break; + + case LDAP_DN_FORMAT_AD_CANONICAL: + if ( rdn2ADstrlen( rdn, flags, &l ) ) { + return LDAP_DECODING_ERROR; + } + break; + + default: + return LDAP_PARAM_ERROR; + } + + bv->bv_val = LDAP_MALLOCX( l + 1, ctx ); + if ( bv->bv_val == NULL ) { + return LDAP_NO_MEMORY; + } + + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2str ); + back = 1; + break; + + case LDAP_DN_FORMAT_LDAPV2: + rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2IA5str ); + back = 1; + break; + + case LDAP_DN_FORMAT_UFN: + rc = rdn2UFNstr( rdn, bv->bv_val, flags, &l ); + back = 2; + break; + + case LDAP_DN_FORMAT_DCE: + rc = rdn2DCEstr( rdn, bv->bv_val, flags, &l, 1 ); + back = 0; + break; + + case LDAP_DN_FORMAT_AD_CANONICAL: + rc = rdn2ADstr( rdn, bv->bv_val, flags, &l, 1 ); + back = 0; + break; + + default: + /* need at least one of the previous */ + return LDAP_PARAM_ERROR; + } + + if ( rc ) { + LDAP_FREEX( bv->bv_val, ctx ); + return rc; + } + + bv->bv_len = l - back; + bv->bv_val[ bv->bv_len ] = '\0'; + + return LDAP_SUCCESS; +} + +/* + * Very bulk implementation; many optimizations can be performed + * - a NULL dn results in an empty string "" + * + * FIXME: doubts + * a) what do we do if a UTF-8 string must be converted in LDAPv2? + * we must encode it in binary form ('#' + HEXPAIRs) + * b) does DCE/AD support UTF-8? + * no clue; don't think so. + * c) what do we do when binary values must be converted in UTF/DCE/AD? + * use binary encoded BER + */ +int ldap_dn2str( LDAPDN dn, char **str, unsigned flags ) +{ + struct berval bv; + int rc; + + assert( str != NULL ); + + if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { + return LDAP_PARAM_ERROR; + } + + rc = ldap_dn2bv_x( dn, &bv, flags, NULL ); + *str = bv.bv_val; + return rc; +} + +int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags ) +{ + return ldap_dn2bv_x( dn, bv, flags, NULL ); +} + +int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx ) +{ + int iRDN; + int rc = LDAP_ENCODING_ERROR; + ber_len_t len, l; + + /* stringifying helpers for LDAPv3/LDAPv2 */ + int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l ); + int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l ); + + assert( bv != NULL ); + bv->bv_len = 0; + bv->bv_val = NULL; + + Debug1( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags ); + + /* + * a null dn means an empty dn string + * FIXME: better raise an error? + */ + if ( dn == NULL || dn[0] == NULL ) { + bv->bv_val = LDAP_STRDUPX( "", ctx ); + return( LDAP_SUCCESS ); + } + + switch ( LDAP_DN_FORMAT( flags ) ) { + case LDAP_DN_FORMAT_LDAPV3: + sv2l = strval2strlen; + sv2s = strval2str; + + if( 0 ) { + case LDAP_DN_FORMAT_LDAPV2: + sv2l = strval2IA5strlen; + sv2s = strval2IA5str; + } + + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { + ber_len_t rdnl; + if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) { + goto return_results; + } + + len += rdnl; + } + + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + + for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { + ber_len_t rdnl; + + if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags, + &rdnl, sv2s ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + l += rdnl; + } + + assert( l == len ); + + /* + * trim the last ',' (the allocated memory + * is one byte longer than required) + */ + bv->bv_len = len - 1; + bv->bv_val[ bv->bv_len ] = '\0'; + + rc = LDAP_SUCCESS; + break; + + case LDAP_DN_FORMAT_UFN: { + /* + * FIXME: quoting from RFC 1781: + * + To take a distinguished name, and generate a name of this format with + attribute types omitted, the following steps are followed. + + 1. If the first attribute is of type CommonName, the type may be + omitted. + + 2. If the last attribute is of type Country, the type may be + omitted. + + 3. If the last attribute is of type Country, the last + Organisation attribute may have the type omitted. + + 4. All attributes of type OrganisationalUnit may have the type + omitted, unless they are after an Organisation attribute or + the first attribute is of type OrganisationalUnit. + + * this should be the pedantic implementation. + * + * Here the standard implementation reflects + * the one historically provided by OpenLDAP + * (and UMIch, I presume), with the variant + * of spaces and plusses (' + ') separating + * rdn components. + * + * A non-standard but nice implementation could + * be to turn the final "dc" attributes into a + * dot-separated domain. + * + * Other improvements could involve the use of + * friendly country names and so. + */ +#ifdef DC_IN_UFN + int leftmost_dc = -1; + int last_iRDN = -1; +#endif /* DC_IN_UFN */ + + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { + ber_len_t rdnl; + + if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) { + goto return_results; + } + len += rdnl; + +#ifdef DC_IN_UFN + if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) { + if ( leftmost_dc == -1 ) { + leftmost_dc = iRDN; + } + } else { + leftmost_dc = -1; + } +#endif /* DC_IN_UFN */ + } + + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + +#ifdef DC_IN_UFN + if ( leftmost_dc == -1 ) { +#endif /* DC_IN_UFN */ + for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { + ber_len_t vl; + + if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], + flags, &vl ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + l += vl; + } + + /* + * trim the last ', ' (the allocated memory + * is two bytes longer than required) + */ + bv->bv_len = len - 2; + bv->bv_val[ bv->bv_len ] = '\0'; +#ifdef DC_IN_UFN + } else { + last_iRDN = iRDN - 1; + + for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) { + ber_len_t vl; + + if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], + flags, &vl ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + l += vl; + } + + if ( !dn2domain( dn, bv, l, &last_iRDN ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + + /* the string is correctly terminated by dn2domain */ + } +#endif /* DC_IN_UFN */ + + rc = LDAP_SUCCESS; + + } break; + + case LDAP_DN_FORMAT_DCE: + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { + ber_len_t rdnl; + if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) { + goto return_results; + } + + len += rdnl; + } + + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + + for ( l = 0; iRDN--; ) { + ber_len_t rdnl; + + if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags, + &rdnl, 0 ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + l += rdnl; + } + + assert( l == len ); + + bv->bv_len = len; + bv->bv_val[ bv->bv_len ] = '\0'; + + rc = LDAP_SUCCESS; + break; + + case LDAP_DN_FORMAT_AD_CANONICAL: { + int trailing_slash = 1; + + /* + * Sort of UFN for DCE DNs: a slash ('/') separated + * global->local DN with no types; strictly speaking, + * the naming context should be a domain, which is + * written in DNS-style, e.g. dot-separated. + * + * Example: + * + * "givenName=Bill+sn=Gates,ou=People,dc=microsoft,dc=com" + * + * will read + * + * "microsoft.com/People/Bill,Gates" + */ + for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) { + ber_len_t rdnl; + + if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) { + goto return_results; + } + + len += rdnl; + } + + /* reserve room for trailing '/' in case the DN + * is exactly a domain */ + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1 + 1, ctx ) ) == NULL ) + { + rc = LDAP_NO_MEMORY; + break; + } + + iRDN--; + if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) { + for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) { + ber_len_t rdnl; + + trailing_slash = 0; + + if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], + flags, &rdnl, 0 ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + l += rdnl; + } + + } else { + int first = 1; + + /* + * Strictly speaking, AD canonical requires + * a DN to be in the form "..., dc=smtg", + * i.e. terminated by a domain component + */ + if ( flags & LDAP_DN_PEDANTIC ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + rc = LDAP_ENCODING_ERROR; + break; + } + + for ( l = 0; iRDN >= 0 ; iRDN-- ) { + ber_len_t rdnl; + + if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], + flags, &rdnl, first ) ) { + LDAP_FREEX( bv->bv_val, ctx ); + bv->bv_val = NULL; + goto return_results; + } + if ( first ) { + first = 0; + } + l += rdnl; + } + } + + if ( trailing_slash ) { + /* the DN is exactly a domain -- need a trailing + * slash; room was reserved in advance */ + bv->bv_val[ len ] = '/'; + len++; + } + + bv->bv_len = len; + bv->bv_val[ bv->bv_len ] = '\0'; + + rc = LDAP_SUCCESS; + } break; + + default: + return LDAP_PARAM_ERROR; + } + + Debug3( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n", + bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" ); + +return_results:; + return( rc ); +} diff --git a/libs/ldap/libldap/getentry.c b/libs/ldap/libldap/getentry.c new file mode 100644 index 00000000000..1e722b41bb2 --- /dev/null +++ b/libs/ldap/libldap/getentry.c @@ -0,0 +1,124 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* ARGSUSED */ +LDAPMessage * +ldap_first_entry( LDAP *ld, LDAPMessage *chain ) +{ + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( chain != NULL ); + + return chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY + ? chain + : ldap_next_entry( ld, chain ); +} + +LDAPMessage * +ldap_next_entry( LDAP *ld, LDAPMessage *entry ) +{ + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + + for( + entry = entry->lm_chain; + entry != NULL; + entry = entry->lm_chain ) + { + if( entry->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { + return( entry ); + } + } + + return( NULL ); +} + +int +ldap_count_entries( LDAP *ld, LDAPMessage *chain ) +{ + int i; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + for ( i = 0; chain != NULL; chain = chain->lm_chain ) { + if( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) { + i++; + } + } + + return( i ); +} + +int +ldap_get_entry_controls( + LDAP *ld, + LDAPMessage *entry, + LDAPControl ***sctrls ) +{ + int rc; + BerElement be; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( sctrls != NULL ); + + if ( entry->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) { + return LDAP_PARAM_ERROR; + } + + /* make a local copy of the BerElement */ + AC_MEMCPY(&be, entry->lm_ber, sizeof(be)); + + if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto cleanup_and_return; + } + + rc = ldap_pvt_get_controls( &be, sctrls ); + +cleanup_and_return: + if( rc != LDAP_SUCCESS ) { + ld->ld_errno = rc; + + if( ld->ld_matched != NULL ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + if( ld->ld_error != NULL ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + } + + return rc; +} diff --git a/libs/ldap/libldap/getvalues.c b/libs/ldap/libldap/getvalues.c new file mode 100644 index 00000000000..210798a652c --- /dev/null +++ b/libs/ldap/libldap/getvalues.c @@ -0,0 +1,210 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/ctype.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +char ** +ldap_get_values( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target ) +{ + BerElement ber; + char *attr; + int found = 0; + char **vals; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( target != NULL ); + + Debug0( LDAP_DEBUG_TRACE, "ldap_get_values\n" ); + + ber = *entry->lm_ber; + + /* skip sequence, dn, sequence of, and snag the first attr */ + if ( ber_scanf( &ber, "{x{{a" /*}}}*/, &attr ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + if ( strcasecmp( target, attr ) == 0 ) + found = 1; + + /* break out on success, return out on error */ + while ( ! found ) { + LDAP_FREE(attr); + attr = NULL; + + if ( ber_scanf( &ber, /*{*/ "x}{a" /*}*/, &attr ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + if ( strcasecmp( target, attr ) == 0 ) + break; + + } + + LDAP_FREE(attr); + attr = NULL; + + /* + * if we get this far, we've found the attribute and are sitting + * just before the set of values. + */ + + if ( ber_scanf( &ber, "[v]", &vals ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + return( vals ); +} + +struct berval ** +ldap_get_values_len( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target ) +{ + BerElement ber; + char *attr; + int found = 0; + struct berval **vals; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( entry != NULL ); + assert( target != NULL ); + + Debug0( LDAP_DEBUG_TRACE, "ldap_get_values_len\n" ); + + ber = *entry->lm_ber; + + /* skip sequence, dn, sequence of, and snag the first attr */ + if ( ber_scanf( &ber, "{x{{a" /* }}} */, &attr ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + if ( strcasecmp( target, attr ) == 0 ) + found = 1; + + /* break out on success, return out on error */ + while ( ! found ) { + LDAP_FREE( attr ); + attr = NULL; + + if ( ber_scanf( &ber, /*{*/ "x}{a" /*}*/, &attr ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + if ( strcasecmp( target, attr ) == 0 ) + break; + } + + LDAP_FREE( attr ); + attr = NULL; + + /* + * if we get this far, we've found the attribute and are sitting + * just before the set of values. + */ + + if ( ber_scanf( &ber, "[V]", &vals ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + return( vals ); +} + +int +ldap_count_values( char **vals ) +{ + int i; + + if ( vals == NULL ) + return( 0 ); + + for ( i = 0; vals[i] != NULL; i++ ) + ; /* NULL */ + + return( i ); +} + +int +ldap_count_values_len( struct berval **vals ) +{ + return( ldap_count_values( (char **) vals ) ); +} + +void +ldap_value_free( char **vals ) +{ + LDAP_VFREE( vals ); +} + +void +ldap_value_free_len( struct berval **vals ) +{ + ber_bvecfree( vals ); +} + +char ** +ldap_value_dup( char *const *vals ) +{ + char **new; + int i; + + if( vals == NULL ) { + return NULL; + } + + for( i=0; vals[i]; i++ ) { + ; /* Count the number of values */ + } + + if( i == 0 ) { + return NULL; + } + + new = LDAP_MALLOC( (i+1)*sizeof(char *) ); /* Alloc array of pointers */ + if( new == NULL ) { + return NULL; + } + + for( i=0; vals[i]; i++ ) { + new[i] = LDAP_STRDUP( vals[i] ); /* Dup each value */ + if( new[i] == NULL ) { + LDAP_VFREE( new ); + return NULL; + } + } + new[i] = NULL; + + return new; +} diff --git a/libs/ldap/libldap/init.c b/libs/ldap/libldap/init.c new file mode 100644 index 00000000000..5f8f6ec7bdd --- /dev/null +++ b/libs/ldap/libldap/init.c @@ -0,0 +1,782 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#ifdef HAVE_GETEUID +#include <ac/unistd.h> +#endif + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/ctype.h> +#include <ac/time.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include "ldap-int.h" +#include "ldap_defaults.h" +#include "lutil.h" + +struct ldapoptions ldap_int_global_options = + { LDAP_UNINITIALIZED, LDAP_DEBUG_NONE + LDAP_LDO_NULLARG + LDAP_LDO_SOURCEIP_NULLARG + LDAP_LDO_CONNECTIONLESS_NULLARG + LDAP_LDO_TLS_NULLARG + LDAP_LDO_SASL_NULLARG + LDAP_LDO_MUTEX_NULLARG }; + +#define ATTR_NONE 0 +#define ATTR_BOOL 1 +#define ATTR_INT 2 +#define ATTR_KV 3 +#define ATTR_STRING 4 +#define ATTR_OPTION 5 + +#define ATTR_SASL 6 +#define ATTR_TLS 7 + +#define ATTR_OPT_TV 8 +#define ATTR_OPT_INT 9 + +struct ol_keyvalue { + const char * key; + int value; +}; + +static const struct ol_keyvalue deref_kv[] = { + {"never", LDAP_DEREF_NEVER}, + {"searching", LDAP_DEREF_SEARCHING}, + {"finding", LDAP_DEREF_FINDING}, + {"always", LDAP_DEREF_ALWAYS}, + {NULL, 0} +}; + +static const struct ol_attribute { + int useronly; + int type; + const char * name; + const void * data; + size_t offset; +} attrs[] = { + {0, ATTR_OPT_TV, "TIMEOUT", NULL, LDAP_OPT_TIMEOUT}, + {0, ATTR_OPT_TV, "NETWORK_TIMEOUT", NULL, LDAP_OPT_NETWORK_TIMEOUT}, + {0, ATTR_OPT_INT, "VERSION", NULL, LDAP_OPT_PROTOCOL_VERSION}, + {0, ATTR_KV, "DEREF", deref_kv, /* or &deref_kv[0] */ + offsetof(struct ldapoptions, ldo_deref)}, + {0, ATTR_INT, "SIZELIMIT", NULL, + offsetof(struct ldapoptions, ldo_sizelimit)}, + {0, ATTR_INT, "TIMELIMIT", NULL, + offsetof(struct ldapoptions, ldo_timelimit)}, + {1, ATTR_STRING, "BINDDN", NULL, + offsetof(struct ldapoptions, ldo_defbinddn)}, + {0, ATTR_STRING, "BASE", NULL, + offsetof(struct ldapoptions, ldo_defbase)}, + {0, ATTR_INT, "PORT", NULL, /* deprecated */ + offsetof(struct ldapoptions, ldo_defport)}, + {0, ATTR_OPTION, "HOST", NULL, LDAP_OPT_HOST_NAME}, /* deprecated */ + {0, ATTR_OPTION, "URI", NULL, LDAP_OPT_URI}, /* replaces HOST/PORT */ + {0, ATTR_OPTION, "SOCKET_BIND_ADDRESSES", NULL, LDAP_OPT_SOCKET_BIND_ADDRESSES}, + {0, ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS}, + {0, ATTR_INT, "KEEPALIVE_IDLE", NULL, LDAP_OPT_X_KEEPALIVE_IDLE}, + {0, ATTR_INT, "KEEPALIVE_PROBES", NULL, LDAP_OPT_X_KEEPALIVE_PROBES}, + {0, ATTR_INT, "KEEPALIVE_INTERVAL", NULL, LDAP_OPT_X_KEEPALIVE_INTERVAL}, + +#if 0 + /* This should only be allowed via ldap_set_option(3) */ + {0, ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, +#endif + +#ifdef HAVE_CYRUS_SASL + {0, ATTR_STRING, "SASL_MECH", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_mech)}, + {0, ATTR_STRING, "SASL_REALM", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_realm)}, + {1, ATTR_STRING, "SASL_AUTHCID", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_authcid)}, + {1, ATTR_STRING, "SASL_AUTHZID", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_authzid)}, + {0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS}, + {0, ATTR_BOOL, "SASL_NOCANON", NULL, LDAP_BOOL_SASL_NOCANON}, + {0, ATTR_SASL, "SASL_CBINDING", NULL, LDAP_OPT_X_SASL_CBINDING}, +#endif + +#ifdef HAVE_TLS + {1, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, + {1, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, + {0, ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, + {0, ATTR_TLS, "TLS_CACERTDIR", NULL, LDAP_OPT_X_TLS_CACERTDIR}, + {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, + {0, ATTR_TLS, "TLS_REQSAN", NULL, LDAP_OPT_X_TLS_REQUIRE_SAN}, + {0, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, + {0, ATTR_TLS, "TLS_CIPHER_SUITE", NULL, LDAP_OPT_X_TLS_CIPHER_SUITE}, + {0, ATTR_TLS, "TLS_PROTOCOL_MIN", NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN}, + {0, ATTR_TLS, "TLS_PROTOCOL_MAX", NULL, LDAP_OPT_X_TLS_PROTOCOL_MAX}, + {0, ATTR_TLS, "TLS_PEERKEY_HASH", NULL, LDAP_OPT_X_TLS_PEERKEY_HASH}, + {0, ATTR_TLS, "TLS_ECNAME", NULL, LDAP_OPT_X_TLS_ECNAME}, + +#ifdef HAVE_OPENSSL + {0, ATTR_TLS, "TLS_CRLCHECK", NULL, LDAP_OPT_X_TLS_CRLCHECK}, +#endif +#ifdef HAVE_GNUTLS + {0, ATTR_TLS, "TLS_CRLFILE", NULL, LDAP_OPT_X_TLS_CRLFILE}, +#endif + +#endif + + {0, ATTR_NONE, NULL, NULL, 0} +}; + +#define MAX_LDAP_ATTR_LEN sizeof("SOCKET_BIND_ADDRESSES") +#define MAX_LDAP_ENV_PREFIX_LEN 8 + +static int +ldap_int_conf_option( + struct ldapoptions *gopts, + char *cmd, char *opt, int userconf ) +{ + int i; + + for(i=0; attrs[i].type != ATTR_NONE; i++) { + void *p; + + if( !userconf && attrs[i].useronly ) { + continue; + } + + if(strcasecmp(cmd, attrs[i].name) != 0) { + continue; + } + + switch(attrs[i].type) { + case ATTR_BOOL: + if((strcasecmp(opt, "on") == 0) + || (strcasecmp(opt, "yes") == 0) + || (strcasecmp(opt, "true") == 0)) + { + LDAP_BOOL_SET(gopts, attrs[i].offset); + + } else { + LDAP_BOOL_CLR(gopts, attrs[i].offset); + } + + break; + + case ATTR_INT: { + char *next; + long l; + p = &((char *) gopts)[attrs[i].offset]; + l = strtol( opt, &next, 10 ); + if ( next != opt && next[ 0 ] == '\0' ) { + * (int*) p = l; + } + } break; + + case ATTR_KV: { + const struct ol_keyvalue *kv; + + for(kv = attrs[i].data; + kv->key != NULL; + kv++) { + + if(strcasecmp(opt, kv->key) == 0) { + p = &((char *) gopts)[attrs[i].offset]; + * (int*) p = kv->value; + break; + } + } + } break; + + case ATTR_STRING: + p = &((char *) gopts)[attrs[i].offset]; + if (* (char**) p != NULL) LDAP_FREE(* (char**) p); + * (char**) p = LDAP_STRDUP(opt); + break; + case ATTR_OPTION: + ldap_set_option( NULL, attrs[i].offset, opt ); + break; + case ATTR_SASL: +#ifdef HAVE_CYRUS_SASL + ldap_int_sasl_config( gopts, attrs[i].offset, opt ); +#endif + break; + case ATTR_TLS: +#ifdef HAVE_TLS + ldap_pvt_tls_config( NULL, attrs[i].offset, opt ); +#endif + break; + case ATTR_OPT_TV: { + struct timeval tv; + char *next; + tv.tv_usec = 0; + tv.tv_sec = strtol( opt, &next, 10 ); + if ( next != opt && next[ 0 ] == '\0' && tv.tv_sec > 0 ) { + (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv ); + } + } break; + case ATTR_OPT_INT: { + long l; + char *next; + l = strtol( opt, &next, 10 ); + if ( next != opt && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) { + int v = (int)l; + (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v ); + } + } break; + } + + break; + } + + if ( attrs[i].type == ATTR_NONE ) { + Debug1( LDAP_DEBUG_TRACE, "ldap_pvt_tls_config: " + "unknown option '%s'", + cmd ); + return 1; + } + + return 0; +} + +int +ldap_pvt_conf_option( + char *cmd, char *opt, int userconf ) +{ + struct ldapoptions *gopts; + int rc = LDAP_OPT_ERROR; + + /* Get pointer to global option structure */ + gopts = LDAP_INT_GLOBAL_OPT(); + if (NULL == gopts) { + return LDAP_NO_MEMORY; + } + + if ( gopts->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(gopts, NULL); + if ( gopts->ldo_valid != LDAP_INITIALIZED ) + return LDAP_LOCAL_ERROR; + } + + return ldap_int_conf_option( gopts, cmd, opt, userconf ); +} + +static void openldap_ldap_init_w_conf( + const char *file, int userconf ) +{ + char linebuf[ AC_LINE_MAX ]; + FILE *fp; + int i; + char *cmd, *opt; + char *start, *end; + struct ldapoptions *gopts; + + if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { + return; /* Could not allocate mem for global options */ + } + + if (file == NULL) { + /* no file name */ + return; + } + + Debug1(LDAP_DEBUG_TRACE, "ldap_init: trying %s\n", file ); + + fp = fopen(file, "r"); + if(fp == NULL) { + /* could not open file */ + return; + } + + Debug1(LDAP_DEBUG_TRACE, "ldap_init: using %s\n", file ); + + while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) { + /* skip lines starting with '#' */ + if(*start == '#') continue; + + /* trim leading white space */ + while((*start != '\0') && isspace((unsigned char) *start)) + start++; + + /* anything left? */ + if(*start == '\0') continue; + + /* trim trailing white space */ + end = &start[strlen(start)-1]; + while(isspace((unsigned char)*end)) end--; + end[1] = '\0'; + + /* anything left? */ + if(*start == '\0') continue; + + + /* parse the command */ + cmd=start; + while((*start != '\0') && !isspace((unsigned char)*start)) { + start++; + } + if(*start == '\0') { + /* command has no argument */ + continue; + } + + *start++ = '\0'; + + /* we must have some whitespace to skip */ + while(isspace((unsigned char)*start)) start++; + opt = start; + + ldap_int_conf_option( gopts, cmd, opt, userconf ); + } + + fclose(fp); +} + +static void openldap_ldap_init_w_sysconf(const char *file) +{ + openldap_ldap_init_w_conf( file, 0 ); +} + +static void openldap_ldap_init_w_userconf(const char *file) +{ + char *home; + char *path = NULL; + + if (file == NULL) { + /* no file name */ + return; + } + + home = getenv("HOME"); + + if (home != NULL) { + Debug1(LDAP_DEBUG_TRACE, "ldap_init: HOME env is %s\n", + home ); + path = LDAP_MALLOC(strlen(home) + strlen(file) + sizeof( LDAP_DIRSEP ".")); + } else { + Debug0(LDAP_DEBUG_TRACE, "ldap_init: HOME env is NULL\n" ); + } + + if(home != NULL && path != NULL) { + /* we assume UNIX path syntax is used... */ + + /* try ~/file */ + sprintf(path, "%s" LDAP_DIRSEP "%s", home, file); + openldap_ldap_init_w_conf(path, 1); + + /* try ~/.file */ + sprintf(path, "%s" LDAP_DIRSEP ".%s", home, file); + openldap_ldap_init_w_conf(path, 1); + } + + if(path != NULL) { + LDAP_FREE(path); + } + + /* try file */ + openldap_ldap_init_w_conf(file, 1); +} + +static void openldap_ldap_init_w_env( + struct ldapoptions *gopts, + const char *prefix) +{ + char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN]; + int len; + int i; + void *p; + char *value; + + if (prefix == NULL) { + prefix = LDAP_ENV_PREFIX; + } + + strncpy(buf, prefix, MAX_LDAP_ENV_PREFIX_LEN); + buf[MAX_LDAP_ENV_PREFIX_LEN] = '\0'; + len = strlen(buf); + + for(i=0; attrs[i].type != ATTR_NONE; i++) { + strcpy(&buf[len], attrs[i].name); + value = getenv(buf); + + if(value == NULL) { + continue; + } + + switch(attrs[i].type) { + case ATTR_BOOL: + if((strcasecmp(value, "on") == 0) + || (strcasecmp(value, "yes") == 0) + || (strcasecmp(value, "true") == 0)) + { + LDAP_BOOL_SET(gopts, attrs[i].offset); + + } else { + LDAP_BOOL_CLR(gopts, attrs[i].offset); + } + break; + + case ATTR_INT: + p = &((char *) gopts)[attrs[i].offset]; + * (int*) p = atoi(value); + break; + + case ATTR_KV: { + const struct ol_keyvalue *kv; + + for(kv = attrs[i].data; + kv->key != NULL; + kv++) { + + if(strcasecmp(value, kv->key) == 0) { + p = &((char *) gopts)[attrs[i].offset]; + * (int*) p = kv->value; + break; + } + } + } break; + + case ATTR_STRING: + p = &((char *) gopts)[attrs[i].offset]; + if (* (char**) p != NULL) LDAP_FREE(* (char**) p); + if (*value == '\0') { + * (char**) p = NULL; + } else { + * (char**) p = LDAP_STRDUP(value); + } + break; + case ATTR_OPTION: + ldap_set_option( NULL, attrs[i].offset, value ); + break; + case ATTR_SASL: +#ifdef HAVE_CYRUS_SASL + ldap_int_sasl_config( gopts, attrs[i].offset, value ); +#endif + break; + case ATTR_TLS: +#ifdef HAVE_TLS + ldap_pvt_tls_config( NULL, attrs[i].offset, value ); +#endif + break; + case ATTR_OPT_TV: { + struct timeval tv; + char *next; + tv.tv_usec = 0; + tv.tv_sec = strtol( value, &next, 10 ); + if ( next != value && next[ 0 ] == '\0' && tv.tv_sec > 0 ) { + (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv ); + } + } break; + case ATTR_OPT_INT: { + long l; + char *next; + l = strtol( value, &next, 10 ); + if ( next != value && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) { + int v = (int)l; + (void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v ); + } + } break; + } + } +} + +#if defined(__GNUC__) +/* Declare this function as a destructor so that it will automatically be + * invoked either at program exit (if libldap is a static library) or + * at unload time (if libldap is a dynamic library). + * + * Sorry, don't know how to handle this for non-GCC environments. + */ +static void ldap_int_destroy_global_options(void) + __attribute__ ((destructor)); +#endif + +static void +ldap_int_destroy_global_options(void) +{ + struct ldapoptions *gopts = LDAP_INT_GLOBAL_OPT(); + + if ( gopts == NULL ) + return; + + gopts->ldo_valid = LDAP_UNINITIALIZED; + + if ( gopts->ldo_defludp ) { + ldap_free_urllist( gopts->ldo_defludp ); + gopts->ldo_defludp = NULL; + } + + if ( gopts->ldo_local_ip_addrs.local_ip_addrs ) { + LDAP_FREE( gopts->ldo_local_ip_addrs.local_ip_addrs ); + gopts->ldo_local_ip_addrs.local_ip_addrs = NULL; + } + +#if defined(HAVE_WINSOCK) || defined(HAVE_WINSOCK2) + WSACleanup( ); +#endif + +#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) + if ( ldap_int_hostname ) { + LDAP_FREE( ldap_int_hostname ); + ldap_int_hostname = NULL; + } +#endif +#ifdef HAVE_CYRUS_SASL + if ( gopts->ldo_def_sasl_authcid ) { + LDAP_FREE( gopts->ldo_def_sasl_authcid ); + gopts->ldo_def_sasl_authcid = NULL; + } +#endif +#ifdef HAVE_TLS + ldap_int_tls_destroy( gopts ); +#endif +} + +/* + * Initialize the global options structure with default values. + */ +void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl ) +{ + if (dbglvl) + gopts->ldo_debug = *dbglvl; + else + gopts->ldo_debug = 0; + + gopts->ldo_version = LDAP_VERSION2; + gopts->ldo_deref = LDAP_DEREF_NEVER; + gopts->ldo_timelimit = LDAP_NO_LIMIT; + gopts->ldo_sizelimit = LDAP_NO_LIMIT; + + gopts->ldo_tm_api.tv_sec = -1; + gopts->ldo_tm_net.tv_sec = -1; + + memset( &gopts->ldo_local_ip_addrs, 0, + sizeof( gopts->ldo_local_ip_addrs ) ); + + /* ldo_defludp will be freed by the termination handler + */ + ldap_url_parselist(&gopts->ldo_defludp, "ldap://localhost/"); + gopts->ldo_defport = LDAP_PORT; +#if !defined(__GNUC__) && !defined(PIC) + /* Do this only for a static library, and only if we can't + * arrange for it to be executed as a library destructor + */ + atexit(ldap_int_destroy_global_options); +#endif + + gopts->ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT; + gopts->ldo_rebind_proc = NULL; + gopts->ldo_rebind_params = NULL; + + LDAP_BOOL_ZERO(gopts); + + LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS); + +#ifdef LDAP_CONNECTIONLESS + gopts->ldo_peer = NULL; + gopts->ldo_cldapdn = NULL; + gopts->ldo_is_udp = 0; +#endif + +#ifdef HAVE_CYRUS_SASL + gopts->ldo_def_sasl_mech = NULL; + gopts->ldo_def_sasl_realm = NULL; + gopts->ldo_def_sasl_authcid = NULL; + gopts->ldo_def_sasl_authzid = NULL; + + memset( &gopts->ldo_sasl_secprops, + '\0', sizeof(gopts->ldo_sasl_secprops) ); + + gopts->ldo_sasl_secprops.max_ssf = INT_MAX; + gopts->ldo_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE; + gopts->ldo_sasl_secprops.security_flags = + SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; +#endif + +#ifdef HAVE_TLS + gopts->ldo_tls_connect_cb = NULL; + gopts->ldo_tls_connect_arg = NULL; + gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND; + gopts->ldo_tls_require_san = LDAP_OPT_X_TLS_ALLOW; +#endif + gopts->ldo_keepalive_probes = 0; + gopts->ldo_keepalive_interval = 0; + gopts->ldo_keepalive_idle = 0; + + gopts->ldo_tcp_user_timeout = 0; + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &gopts->ldo_mutex ); +#endif + gopts->ldo_valid = LDAP_INITIALIZED; + return; +} + +#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) +char * ldap_int_hostname = NULL; +#endif + +#ifdef LDAP_R_COMPILE +int ldap_int_stackguard; +#endif + +void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) +{ +#ifdef LDAP_R_COMPILE + static ldap_pvt_thread_mutex_t init_mutex; + LDAP_PVT_MUTEX_FIRSTCREATE( init_mutex ); + + LDAP_MUTEX_LOCK( &init_mutex ); +#endif + if ( gopts->ldo_valid == LDAP_INITIALIZED ) { + /* someone else got here first */ + goto done; + } + + ldap_int_error_init(); + + ldap_int_utils_init(); + +#ifdef HAVE_WINSOCK2 +{ WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 2, 0 ); + if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) { + /* Tell the user that we couldn't find a usable */ + /* WinSock DLL. */ + goto done; + } + + /* Confirm that the WinSock DLL supports 2.0.*/ + /* Note that if the DLL supports versions greater */ + /* than 2.0 in addition to 2.0, it will still return */ + /* 2.0 in wVersion since that is the version we */ + /* requested. */ + + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) + { + /* Tell the user that we couldn't find a usable */ + /* WinSock DLL. */ + WSACleanup( ); + goto done; + } +} /* The WinSock DLL is acceptable. Proceed. */ +#elif defined(HAVE_WINSOCK) +{ WSADATA wsaData; + if ( WSAStartup( 0x0101, &wsaData ) != 0 ) { + goto done; + } +} +#endif + +#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) + LDAP_MUTEX_LOCK( &ldap_int_hostname_mutex ); + { + char *name = ldap_int_hostname; + + ldap_int_hostname = ldap_pvt_get_fqdn( name ); + + if ( name != NULL && name != ldap_int_hostname ) { + LDAP_FREE( name ); + } + } + LDAP_MUTEX_UNLOCK( &ldap_int_hostname_mutex ); +#endif + +#ifndef HAVE_POLL + if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); +#endif + +#ifdef HAVE_CYRUS_SASL + if ( ldap_int_sasl_init() != 0 ) { + goto done; + } +#endif + + ldap_int_initialize_global_options(gopts, dbglvl); + + if( getenv("LDAPNOINIT") != NULL ) { + goto done; + } + +#ifdef LDAP_R_COMPILE + if( getenv("LDAPSTACKGUARD") != NULL ) { + ldap_int_stackguard = 1; + } +#endif + +#ifdef HAVE_CYRUS_SASL + { + /* set authentication identity to current user name */ + char *user = getenv("USER"); + + if( user == NULL ) user = getenv("USERNAME"); + if( user == NULL ) user = getenv("LOGNAME"); + + if( user != NULL ) { + gopts->ldo_def_sasl_authcid = LDAP_STRDUP( user ); + } + } +#endif + + openldap_ldap_init_w_sysconf(LDAP_CONF_FILE); + +#ifdef HAVE_GETEUID + if ( geteuid() != getuid() ) + goto done; +#endif + + openldap_ldap_init_w_userconf(LDAP_USERRC_FILE); + + { + char *altfile = getenv(LDAP_ENV_PREFIX "CONF"); + + if( altfile != NULL ) { + Debug2(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", + LDAP_ENV_PREFIX "CONF", altfile ); + openldap_ldap_init_w_sysconf( altfile ); + } + else + Debug1(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", + LDAP_ENV_PREFIX "CONF" ); + } + + { + char *altfile = getenv(LDAP_ENV_PREFIX "RC"); + + if( altfile != NULL ) { + Debug2(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n", + LDAP_ENV_PREFIX "RC", altfile ); + openldap_ldap_init_w_userconf( altfile ); + } + else + Debug1(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n", + LDAP_ENV_PREFIX "RC" ); + } + + openldap_ldap_init_w_env(gopts, NULL); + +done:; +#ifdef LDAP_R_COMPILE + LDAP_MUTEX_UNLOCK( &init_mutex ); +#endif +} diff --git a/libs/ldap/libldap/lbase64.c b/libs/ldap/libldap/lbase64.c new file mode 100644 index 00000000000..aa4a622fd03 --- /dev/null +++ b/libs/ldap/libldap/lbase64.c @@ -0,0 +1,108 @@ +/* lbase64.c - routines for dealing with base64 strings */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. This + * software is provided ``as is'' without express or implied warranty. + */ +/* This work was originally developed by the University of Michigan + * and distributed as part of U-MICH LDAP. + */ + +#include "portable.h" + +#include "ldap-int.h" + +#define RIGHT2 0x03 +#define RIGHT4 0x0f + +static const 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 +}; + +int +ldap_int_decode_b64_inplace( struct berval *value ) +{ + char *p, *end, *byte; + char nib; + + byte = value->bv_val; + end = value->bv_val + value->bv_len; + + for ( p = value->bv_val, value->bv_len = 0; + p < end; + p += 4, value->bv_len += 3 ) + { + int i; + for ( i = 0; i < 4; i++ ) { + if ( p[i] != '=' && (p[i] & 0x80 || + b642nib[ p[i] & 0x7f ] > 0x3f) ) { + Debug2( LDAP_DEBUG_ANY, + _("ldap_pvt_decode_b64_inplace: invalid base64 encoding" + " char (%c) 0x%x\n"), p[i], p[i] ); + return( -1 ); + } + } + + /* first digit */ + nib = b642nib[ p[0] & 0x7f ]; + byte[0] = nib << 2; + /* second digit */ + nib = b642nib[ p[1] & 0x7f ]; + byte[0] |= nib >> 4; + byte[1] = (nib & RIGHT4) << 4; + /* third digit */ + if ( p[2] == '=' ) { + value->bv_len += 1; + break; + } + nib = b642nib[ p[2] & 0x7f ]; + byte[1] |= nib >> 2; + byte[2] = (nib & RIGHT2) << 6; + /* fourth digit */ + if ( p[3] == '=' ) { + value->bv_len += 2; + break; + } + nib = b642nib[ p[3] & 0x7f ]; + byte[2] |= nib; + + byte += 3; + } + value->bv_val[ value->bv_len ] = '\0'; + + return LDAP_SUCCESS; +} diff --git a/libs/ldap/libldap/ldap-int.h b/libs/ldap/libldap/ldap-int.h new file mode 100644 index 00000000000..338992e5083 --- /dev/null +++ b/libs/ldap/libldap/ldap-int.h @@ -0,0 +1,925 @@ +/* ldap-int.h - defines & prototypes internal to the LDAP library */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ + +#ifndef _LDAP_INT_H +#define _LDAP_INT_H 1 + +#ifndef NO_THREADS +#define LDAP_R_COMPILE 1 +#endif + +#include "../liblber/lber-int.h" +#include "lutil.h" +#include "ldap_avl.h" + +#ifdef LDAP_R_COMPILE +#include <ldap_pvt_thread.h> +#endif + +#ifdef HAVE_CYRUS_SASL + /* the need for this should be removed */ +#ifdef HAVE_SASL_SASL_H +#include <sasl/sasl.h> +#else +#include <sasl.h> +#endif + +#define SASL_MAX_BUFF_SIZE (0xffffff) +#define SASL_MIN_BUFF_SIZE 4096 +#endif + +/* for struct timeval */ +#include <ac/time.h> +#include <ac/socket.h> + +#undef TV2MILLISEC +#define TV2MILLISEC(tv) (((tv)->tv_sec * 1000) + ((tv)->tv_usec/1000)) + +/* + * Support needed if the library is running in the kernel + */ +#if LDAP_INT_IN_KERNEL + /* + * Platform specific function to return a pointer to the + * process-specific global options. + * + * This function should perform the following functions: + * Allocate and initialize a global options struct on a per process basis + * Use callers process identifier to return its global options struct + * Note: Deallocate structure when the process exits + */ +# define LDAP_INT_GLOBAL_OPT() ldap_int_global_opt() + struct ldapoptions *ldap_int_global_opt(void); +#else +# define LDAP_INT_GLOBAL_OPT() (&ldap_int_global_options) +#endif + +/* if used from server code, ldap_debug already points elsewhere */ +#ifndef ldap_debug +#define ldap_debug ((LDAP_INT_GLOBAL_OPT())->ldo_debug) +#endif /* !ldap_debug */ + +#define LDAP_INT_DEBUG +#include "ldap_log.h" + +#ifdef LDAP_DEBUG + +#define DebugTest( level ) \ + ( ldap_debug & level ) + +#define Debug0( level, fmt ) \ + do { if ( DebugTest( (level) ) ) \ + ldap_log_printf( NULL, (level), fmt ); \ + } while ( 0 ) + +#define Debug1( level, fmt, arg1 ) \ + do { if ( DebugTest( (level) ) ) \ + ldap_log_printf( NULL, (level), fmt, arg1 ); \ + } while ( 0 ) + +#define Debug2( level, fmt, arg1, arg2 ) \ + do { if ( DebugTest( (level) ) ) \ + ldap_log_printf( NULL, (level), fmt, arg1, arg2 ); \ + } while ( 0 ) + +#define Debug3( level, fmt, arg1, arg2, arg3 ) \ + do { if ( DebugTest( (level) ) ) \ + ldap_log_printf( NULL, (level), fmt, arg1, arg2, arg3 ); \ + } while ( 0 ) + +#else + +#define DebugTest( level ) (0 == 1) +#define Debug0( level, fmt ) ((void)0) +#define Debug1( level, fmt, arg1 ) ((void)0) +#define Debug2( level, fmt, arg1, arg2 ) ((void)0) +#define Debug3( level, fmt, arg1, arg2, arg3 ) ((void)0) + +#endif /* LDAP_DEBUG */ + +#define LDAP_DEPRECATED 1 +#include "ldap.h" + +#include "ldap_pvt.h" + +LDAP_BEGIN_DECL + +#define LDAP_URL_PREFIX "ldap://" +#define LDAP_URL_PREFIX_LEN STRLENOF(LDAP_URL_PREFIX) +#define PLDAP_URL_PREFIX "pldap://" +#define PLDAP_URL_PREFIX_LEN STRLENOF(PLDAP_URL_PREFIX) +#define LDAPS_URL_PREFIX "ldaps://" +#define LDAPS_URL_PREFIX_LEN STRLENOF(LDAPS_URL_PREFIX) +#define PLDAPS_URL_PREFIX "pldaps://" +#define PLDAPS_URL_PREFIX_LEN STRLENOF(PLDAPS_URL_PREFIX) +#define LDAPI_URL_PREFIX "ldapi://" +#define LDAPI_URL_PREFIX_LEN STRLENOF(LDAPI_URL_PREFIX) +#ifdef LDAP_CONNECTIONLESS +#define LDAPC_URL_PREFIX "cldap://" +#define LDAPC_URL_PREFIX_LEN STRLENOF(LDAPC_URL_PREFIX) +#endif +#define LDAP_URL_URLCOLON "URL:" +#define LDAP_URL_URLCOLON_LEN STRLENOF(LDAP_URL_URLCOLON) + +#define LDAP_REF_STR "Referral:\n" +#define LDAP_REF_STR_LEN STRLENOF(LDAP_REF_STR) +#define LDAP_LDAP_REF_STR LDAP_URL_PREFIX +#define LDAP_LDAP_REF_STR_LEN LDAP_URL_PREFIX_LEN + +#define LDAP_DEFAULT_REFHOPLIMIT 5 + +#define LDAP_BOOL_REFERRALS 0 +#define LDAP_BOOL_RESTART 1 +#define LDAP_BOOL_TLS 3 +#define LDAP_BOOL_CONNECT_ASYNC 4 +#define LDAP_BOOL_SASL_NOCANON 5 +#define LDAP_BOOL_KEEPCONN 6 + +#define LDAP_BOOLEANS unsigned long +#define LDAP_BOOL(n) ((LDAP_BOOLEANS)1 << (n)) +#define LDAP_BOOL_GET(lo, bool) \ + ((lo)->ldo_booleans & LDAP_BOOL(bool) ? -1 : 0) +#define LDAP_BOOL_SET(lo, bool) ((lo)->ldo_booleans |= LDAP_BOOL(bool)) +#define LDAP_BOOL_CLR(lo, bool) ((lo)->ldo_booleans &= ~LDAP_BOOL(bool)) +#define LDAP_BOOL_ZERO(lo) ((lo)->ldo_booleans = 0) + +/* + * 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 { + ber_int_t 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_chain_tail; + struct ldapmsg *lm_next; /* next response */ + time_t lm_time; /* used to maintain cache */ +}; + +#ifdef HAVE_TLS +struct ldaptls { + char *lt_certfile; + char *lt_keyfile; + char *lt_dhfile; + char *lt_cacertfile; + char *lt_cacertdir; + char *lt_ciphersuite; + char *lt_crlfile; + char *lt_randfile; /* OpenSSL only */ + char *lt_ecname; /* OpenSSL only */ + int lt_protocol_min; + int lt_protocol_max; + struct berval lt_cacert; + struct berval lt_cert; + struct berval lt_key; +}; +#endif + +typedef struct ldaplist { + struct ldaplist *ll_next; + void *ll_data; +} ldaplist; + +/* + * LDAP Client Source IP structure + */ +typedef struct ldapsourceip { + char *local_ip_addrs; + struct in_addr ip4_addr; + unsigned short has_ipv4; +#ifdef LDAP_PF_INET6 + struct in6_addr ip6_addr; + unsigned short has_ipv6; +#endif +} ldapsourceip; + +/* + * structure representing get/set'able options + * which have global defaults. + * Protect access to this struct with ldo_mutex + * ldap_log.h:ldapoptions_prefix must match the head of this struct. + */ +struct ldapoptions { + short ldo_valid; +#define LDAP_UNINITIALIZED 0x0 +#define LDAP_INITIALIZED 0x1 +#define LDAP_VALID_SESSION 0x2 +#define LDAP_TRASHED_SESSION 0xFF + int ldo_debug; + + ber_int_t ldo_version; + ber_int_t ldo_deref; + ber_int_t ldo_timelimit; + ber_int_t ldo_sizelimit; + + /* per API call timeout */ + struct timeval ldo_tm_api; + struct timeval ldo_tm_net; + + LDAPURLDesc *ldo_defludp; + int ldo_defport; + char* ldo_defbase; + char* ldo_defbinddn; /* bind dn */ + + /* + * Per connection tcp-keepalive settings (Linux only, + * ignored where unsupported) + */ + ber_int_t ldo_keepalive_idle; + ber_int_t ldo_keepalive_probes; + ber_int_t ldo_keepalive_interval; + + /* + * Per connection tcp user timeout (Linux >= 2.6.37 only, + * ignored where unsupported) + */ + ber_uint_t ldo_tcp_user_timeout; + + int ldo_refhoplimit; /* limit on referral nesting */ + + /* LDAPv3 server and client controls */ + LDAPControl **ldo_sctrls; + LDAPControl **ldo_cctrls; + + /* LDAP rebind callback function */ + LDAP_REBIND_PROC *ldo_rebind_proc; + void *ldo_rebind_params; + LDAP_NEXTREF_PROC *ldo_nextref_proc; + void *ldo_nextref_params; + LDAP_URLLIST_PROC *ldo_urllist_proc; + void *ldo_urllist_params; + + /* LDAP connection callback stack */ + ldaplist *ldo_conn_cbs; + + LDAP_BOOLEANS ldo_booleans; /* boolean options */ + +#define LDAP_LDO_NULLARG ,0,0,0,0 ,{0},{0} ,0,0,0,0, 0,0,0,0,0, 0,0, 0,0,0,0,0,0, 0, 0 + + /* LDAP user configured bind IPs */ + struct ldapsourceip ldo_local_ip_addrs; + +#ifdef LDAP_PF_INET6 +#define LDAP_LDO_SOURCEIP_NULLARG ,{0,0,0,0,0} +#else +#define LDAP_LDO_SOURCEIP_NULLARG ,{0,0,0} +#endif + +#ifdef LDAP_CONNECTIONLESS +#define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp) + void* ldo_peer; /* struct sockaddr* */ + char* ldo_cldapdn; + int ldo_is_udp; +#define LDAP_LDO_CONNECTIONLESS_NULLARG ,0,0,0 +#else +#define LDAP_LDO_CONNECTIONLESS_NULLARG +#endif + +#ifdef HAVE_TLS + /* tls context */ + void *ldo_tls_ctx; + LDAP_TLS_CONNECT_CB *ldo_tls_connect_cb; + void* ldo_tls_connect_arg; + struct ldaptls ldo_tls_info; +#define ldo_tls_certfile ldo_tls_info.lt_certfile +#define ldo_tls_keyfile ldo_tls_info.lt_keyfile +#define ldo_tls_dhfile ldo_tls_info.lt_dhfile +#define ldo_tls_ecname ldo_tls_info.lt_ecname +#define ldo_tls_cacertfile ldo_tls_info.lt_cacertfile +#define ldo_tls_cacertdir ldo_tls_info.lt_cacertdir +#define ldo_tls_ciphersuite ldo_tls_info.lt_ciphersuite +#define ldo_tls_protocol_min ldo_tls_info.lt_protocol_min +#define ldo_tls_protocol_max ldo_tls_info.lt_protocol_max +#define ldo_tls_crlfile ldo_tls_info.lt_crlfile +#define ldo_tls_randfile ldo_tls_info.lt_randfile +#define ldo_tls_cacert ldo_tls_info.lt_cacert +#define ldo_tls_cert ldo_tls_info.lt_cert +#define ldo_tls_key ldo_tls_info.lt_key + int ldo_tls_mode; + int ldo_tls_require_cert; + int ldo_tls_impl; + int ldo_tls_crlcheck; + int ldo_tls_require_san; + char *ldo_tls_pin_hashalg; + struct berval ldo_tls_pin; +#define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0},0,0,0,0,0,0,{0,0} +#else +#define LDAP_LDO_TLS_NULLARG +#endif + +#ifdef HAVE_CYRUS_SASL + char* ldo_def_sasl_mech; /* SASL Mechanism(s) */ + char* ldo_def_sasl_realm; /* SASL realm */ + char* ldo_def_sasl_authcid; /* SASL authentication identity */ + char* ldo_def_sasl_authzid; /* SASL authorization identity */ + + /* SASL Security Properties */ + struct sasl_security_properties ldo_sasl_secprops; + int ldo_sasl_cbinding; +#define LDAP_LDO_SASL_NULLARG ,0,0,0,0,{0},0 +#else +#define LDAP_LDO_SASL_NULLARG +#endif + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_t ldo_mutex; +#define LDAP_LDO_MUTEX_NULLARG , LDAP_PVT_MUTEX_NULL +#else +#define LDAP_LDO_MUTEX_NULLARG +#endif +}; + + +/* + * structure for representing an LDAP server connection + */ +typedef struct ldap_conn { + Sockbuf *lconn_sb; +#ifdef HAVE_CYRUS_SASL + void *lconn_sasl_authctx; /* context for bind */ + void *lconn_sasl_sockctx; /* for security layer */ + void *lconn_sasl_cbind; /* for channel binding */ +#endif + int lconn_refcnt; + time_t lconn_created; /* time */ + time_t lconn_lastused; /* time */ + int lconn_rebind_inprogress; /* set if rebind in progress */ + char ***lconn_rebind_queue; /* used if rebind in progress */ + int lconn_status; +#define LDAP_CONNST_NEEDSOCKET 1 +#define LDAP_CONNST_CONNECTING 2 +#define LDAP_CONNST_CONNECTED 3 + LDAPURLDesc *lconn_server; + BerElement *lconn_ber; /* ber receiving on this conn. */ + + struct ldap_conn *lconn_next; +} LDAPConn; + + +/* + * structure used to track outstanding requests + */ +typedef struct ldapreq { + ber_int_t lr_msgid; /* the message id */ + int lr_status; /* status of request */ +#define LDAP_REQST_COMPLETED 0 +#define LDAP_REQST_INPROGRESS 1 +#define LDAP_REQST_CHASINGREFS 2 +#define LDAP_REQST_NOTCONNECTED 3 +#define LDAP_REQST_WRITING 4 + int lr_refcnt; /* count of references */ + int lr_outrefcnt; /* count of outstanding referrals */ + int lr_abandoned; /* the request has been abandoned */ + ber_int_t lr_origid; /* original request's message id */ + int lr_parentcnt; /* count of parent requests */ + ber_tag_t lr_res_msgtype; /* result message type */ + ber_int_t 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 */ + struct berval lr_dn; /* DN of request, in lr_ber */ + struct ldapreq *lr_parent; /* request that spawned this referral */ + struct ldapreq *lr_child; /* first child request */ + struct ldapreq *lr_refnext; /* next referral spawned */ + struct ldapreq *lr_prev; /* previous request */ + struct ldapreq *lr_next; /* next request */ +} LDAPRequest; + +/* + * structure for client cache + */ +#define LDAP_CACHE_BUCKETS 31 /* cache hash table size */ +typedef struct ldapcache { + LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */ + LDAPMessage *lc_requests; /* unfulfilled reqs */ + long lc_timeout; /* request timeout */ + ber_len_t lc_maxmem; /* memory to use */ + ber_len_t lc_memused; /* memory in use */ + int lc_enabled; /* enabled? */ + unsigned long lc_options; /* options */ +#define LDAP_CACHE_OPT_CACHENOERRS 0x00000001 +#define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002 +} LDAPCache; + +/* + * structure containing referral request info for rebind procedure + */ +typedef struct ldapreqinfo { + ber_len_t ri_msgid; + int ri_request; + char *ri_url; +} LDAPreqinfo; + +/* + * structure representing an ldap connection + */ + +struct ldap_common { + Sockbuf *ldc_sb; /* socket descriptor & buffer */ +#define ld_sb ldc->ldc_sb + + unsigned short ldc_lberoptions; +#define ld_lberoptions ldc->ldc_lberoptions + + /* protected by msgid_mutex */ + ber_len_t ldc_msgid; +#define ld_msgid ldc->ldc_msgid + + /* do not mess with these */ + /* protected by req_mutex */ + TAvlnode *ldc_requests; /* list of outstanding requests */ + /* protected by res_mutex */ + LDAPMessage *ldc_responses; /* list of outstanding responses */ +#define ld_requests ldc->ldc_requests +#define ld_responses ldc->ldc_responses + + /* protected by abandon_mutex */ + ber_len_t ldc_nabandoned; + ber_int_t *ldc_abandoned; /* array of abandoned requests */ +#define ld_nabandoned ldc->ldc_nabandoned +#define ld_abandoned ldc->ldc_abandoned + + /* unused by libldap */ + LDAPCache *ldc_cache; /* non-null if cache is initialized */ +#define ld_cache ldc->ldc_cache + + /* do not mess with the rest though */ + + /* protected by conn_mutex */ + LDAPConn *ldc_defconn; /* default connection */ +#define ld_defconn ldc->ldc_defconn + LDAPConn *ldc_conns; /* list of server connections */ +#define ld_conns ldc->ldc_conns + void *ldc_selectinfo;/* platform specifics for select */ +#define ld_selectinfo ldc->ldc_selectinfo + + /* ldap_common refcnt - free only if 0 */ + /* protected by ldc_mutex */ + unsigned int ldc_refcnt; +#define ld_ldcrefcnt ldc->ldc_refcnt + + /* protected by ldo_mutex */ + struct ldapoptions ldc_options; +#define ld_options ldc->ldc_options + +#define ld_valid ld_options.ldo_valid +#define ld_debug ld_options.ldo_debug + +#define ld_deref ld_options.ldo_deref +#define ld_timelimit ld_options.ldo_timelimit +#define ld_sizelimit ld_options.ldo_sizelimit + +#define ld_defbinddn ld_options.ldo_defbinddn +#define ld_defbase ld_options.ldo_defbase +#define ld_defhost ld_options.ldo_defhost +#define ld_defport ld_options.ldo_defport + +#define ld_refhoplimit ld_options.ldo_refhoplimit + +#define ld_sctrls ld_options.ldo_sctrls +#define ld_cctrls ld_options.ldo_cctrls +#define ld_rebind_proc ld_options.ldo_rebind_proc +#define ld_rebind_params ld_options.ldo_rebind_params +#define ld_nextref_proc ld_options.ldo_nextref_proc +#define ld_nextref_params ld_options.ldo_nextref_params +#define ld_urllist_proc ld_options.ldo_urllist_proc +#define ld_urllist_params ld_options.ldo_urllist_params + +#define ld_version ld_options.ldo_version + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_t ldc_mutex; + ldap_pvt_thread_mutex_t ldc_msgid_mutex; + ldap_pvt_thread_mutex_t ldc_conn_mutex; + ldap_pvt_thread_mutex_t ldc_req_mutex; + ldap_pvt_thread_mutex_t ldc_res_mutex; + ldap_pvt_thread_mutex_t ldc_abandon_mutex; +#define ld_ldopts_mutex ld_options.ldo_mutex +#define ld_ldcmutex ldc->ldc_mutex +#define ld_msgid_mutex ldc->ldc_msgid_mutex +#define ld_conn_mutex ldc->ldc_conn_mutex +#define ld_req_mutex ldc->ldc_req_mutex +#define ld_res_mutex ldc->ldc_res_mutex +#define ld_abandon_mutex ldc->ldc_abandon_mutex +#endif +}; + +struct ldap { + /* thread shared */ + struct ldap_common *ldc; + + /* thread specific */ + ber_int_t ld_errno; + char *ld_error; + char *ld_matched; + char **ld_referrals; +}; + +#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) +#define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION ) +#define LDAP_TRASH(ld) ( (ld)->ld_valid = LDAP_TRASHED_SESSION ) + +#ifdef LDAP_R_COMPILE +LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex; +LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_hostname_mutex; +LDAP_V ( int ) ldap_int_stackguard; + +#endif + +#ifdef LDAP_R_COMPILE +#define LDAP_MUTEX_LOCK(mutex) ldap_pvt_thread_mutex_lock( mutex ) +#define LDAP_MUTEX_UNLOCK(mutex) ldap_pvt_thread_mutex_unlock( mutex ) +#define LDAP_ASSERT_MUTEX_OWNER(mutex) \ + LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER(mutex) +#else +#define LDAP_MUTEX_LOCK(mutex) ((void) 0) +#define LDAP_MUTEX_UNLOCK(mutex) ((void) 0) +#define LDAP_ASSERT_MUTEX_OWNER(mutex) ((void) 0) +#endif + +#define LDAP_NEXT_MSGID(ld, id) do { \ + LDAP_MUTEX_LOCK( &(ld)->ld_msgid_mutex ); \ + (id) = ++(ld)->ld_msgid; \ + LDAP_MUTEX_UNLOCK( &(ld)->ld_msgid_mutex ); \ +} while (0) + +/* + * in abandon.c + */ + +LDAP_F (int) +ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp ); +LDAP_F (int) +ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx ); +LDAP_F (int) +ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx ); + +/* + * in add.c + */ + +LDAP_F (BerElement *) ldap_build_add_req LDAP_P(( + LDAP *ld, + const char *dn, + LDAPMod **attrs, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in lbase64.c + */ + +LDAP_F (int) ldap_int_decode_b64_inplace LDAP_P(( + struct berval *value )); + +/* + * in compare.c + */ + +LDAP_F (BerElement *) ldap_build_compare_req LDAP_P(( + LDAP *ld, + const char *dn, + const char *attr, + struct berval *bvalue, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in delete.c + */ + +LDAP_F (BerElement *) ldap_build_delete_req LDAP_P(( + LDAP *ld, + const char *dn, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in extended.c + */ + +LDAP_F (BerElement *) ldap_build_extended_req LDAP_P(( + LDAP *ld, + const char *reqoid, + struct berval *reqdata, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in init.c + */ + +LDAP_V ( struct ldapoptions ) ldap_int_global_options; + +LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *)); +LDAP_F ( void ) ldap_int_initialize_global_options LDAP_P(( + struct ldapoptions *, int *)); + +/* memory.c */ + /* simple macros to realloc for now */ +#define LDAP_MALLOC(s) (ber_memalloc_x((s),NULL)) +#define LDAP_CALLOC(n,s) (ber_memcalloc_x((n),(s),NULL)) +#define LDAP_REALLOC(p,s) (ber_memrealloc_x((p),(s),NULL)) +#define LDAP_FREE(p) (ber_memfree_x((p),NULL)) +#define LDAP_VFREE(v) (ber_memvfree_x((void **)(v),NULL)) +#define LDAP_STRDUP(s) (ber_strdup_x((s),NULL)) +#define LDAP_STRNDUP(s,l) (ber_strndup_x((s),(l),NULL)) + +#define LDAP_MALLOCX(s,x) (ber_memalloc_x((s),(x))) +#define LDAP_CALLOCX(n,s,x) (ber_memcalloc_x((n),(s),(x))) +#define LDAP_REALLOCX(p,s,x) (ber_memrealloc_x((p),(s),(x))) +#define LDAP_FREEX(p,x) (ber_memfree_x((p),(x))) +#define LDAP_VFREEX(v,x) (ber_memvfree_x((void **)(v),(x))) +#define LDAP_STRDUPX(s,x) (ber_strdup_x((s),(x))) +#define LDAP_STRNDUPX(s,l,x) (ber_strndup_x((s),(l),(x))) + +/* + * in error.c + */ +LDAP_F (void) ldap_int_error_init( void ); + +/* + * in modify.c + */ + +LDAP_F (BerElement *) ldap_build_modify_req LDAP_P(( + LDAP *ld, + const char *dn, + LDAPMod **mods, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in modrdn.c + */ + +LDAP_F (BerElement *) ldap_build_moddn_req LDAP_P(( + LDAP *ld, + const char *dn, + const char *newrdn, + const char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* + * in unit-int.c + */ +LDAP_F (void) ldap_int_utils_init LDAP_P(( void )); + + +/* + * in print.c + */ +LDAP_F (int) ldap_log_printf LDAP_P((LDAP *ld, int level, const char *fmt, ...)) LDAP_GCCATTR((format(printf, 3, 4))); + +/* + * in controls.c + */ +LDAP_F (int) ldap_int_put_controls LDAP_P(( + LDAP *ld, + LDAPControl *const *ctrls, + BerElement *ber )); + +LDAP_F (int) ldap_int_client_controls LDAP_P(( + LDAP *ld, + LDAPControl **ctrlp )); + +/* + * in dsparse.c + */ +LDAP_F (int) ldap_int_next_line_tokens LDAP_P(( char **bufp, ber_len_t *blenp, char ***toksp )); + + +/* + * in open.c + */ +LDAP_F (int) ldap_open_defconn( LDAP *ld ); +LDAP_F (int) ldap_int_open_connection( LDAP *ld, + LDAPConn *conn, LDAPURLDesc *srvlist, int async ); +LDAP_F (int) ldap_int_check_async_open( LDAP *ld, ber_socket_t sd ); + +/* + * in os-ip.c + */ +#ifndef HAVE_POLL +LDAP_V (int) ldap_int_tblsize; +LDAP_F (void) ldap_int_ip_init( void ); +#endif + +LDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, + const struct timeval *tm ); +LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, + int proto, LDAPURLDesc *srv, int async ); +LDAP_F (int) ldap_int_poll( LDAP *ld, ber_socket_t s, + struct timeval *tvp, int wr ); + +#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) +LDAP_V (char *) ldap_int_hostname; +LDAP_F (char *) ldap_host_connected_to( Sockbuf *sb, + const char *host ); +#endif + +LDAP_F (int) ldap_int_select( LDAP *ld, struct timeval *timeout ); +LDAP_F (void *) ldap_new_select_info( void ); +LDAP_F (void) ldap_free_select_info( void *sip ); +LDAP_F (void) ldap_mark_select_write( LDAP *ld, Sockbuf *sb ); +LDAP_F (void) ldap_mark_select_read( LDAP *ld, Sockbuf *sb ); +LDAP_F (void) ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ); +LDAP_F (void) ldap_clear_select_write( LDAP *ld, Sockbuf *sb ); +LDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb ); +LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); + +LDAP_F (int) ldap_validate_and_fill_sourceip ( char** source_ip_lst, + ldapsourceip* temp_source_ip ); + +LDAP_F (int) ldap_int_connect_cbs( LDAP *ld, Sockbuf *sb, + ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr ); + +/* + * in os-local.c + */ +#ifdef LDAP_PF_LOCAL +LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, + LDAPURLDesc *srv, int async ); +#endif /* LDAP_PF_LOCAL */ + +/* + * in request.c + */ +LDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype, + const char *dn, BerElement *ber, ber_int_t msgid ); +LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld ); +LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber ); + +LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, + ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, + LDAPConn *lc, LDAPreqinfo *bind, int noconn, int m_res ); +LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, + int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res ); +LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ); +LDAP_F (void) ldap_return_request( LDAP *ld, LDAPRequest *lr, int freeit ); +LDAP_F (int) ldap_req_cmp( const void *l, const void *r ); +LDAP_F (void) ldap_do_free_request( void *arg ); +LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr ); +LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ); +LDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ); +LDAP_F (void) ldap_dump_requests_and_responses( LDAP *ld ); +LDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, + char **errstrp, int sref, int *hadrefp ); +LDAP_F (int) ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, + char **refs, int sref, char **referralsp, int *hadrefp ); +LDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s ); +LDAP_F (int) ldap_int_flush_request( LDAP *ld, LDAPRequest *lr ); + +/* + * in result.c: + */ +LDAP_F (const char *) ldap_int_msgtype2str( ber_tag_t tag ); + +/* + * in search.c + */ +LDAP_F (BerElement *) ldap_build_search_req LDAP_P(( + LDAP *ld, + const char *base, + ber_int_t scope, + const char *filter, + char **attrs, + ber_int_t attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t timelimit, + ber_int_t sizelimit, + ber_int_t deref, + ber_int_t *msgidp)); + + +/* + * in unbind.c + */ +LDAP_F (int) ldap_ld_free LDAP_P(( + LDAP *ld, + int close, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +LDAP_F (int) ldap_send_unbind LDAP_P(( + LDAP *ld, + Sockbuf *sb, + LDAPControl **sctrls, + LDAPControl **cctrls )); + +/* + * in url.c + */ +LDAP_F (LDAPURLDesc *) ldap_url_dup LDAP_P(( + LDAPURLDesc *ludp )); + +LDAP_F (LDAPURLDesc *) ldap_url_duplist LDAP_P(( + LDAPURLDesc *ludlist )); + +LDAP_F (int) ldap_url_parsehosts LDAP_P(( + LDAPURLDesc **ludlist, + const char *hosts, + int port )); + +LDAP_F (char *) ldap_url_list2hosts LDAP_P(( + LDAPURLDesc *ludlist )); + +/* + * in cyrus.c + */ + +LDAP_F (int) ldap_int_sasl_init LDAP_P(( void )); + +LDAP_F (int) ldap_int_sasl_open LDAP_P(( + LDAP *ld, LDAPConn *conn, + const char* host )); +LDAP_F (int) ldap_int_sasl_close LDAP_P(( LDAP *ld, LDAPConn *conn )); + +LDAP_F (int) ldap_int_sasl_external LDAP_P(( + LDAP *ld, LDAPConn *conn, + const char* authid, ber_len_t ssf )); + +LDAP_F (int) ldap_int_sasl_get_option LDAP_P(( LDAP *ld, + int option, void *arg )); +LDAP_F (int) ldap_int_sasl_set_option LDAP_P(( LDAP *ld, + int option, void *arg )); +LDAP_F (int) ldap_int_sasl_config LDAP_P(( struct ldapoptions *lo, + int option, const char *arg )); + +LDAP_F (int) ldap_int_sasl_bind LDAP_P(( + LDAP *ld, + const char *, + const char *, + LDAPControl **, LDAPControl **, + + /* should be passed in client controls */ + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults, + LDAPMessage *result, + const char **rmech, + int *msgid )); + +/* in sasl.c */ + +LDAP_F (BerElement *) ldap_build_bind_req LDAP_P(( + LDAP *ld, + const char *dn, + const char *mech, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp )); + +/* in schema.c */ +LDAP_F (char *) ldap_int_parse_numericoid LDAP_P(( + const char **sp, + int *code, + const int flags )); + +/* + * in tls.c + */ +LDAP_F (int) ldap_int_tls_start LDAP_P(( LDAP *ld, + LDAPConn *conn, LDAPURLDesc *srv )); + +LDAP_F (void) ldap_int_tls_destroy LDAP_P(( struct ldapoptions *lo )); + +/* + * in getvalues.c + */ +LDAP_F (char **) ldap_value_dup LDAP_P(( + char *const *vals )); + +LDAP_END_DECL + +#endif /* _LDAP_INT_H */ diff --git a/libs/ldap/libldap/ldap-tls.h b/libs/ldap/libldap/ldap-tls.h new file mode 100644 index 00000000000..ef2a1d88060 --- /dev/null +++ b/libs/ldap/libldap/ldap-tls.h @@ -0,0 +1,88 @@ +/* ldap-tls.h - TLS defines & prototypes internal to the LDAP library */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2008-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifndef _LDAP_TLS_H +#define _LDAP_TLS_H 1 + +struct tls_impl; + +struct tls_ctx; +struct tls_session; + +typedef struct tls_ctx tls_ctx; +typedef struct tls_session tls_session; + +typedef int (TI_tls_init)(void); +typedef void (TI_tls_destroy)(void); + +typedef tls_ctx *(TI_ctx_new)(struct ldapoptions *lo); +typedef void (TI_ctx_ref)(tls_ctx *ctx); +typedef void (TI_ctx_free)(tls_ctx *ctx); +typedef int (TI_ctx_init)(struct ldapoptions *lo, struct ldaptls *lt, int is_server); + +typedef tls_session *(TI_session_new)(tls_ctx *ctx, int is_server); +typedef int (TI_session_connect)(LDAP *ld, tls_session *s, const char *name_in); +typedef int (TI_session_accept)(tls_session *s); +typedef int (TI_session_upflags)(Sockbuf *sb, tls_session *s, int rc); +typedef char *(TI_session_errmsg)(tls_session *s, int rc, char *buf, size_t len ); +typedef int (TI_session_dn)(tls_session *sess, struct berval *dn); +typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in); +typedef int (TI_session_strength)(tls_session *sess); +typedef int (TI_session_unique)(tls_session *sess, struct berval *buf, int is_server); +typedef int (TI_session_endpoint)(tls_session *sess, struct berval *buf, int is_server); +typedef const char *(TI_session_name)(tls_session *s); +typedef int (TI_session_peercert)(tls_session *s, struct berval *der); +typedef int (TI_session_pinning)(LDAP *ld, tls_session *s, char *hashalg, struct berval *hash); + +typedef void (TI_thr_init)(void); + +typedef struct tls_impl { + const char *ti_name; + + TI_tls_init *ti_tls_init; /* library initialization */ + TI_tls_destroy *ti_tls_destroy; + + TI_ctx_new *ti_ctx_new; + TI_ctx_ref *ti_ctx_ref; + TI_ctx_free *ti_ctx_free; + TI_ctx_init *ti_ctx_init; + + TI_session_new *ti_session_new; + TI_session_connect *ti_session_connect; + TI_session_accept *ti_session_accept; + TI_session_upflags *ti_session_upflags; + TI_session_errmsg *ti_session_errmsg; + TI_session_dn *ti_session_my_dn; + TI_session_dn *ti_session_peer_dn; + TI_session_chkhost *ti_session_chkhost; + TI_session_strength *ti_session_strength; + TI_session_unique *ti_session_unique; + TI_session_endpoint *ti_session_endpoint; + TI_session_name *ti_session_version; + TI_session_name *ti_session_cipher; + TI_session_peercert *ti_session_peercert; + TI_session_pinning *ti_session_pinning; + + Sockbuf_IO *ti_sbio; + + TI_thr_init *ti_thr_init; + + int ti_inited; +} tls_impl; + +extern tls_impl ldap_int_tls_impl; + +#endif /* _LDAP_TLS_H */ diff --git a/libs/ldap/libldap/ldap_thr_debug.h b/libs/ldap/libldap/ldap_thr_debug.h new file mode 100644 index 00000000000..db6a052185c --- /dev/null +++ b/libs/ldap/libldap/ldap_thr_debug.h @@ -0,0 +1,197 @@ +/* ldap_thr_debug.h - preprocessor magic for LDAP_THREAD_DEBUG */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2005-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#ifdef LDAP_THREAD_DEBUG + +/* + * libldap .c files should include this file after ldap_pvt_thread.h, + * with the appropriate LDAP_THREAD*_IMPLEMENTATION macro(s) defined. + */ + +#ifndef _LDAP_PVT_THREAD_H +#error "ldap_pvt_thread.h" must be included before "ldap_thr_debug.h" +#endif + +/* + * Support for thr_debug.c: + * + * thr_debug.c defines ldap_pvt_thread_* as wrappers around the real + * ldap_pvt_thread_* implementation, which this file renames to + * ldap_int_thread_*. + * + * Implementation: + * + * This file re#defines selected ldap_pvt_thread_* names to + * ldap_int_thread_*, which will be used from wrappers in thr_debug.c. + * Two ldap_int_*() calls are redirected to call ldap_debug_*(): These + * are wrappers around the originals, whose definitions are not renamed. + * This file then #includes ldap_pvt_thread.h to declare the renamed + * functions/types. If #included from thr_debug.c it finally #undefines + * the macros again. + * + * include/ldap_pvt_thread.h declares the typedefs ldap_pvt_thread*_t as + * either wrapper types ldap_debug_thread*_t or their usual definitions + * ldap_int_thread*_t, depending on the LDAP_THREAD_DEBUG_WRAP option. + * When defining the underlying implementation, this file then redirects + * the type names back to the original ldap_int_thread*_t types. + * include/ldap_<int,pvt>_thread.h also do some thr_debug magic. + * + * So, + * libldap/<not thr_debug.c> thus define ldap_int_thread_*() instead + * of ldap_pvt_thread_*(). + * thr_debug.c defines the ldap_pvt_*() and ldap_debug_*() functions. + * In thread.c, ldap_pvt_thread_<initialize/destroy>() will call + * ldap_debug_thread_*() instead of ldap_int_thread_*(). + * In tpool.c, ldap_int_thread_pool_shutdown() has explicit thr_debug.c + * support which treats ldap_pvt_thread_pool_destroy() the same way. + */ + +#ifndef LDAP_THREAD_IMPLEMENTATION /* for first part of threads.c */ +#define ldap_int_thread_initialize ldap_debug_thread_initialize +#define ldap_int_thread_destroy ldap_debug_thread_destroy +#else /* LDAP_THREAD_IMPLEMENTATION -- for thr_*.c and end of threads.c */ +#undef ldap_int_thread_initialize +#undef ldap_int_thread_destroy +#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ +#define ldap_pvt_thread_mutex_t ldap_int_thread_mutex_t +#define ldap_pvt_thread_cond_t ldap_int_thread_cond_t +#endif +#define ldap_pvt_thread_sleep ldap_int_thread_sleep +#define ldap_pvt_thread_get_concurrency ldap_int_thread_get_concurrency +#define ldap_pvt_thread_set_concurrency ldap_int_thread_set_concurrency +#define ldap_pvt_thread_create ldap_int_thread_create +#define ldap_pvt_thread_exit ldap_int_thread_exit +#define ldap_pvt_thread_join ldap_int_thread_join +#define ldap_pvt_thread_kill ldap_int_thread_kill +#define ldap_pvt_thread_yield ldap_int_thread_yield +#define ldap_pvt_thread_cond_init ldap_int_thread_cond_init +#define ldap_pvt_thread_cond_destroy ldap_int_thread_cond_destroy +#define ldap_pvt_thread_cond_signal ldap_int_thread_cond_signal +#define ldap_pvt_thread_cond_broadcast ldap_int_thread_cond_broadcast +#define ldap_pvt_thread_cond_wait ldap_int_thread_cond_wait +#define ldap_pvt_thread_mutex_init ldap_int_thread_mutex_init +#define ldap_pvt_thread_mutex_recursive_init ldap_int_thread_mutex_recursive_init +#define ldap_pvt_thread_mutex_destroy ldap_int_thread_mutex_destroy +#define ldap_pvt_thread_mutex_lock ldap_int_thread_mutex_lock +#define ldap_pvt_thread_mutex_trylock ldap_int_thread_mutex_trylock +#define ldap_pvt_thread_mutex_unlock ldap_int_thread_mutex_unlock +#define ldap_pvt_thread_self ldap_int_thread_self +#endif /* LDAP_THREAD_IMPLEMENTATION */ + +#ifdef LDAP_THREAD_RDWR_IMPLEMENTATION /* rdwr.c, thr_debug.c */ +#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ +#define ldap_pvt_thread_rdwr_t ldap_int_thread_rdwr_t +#endif +#define ldap_pvt_thread_rdwr_init ldap_int_thread_rdwr_init +#define ldap_pvt_thread_rdwr_destroy ldap_int_thread_rdwr_destroy +#define ldap_pvt_thread_rdwr_rlock ldap_int_thread_rdwr_rlock +#define ldap_pvt_thread_rdwr_rtrylock ldap_int_thread_rdwr_rtrylock +#define ldap_pvt_thread_rdwr_runlock ldap_int_thread_rdwr_runlock +#define ldap_pvt_thread_rdwr_wlock ldap_int_thread_rdwr_wlock +#define ldap_pvt_thread_rdwr_wtrylock ldap_int_thread_rdwr_wtrylock +#define ldap_pvt_thread_rdwr_wunlock ldap_int_thread_rdwr_wunlock +#define ldap_pvt_thread_rdwr_readers ldap_int_thread_rdwr_readers +#define ldap_pvt_thread_rdwr_writers ldap_int_thread_rdwr_writers +#define ldap_pvt_thread_rdwr_active ldap_int_thread_rdwr_active +#endif /* LDAP_THREAD_RDWR_IMPLEMENTATION */ + +#ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c, thr_debug.c */ +#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */ +#define ldap_pvt_thread_pool_t ldap_int_thread_pool_t +#endif +#define ldap_pvt_thread_pool_init ldap_int_thread_pool_init +#define ldap_pvt_thread_pool_submit ldap_int_thread_pool_submit +#define ldap_pvt_thread_pool_maxthreads ldap_int_thread_pool_maxthreads +#define ldap_pvt_thread_pool_backload ldap_int_thread_pool_backload +#define ldap_pvt_thread_pool_pause ldap_int_thread_pool_pause +#define ldap_pvt_thread_pool_resume ldap_int_thread_pool_resume +#define ldap_pvt_thread_pool_destroy ldap_int_thread_pool_destroy +#define ldap_pvt_thread_pool_close ldap_int_thread_pool_close +#define ldap_pvt_thread_pool_free ldap_int_thread_pool_free +#define ldap_pvt_thread_pool_getkey ldap_int_thread_pool_getkey +#define ldap_pvt_thread_pool_setkey ldap_int_thread_pool_setkey +#define ldap_pvt_thread_pool_purgekey ldap_int_thread_pool_purgekey +#define ldap_pvt_thread_pool_context ldap_int_thread_pool_context +#define ldap_pvt_thread_pool_context_reset ldap_int_thread_pool_context_reset +#endif /* LDAP_THREAD_POOL_IMPLEMENTATION */ + +#undef _LDAP_PVT_THREAD_H +#include "ldap_pvt_thread.h" + +#ifdef LDAP_THREAD_POOL_IMPLEMENTATION /* tpool.c */ +/* + * tpool.c:ldap_int_thread_pool_shutdown() needs this. Could not + * use it for ldap_pvt_thread.h above because of its use of LDAP_P(). + */ +#undef ldap_pvt_thread_pool_destroy +#define ldap_pvt_thread_pool_destroy(p,r) ldap_int_thread_pool_destroy(p,r) +#endif + +#ifdef LDAP_THREAD_DEBUG_IMPLEMENTATION /* thr_debug.c */ +#undef ldap_pvt_thread_mutex_t +#undef ldap_pvt_thread_cond_t +#undef ldap_pvt_thread_sleep +#undef ldap_pvt_thread_get_concurrency +#undef ldap_pvt_thread_set_concurrency +#undef ldap_pvt_thread_create +#undef ldap_pvt_thread_exit +#undef ldap_pvt_thread_join +#undef ldap_pvt_thread_kill +#undef ldap_pvt_thread_yield +#undef ldap_pvt_thread_cond_init +#undef ldap_pvt_thread_cond_destroy +#undef ldap_pvt_thread_cond_signal +#undef ldap_pvt_thread_cond_broadcast +#undef ldap_pvt_thread_cond_wait +#undef ldap_pvt_thread_mutex_init +#undef ldap_pvt_thread_mutex_recursive_init +#undef ldap_pvt_thread_mutex_destroy +#undef ldap_pvt_thread_mutex_lock +#undef ldap_pvt_thread_mutex_trylock +#undef ldap_pvt_thread_mutex_unlock +#undef ldap_pvt_thread_self +/* LDAP_THREAD_RDWR_IMPLEMENTATION: */ +#undef ldap_pvt_thread_rdwr_t +#undef ldap_pvt_thread_rdwr_init +#undef ldap_pvt_thread_rdwr_destroy +#undef ldap_pvt_thread_rdwr_rlock +#undef ldap_pvt_thread_rdwr_rtrylock +#undef ldap_pvt_thread_rdwr_runlock +#undef ldap_pvt_thread_rdwr_wlock +#undef ldap_pvt_thread_rdwr_wtrylock +#undef ldap_pvt_thread_rdwr_wunlock +#undef ldap_pvt_thread_rdwr_readers +#undef ldap_pvt_thread_rdwr_writers +#undef ldap_pvt_thread_rdwr_active +/* LDAP_THREAD_POOL_IMPLEMENTATION: */ +#undef ldap_pvt_thread_pool_t +#undef ldap_pvt_thread_pool_init +#undef ldap_pvt_thread_pool_submit +#undef ldap_pvt_thread_pool_maxthreads +#undef ldap_pvt_thread_pool_backload +#undef ldap_pvt_thread_pool_pause +#undef ldap_pvt_thread_pool_resume +#undef ldap_pvt_thread_pool_destroy +#undef ldap_pvt_thread_pool_close +#undef ldap_pvt_thread_pool_free +#undef ldap_pvt_thread_pool_getkey +#undef ldap_pvt_thread_pool_setkey +#undef ldap_pvt_thread_pool_purgekey +#undef ldap_pvt_thread_pool_context +#undef ldap_pvt_thread_pool_context_reset +#endif /* LDAP_THREAD_DEBUG_IMPLEMENTATION */ + +#endif /* LDAP_THREAD_DEBUG */ diff --git a/libs/ldap/libldap/ldif.c b/libs/ldap/libldap/ldif.c new file mode 100644 index 00000000000..bf75dd0b013 --- /dev/null +++ b/libs/ldap/libldap/ldif.c @@ -0,0 +1,919 @@ +/* ldif.c - routines for dealing with LDIF files */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. This + * software is provided ``as is'' without express or implied warranty. + */ +/* This work was originally developed by the University of Michigan + * and distributed as part of U-MICH LDAP. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/ctype.h> + +#include <ac/string.h> +#include <ac/socket.h> +#include <ac/time.h> + +int ldif_debug = 0; + +#include "ldap-int.h" +#include "ldif.h" + +#define CONTINUED_LINE_MARKER '\r' + +#ifdef CSRIMALLOC +#define ber_memalloc malloc +#define ber_memcalloc calloc +#define ber_memrealloc realloc +#define ber_strdup strdup +#endif + +static const char nib2b64[0x40] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* + * 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. The type and value are stored in malloc'd + * memory which must be freed by the caller. + * + * ldif_parse_line2 - operates in-place on input buffer, returning type + * in-place. Will return value in-place if possible, (must malloc for + * fetched URLs). If freeval is NULL, all return data will be malloc'd + * and the input line will be unmodified. Otherwise freeval is set to + * True if the value was malloc'd. + */ + +int +ldif_parse_line( + LDAP_CONST char *line, + char **typep, + char **valuep, + ber_len_t *vlenp +) +{ + struct berval type, value; + int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); + + *typep = type.bv_val; + *valuep = value.bv_val; + *vlenp = value.bv_len; + return rc; +} + +int +ldif_parse_line2( + char *line, + struct berval *type, + struct berval *value, + int *freeval +) +{ + char *s, *p, *d; + int b64, url; + + BER_BVZERO( type ); + BER_BVZERO( value ); + + /* skip any leading space */ + while ( isspace( (unsigned char) *line ) ) { + line++; + } + + if ( freeval ) { + *freeval = 0; + } else { + line = ber_strdup( line ); + + if( line == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: line malloc failed\n")); + return( -1 ); + } + } + + type->bv_val = line; + + s = strchr( type->bv_val, ':' ); + + if ( s == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: missing ':' after %s\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + /* trim any space between type and : */ + for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { + *p = '\0'; + } + *s++ = '\0'; + type->bv_len = s - type->bv_val - 1; + + url = 0; + b64 = 0; + + if ( *s == '<' ) { + s++; + url = 1; + + } else if ( *s == ':' ) { + /* base 64 encoded value */ + s++; + b64 = 1; + } + + /* skip space between : and value */ + while ( isspace( (unsigned char) *s ) ) { + s++; + } + + /* check for continued line markers that should be deleted */ + for ( p = s, d = s; *p; p++ ) { + if ( *p != CONTINUED_LINE_MARKER ) + *d++ = *p; + } + *d = '\0'; + + if ( b64 ) { + char *byte = s; + + if ( *s == '\0' ) { + /* no value is present, error out */ + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: %s missing base64 value\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + value->bv_val = s; + value->bv_len = d - s; + if ( ldap_int_decode_b64_inplace( value ) != LDAP_SUCCESS ) { + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: %s base64 decode failed\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + } else if ( url ) { + if ( *s == '\0' ) { + /* no value is present, error out */ + ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, + _("ldif_parse_line: %s missing URL value\n"), + type->bv_val ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + + if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: %s: URL "%s" fetch failed\n"), + type->bv_val, s ); + if ( !freeval ) ber_memfree( line ); + return( -1 ); + } + if ( freeval ) *freeval = 1; + + } else { + value->bv_val = s; + value->bv_len = (int) (d - s); + } + + if ( !freeval ) { + struct berval bv = *type; + + ber_dupbv( type, &bv ); + + if( BER_BVISNULL( type )) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: type malloc failed\n")); + if( url ) ber_memfree( value->bv_val ); + ber_memfree( line ); + return( -1 ); + } + + if( !url ) { + bv = *value; + ber_dupbv( value, &bv ); + if( BER_BVISNULL( value )) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_parse_line: value malloc failed\n")); + ber_memfree( type->bv_val ); + ber_memfree( line ); + return( -1 ); + } + } + + ber_memfree( line ); + } + + return( 0 ); +} + +/* + * 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 preceding newline are changed + * into CONTINUED_LINE_MARKER chars, to be deleted later by the + * ldif_parse_line() routine above. + * + * ldif_getline will skip over any line which starts '#'. + * + * ldif_getline takes a pointer to a pointer to the buffer on the first call, + * which it updates and must be supplied on subsequent calls. + */ + +int +ldif_countlines( LDAP_CONST char *buf ) +{ + char *nl; + int ret = 0; + + if ( !buf ) return ret; + + for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { + nl++; + if ( *nl != ' ' ) ret++; + } + return ret; +} + +char * +ldif_getline( char **next ) +{ + char *line; + + do { + if ( *next == NULL || **next == '\n' || **next == '\0' ) { + return( NULL ); + } + + line = *next; + + while ( (*next = strchr( *next, '\n' )) != NULL ) { +#if CONTINUED_LINE_MARKER != '\r' + if ( (*next)[-1] == '\r' ) { + (*next)[-1] = CONTINUED_LINE_MARKER; + } +#endif + + if ( (*next)[1] != ' ' ) { + if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { + *(*next)++ = '\0'; + } + *(*next)++ = '\0'; + break; + } + + **next = CONTINUED_LINE_MARKER; + (*next)[1] = CONTINUED_LINE_MARKER; + (*next)++; + } + } while( *line == '#' ); + + return( line ); +} + +/* + * name and OID of attributeTypes that must be base64 encoded in any case + */ +typedef struct must_b64_encode_s { + struct berval name; + struct berval oid; +} must_b64_encode_s; + +static must_b64_encode_s default_must_b64_encode[] = { + { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, + { BER_BVNULL, BER_BVNULL } +}; + +static must_b64_encode_s *must_b64_encode = default_must_b64_encode; + +/* + * register name and OID of attributeTypes that must always be base64 + * encoded + * + * NOTE: this routine mallocs memory in a static struct which must + * be explicitly freed when no longer required + */ +int +ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) +{ + int i; + ber_len_t len; + + assert( must_b64_encode != NULL ); + assert( name != NULL ); + assert( oid != NULL ); + + len = strlen( name ); + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + if ( len != must_b64_encode[i].name.bv_len ) { + continue; + } + + if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { + break; + } + } + + if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { + return 1; + } + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) + /* just count */ ; + + if ( must_b64_encode == default_must_b64_encode ) { + must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); + if ( must_b64_encode == NULL ) { + return 1; + } + + for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { + ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); + ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); + } + + } else { + must_b64_encode_s *tmp; + + tmp = ber_memrealloc( must_b64_encode, + sizeof( must_b64_encode_s ) * ( i + 2 ) ); + if ( tmp == NULL ) { + return 1; + } + must_b64_encode = tmp; + } + + ber_str2bv( name, len, 1, &must_b64_encode[i].name ); + ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); + + BER_BVZERO( &must_b64_encode[i + 1].name ); + + return 0; +} + +void +ldif_must_b64_encode_release( void ) +{ + int i; + + assert( must_b64_encode != NULL ); + + if ( must_b64_encode == default_must_b64_encode ) { + return; + } + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + ber_memfree( must_b64_encode[i].name.bv_val ); + ber_memfree( must_b64_encode[i].oid.bv_val ); + } + + ber_memfree( must_b64_encode ); + + must_b64_encode = default_must_b64_encode; +} + +/* + * returns 1 iff the string corresponds to the name or the OID of any + * of the attributeTypes listed in must_b64_encode + */ +static int +ldif_must_b64_encode( LDAP_CONST char *s ) +{ + int i; + struct berval bv; + + assert( must_b64_encode != NULL ); + assert( s != NULL ); + + ber_str2bv( s, 0, 0, &bv ); + + for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { + if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 + || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) + { + return 1; + } + } + + return 0; +} + +/* NOTE: only preserved for binary compatibility */ +void +ldif_sput( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen ) +{ + ldif_sput_wrap( out, type, name, val, vlen, 0 ); +} + +void +ldif_sput_wrap( + char **out, + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap ) +{ + const unsigned char *byte, *stop; + unsigned char buf[3]; + unsigned long bits; + char *save; + int pad; + int namelen = 0; + + ber_len_t savelen; + ber_len_t len=0; + ber_len_t i; + + if ( !wrap ) + wrap = LDIF_LINE_WIDTH; + + /* prefix */ + switch( type ) { + case LDIF_PUT_COMMENT: + *(*out)++ = '#'; + len++; + + if( vlen ) { + *(*out)++ = ' '; + len++; + } + + break; + + case LDIF_PUT_SEP: + *(*out)++ = '\n'; + return; + } + + /* name (attribute type) */ + if( name != NULL ) { + /* put the name + ":" */ + namelen = strlen(name); + strcpy(*out, name); + *out += namelen; + len += namelen; + + if( type != LDIF_PUT_COMMENT ) { + *(*out)++ = ':'; + len++; + } + + } +#ifdef LDAP_DEBUG + else { + assert( type == LDIF_PUT_COMMENT ); + } +#endif + + if( vlen == 0 ) { + *(*out)++ = '\n'; + return; + } + + switch( type ) { + case LDIF_PUT_NOVALUE: + *(*out)++ = '\n'; + return; + + case LDIF_PUT_URL: /* url value */ + *(*out)++ = '<'; + len++; + break; + + case LDIF_PUT_B64: /* base64 value */ + *(*out)++ = ':'; + len++; + break; + } + + switch( type ) { + case LDIF_PUT_TEXT: + case LDIF_PUT_URL: + case LDIF_PUT_B64: + *(*out)++ = ' '; + len++; + /* fall-thru */ + + case LDIF_PUT_COMMENT: + /* pre-encoded names */ + for ( i=0; i < vlen; i++ ) { + if ( len > wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + *(*out)++ = val[i]; + len++; + } + *(*out)++ = '\n'; + return; + } + + save = *out; + savelen = len; + + *(*out)++ = ' '; + len++; + + stop = (const unsigned char *) (val + vlen); + + if ( type == LDIF_PUT_VALUE + && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' + && isgraph( (unsigned char) val[vlen-1] ) +#ifndef LDAP_BINARY_DEBUG + && strstr( name, ";binary" ) == NULL +#endif +#ifndef LDAP_PASSWD_DEBUG + && !ldif_must_b64_encode( name ) +#endif + ) { + int b64 = 0; + + for ( byte = (const unsigned char *) val; byte < stop; + byte++, len++ ) + { + if ( !isascii( *byte ) || !isprint( *byte ) ) { + b64 = 1; + break; + } + if ( len >= wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + *(*out)++ = *byte; + } + + if( !b64 ) { + *(*out)++ = '\n'; + return; + } + } + + *out = save; + *(*out)++ = ':'; + *(*out)++ = ' '; + len = savelen + 2; + + /* convert to base 64 (3 bytes => 4 base 64 digits) */ + for ( byte = (const unsigned char *) val; + 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++, len++, bits <<= 6 ) { + if ( len >= wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + /* 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++, len++, bits <<= 6 ) { + if ( len >= wrap ) { + *(*out)++ = '\n'; + *(*out)++ = ' '; + len = 1; + } + + if( i + pad < 4 ) { + /* get b64 digit from low order 6 bits */ + *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; + } else { + *(*out)++ = '='; + } + } + } + *(*out)++ = '\n'; +} + + +/* + * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line + */ + +/* NOTE: only preserved for binary compatibility */ +char * +ldif_put( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen ) +{ + return ldif_put_wrap( type, name, val, vlen, 0 ); +} + +char * +ldif_put_wrap( + int type, + LDAP_CONST char *name, + LDAP_CONST char *val, + ber_len_t vlen, + ber_len_t wrap ) +{ + char *buf, *p; + ber_len_t nlen; + + nlen = ( name != NULL ) ? strlen( name ) : 0; + + buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); + + if ( buf == NULL ) { + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_type_and_value: malloc failed!")); + return NULL; + } + + p = buf; + ldif_sput_wrap( &p, type, name, val, vlen, wrap ); + *p = '\0'; + + return( buf ); +} + +int ldif_is_not_printable( + LDAP_CONST char *val, + ber_len_t vlen ) +{ + if( vlen == 0 || val == NULL ) { + return -1; + } + + if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && + isgraph( (unsigned char) val[vlen-1] ) ) + { + ber_len_t i; + + for ( i = 0; val[i]; i++ ) { + if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { + return 1; + } + } + + return 0; + } + + return 1; +} + +LDIFFP * +ldif_open( + LDAP_CONST char *file, + LDAP_CONST char *mode +) +{ + FILE *fp = fopen( file, mode ); + LDIFFP *lfp = NULL; + + if ( fp ) { + lfp = ber_memalloc( sizeof( LDIFFP )); + if ( lfp == NULL ) { + fclose( fp ); + return NULL; + } + lfp->fp = fp; + lfp->prev = NULL; + } + return lfp; +} + +LDIFFP * +ldif_open_mem( + char *ldif, + size_t size, + LDAP_CONST char *mode +) +{ +#ifdef HAVE_FMEMOPEN + FILE *fp = fmemopen( ldif, size, mode ); + LDIFFP *lfp = NULL; + + if ( fp ) { + lfp = ber_memalloc( sizeof( LDIFFP )); + lfp->fp = fp; + lfp->prev = NULL; + } + return lfp; +#else /* !HAVE_FMEMOPEN */ + return NULL; +#endif /* !HAVE_FMEMOPEN */ +} + +void +ldif_close( + LDIFFP *lfp +) +{ + LDIFFP *prev; + + while ( lfp ) { + fclose( lfp->fp ); + prev = lfp->prev; + ber_memfree( lfp ); + lfp = prev; + } +} + +#define LDIF_MAXLINE 4096 + +/* + * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, + * -1 for error. + */ +int +ldif_read_record( + LDIFFP *lfp, + unsigned long *lno, /* ptr to line number counter */ + char **bufp, /* ptr to malloced output buffer */ + int *buflenp ) /* ptr to length of *bufp */ +{ + char line[LDIF_MAXLINE], *nbufp; + ber_len_t lcur = 0, len; + int last_ch = '\n', found_entry = 0, stop, top_comment = 0; + + for ( stop = 0; !stop; last_ch = line[len-1] ) { + /* If we're at the end of this file, see if we should pop + * back to a previous file. (return from an include) + */ + while ( feof( lfp->fp )) { +pop: + if ( lfp->prev ) { + LDIFFP *tmp = lfp->prev; + fclose( lfp->fp ); + *lfp = *tmp; + ber_memfree( tmp ); + } else { + stop = 1; + break; + } + } + if ( !stop ) { + if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) { + if ( !found_entry && !ferror( lfp->fp ) ) { + /* ITS#9811 Reached the end looking for an entry, try again */ + goto pop; + } + stop = 1; + len = 0; + } else { + len = strlen( line ); + } + } + + if ( stop ) { + /* Add \n in case the file does not end with newline */ + if (last_ch != '\n') { + len = 1; + line[0] = '\n'; + line[1] = '\0'; + goto last; + } + break; + } + + /* Squash \r\n to \n */ + if ( len > 1 && line[len-2] == '\r' ) { + len--; + line[len] = '\0'; + line[len-1] = '\n'; + } + + if ( last_ch == '\n' ) { + (*lno)++; + + if ( line[0] == '\n' ) { + if ( !found_entry ) { + lcur = 0; + top_comment = 0; + continue; + } + break; + } + + if ( !found_entry ) { + if ( line[0] == '#' ) { + top_comment = 1; + } else if ( ! ( top_comment && line[0] == ' ' ) ) { + /* Found a new entry */ + found_entry = 1; + + if ( isdigit( (unsigned char) line[0] ) ) { + /* skip index */ + continue; + } + if ( !strncasecmp( line, "include:", + STRLENOF("include:"))) { + FILE *fp2; + char *ptr; + found_entry = 0; + + if ( line[len-1] == '\n' ) { + len--; + line[len] = '\0'; + } + + ptr = line + STRLENOF("include:"); + while (isspace((unsigned char) *ptr)) ptr++; + fp2 = ldif_open_url( ptr ); + if ( fp2 ) { + LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); + if ( lnew == NULL ) { + fclose( fp2 ); + return 0; + } + lnew->prev = lfp->prev; + lnew->fp = lfp->fp; + lfp->prev = lnew; + lfp->fp = fp2; + line[len] = '\n'; + len++; + continue; + } else { + /* We failed to open the file, this should + * be reported as an error somehow. + */ + ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, + _("ldif_read_record: include %s failed\n"), ptr ); + return -1; + } + } + } + } + } + +last: + if ( *buflenp - lcur <= len ) { + *buflenp += len + LDIF_MAXLINE; + nbufp = ber_memrealloc( *bufp, *buflenp ); + if( nbufp == NULL ) { + return 0; + } + *bufp = nbufp; + } + strcpy( *bufp + lcur, line ); + lcur += len; + } + + return( found_entry ); +} diff --git a/libs/ldap/libldap/modify.c b/libs/ldap/libldap/modify.c new file mode 100644 index 00000000000..44b9610cc6b --- /dev/null +++ b/libs/ldap/libldap/modify.c @@ -0,0 +1,232 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* A modify request/response looks like this: + * ModifyRequest ::= [APPLICATION 6] SEQUENCE { + * object LDAPDN, + * changes SEQUENCE OF change SEQUENCE { + * operation ENUMERATED { + * add (0), + * delete (1), + * replace (2), + * ... }, + * modification PartialAttribute } } + * + * PartialAttribute ::= SEQUENCE { + * type AttributeDescription, + * vals SET OF value AttributeValue } + * + * AttributeDescription ::= LDAPString + * -- Constrained to <attributedescription> [RFC4512] + * + * AttributeValue ::= OCTET STRING + * + * ModifyResponse ::= [APPLICATION 7] LDAPResult + * + * (Source: RFC 4511) + */ + +BerElement * +ldap_build_modify_req( + LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp ) +{ + BerElement *ber; + int i, rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID( ld, *msgidp ); + rc = ber_printf( ber, "{it{s{" /*}}}*/, *msgidp, LDAP_REQ_MODIFY, dn ); + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* allow mods to be NULL ("touch") */ + if ( mods ) { + /* 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]N}N}", + (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), + mods[i]->mod_type, mods[i]->mod_bvalues ); + } else { + rc = ber_printf( ber, "{e{s[v]N}N}", + (ber_int_t) mods[i]->mod_op, + mods[i]->mod_type, mods[i]->mod_values ); + } + + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + } + } + + if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_modify_ext - initiate an ldap extended 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. + * sctrls Server Controls + * cctrls Client Controls + * msgidp Message ID pointer + * + * Example: + * LDAPMod *mods[] = { + * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, + * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, + * { LDAP_MOD_DELETE, "ou", 0 }, + * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } + * 0 + * } + * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); + */ +int +ldap_modify_ext( LDAP *ld, + LDAP_CONST char *dn, + LDAPMod **mods, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_modify_ext\n" ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_modify_req( ld, dn, mods, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id ); + return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); +} + +/* + * 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", { "babs jensen", "babs", 0 } }, + * { LDAP_MOD_DELETE, "ou", 0 }, + * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } + * 0 + * } + * msgid = ldap_modify( ld, dn, mods ); + */ +int +ldap_modify( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) +{ + int rc, msgid; + + Debug0( LDAP_DEBUG_TRACE, "ldap_modify\n" ); + + rc = ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid ); + + if ( rc != LDAP_SUCCESS ) + return -1; + + return msgid; +} + +int +ldap_modify_ext_s( LDAP *ld, LDAP_CONST char *dn, + LDAPMod **mods, LDAPControl **sctrl, LDAPControl **cctrl ) +{ + int rc; + int msgid; + LDAPMessage *res; + + rc = ldap_modify_ext( ld, dn, mods, sctrl, cctrl, &msgid ); + + if ( rc != LDAP_SUCCESS ) + return( rc ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, res, 1 ) ); +} + +int +ldap_modify_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) +{ + return ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); +} diff --git a/libs/ldap/libldap/modrdn.c b/libs/ldap/libldap/modrdn.c new file mode 100644 index 00000000000..7946cfa8784 --- /dev/null +++ b/libs/ldap/libldap/modrdn.c @@ -0,0 +1,272 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* Copyright 1999, Juan C. Gomez, All rights reserved. + * This software is not subject to any license of Silicon Graphics + * Inc. or Purdue University. + * + * Redistribution and use in source and binary forms are permitted + * without restriction or fee of any kind as long as this notice + * is preserved. + */ + +/* ACKNOWLEDGEMENTS: + * Juan C. Gomez + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* + * A modify rdn request looks like this: + * ModifyRDNRequest ::= SEQUENCE { + * entry DistinguishedName, + * newrdn RelativeDistinguishedName, + * deleteoldrdn BOOLEAN + * newSuperior [0] DistinguishedName [v3 only] + * } + */ + +BerElement * +ldap_build_moddn_req( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp ) +{ + BerElement *ber; + int rc; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID( ld, *msgidp ); + if( newSuperior != NULL ) { + /* must be version 3 (or greater) */ + if ( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + ber_free( ber, 1 ); + return( NULL ); + } + rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ + *msgidp, LDAP_REQ_MODDN, + dn, newrdn, (ber_int_t) deleteoldrdn, + LDAP_TAG_NEWSUPERIOR, newSuperior ); + + } else { + rc = ber_printf( ber, "{it{ssbN}", /* '}' */ + *msgidp, LDAP_REQ_MODDN, + dn, newrdn, (ber_int_t) deleteoldrdn ); + } + + if ( rc < 0 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + rc = ber_printf( ber, /*{*/ "N}" ); + if ( rc < 0 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_rename - initiate an ldap extended modifyDN operation. + * + * Parameters: + * ld LDAP descriptor + * dn DN of the object to modify + * newrdn RDN to give the object + * deleteoldrdn nonzero means to delete old rdn values from the entry + * newSuperior DN of the new parent if applicable + * + * Returns the LDAP error code. + */ + +int +ldap_rename( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_rename\n" ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_moddn_req( ld, dn, newrdn, newSuperior, + deleteoldrdn, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id ); + + if( *msgidp < 0 ) { + return( ld->ld_errno ); + } + + return LDAP_SUCCESS; +} + + +/* + * ldap_rename2 - initiate an ldap (and X.500) modifyDN operation. Parameters: + * (LDAP V3 MODIFYDN REQUEST) + * ld LDAP descriptor + * dn DN of the object to modify + * newrdn RDN to give the object + * deleteoldrdn nonzero means to delete old rdn values from the entry + * newSuperior DN of the new parent if applicable + * + * ldap_rename2 uses a U-Mich Style API. It returns the msgid. + */ + +int +ldap_rename2( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn ) +{ + int msgid; + int rc; + + Debug0( LDAP_DEBUG_TRACE, "ldap_rename2\n" ); + + rc = ldap_rename( ld, dn, newrdn, newSuperior, + deleteoldrdn, NULL, NULL, &msgid ); + + return rc == LDAP_SUCCESS ? msgid : -1; +} + + +/* + * ldap_modrdn2 - initiate an ldap modifyRDN operation. Parameters: + * + * ld LDAP descriptor + * dn DN of the object to modify + * newrdn RDN to give the object + * deleteoldrdn nonzero means to delete old rdn values from the entry + * + * Example: + * msgid = ldap_modrdn( ld, dn, newrdn ); + */ +int +ldap_modrdn2( LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + int deleteoldrdn ) +{ + return ldap_rename2( ld, dn, newrdn, NULL, deleteoldrdn ); +} + +int +ldap_modrdn( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) +{ + return( ldap_rename2( ld, dn, newrdn, NULL, 1 ) ); +} + + +int +ldap_rename_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int rc; + int msgid; + LDAPMessage *res; + + rc = ldap_rename( ld, dn, newrdn, newSuperior, + deleteoldrdn, sctrls, cctrls, &msgid ); + + if( rc != LDAP_SUCCESS ) { + return rc; + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &res ); + + if( rc == -1 || !res ) { + return ld->ld_errno; + } + + return ldap_result2error( ld, res, 1 ); +} + +int +ldap_rename2_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *newrdn, + LDAP_CONST char *newSuperior, + int deleteoldrdn ) +{ + return ldap_rename_s( ld, dn, newrdn, newSuperior, + deleteoldrdn, NULL, NULL ); +} + +int +ldap_modrdn2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn ) +{ + return ldap_rename_s( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL ); +} + +int +ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) +{ + return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL ); +} diff --git a/libs/ldap/libldap/open.c b/libs/ldap/libldap/open.c new file mode 100644 index 00000000000..db84a74d6ce --- /dev/null +++ b/libs/ldap/libldap/open.c @@ -0,0 +1,673 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include <ac/stdlib.h> + +#include <ac/param.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include <ac/unistd.h> + +#include "ldap-int.h" +#include "ldap.h" +#include "ldap_log.h" + +/* Caller must hold the conn_mutex since simultaneous accesses are possible */ +int ldap_open_defconn( LDAP *ld ) +{ + ld->ld_defconn = ldap_new_connection( ld, + &ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 ); + + if( ld->ld_defconn == NULL ) { + ld->ld_errno = LDAP_SERVER_DOWN; + return -1; + } + + ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ + return 0; +} + +/* + * ldap_connect - Connect to an ldap server. + * + * Example: + * LDAP *ld; + * ldap_initialize( &ld, url ); + * ldap_connect( ld ); + */ +int +ldap_connect( LDAP *ld ) +{ + ber_socket_t sd = AC_SOCKET_INVALID; + int rc = LDAP_SUCCESS; + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) { + rc = ldap_open_defconn( ld ); + } + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + + return rc; +} + +/* + * 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_open( LDAP_CONST char *host, int port ) +{ + int rc; + LDAP *ld; + + Debug2( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n", + host, port ); + + ld = ldap_init( host, port ); + if ( ld == NULL ) { + return( NULL ); + } + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + rc = ldap_open_defconn( ld ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + + if( rc < 0 ) { + ldap_ld_free( ld, 0, NULL, NULL ); + ld = NULL; + } + + Debug1( LDAP_DEBUG_TRACE, "ldap_open: %s\n", + ld != NULL ? "succeeded" : "failed" ); + + return ld; +} + + + +int +ldap_create( LDAP **ldp ) +{ + LDAP *ld; + struct ldapoptions *gopts; + + *ldp = NULL; + /* Get pointer to global option structure */ + if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { + return LDAP_NO_MEMORY; + } + + /* Initialize the global options, if not already done. */ + if( gopts->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(gopts, NULL); + if ( gopts->ldo_valid != LDAP_INITIALIZED ) + return LDAP_LOCAL_ERROR; + } + + Debug0( LDAP_DEBUG_TRACE, "ldap_create\n" ); + + if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { + return( LDAP_NO_MEMORY ); + } + + if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1, + sizeof(struct ldap_common) )) == NULL ) { + LDAP_FREE( (char *)ld ); + return( LDAP_NO_MEMORY ); + } + /* copy the global options */ + LDAP_MUTEX_LOCK( &gopts->ldo_mutex ); + AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options)); +#ifdef LDAP_R_COMPILE + /* Properly initialize the structs mutex */ + ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) ); +#endif + +#ifdef HAVE_TLS + if ( ld->ld_options.ldo_tls_pin_hashalg ) { + int len = strlen( gopts->ldo_tls_pin_hashalg ); + + ld->ld_options.ldo_tls_pin_hashalg = + LDAP_MALLOC( len + 1 + gopts->ldo_tls_pin.bv_len ); + if ( !ld->ld_options.ldo_tls_pin_hashalg ) goto nomem; + + ld->ld_options.ldo_tls_pin.bv_val = ld->ld_options.ldo_tls_pin_hashalg + + len + 1; + AC_MEMCPY( ld->ld_options.ldo_tls_pin_hashalg, gopts->ldo_tls_pin_hashalg, + len + 1 + gopts->ldo_tls_pin.bv_len ); + } else if ( !BER_BVISEMPTY(&ld->ld_options.ldo_tls_pin) ) { + ber_dupbv( &ld->ld_options.ldo_tls_pin, &gopts->ldo_tls_pin ); + } +#endif + LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex ); + + ld->ld_valid = LDAP_VALID_SESSION; + + /* but not pointers to malloc'ed items */ + ld->ld_options.ldo_sctrls = NULL; + ld->ld_options.ldo_cctrls = NULL; + ld->ld_options.ldo_defludp = NULL; + ld->ld_options.ldo_conn_cbs = NULL; + + ld->ld_options.ldo_defbase = gopts->ldo_defbase + ? LDAP_STRDUP( gopts->ldo_defbase ) : NULL; + +#ifdef HAVE_CYRUS_SASL + ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech + ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; + ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm + ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; + ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid + ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; + ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid + ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; +#endif + +#ifdef HAVE_TLS + /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave + * them empty to allow new SSL_CTX's to be created from scratch. + */ + memset( &ld->ld_options.ldo_tls_info, 0, + sizeof( ld->ld_options.ldo_tls_info )); + ld->ld_options.ldo_tls_ctx = NULL; +#endif + + if ( gopts->ldo_defludp ) { + ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); + + if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; + } + + if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; + + ld->ld_options.ldo_local_ip_addrs.local_ip_addrs = NULL; + if( gopts->ldo_local_ip_addrs.local_ip_addrs ) { + ld->ld_options.ldo_local_ip_addrs.local_ip_addrs = + LDAP_STRDUP( gopts->ldo_local_ip_addrs.local_ip_addrs ); + if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs == NULL ) + goto nomem; + } + + ld->ld_lberoptions = LBER_USE_DER; + + ld->ld_sb = ber_sockbuf_alloc( ); + if ( ld->ld_sb == NULL ) goto nomem; + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex ); + ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex ); + ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); + ldap_pvt_thread_mutex_init( &ld->ld_res_mutex ); + ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex ); + ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex ); +#endif + ld->ld_ldcrefcnt = 1; + *ldp = ld; + return LDAP_SUCCESS; + +nomem: + ldap_free_select_info( ld->ld_selectinfo ); + ldap_free_urllist( ld->ld_options.ldo_defludp ); +#ifdef HAVE_CYRUS_SASL + LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); +#endif + +#ifdef HAVE_TLS + /* tls_pin_hashalg and tls_pin share the same buffer */ + if ( ld->ld_options.ldo_tls_pin_hashalg ) { + LDAP_FREE( ld->ld_options.ldo_tls_pin_hashalg ); + } else { + LDAP_FREE( ld->ld_options.ldo_tls_pin.bv_val ); + } +#endif + LDAP_FREE( (char *)ld ); + return LDAP_NO_MEMORY; +} + +/* + * ldap_init - initialize the LDAP library. A magic cookie to be used for + * future communication is returned on success, NULL on failure. + * "host" may be a space-separated list of hosts or IP addresses + * + * Example: + * LDAP *ld; + * ld = ldap_init( host, port ); + */ +LDAP * +ldap_init( LDAP_CONST char *defhost, int defport ) +{ + LDAP *ld; + int rc; + + rc = ldap_create(&ld); + if ( rc != LDAP_SUCCESS ) + return NULL; + + if (defport != 0) + ld->ld_options.ldo_defport = defport; + + if (defhost != NULL) { + rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost); + if ( rc != LDAP_SUCCESS ) { + ldap_ld_free(ld, 1, NULL, NULL); + return NULL; + } + } + + return( ld ); +} + + +int +ldap_initialize( LDAP **ldp, LDAP_CONST char *url ) +{ + int rc; + LDAP *ld; + + *ldp = NULL; + rc = ldap_create(&ld); + if ( rc != LDAP_SUCCESS ) + return rc; + + if (url != NULL) { + rc = ldap_set_option(ld, LDAP_OPT_URI, url); + if ( rc != LDAP_SUCCESS ) { + ldap_ld_free(ld, 1, NULL, NULL); + return rc; + } +#ifdef LDAP_CONNECTIONLESS + if (ldap_is_ldapc_url(url)) + LDAP_IS_UDP(ld) = 1; +#endif + } + + *ldp = ld; + return LDAP_SUCCESS; +} + +int +ldap_init_fd( + ber_socket_t fd, + int proto, + LDAP_CONST char *url, + LDAP **ldp +) +{ + int rc; + LDAP *ld; + LDAPConn *conn; +#ifdef LDAP_CONNECTIONLESS + ber_socklen_t len; +#endif + + *ldp = NULL; + rc = ldap_create( &ld ); + if( rc != LDAP_SUCCESS ) + return( rc ); + + if (url != NULL) { + rc = ldap_set_option(ld, LDAP_OPT_URI, url); + if ( rc != LDAP_SUCCESS ) { + ldap_ld_free(ld, 1, NULL, NULL); + return rc; + } + } + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + /* Attach the passed socket as the LDAP's connection */ + conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 ); + if( conn == NULL ) { + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + ldap_unbind_ext( ld, NULL, NULL ); + return( LDAP_NO_MEMORY ); + } + if( url ) + conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp ); + ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd ); + ld->ld_defconn = conn; + ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + + switch( proto ) { + case LDAP_PROTO_TCP: +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; + +#ifdef LDAP_CONNECTIONLESS + case LDAP_PROTO_UDP: + LDAP_IS_UDP(ld) = 1; + if( ld->ld_options.ldo_peer ) + ldap_memfree( ld->ld_options.ldo_peer ); + ld->ld_options.ldo_peer = ldap_memcalloc( 1, sizeof( struct sockaddr_storage ) ); + len = sizeof( struct sockaddr_storage ); + if( getpeername ( fd, ld->ld_options.ldo_peer, &len ) < 0) { + ldap_unbind_ext( ld, NULL, NULL ); + return( AC_SOCKET_ERROR ); + } +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; +#endif /* LDAP_CONNECTIONLESS */ + + case LDAP_PROTO_IPC: +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + break; + + case LDAP_PROTO_EXT: + /* caller must supply sockbuf handlers */ + break; + + default: + ldap_unbind_ext( ld, NULL, NULL ); + return LDAP_PARAM_ERROR; + } + +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + INT_MAX, (void *)"ldap_" ); +#endif + + /* Add the connection to the *LDAP's select pool */ + ldap_mark_select_read( ld, conn->lconn_sb ); + + *ldp = ld; + return LDAP_SUCCESS; +} + +/* Protected by ld_conn_mutex */ +int +ldap_int_open_connection( + LDAP *ld, + LDAPConn *conn, + LDAPURLDesc *srv, + int async ) +{ + int rc = -1; + int proto; + + Debug0( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n" ); + + switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { + case LDAP_PROTO_TCP: + rc = ldap_connect_to_host( ld, conn->lconn_sb, + proto, srv, async ); + + if ( rc == -1 ) return rc; +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + + break; + +#ifdef LDAP_CONNECTIONLESS + case LDAP_PROTO_UDP: + LDAP_IS_UDP(ld) = 1; + rc = ldap_connect_to_host( ld, conn->lconn_sb, + proto, srv, async ); + + if ( rc == -1 ) return rc; +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + + break; +#endif + case LDAP_PROTO_IPC: +#ifdef LDAP_PF_LOCAL + /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */ + rc = ldap_connect_to_path( ld, conn->lconn_sb, + srv, async ); + if ( rc == -1 ) return rc; +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); +#endif + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + + break; +#endif /* LDAP_PF_LOCAL */ + default: + return -1; + break; + } + + conn->lconn_created = time( NULL ); + +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + INT_MAX, (void *)"ldap_" ); +#endif + +#ifdef LDAP_CONNECTIONLESS + if( proto == LDAP_PROTO_UDP ) return 0; +#endif + +#ifdef HAVE_TLS + if ((rc == 0 || rc == -2) && ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || + strcmp( srv->lud_scheme, "ldaps" ) == 0 )) + { + ++conn->lconn_refcnt; /* avoid premature free */ + + rc = ldap_int_tls_start( ld, conn, srv ); + + --conn->lconn_refcnt; + + if (rc != LDAP_SUCCESS) { + /* process connection callbacks */ + { + struct ldapoptions *lo; + ldaplist *ll; + ldap_conncb *cb; + + lo = &ld->ld_options; + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, conn->lconn_sb, cb ); + } + } + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + lo = LDAP_INT_GLOBAL_OPT(); + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, conn->lconn_sb, cb ); + } + } + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + } + ber_int_sb_close( conn->lconn_sb ); + return -1; + } + } +#endif + + return( 0 ); +} + +/* + * ldap_open_internal_connection - open connection and set file descriptor + * + * note: ldap_init_fd() may be preferable + */ + +int +ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp ) +{ + int rc; + LDAPConn *c; + LDAPRequest *lr; + LDAP *ld; + + rc = ldap_create( &ld ); + if( rc != LDAP_SUCCESS ) { + *ldp = NULL; + return( rc ); + } + + /* Make it appear that a search request, msgid 0, was sent */ + lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest )); + if( lr == NULL ) { + ldap_unbind_ext( ld, NULL, NULL ); + *ldp = NULL; + return( LDAP_NO_MEMORY ); + } + memset(lr, 0, sizeof( LDAPRequest )); + lr->lr_msgid = 0; + lr->lr_status = LDAP_REQST_INPROGRESS; + lr->lr_res_errno = LDAP_SUCCESS; + /* no mutex lock needed, we just created this ld here */ + rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error ); + assert( rc == LDAP_SUCCESS ); + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + /* Attach the passed socket as the *LDAP's connection */ + c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 ); + if( c == NULL ) { + ldap_unbind_ext( ld, NULL, NULL ); + *ldp = NULL; + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return( LDAP_NO_MEMORY ); + } + ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp ); +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" ); +#endif + ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp, + LBER_SBIOD_LEVEL_PROVIDER, NULL ); + ld->ld_defconn = c; + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + + /* Add the connection to the *LDAP's select pool */ + ldap_mark_select_read( ld, c->lconn_sb ); + + /* Make this connection an LDAP V3 protocol connection */ + rc = LDAP_VERSION3; + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc ); + *ldp = ld; + + ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ + + return( LDAP_SUCCESS ); +} + +LDAP * +ldap_dup( LDAP *old ) +{ + LDAP *ld; + + if ( old == NULL ) { + return( NULL ); + } + + Debug0( LDAP_DEBUG_TRACE, "ldap_dup\n" ); + + if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { + return( NULL ); + } + + LDAP_MUTEX_LOCK( &old->ld_ldcmutex ); + ld->ldc = old->ldc; + old->ld_ldcrefcnt++; + LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex ); + return ( ld ); +} + +int +ldap_int_check_async_open( LDAP *ld, ber_socket_t sd ) +{ + struct timeval tv = { 0 }; + int rc; + + rc = ldap_int_poll( ld, sd, &tv, 1 ); + switch ( rc ) { + case 0: + /* now ready to start tls */ + ld->ld_defconn->lconn_status = LDAP_CONNST_CONNECTED; + break; + + default: + ld->ld_errno = LDAP_CONNECT_ERROR; + return -1; + + case -2: + /* connect not completed yet */ + ld->ld_errno = LDAP_X_CONNECTING; + return rc; + } + +#ifdef HAVE_TLS + if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || + !strcmp( ld->ld_defconn->lconn_server->lud_scheme, "ldaps" )) { + + ++ld->ld_defconn->lconn_refcnt; /* avoid premature free */ + + rc = ldap_int_tls_start( ld, ld->ld_defconn, ld->ld_defconn->lconn_server ); + + --ld->ld_defconn->lconn_refcnt; + } +#endif + return rc; +} diff --git a/libs/ldap/libldap/options.c b/libs/ldap/libldap/options.c new file mode 100644 index 00000000000..205ac764255 --- /dev/null +++ b/libs/ldap/libldap/options.c @@ -0,0 +1,1012 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +#define LDAP_OPT_REBIND_PROC 0x4e814d +#define LDAP_OPT_REBIND_PARAMS 0x4e814e + +#define LDAP_OPT_NEXTREF_PROC 0x4e815d +#define LDAP_OPT_NEXTREF_PARAMS 0x4e815e + +#define LDAP_OPT_URLLIST_PROC 0x4e816d +#define LDAP_OPT_URLLIST_PARAMS 0x4e816e + +static const LDAPAPIFeatureInfo features[] = { +#ifdef LDAP_API_FEATURE_X_OPENLDAP + { /* OpenLDAP Extensions API Feature */ + LDAP_FEATURE_INFO_VERSION, + "X_OPENLDAP", + LDAP_API_FEATURE_X_OPENLDAP + }, +#endif + +#ifdef LDAP_API_FEATURE_THREAD_SAFE + { /* Basic Thread Safe */ + LDAP_FEATURE_INFO_VERSION, + "THREAD_SAFE", + LDAP_API_FEATURE_THREAD_SAFE + }, +#endif +#ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE + { /* Session Thread Safe */ + LDAP_FEATURE_INFO_VERSION, + "SESSION_THREAD_SAFE", + LDAP_API_FEATURE_SESSION_THREAD_SAFE + }, +#endif +#ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE + { /* Operation Thread Safe */ + LDAP_FEATURE_INFO_VERSION, + "OPERATION_THREAD_SAFE", + LDAP_API_FEATURE_OPERATION_THREAD_SAFE + }, +#endif +#ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT + { /* OpenLDAP Reentrant */ + LDAP_FEATURE_INFO_VERSION, + "X_OPENLDAP_REENTRANT", + LDAP_API_FEATURE_X_OPENLDAP_REENTRANT + }, +#endif +#ifdef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE + { /* OpenLDAP Thread Safe */ + LDAP_FEATURE_INFO_VERSION, + "X_OPENLDAP_THREAD_SAFE", + LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE + }, +#endif +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS + { /* V2 Referrals */ + LDAP_FEATURE_INFO_VERSION, + "X_OPENLDAP_V2_REFERRALS", + LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS + }, +#endif + {0, NULL, 0} +}; + +int +ldap_get_option( + LDAP *ld, + int option, + void *outvalue) +{ + struct ldapoptions *lo; + int rc = LDAP_OPT_ERROR; + + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if (NULL == lo) { + return LDAP_NO_MEMORY; + } + + if( lo->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(lo, NULL); + if ( lo->ldo_valid != LDAP_INITIALIZED ) + return LDAP_LOCAL_ERROR; + } + + if(ld != NULL) { + if( !LDAP_VALID( ld ) ) { + return LDAP_OPT_ERROR; + } + + lo = &ld->ld_options; + } + + if(outvalue == NULL) { + /* no place to get to */ + return LDAP_OPT_ERROR; + } + + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + + switch(option) { + case LDAP_OPT_API_INFO: { + struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue; + + if(info == NULL) { + /* outvalue must point to an apiinfo structure */ + break; /* LDAP_OPT_ERROR */ + } + + if(info->ldapai_info_version != LDAP_API_INFO_VERSION) { + /* api info version mismatch */ + info->ldapai_info_version = LDAP_API_INFO_VERSION; + break; /* LDAP_OPT_ERROR */ + } + + info->ldapai_api_version = LDAP_API_VERSION; + info->ldapai_protocol_version = LDAP_VERSION_MAX; + + if(features[0].ldapaif_name == NULL) { + info->ldapai_extensions = NULL; + } else { + int i; + info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) * + sizeof(features)/sizeof(LDAPAPIFeatureInfo)); + if ( info->ldapai_extensions == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + + for(i=0; features[i].ldapaif_name != NULL; i++) { + info->ldapai_extensions[i] = + LDAP_STRDUP(features[i].ldapaif_name); + if ( info->ldapai_extensions[i] == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + } + if ( features[i].ldapaif_name != NULL ) { + break; /* LDAP_NO_MEMORY */ + } + + info->ldapai_extensions[i] = NULL; + } + + info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME); + info->ldapai_vendor_version = LDAP_VENDOR_VERSION; + + rc = LDAP_OPT_SUCCESS; + break; + } break; + + case LDAP_OPT_DESC: + if( ld == NULL || ld->ld_sb == NULL ) { + /* bad param */ + break; + } + + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue ); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SOCKBUF: + if( ld == NULL ) break; + *(Sockbuf **)outvalue = ld->ld_sb; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_TIMEOUT: + /* the caller has to free outvalue ! */ + if ( lo->ldo_tm_api.tv_sec < 0 ) { + *(void **)outvalue = NULL; + } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) { + break; /* LDAP_OPT_ERROR */ + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_NETWORK_TIMEOUT: + /* the caller has to free outvalue ! */ + if ( lo->ldo_tm_net.tv_sec < 0 ) { + *(void **)outvalue = NULL; + } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) { + break; /* LDAP_OPT_ERROR */ + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_DEREF: + * (int *) outvalue = lo->ldo_deref; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SIZELIMIT: + * (int *) outvalue = lo->ldo_sizelimit; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_TIMELIMIT: + * (int *) outvalue = lo->ldo_timelimit; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_REFERRALS: + * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_RESTART: + * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_PROTOCOL_VERSION: + * (int *) outvalue = lo->ldo_version; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SERVER_CONTROLS: + * (LDAPControl ***) outvalue = + ldap_controls_dup( lo->ldo_sctrls ); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CLIENT_CONTROLS: + * (LDAPControl ***) outvalue = + ldap_controls_dup( lo->ldo_cctrls ); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_HOST_NAME: + * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SOCKET_BIND_ADDRESSES: + if ( lo->ldo_local_ip_addrs.local_ip_addrs == NULL ) { + * (void **) outvalue = NULL; + } + else { + * (char **) outvalue = + LDAP_STRDUP( lo->ldo_local_ip_addrs.local_ip_addrs ); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_URI: + * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_DEFBASE: + if( lo->ldo_defbase == NULL ) { + * (char **) outvalue = NULL; + } else { + * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CONNECT_ASYNC: + * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CONNECT_CB: + { + /* Getting deletes the specified callback */ + ldaplist **ll = &lo->ldo_conn_cbs; + for (;*ll;ll = &(*ll)->ll_next) { + if ((*ll)->ll_data == outvalue) { + ldaplist *lc = *ll; + *ll = lc->ll_next; + LDAP_FREE(lc); + break; + } + } + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_RESULT_CODE: + if(ld == NULL) { + /* bad param */ + break; + } + * (int *) outvalue = ld->ld_errno; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_DIAGNOSTIC_MESSAGE: + if(ld == NULL) { + /* bad param */ + break; + } + + if( ld->ld_error == NULL ) { + * (char **) outvalue = NULL; + } else { + * (char **) outvalue = LDAP_STRDUP(ld->ld_error); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_MATCHED_DN: + if(ld == NULL) { + /* bad param */ + break; + } + + if( ld->ld_matched == NULL ) { + * (char **) outvalue = NULL; + } else { + * (char **) outvalue = LDAP_STRDUP( ld->ld_matched ); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_REFERRAL_URLS: + if(ld == NULL) { + /* bad param */ + break; + } + + if( ld->ld_referrals == NULL ) { + * (char ***) outvalue = NULL; + } else { + * (char ***) outvalue = ldap_value_dup(ld->ld_referrals); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_API_FEATURE_INFO: { + LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue; + int i; + + if(info == NULL) + break; /* LDAP_OPT_ERROR */ + + if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) { + /* api info version mismatch */ + info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; + break; /* LDAP_OPT_ERROR */ + } + + if(info->ldapaif_name == NULL) + break; /* LDAP_OPT_ERROR */ + + for(i=0; features[i].ldapaif_name != NULL; i++) { + if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) { + info->ldapaif_version = + features[i].ldapaif_version; + rc = LDAP_OPT_SUCCESS; + break; + } + } + } + break; + + case LDAP_OPT_DEBUG_LEVEL: + * (int *) outvalue = lo->ldo_debug; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SESSION_REFCNT: + if(ld == NULL) { + /* bad param */ + break; + } + LDAP_MUTEX_LOCK( &ld->ld_ldcmutex ); + * (int *) outvalue = ld->ld_ldcrefcnt; + LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_KEEPCONN: + * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_KEEPCONN); + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_X_KEEPALIVE_IDLE: + * (int *) outvalue = lo->ldo_keepalive_idle; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_X_KEEPALIVE_PROBES: + * (int *) outvalue = lo->ldo_keepalive_probes; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_X_KEEPALIVE_INTERVAL: + * (int *) outvalue = lo->ldo_keepalive_interval; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_TCP_USER_TIMEOUT: + * (unsigned int *) outvalue = lo->ldo_tcp_user_timeout; + rc = LDAP_OPT_SUCCESS; + break; + + default: +#ifdef HAVE_TLS + if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) { + rc = LDAP_OPT_SUCCESS; + break; + } +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) { + rc = LDAP_OPT_SUCCESS; + break; + } +#endif + /* bad param */ + break; + } + + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + return ( rc ); +} + +int +ldap_set_option( + LDAP *ld, + int option, + LDAP_CONST void *invalue) +{ + struct ldapoptions *lo; + int *dbglvl = NULL; + int rc = LDAP_OPT_ERROR; + + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if (lo == NULL) { + return LDAP_NO_MEMORY; + } + + /* + * The architecture to turn on debugging has a chicken and egg + * problem. Thus, we introduce a fix here. + */ + + if (option == LDAP_OPT_DEBUG_LEVEL) { + dbglvl = (int *) invalue; + } + + if( lo->ldo_valid != LDAP_INITIALIZED ) { + ldap_int_initialize(lo, dbglvl); + if ( lo->ldo_valid != LDAP_INITIALIZED ) + return LDAP_LOCAL_ERROR; + } + + if(ld != NULL) { + assert( LDAP_VALID( ld ) ); + + if( !LDAP_VALID( ld ) ) { + return LDAP_OPT_ERROR; + } + + lo = &ld->ld_options; + } + + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + + switch ( option ) { + + /* options with boolean values */ + case LDAP_OPT_REFERRALS: + if(invalue == LDAP_OPT_OFF) { + LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS); + } else { + LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_RESTART: + if(invalue == LDAP_OPT_OFF) { + LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART); + } else { + LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CONNECT_ASYNC: + if(invalue == LDAP_OPT_OFF) { + LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC); + } else { + LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC); + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_KEEPCONN: + if(invalue == LDAP_OPT_OFF) { + LDAP_BOOL_CLR(lo, LDAP_BOOL_KEEPCONN); + } else { + LDAP_BOOL_SET(lo, LDAP_BOOL_KEEPCONN); + } + rc = LDAP_OPT_SUCCESS; + break; + /* options which can withstand invalue == NULL */ + case LDAP_OPT_SERVER_CONTROLS: { + LDAPControl *const *controls = + (LDAPControl *const *) invalue; + + if( lo->ldo_sctrls ) + ldap_controls_free( lo->ldo_sctrls ); + + if( controls == NULL || *controls == NULL ) { + lo->ldo_sctrls = NULL; + rc = LDAP_OPT_SUCCESS; + break; + } + + lo->ldo_sctrls = ldap_controls_dup( controls ); + + if(lo->ldo_sctrls == NULL) { + /* memory allocation error ? */ + break; /* LDAP_OPT_ERROR */ + } + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CLIENT_CONTROLS: { + LDAPControl *const *controls = + (LDAPControl *const *) invalue; + + if( lo->ldo_cctrls ) + ldap_controls_free( lo->ldo_cctrls ); + + if( controls == NULL || *controls == NULL ) { + lo->ldo_cctrls = NULL; + rc = LDAP_OPT_SUCCESS; + break; + } + + lo->ldo_cctrls = ldap_controls_dup( controls ); + + if(lo->ldo_cctrls == NULL) { + /* memory allocation error ? */ + break; /* LDAP_OPT_ERROR */ + } + } + rc = LDAP_OPT_SUCCESS; + break; + + + case LDAP_OPT_HOST_NAME: { + const char *host = (const char *) invalue; + LDAPURLDesc *ludlist = NULL; + rc = LDAP_OPT_SUCCESS; + + if(host != NULL) { + rc = ldap_url_parsehosts( &ludlist, host, + lo->ldo_defport ? lo->ldo_defport : LDAP_PORT ); + + } else if(ld == NULL) { + /* + * must want global default returned + * to initial condition. + */ + rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, + LDAP_PVT_URL_PARSE_NOEMPTY_HOST + | LDAP_PVT_URL_PARSE_DEF_PORT ); + + } else { + /* + * must want the session default + * updated to the current global default + */ + ludlist = ldap_url_duplist( + ldap_int_global_options.ldo_defludp); + if (ludlist == NULL) + rc = LDAP_NO_MEMORY; + } + + if (rc == LDAP_OPT_SUCCESS) { + if (lo->ldo_defludp != NULL) + ldap_free_urllist(lo->ldo_defludp); + lo->ldo_defludp = ludlist; + } + break; + } + + case LDAP_OPT_SOCKET_BIND_ADDRESSES: { + const char *source_ip = (const char *) invalue; + char **source_ip_lst = NULL; + + ldapsourceip temp_source_ip; + memset( &temp_source_ip, 0, sizeof( ldapsourceip ) ); + rc = LDAP_OPT_SUCCESS; + if( source_ip == NULL ) { + if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ) { + LDAP_FREE( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ); + memset( &ld->ld_options.ldo_local_ip_addrs, 0, + sizeof( ldapsourceip ) ); + } + } + else { + source_ip_lst = ldap_str2charray( source_ip, " " ); + + if ( source_ip_lst == NULL ) + rc = LDAP_NO_MEMORY; + + if( rc == LDAP_OPT_SUCCESS ) { + rc = ldap_validate_and_fill_sourceip ( source_ip_lst, + &temp_source_ip ); + ldap_charray_free( source_ip_lst ); + } + if ( rc == LDAP_OPT_SUCCESS ) { + if ( lo->ldo_local_ip_addrs.local_ip_addrs != NULL ) { + LDAP_FREE( lo->ldo_local_ip_addrs.local_ip_addrs ); + lo->ldo_local_ip_addrs.local_ip_addrs = NULL; + } + lo->ldo_local_ip_addrs = temp_source_ip; + lo->ldo_local_ip_addrs.local_ip_addrs = LDAP_STRDUP( source_ip ); + } + } + break; + } + + case LDAP_OPT_URI: { + const char *urls = (const char *) invalue; + LDAPURLDesc *ludlist = NULL; + rc = LDAP_OPT_SUCCESS; + + if(urls != NULL) { + rc = ldap_url_parselist_ext(&ludlist, urls, NULL, + LDAP_PVT_URL_PARSE_NOEMPTY_HOST + | LDAP_PVT_URL_PARSE_DEF_PORT ); + } else if(ld == NULL) { + /* + * must want global default returned + * to initial condition. + */ + rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, + LDAP_PVT_URL_PARSE_NOEMPTY_HOST + | LDAP_PVT_URL_PARSE_DEF_PORT ); + + } else { + /* + * must want the session default + * updated to the current global default + */ + ludlist = ldap_url_duplist( + ldap_int_global_options.ldo_defludp); + if (ludlist == NULL) + rc = LDAP_URL_ERR_MEM; + } + + switch (rc) { + case LDAP_URL_SUCCESS: /* Success */ + rc = LDAP_SUCCESS; + break; + + case LDAP_URL_ERR_MEM: /* can't allocate memory space */ + rc = LDAP_NO_MEMORY; + break; + + case LDAP_URL_ERR_PARAM: /* parameter is bad */ + case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */ + case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */ + case LDAP_URL_ERR_BADURL: /* URL is bad */ + case LDAP_URL_ERR_BADHOST: /* host port is bad */ + case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */ + case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */ + case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */ + case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */ + rc = LDAP_PARAM_ERROR; + break; + } + + if (rc == LDAP_SUCCESS) { + if (lo->ldo_defludp != NULL) + ldap_free_urllist(lo->ldo_defludp); + lo->ldo_defludp = ludlist; + } + break; + } + + case LDAP_OPT_DEFBASE: { + const char *newbase = (const char *) invalue; + char *defbase = NULL; + + if ( newbase != NULL ) { + defbase = LDAP_STRDUP( newbase ); + if ( defbase == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + + } else if ( ld != NULL ) { + defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase ); + if ( defbase == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + } + + if ( lo->ldo_defbase != NULL ) + LDAP_FREE( lo->ldo_defbase ); + lo->ldo_defbase = defbase; + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_DIAGNOSTIC_MESSAGE: { + const char *err = (const char *) invalue; + + if(ld == NULL) { + /* need a struct ldap */ + break; /* LDAP_OPT_ERROR */ + } + + if( ld->ld_error ) { + LDAP_FREE(ld->ld_error); + ld->ld_error = NULL; + } + + if ( err ) { + ld->ld_error = LDAP_STRDUP(err); + } + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_MATCHED_DN: { + const char *matched = (const char *) invalue; + + if (ld == NULL) { + /* need a struct ldap */ + break; /* LDAP_OPT_ERROR */ + } + + if( ld->ld_matched ) { + LDAP_FREE(ld->ld_matched); + ld->ld_matched = NULL; + } + + if ( matched ) { + ld->ld_matched = LDAP_STRDUP( matched ); + } + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_REFERRAL_URLS: { + char *const *referrals = (char *const *) invalue; + + if(ld == NULL) { + /* need a struct ldap */ + break; /* LDAP_OPT_ERROR */ + } + + if( ld->ld_referrals ) { + LDAP_VFREE(ld->ld_referrals); + } + + if ( referrals ) { + ld->ld_referrals = ldap_value_dup(referrals); + } + } + rc = LDAP_OPT_SUCCESS; + break; + + /* Only accessed from inside this function by ldap_set_rebind_proc() */ + case LDAP_OPT_REBIND_PROC: { + lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_REBIND_PARAMS: { + lo->ldo_rebind_params = (void *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + + /* Only accessed from inside this function by ldap_set_nextref_proc() */ + case LDAP_OPT_NEXTREF_PROC: { + lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_NEXTREF_PARAMS: { + lo->ldo_nextref_params = (void *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + + /* Only accessed from inside this function by ldap_set_urllist_proc() */ + case LDAP_OPT_URLLIST_PROC: { + lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_URLLIST_PARAMS: { + lo->ldo_urllist_params = (void *)invalue; + } + rc = LDAP_OPT_SUCCESS; + break; + + /* read-only options */ + case LDAP_OPT_API_INFO: + case LDAP_OPT_DESC: + case LDAP_OPT_SOCKBUF: + case LDAP_OPT_API_FEATURE_INFO: + break; /* LDAP_OPT_ERROR */ + + /* options which cannot withstand invalue == NULL */ + case LDAP_OPT_DEREF: + case LDAP_OPT_SIZELIMIT: + case LDAP_OPT_TIMELIMIT: + case LDAP_OPT_PROTOCOL_VERSION: + case LDAP_OPT_RESULT_CODE: + case LDAP_OPT_DEBUG_LEVEL: + case LDAP_OPT_TIMEOUT: + case LDAP_OPT_NETWORK_TIMEOUT: + case LDAP_OPT_CONNECT_CB: + case LDAP_OPT_X_KEEPALIVE_IDLE: + case LDAP_OPT_X_KEEPALIVE_PROBES : + case LDAP_OPT_X_KEEPALIVE_INTERVAL : + case LDAP_OPT_TCP_USER_TIMEOUT: + if(invalue == NULL) { + /* no place to set from */ + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + return ( LDAP_OPT_ERROR ); + } + break; + + default: +#ifdef HAVE_TLS + if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) { + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + return ( LDAP_OPT_SUCCESS ); + } +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) { + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + return ( LDAP_OPT_SUCCESS ); + } +#endif + /* bad param */ + break; /* LDAP_OPT_ERROR */ + } + + /* options which cannot withstand invalue == NULL */ + + switch(option) { + case LDAP_OPT_DEREF: + /* FIXME: check value for protocol compliance? */ + lo->ldo_deref = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_SIZELIMIT: + /* FIXME: check value for protocol compliance? */ + lo->ldo_sizelimit = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_TIMELIMIT: + /* FIXME: check value for protocol compliance? */ + lo->ldo_timelimit = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_TIMEOUT: { + const struct timeval *tv = + (const struct timeval *) invalue; + + lo->ldo_tm_api = *tv; + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_NETWORK_TIMEOUT: { + const struct timeval *tv = + (const struct timeval *) invalue; + + lo->ldo_tm_net = *tv; + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_PROTOCOL_VERSION: { + int vers = * (const int *) invalue; + if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) { + /* not supported */ + break; + } + lo->ldo_version = vers; + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_RESULT_CODE: { + int err = * (const int *) invalue; + + if(ld == NULL) { + /* need a struct ldap */ + break; + } + + ld->ld_errno = err; + } + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_DEBUG_LEVEL: + lo->ldo_debug = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + + case LDAP_OPT_CONNECT_CB: + { + /* setting pushes the callback */ + ldaplist *ll; + ll = LDAP_MALLOC( sizeof( *ll )); + if ( ll == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + + ll->ll_data = (void *)invalue; + ll->ll_next = lo->ldo_conn_cbs; + lo->ldo_conn_cbs = ll; + } + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_X_KEEPALIVE_IDLE: + lo->ldo_keepalive_idle = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_X_KEEPALIVE_PROBES : + lo->ldo_keepalive_probes = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_X_KEEPALIVE_INTERVAL : + lo->ldo_keepalive_interval = * (const int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + case LDAP_OPT_TCP_USER_TIMEOUT: + lo->ldo_tcp_user_timeout = * (const unsigned int *) invalue; + rc = LDAP_OPT_SUCCESS; + break; + + } + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + return ( rc ); +} + +int +ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params ) +{ + int rc; + rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc ); + if( rc != LDAP_OPT_SUCCESS ) return rc; + + rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params ); + return rc; +} + +int +ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params ) +{ + int rc; + rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc ); + if( rc != LDAP_OPT_SUCCESS ) return rc; + + rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params ); + return rc; +} + +int +ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params ) +{ + int rc; + rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc ); + if( rc != LDAP_OPT_SUCCESS ) return rc; + + rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params ); + return rc; +} diff --git a/libs/ldap/libldap/os-ip.c b/libs/ldap/libldap/os-ip.c new file mode 100644 index 00000000000..f31d95c2ec8 --- /dev/null +++ b/libs/ldap/libldap/os-ip.c @@ -0,0 +1,1265 @@ +/* os-ip.c -- platform-specific TCP & UDP related code */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * Portions Copyright 1999 Lars Uffmann. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* Significant additional contributors include: + * Lars Uffman + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif /* HAVE_IO_H */ +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include "ldap-int.h" + +#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) +# ifdef LDAP_PF_INET6 +int ldap_int_inet4or6 = AF_UNSPEC; +# else +int ldap_int_inet4or6 = AF_INET; +# endif +#endif + +static void +ldap_pvt_set_errno(int err) +{ + sock_errset(err); +} + +int +ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src ) +{ + struct timeval *new; + + assert( dest != NULL ); + + if (src == NULL) { + *dest = NULL; + return 0; + } + + new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval)); + + if( new == NULL ) { + *dest = NULL; + return 1; + } + + AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval)); + + *dest = new; + return 0; +} + +static int +ldap_pvt_ndelay_on(LDAP *ld, int fd) +{ + Debug1(LDAP_DEBUG_TRACE, "ldap_ndelay_on: %d\n",fd ); + return ber_pvt_socket_set_nonblock( fd, 1 ); +} + +static int +ldap_pvt_ndelay_off(LDAP *ld, int fd) +{ + Debug1(LDAP_DEBUG_TRACE, "ldap_ndelay_off: %d\n",fd ); + return ber_pvt_socket_set_nonblock( fd, 0 ); +} + +static ber_socket_t +ldap_int_socket(LDAP *ld, int family, int type ) +{ + ber_socket_t s = socket(family, type, 0); + Debug1(LDAP_DEBUG_TRACE, "ldap_new_socket: %d\n",s ); +#ifdef FD_CLOEXEC + fcntl(s, F_SETFD, FD_CLOEXEC); +#endif + return ( s ); +} + +static int +ldap_pvt_close_socket(LDAP *ld, int s) +{ + Debug1(LDAP_DEBUG_TRACE, "ldap_close_socket: %d\n",s ); + return tcp_close(s); +} + +static int +ldap_int_prepare_socket(LDAP *ld, int s, int proto ) +{ + Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: %d\n", s ); + +#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) || defined( TCP_USER_TIMEOUT ) + if ( proto == LDAP_PROTO_TCP ) { + int dummy = 1; +#ifdef SO_KEEPALIVE + if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, + (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n", + s ); + } + if ( ld->ld_options.ldo_keepalive_idle > 0 ) + { +#ifdef TCP_KEEPIDLE + if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE, + (void*) &ld->ld_options.ldo_keepalive_idle, + sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, + "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n", + s ); + } +#else + Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "sockopt TCP_KEEPIDLE not supported on this system.\n" ); +#endif /* TCP_KEEPIDLE */ + } + if ( ld->ld_options.ldo_keepalive_probes > 0 ) + { +#ifdef TCP_KEEPCNT + if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT, + (void*) &ld->ld_options.ldo_keepalive_probes, + sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, + "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n", + s ); + } +#else + Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "sockopt TCP_KEEPCNT not supported on this system.\n" ); +#endif /* TCP_KEEPCNT */ + } + if ( ld->ld_options.ldo_keepalive_interval > 0 ) + { +#ifdef TCP_KEEPINTVL + if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL, + (void*) &ld->ld_options.ldo_keepalive_interval, + sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, + "ldap_prepare_socket: " + "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n", + s ); + } +#else + Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "sockopt TCP_KEEPINTVL not supported on this system.\n" ); +#endif /* TCP_KEEPINTVL */ + } +#endif /* SO_KEEPALIVE */ +#ifdef TCP_NODELAY + if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, + (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", + s ); + } +#endif /* TCP_NODELAY */ + if ( ld->ld_options.ldo_tcp_user_timeout > 0 ) + { +#ifdef TCP_USER_TIMEOUT + if ( setsockopt( s, IPPROTO_TCP, TCP_USER_TIMEOUT, + (void*) &ld->ld_options.ldo_tcp_user_timeout, + sizeof(ld->ld_options.ldo_tcp_user_timeout) ) == AC_SOCKET_ERROR ) + { + Debug1(LDAP_DEBUG_TRACE, + "ldap_prepare_socket: " + "setsockopt(%d, TCP_USER_TIMEOUT) failed (ignored).\n", + s ); + } +#else + Debug0(LDAP_DEBUG_TRACE, "ldap_prepare_socket: " + "sockopt TCP_USER_TIMEOUT not supported on this system.\n" ); +#endif /* TCP_USER_TIMEOUT */ + } + } +#endif /* SO_KEEPALIVE || TCP_NODELAY || TCP_USER_TIMEOUT */ + + return 0; +} + +#ifndef HAVE_WINSOCK + +#undef TRACE +#define TRACE do { \ + char ebuf[128]; \ + int saved_errno = errno; \ + Debug3(LDAP_DEBUG_TRACE, "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \ + s, \ + saved_errno, \ + sock_errstr(saved_errno, ebuf, sizeof(ebuf)) ); \ +} while( 0 ) + +/* + * check the socket for errors after select returned. + */ +static int +ldap_pvt_is_socket_ready(LDAP *ld, int s) +{ + Debug1(LDAP_DEBUG_TRACE, "ldap_is_sock_ready: %d\n",s ); + +#if defined( notyet ) /* && defined( SO_ERROR ) */ +{ + int so_errno; + ber_socklen_t dummy = sizeof(so_errno); + if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) + == AC_SOCKET_ERROR ) + { + return -1; + } + if ( so_errno ) { + ldap_pvt_set_errno(so_errno); + TRACE; + return -1; + } + return 0; +} +#else +{ + /* error slippery */ +#ifdef LDAP_PF_INET6 + struct sockaddr_storage sin; +#else + struct sockaddr_in sin; +#endif + char ch; + ber_socklen_t dummy = sizeof(sin); + if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) + == AC_SOCKET_ERROR ) + { + /* XXX: needs to be replace with ber_stream_read() */ + (void)!read(s, &ch, 1); + TRACE; + return -1; + } + return 0; +} +#endif + return -1; +} +#undef TRACE + +#endif /* HAVE_WINSOCK */ + +/* NOTE: this is identical to analogous code in os-local.c */ +int +ldap_int_poll( + LDAP *ld, + ber_socket_t s, + struct timeval *tvp, + int wr ) +{ + int rc; + + + Debug2(LDAP_DEBUG_TRACE, "ldap_int_poll: fd: %d tm: %ld\n", + s, tvp ? tvp->tv_sec : -1L ); + +#ifdef HAVE_POLL + { + struct pollfd fd; + int timeout = INFTIM; + short event = wr ? POLL_WRITE : POLL_READ; + + fd.fd = s; + fd.events = event; + + if ( tvp != NULL ) { + timeout = TV2MILLISEC( tvp ); + } + do { + fd.revents = 0; + rc = poll( &fd, 1, timeout ); + + } while ( rc == AC_SOCKET_ERROR && errno == EINTR && + LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); + + if ( rc == AC_SOCKET_ERROR ) { + return rc; + } + + if ( timeout == 0 && rc == 0 ) { + return -2; + } + + if ( fd.revents & event ) { + if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { + return -1; + } + + if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) { + return -1; + } + return 0; + } + } +#else + { + fd_set wfds, *z = NULL; +#ifdef HAVE_WINSOCK + fd_set efds; +#endif + struct timeval tv = { 0 }; + +#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK ) + if ( s >= FD_SETSIZE ) { + rc = AC_SOCKET_ERROR; + tcp_close( s ); + ldap_pvt_set_errno( EMFILE ); + return rc; + } +#endif + + if ( tvp != NULL ) { + tv = *tvp; + } + + do { + FD_ZERO(&wfds); + FD_SET(s, &wfds ); + +#ifdef HAVE_WINSOCK + FD_ZERO(&efds); + FD_SET(s, &efds ); +#endif + + rc = select( ldap_int_tblsize, z, &wfds, +#ifdef HAVE_WINSOCK + &efds, +#else + z, +#endif + tvp ? &tv : NULL ); + } while ( rc == AC_SOCKET_ERROR && errno == EINTR && + LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) ); + + if ( rc == AC_SOCKET_ERROR ) { + return rc; + } + + if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) { + return -2; + } + +#ifdef HAVE_WINSOCK + /* This means the connection failed */ + if ( FD_ISSET(s, &efds) ) { + int so_errno; + ber_socklen_t dummy = sizeof(so_errno); + if ( getsockopt( s, SOL_SOCKET, SO_ERROR, + (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno ) + { + /* impossible */ + so_errno = WSAGetLastError(); + } + ldap_pvt_set_errno( so_errno ); + Debug3(LDAP_DEBUG_TRACE, + "ldap_int_poll: error on socket %d: " + "errno: %d (%s)\n", s, so_errno, sock_errstr( so_errno, dummy, dummy )); + return -1; + } +#endif + if ( FD_ISSET(s, &wfds) ) { +#ifndef HAVE_WINSOCK + if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) { + return -1; + } +#endif + if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { + return -1; + } + return 0; + } + } +#endif + + Debug0(LDAP_DEBUG_TRACE, "ldap_int_poll: timed out\n" ); + ldap_pvt_set_errno( ETIMEDOUT ); + return -1; +} + +static int +ldap_pvt_connect(LDAP *ld, ber_socket_t s, + struct sockaddr *sin, ber_socklen_t addrlen, + int async) +{ + int rc, err; + struct timeval tv, *opt_tv = NULL; + +#ifdef LDAP_CONNECTIONLESS + /* We could do a connect() but that would interfere with + * attempts to poll a broadcast address + */ + if (LDAP_IS_UDP(ld)) { + if (ld->ld_options.ldo_peer) + ldap_memfree(ld->ld_options.ldo_peer); + ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage)); + AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen); + return ( 0 ); + } +#endif + if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { + tv = ld->ld_options.ldo_tm_net; + opt_tv = &tv; + } + + Debug3(LDAP_DEBUG_TRACE, + "ldap_pvt_connect: fd: %d tm: %ld async: %d\n", + s, opt_tv ? tv.tv_sec : -1L, async); + + if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 ) + return ( -1 ); + + do{ + Debug0(LDAP_DEBUG_TRACE, "attempting to connect: \n" ); + if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { + Debug0(LDAP_DEBUG_TRACE, "connect success\n" ); + + if ( !async && opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) + return ( -1 ); + return ( 0 ); + } + err = sock_errno(); + Debug1(LDAP_DEBUG_TRACE, "connect errno: %d\n", err ); + + } while(err == EINTR && + LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART )); + + if ( err != EINPROGRESS && err != EWOULDBLOCK ) { + return ( -1 ); + } + + if ( async ) { + /* caller will call ldap_int_poll() as appropriate? */ + return ( -2 ); + } + + rc = ldap_int_poll( ld, s, opt_tv, 1 ); + + Debug1(LDAP_DEBUG_TRACE, "ldap_pvt_connect: %d\n", rc ); + + return rc; +} + +#ifndef HAVE_INET_ATON +int +ldap_pvt_inet_aton( const char *host, struct in_addr *in) +{ + unsigned long u = inet_addr( host ); + +#ifdef INADDR_NONE + if ( u == INADDR_NONE ) return 0; +#endif + if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0; + + in->s_addr = u; + return 1; +} +#endif + +int +ldap_validate_and_fill_sourceip (char** source_ip_lst, ldapsourceip* temp_source_ip ) +{ + int i = 0; + int rc = LDAP_PARAM_ERROR; + + for ( i = 0; source_ip_lst[i] != NULL; i++ ) { + Debug1( LDAP_DEBUG_TRACE, + "ldap_validate_and_fill_sourceip(%s)\n", + source_ip_lst[i] ); + + if ( !temp_source_ip->has_ipv4 ) { + if ( inet_aton( source_ip_lst[i], &temp_source_ip->ip4_addr ) ) { + temp_source_ip->has_ipv4 = 1; + rc = LDAP_OPT_SUCCESS; + continue; + } + } +#ifdef LDAP_PF_INET6 + if ( !temp_source_ip->has_ipv6 ) { + if ( inet_pton( AF_INET6, source_ip_lst[i], + & temp_source_ip->ip6_addr ) ) { + temp_source_ip->has_ipv6 = 1; + rc = LDAP_OPT_SUCCESS; + continue; + } + } +#endif + memset( temp_source_ip, 0, sizeof( * (temp_source_ip ) ) ); + Debug1( LDAP_DEBUG_TRACE, + "ldap_validate_and_fill_sourceip: validation failed for (%s)\n", + source_ip_lst[i] ); + break; + } + return rc; +} + +int +ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr) +{ + struct ldapoptions *lo; + ldaplist *ll; + ldap_conncb *cb; + int rc; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); + + /* Invoke all handle-specific callbacks first */ + lo = &ld->ld_options; + for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { + cb = ll->ll_data; + rc = cb->lc_add( ld, sb, srv, addr, cb ); + /* on any failure, call the teardown functions for anything + * that previously succeeded + */ + if ( rc ) { + ldaplist *l2; + for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + /* a failure might have implicitly closed the fd */ + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); + return rc; + } + } + lo = LDAP_INT_GLOBAL_OPT(); + for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { + cb = ll->ll_data; + rc = cb->lc_add( ld, sb, srv, addr, cb ); + if ( rc ) { + ldaplist *l2; + for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + lo = &ld->ld_options; + for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); + return rc; + } + } + return 0; +} + +int +ldap_connect_to_host(LDAP *ld, Sockbuf *sb, + int proto, LDAPURLDesc *srv, + int async ) +{ + int rc; + int socktype, port; + ber_socket_t s = AC_SOCKET_INVALID; + char *host; + +#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) + char serv[7]; + int err; + struct addrinfo hints, *res, *sai; +#else + int i; + int use_hp = 0; + struct hostent *hp = NULL; + struct hostent he_buf; + struct in_addr in; + char *ha_buf=NULL; +#endif + + if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { + host = "localhost"; + } else { + host = srv->lud_host; + } + + port = srv->lud_port; + + if( !port ) { + if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { + port = LDAPS_PORT; + } else { + port = LDAP_PORT; + } + } + + switch(proto) { + case LDAP_PROTO_TCP: socktype = SOCK_STREAM; + Debug2(LDAP_DEBUG_TRACE, "ldap_connect_to_host: TCP %s:%d\n", + host, port ); + break; + case LDAP_PROTO_UDP: socktype = SOCK_DGRAM; + Debug2(LDAP_DEBUG_TRACE, "ldap_connect_to_host: UDP %s:%d\n", + host, port ); + break; + default: + Debug1(LDAP_DEBUG_TRACE, + "ldap_connect_to_host: unknown proto: %d\n", + proto ); + return -1; + } + +#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) + memset( &hints, '\0', sizeof(hints) ); +#ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */ + /* Use AI_ADDRCONFIG only on systems where its known to be needed. */ + hints.ai_flags = AI_ADDRCONFIG; +#endif + hints.ai_family = ldap_int_inet4or6; + hints.ai_socktype = socktype; + snprintf(serv, sizeof serv, "%d", port ); + + /* most getaddrinfo(3) use non-threadsafe resolver libraries */ + LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex); + + err = getaddrinfo( host, serv, &hints, &res ); + + LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex); + + if ( err != 0 ) { + Debug1(LDAP_DEBUG_TRACE, + "ldap_connect_to_host: getaddrinfo failed: %s\n", + AC_GAI_STRERROR(err) ); + return -1; + } + rc = -1; + + for( sai=res; sai != NULL; sai=sai->ai_next) { + unsigned short bind_success = 1; + if( sai->ai_addr == NULL ) { + Debug0(LDAP_DEBUG_TRACE, + "ldap_connect_to_host: getaddrinfo " + "ai_addr is NULL?\n" ); + continue; + } + +#ifndef LDAP_PF_INET6 + if ( sai->ai_family == AF_INET6 ) continue; +#endif + /* we assume AF_x and PF_x are equal for all x */ + s = ldap_int_socket( ld, sai->ai_family, socktype ); + if ( s == AC_SOCKET_INVALID ) { + continue; + } + + if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { + ldap_pvt_close_socket(ld, s); + break; + } + + switch (sai->ai_family) { +#ifdef LDAP_PF_INET6 + case AF_INET6: { + char addr[INET6_ADDRSTRLEN]; + inet_ntop( AF_INET6, + &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr, + addr, sizeof addr); + Debug2(LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Trying %s %s\n", + addr, serv ); + if( ld->ld_options.ldo_local_ip_addrs.has_ipv6 ) { + struct sockaddr_in6 ip6addr; + char bind_addr[INET6_ADDRSTRLEN]; + ip6addr.sin6_family = AF_INET6; + ip6addr.sin6_port = 0; + ip6addr.sin6_addr = ld->ld_options.ldo_local_ip_addrs.ip6_addr; + inet_ntop( AF_INET6, + &(ip6addr.sin6_addr), + bind_addr, sizeof bind_addr ); + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: From source address %s\n", + bind_addr ); + if ( bind( s, ( struct sockaddr* ) &ip6addr, sizeof ip6addr ) != 0 ) { + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Failed to bind source address %s\n", + bind_addr ); + bind_success = 0; + } + } + } break; +#endif + case AF_INET: { + char addr[INET_ADDRSTRLEN]; + inet_ntop( AF_INET, + &((struct sockaddr_in *)sai->ai_addr)->sin_addr, + addr, sizeof addr); + Debug2(LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Trying %s:%s\n", + addr, serv ); + if( ld->ld_options.ldo_local_ip_addrs.has_ipv4 ) { + struct sockaddr_in ip4addr; + char bind_addr[INET_ADDRSTRLEN]; + ip4addr.sin_family = AF_INET; + ip4addr.sin_port = 0; + ip4addr.sin_addr = ld->ld_options.ldo_local_ip_addrs.ip4_addr; + inet_ntop( AF_INET, + &(ip4addr.sin_addr), + bind_addr, sizeof bind_addr ); + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: From source address %s\n", + bind_addr ); + if ( bind(s, ( struct sockaddr* )&ip4addr, sizeof ip4addr ) != 0 ) { + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Failed to bind source address %s\n", + bind_addr ); + bind_success = 0; + } + } + } break; + } + if ( bind_success ) { + rc = ldap_pvt_connect( ld, s, + sai->ai_addr, sai->ai_addrlen, async ); + if ( rc == 0 || rc == -2 ) { + err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr ); + if ( err ) + rc = err; + else + break; + } + } + ldap_pvt_close_socket(ld, s); + } + freeaddrinfo(res); + +#else + if (! inet_aton( host, &in ) ) { + int local_h_errno; + rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf, + &hp, &local_h_errno ); + + if ( (rc < 0) || (hp == NULL) ) { +#ifdef HAVE_WINSOCK + ldap_pvt_set_errno( WSAGetLastError() ); +#else + /* not exactly right, but... */ + ldap_pvt_set_errno( EHOSTUNREACH ); +#endif + if (ha_buf) LDAP_FREE(ha_buf); + return -1; + } + + use_hp = 1; + } + + rc = s = -1; + for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { + struct sockaddr_in sin; + unsigned short bind_success = 1; +#ifdef HAVE_INET_NTOA_B + char address[INET_ADDR_LEN]; + char bind_addr[INET_ADDR_LEN]; +#else + char *address; + char *bind_addr; +#endif + s = ldap_int_socket( ld, PF_INET, socktype ); + if ( s == AC_SOCKET_INVALID ) { + /* use_hp ? continue : break; */ + break; + } + + if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { + ldap_pvt_close_socket(ld, s); + break; + } + + (void)memset((char *)&sin, '\0', sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons((unsigned short) port); + + if( use_hp ) { + AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i], + sizeof(sin.sin_addr) ); + } else { + AC_MEMCPY( &sin.sin_addr, &in.s_addr, + sizeof(sin.sin_addr) ); + } + +#ifdef HAVE_INET_NTOA_B + /* for VxWorks */ + inet_ntoa_b( sin.sin_address, address ); +#else + address = inet_ntoa( sin.sin_addr ); +#endif + Debug2( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Trying %s:%d\n", + address, port ); + if( ld->ld_options.ldo_local_ip_addrs.has_ipv4 ) { + struct sockaddr_in ip4addr; + ip4addr.sin_family = AF_INET; + ip4addr.sin_addr = ld->ld_options.ldo_local_ip_addrs.ip4_addr; +#ifdef HAVE_INET_NTOA_B + inet_ntoa_b( ip4addr.sin_address, bind_addr ); +#else + bind_addr = inet_ntoa( ip4addr.sin_addr ); +#endif + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: From source address %s\n", + bind_addr ); + if ( bind( s, (struct sockaddr*)&ip4addr, sizeof ip4addr ) != 0 ) { + Debug1( LDAP_DEBUG_TRACE, + "ldap_connect_to_host: Failed to bind source address %s\n", + bind_addr ); + bind_success = 0; + } + } + if ( bind_success ) { + rc = ldap_pvt_connect(ld, s, + (struct sockaddr *)&sin, sizeof(sin), + async); + + if ( (rc == 0) || (rc == -2) ) { + int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin ); + if ( err ) + rc = err; + else + break; + } + } + + ldap_pvt_close_socket(ld, s); + + if (!use_hp) break; + } + if (ha_buf) LDAP_FREE(ha_buf); +#endif + + return rc; +} + +#if defined( HAVE_CYRUS_SASL ) +char * +ldap_host_connected_to( Sockbuf *sb, const char *host ) +{ + ber_socklen_t len; +#ifdef LDAP_PF_INET6 + struct sockaddr_storage sabuf; +#else + struct sockaddr sabuf; +#endif + struct sockaddr *sa = (struct sockaddr *) &sabuf; + ber_socket_t sd; + + (void)memset( (char *)sa, '\0', sizeof sabuf ); + len = sizeof sabuf; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + if ( getpeername( sd, sa, &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. + */ + + switch (sa->sa_family) { +#ifdef LDAP_PF_LOCAL + case AF_LOCAL: + return LDAP_STRDUP( ldap_int_hostname ); +#endif +#ifdef LDAP_PF_INET6 + case AF_INET6: + { + struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; + if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, + &localhost, sizeof(localhost)) == 0 ) + { + return LDAP_STRDUP( ldap_int_hostname ); + } + } + break; +#endif + case AF_INET: + { + struct in_addr localhost; + localhost.s_addr = htonl( INADDR_ANY ); + + if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, + &localhost, sizeof(localhost) ) == 0 ) + { + return LDAP_STRDUP( ldap_int_hostname ); + } + +#ifdef INADDR_LOOPBACK + localhost.s_addr = htonl( INADDR_LOOPBACK ); + + if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, + &localhost, sizeof(localhost) ) == 0 ) + { + return LDAP_STRDUP( ldap_int_hostname ); + } +#endif + } + break; + + default: + return( NULL ); + break; + } + + { + char *herr; +#ifdef NI_MAXHOST + char hbuf[NI_MAXHOST]; +#elif defined( MAXHOSTNAMELEN ) + char hbuf[MAXHOSTNAMELEN]; +#else + char hbuf[256]; +#endif + hbuf[0] = 0; + + if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 + && hbuf[0] ) + { + return LDAP_STRDUP( hbuf ); + } + } + + return host ? LDAP_STRDUP( host ) : NULL; +} +#endif + + +struct selectinfo { +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + int si_maxfd; + struct pollfd si_fds[FD_SETSIZE]; +#else + /* for UNIX select(2) */ + fd_set si_readfds; + fd_set si_writefds; + fd_set si_use_readfds; + fd_set si_use_writefds; +#endif +}; + +void +ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int empty=-1; + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + sip->si_fds[i].events |= POLL_WRITE; + return; + } + if( empty==-1 && sip->si_fds[i].fd == -1 ) { + empty=i; + } + } + + if( empty == -1 ) { + if( sip->si_maxfd >= FD_SETSIZE ) { + /* FIXME */ + return; + } + empty = sip->si_maxfd++; + } + + sip->si_fds[empty].fd = sd; + sip->si_fds[empty].events = POLL_WRITE; + } +#else + /* for UNIX select(2) */ + if ( !FD_ISSET( sd, &sip->si_writefds )) { + FD_SET( sd, &sip->si_writefds ); + } +#endif +} + + +void +ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int empty=-1; + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + sip->si_fds[i].events |= POLL_READ; + return; + } + if( empty==-1 && sip->si_fds[i].fd == -1 ) { + empty=i; + } + } + + if( empty == -1 ) { + if( sip->si_maxfd >= FD_SETSIZE ) { + /* FIXME */ + return; + } + empty = sip->si_maxfd++; + } + + sip->si_fds[empty].fd = sd; + sip->si_fds[empty].events = POLL_READ; + } +#else + /* for UNIX select(2) */ + if ( !FD_ISSET( sd, &sip->si_readfds )) { + FD_SET( sd, &sip->si_readfds ); + } +#endif +} + + +void +ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + sip->si_fds[i].fd = -1; + } + } + } +#else + /* for UNIX select(2) */ + FD_CLR( sd, &sip->si_writefds ); + FD_CLR( sd, &sip->si_readfds ); +#endif +} + +void +ldap_clear_select_write( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + sip->si_fds[i].events &= ~POLL_WRITE; + } + } + } +#else + /* for UNIX select(2) */ + FD_CLR( sd, &sip->si_writefds ); +#endif +} + + +int +ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + return sip->si_fds[i].revents & POLL_WRITE; + } + } + + return 0; + } +#else + /* for UNIX select(2) */ + return( FD_ISSET( sd, &sip->si_use_writefds )); +#endif +} + + +int +ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) +{ + struct selectinfo *sip; + ber_socket_t sd; + + sip = (struct selectinfo *)ld->ld_selectinfo; + + if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL )) + return 1; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + { + int i; + for(i=0; i < sip->si_maxfd; i++) { + if( sip->si_fds[i].fd == sd ) { + return sip->si_fds[i].revents & POLL_READ; + } + } + + return 0; + } +#else + /* for UNIX select(2) */ + return( FD_ISSET( sd, &sip->si_use_readfds )); +#endif +} + + +void * +ldap_new_select_info( void ) +{ + struct selectinfo *sip; + + sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo )); + + if ( sip == NULL ) return NULL; + +#ifdef HAVE_POLL + /* for UNIX poll(2) */ + /* sip->si_maxfd=0 */ +#else + /* for UNIX select(2) */ + FD_ZERO( &sip->si_readfds ); + FD_ZERO( &sip->si_writefds ); +#endif + + return( (void *)sip ); +} + + +void +ldap_free_select_info( void *sip ) +{ + LDAP_FREE( sip ); +} + + +#ifndef HAVE_POLL +int ldap_int_tblsize = 0; + +void +ldap_int_ip_init( void ) +{ +#if defined( HAVE_SYSCONF ) + long tblsize = sysconf( _SC_OPEN_MAX ); + if( tblsize > INT_MAX ) tblsize = INT_MAX; + +#elif defined( HAVE_GETDTABLESIZE ) + int tblsize = getdtablesize(); +#else + int tblsize = FD_SETSIZE; +#endif /* !USE_SYSCONF */ + +#ifdef FD_SETSIZE + if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE; +#endif /* FD_SETSIZE */ + + ldap_int_tblsize = tblsize; +} +#endif + + +int +ldap_int_select( LDAP *ld, struct timeval *timeout ) +{ + int rc; + struct selectinfo *sip; + + Debug0( LDAP_DEBUG_TRACE, "ldap_int_select\n" ); + +#ifndef HAVE_POLL + if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); +#endif + + sip = (struct selectinfo *)ld->ld_selectinfo; + assert( sip != NULL ); + +#ifdef HAVE_POLL + { + int to = timeout ? TV2MILLISEC( timeout ) : INFTIM; + rc = poll( sip->si_fds, sip->si_maxfd, to ); + } +#else + sip->si_use_readfds = sip->si_readfds; + sip->si_use_writefds = sip->si_writefds; + + rc = select( ldap_int_tblsize, + &sip->si_use_readfds, &sip->si_use_writefds, + NULL, timeout ); +#endif + + return rc; +} diff --git a/libs/ldap/libldap/pagectrl.c b/libs/ldap/libldap/pagectrl.c new file mode 100644 index 00000000000..c5589a82317 --- /dev/null +++ b/libs/ldap/libldap/pagectrl.c @@ -0,0 +1,270 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * Copyright 2006 Hans Leidekker + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* --------------------------------------------------------------------------- + ldap_create_page_control_value + + Create and encode the value of the paged results control (RFC 2696). + + ld (IN) An LDAP session handle + pagesize (IN) Page size requested + cookie (IN) Opaque structure used by the server to track its + location in the search results. NULL on the + first call. + value (OUT) Control value, SHOULD be freed by calling + ldap_memfree() when done. + + pagedResultsControl ::= SEQUENCE { + controlType 1.2.840.113556.1.4.319, + criticality BOOLEAN DEFAULT FALSE, + controlValue searchControlValue } + + searchControlValue ::= SEQUENCE { + size INTEGER (0..maxInt), + -- requested page size from client + -- result set size estimate from server + cookie OCTET STRING } + + ---------------------------------------------------------------------------*/ + +int +ldap_create_page_control_value( + LDAP *ld, + ber_int_t pagesize, + struct berval *cookie, + struct berval *value ) +{ + BerElement *ber = NULL; + ber_tag_t tag; + struct berval null_cookie = { 0, NULL }; + + if ( ld == NULL || value == NULL || + pagesize < 1 || pagesize > LDAP_MAXINT ) + { + if ( ld ) + ld->ld_errno = LDAP_PARAM_ERROR; + return LDAP_PARAM_ERROR; + } + + assert( LDAP_VALID( ld ) ); + + value->bv_val = NULL; + value->bv_len = 0; + ld->ld_errno = LDAP_SUCCESS; + + if ( cookie == NULL ) { + cookie = &null_cookie; + } + + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_printf( ber, "{iO}", pagesize, cookie ); + if ( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + goto done; + } + + if ( ber_flatten2( ber, value, 1 ) == -1 ) { + ld->ld_errno = LDAP_NO_MEMORY; + } + +done:; + if ( ber != NULL ) { + ber_free( ber, 1 ); + } + + return ld->ld_errno; +} + + +/* --------------------------------------------------------------------------- + ldap_create_page_control + + Create and encode a page control. + + ld (IN) An LDAP session handle + pagesize (IN) Page size requested + cookie (IN) Opaque structure used by the server to track its + location in the search results. NULL on the + first call. + value (OUT) Control value, SHOULD be freed by calling + ldap_memfree() when done. + iscritical (IN) Criticality + ctrlp (OUT) LDAP control, SHOULD be freed by calling + ldap_control_free() when done. + + pagedResultsControl ::= SEQUENCE { + controlType 1.2.840.113556.1.4.319, + criticality BOOLEAN DEFAULT FALSE, + controlValue searchControlValue } + + searchControlValue ::= SEQUENCE { + size INTEGER (0..maxInt), + -- requested page size from client + -- result set size estimate from server + cookie OCTET STRING } + + ---------------------------------------------------------------------------*/ + +int +ldap_create_page_control( + LDAP *ld, + ber_int_t pagesize, + struct berval *cookie, + int iscritical, + LDAPControl **ctrlp ) +{ + struct berval value; + + if ( ctrlp == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + ld->ld_errno = ldap_create_page_control_value( ld, + pagesize, cookie, &value ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS, + iscritical, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { + LDAP_FREE( value.bv_val ); + } + } + + return ld->ld_errno; +} + + +/* --------------------------------------------------------------------------- + ldap_parse_pageresponse_control + + Decode a page control. + + ld (IN) An LDAP session handle + ctrl (IN) The page response control + count (OUT) The number of entries in the page. + cookie (OUT) Opaque cookie. Use ldap_memfree() to + free the bv_val member of this structure. + + ---------------------------------------------------------------------------*/ + +int +ldap_parse_pageresponse_control( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *countp, + struct berval *cookie ) +{ + BerElement *ber; + ber_tag_t tag; + ber_int_t count; + + if ( ld == NULL || ctrl == NULL || cookie == NULL ) { + if ( ld ) + ld->ld_errno = LDAP_PARAM_ERROR; + return LDAP_PARAM_ERROR; + } + + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init( &ctrl->ldctl_value ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + /* Extract the count and cookie from the control. */ + tag = ber_scanf( ber, "{io}", &count, cookie ); + ber_free( ber, 1 ); + + if ( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + } else { + ld->ld_errno = LDAP_SUCCESS; + + if ( countp != NULL ) { + *countp = (unsigned long)count; + } + } + + return ld->ld_errno; +} + +/* --------------------------------------------------------------------------- + ldap_parse_page_control + + Decode a page control. + + ld (IN) An LDAP session handle + ctrls (IN) Response controls + count (OUT) The number of entries in the page. + cookie (OUT) Opaque cookie. Use ldap_memfree() to + free the bv_val member of this structure. + + ---------------------------------------------------------------------------*/ + +int +ldap_parse_page_control( + LDAP *ld, + LDAPControl **ctrls, + ber_int_t *countp, + struct berval **cookiep ) +{ + LDAPControl *c; + struct berval cookie; + + if ( cookiep == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + if ( ctrls == NULL ) { + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return ld->ld_errno; + } + + c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); + if ( c == NULL ) { + /* No page control was found. */ + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return ld->ld_errno; + } + + ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + *cookiep = LDAP_MALLOC( sizeof( struct berval ) ); + if ( *cookiep == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + } else { + **cookiep = cookie; + } + } + + return ld->ld_errno; +} diff --git a/libs/ldap/libldap/print.c b/libs/ldap/libldap/print.c new file mode 100644 index 00000000000..585fbef9498 --- /dev/null +++ b/libs/ldap/libldap/print.c @@ -0,0 +1,62 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/ctype.h> +#include <ac/stdarg.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* + * ldap log + */ + +static int ldap_log_check( LDAP *ld, int loglvl ) +{ + int errlvl; + + if(ld == NULL) { + errlvl = ldap_debug; + } else { + errlvl = ld->ld_debug; + } + + return errlvl & loglvl ? 1 : 0; +} + +int ldap_log_printf( LDAP *ld, int loglvl, const char *fmt, ... ) +{ + char buf[ 1024 ]; + va_list ap; + + if ( !ldap_log_check( ld, loglvl )) { + return 0; + } + + va_start( ap, fmt ); + + buf[sizeof(buf) - 1] = '\0'; + vsnprintf( buf, sizeof(buf)-1, fmt, ap ); + + va_end(ap); + + (*ber_pvt_log_print)( buf ); + return 1; +} diff --git a/libs/ldap/libldap/references.c b/libs/ldap/libldap/references.c new file mode 100644 index 00000000000..357e519d7ba --- /dev/null +++ b/libs/ldap/libldap/references.c @@ -0,0 +1,147 @@ +/* references.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +LDAPMessage * +ldap_first_reference( LDAP *ld, LDAPMessage *chain ) +{ + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( chain != NULL ); + + return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE + ? chain + : ldap_next_reference( ld, chain ); +} + +LDAPMessage * +ldap_next_reference( LDAP *ld, LDAPMessage *ref ) +{ + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( ref != NULL ); + + for ( + ref = ref->lm_chain; + ref != NULL; + ref = ref->lm_chain ) + { + if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + return( ref ); + } + } + + return( NULL ); +} + +int +ldap_count_references( LDAP *ld, LDAPMessage *chain ) +{ + int i; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + for ( i = 0; chain != NULL; chain = chain->lm_chain ) { + if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) { + i++; + } + } + + return( i ); +} + +int +ldap_parse_reference( + LDAP *ld, + LDAPMessage *ref, + char ***referralsp, + LDAPControl ***serverctrls, + int freeit) +{ + BerElement be; + char **refs = NULL; + int rc; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( ref != NULL ); + + if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { + return LDAP_PARAM_ERROR; + } + + /* make a private copy of BerElement */ + AC_MEMCPY(&be, ref->lm_ber, sizeof(be)); + + if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + + if ( serverctrls == NULL ) { + rc = LDAP_SUCCESS; + goto free_and_return; + } + + if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + goto free_and_return; + } + + rc = ldap_pvt_get_controls( &be, serverctrls ); + +free_and_return: + + if( referralsp != NULL ) { + /* provide references regardless of return code */ + *referralsp = refs; + + } else { + LDAP_VFREE( refs ); + } + + if( freeit ) { + ldap_msgfree( ref ); + } + + if( rc != LDAP_SUCCESS ) { + ld->ld_errno = rc; + + if( ld->ld_matched != NULL ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + if( ld->ld_error != NULL ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + } + + return rc; +} diff --git a/libs/ldap/libldap/request.c b/libs/ldap/libldap/request.c new file mode 100644 index 00000000000..4709768379d --- /dev/null +++ b/libs/ldap/libldap/request.c @@ -0,0 +1,1714 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Modification to OpenLDAP source by Novell, Inc. + * April 2000 sfs Added code to chase V3 referrals + * request.c - sending of ldap requests; handling of referrals + *--- + * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/errno.h> +#include <ac/param.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#include "ldap-int.h" +#include "lber.h" + +/* used by ldap_send_server_request and ldap_new_connection */ +#ifdef LDAP_R_COMPILE +#define LDAP_CONN_LOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); } +#define LDAP_CONN_UNLOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); } +#define LDAP_REQ_LOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); } +#define LDAP_REQ_UNLOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); } +#define LDAP_RES_LOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); } +#define LDAP_RES_UNLOCK_IF(nolock) \ + { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); } +#else +#define LDAP_CONN_LOCK_IF(nolock) +#define LDAP_CONN_UNLOCK_IF(nolock) +#define LDAP_REQ_LOCK_IF(nolock) +#define LDAP_REQ_UNLOCK_IF(nolock) +#define LDAP_RES_LOCK_IF(nolock) +#define LDAP_RES_UNLOCK_IF(nolock) +#endif + +static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any )); +static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc )); +static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr )); + +static BerElement * +re_encode_request( LDAP *ld, + BerElement *origber, + ber_int_t msgid, + int sref, + LDAPURLDesc *srv, + int *type ); + +BerElement * +ldap_alloc_ber_with_options( LDAP *ld ) +{ + BerElement *ber; + + ber = ber_alloc_t( ld->ld_lberoptions ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + } + + return( ber ); +} + + +void +ldap_set_ber_options( LDAP *ld, BerElement *ber ) +{ + /* ld_lberoptions is constant, hence no lock */ + ber->ber_options = ld->ld_lberoptions; +} + + +/* sets needed mutexes - no mutexes set to this point */ +ber_int_t +ldap_send_initial_request( + LDAP *ld, + ber_tag_t msgtype, + const char *dn, + BerElement *ber, + ber_int_t msgid) +{ + int rc = 1; + ber_socket_t sd = AC_SOCKET_INVALID; + + Debug0( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n" ); + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) { + /* not connected yet */ + rc = ldap_open_defconn( ld ); + if ( rc == 0 ) { + ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb, + LBER_SB_OPT_GET_FD, &sd ); + } + } + if ( ld->ld_defconn && ld->ld_defconn->lconn_status == LDAP_CONNST_CONNECTING ) + rc = ldap_int_check_async_open( ld, sd ); + if( rc < 0 ) { + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return( -1 ); + } else if ( rc == 0 ) { + Debug0( LDAP_DEBUG_TRACE, + "ldap_open_defconn: successful\n" ); + } + +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld)) { + if (msgtype == LDAP_REQ_BIND) { + LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); + if (ld->ld_options.ldo_cldapdn) + ldap_memfree(ld->ld_options.ldo_cldapdn); + ld->ld_options.ldo_cldapdn = ldap_strdup(dn); + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return 0; + } + if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH) + { + ber_free( ber, 1 ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return LDAP_PARAM_ERROR; + } + } +#endif + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + rc = ldap_send_server_request( ld, ber, msgid, NULL, + NULL, NULL, NULL, 0, 0 ); + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return(rc); +} + + +/* protected by conn_mutex */ +int +ldap_int_flush_request( + LDAP *ld, + LDAPRequest *lr ) +{ + LDAPConn *lc = lr->lr_conn; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) { + if (( sock_errno() == EAGAIN ) || ( sock_errno() == ENOTCONN )) { + /* ENOTCONN is returned in Solaris 10 */ + /* need to continue write later */ + lr->lr_status = LDAP_REQST_WRITING; + ldap_mark_select_write( ld, lc->lconn_sb ); + ld->ld_errno = LDAP_BUSY; + return -2; + } else { + ld->ld_errno = LDAP_SERVER_DOWN; + ldap_free_request( ld, lr ); + ldap_free_connection( ld, lc, 0, 0 ); + return( -1 ); + } + } else { + if ( lr->lr_parent == NULL ) { + 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; + + /* sent -- waiting for a response */ + ldap_mark_select_read( ld, lc->lconn_sb ); + ldap_clear_select_write( ld, lc->lconn_sb ); + } + return 0; +} + +/* + * protected by req_mutex + * if m_noconn then protect using conn_lock + * else already protected with conn_lock + * if m_res then also protected by res_mutex + */ + +int +ldap_send_server_request( + LDAP *ld, + BerElement *ber, + ber_int_t msgid, + LDAPRequest *parentreq, + LDAPURLDesc **srvlist, + LDAPConn *lc, + LDAPreqinfo *bind, + int m_noconn, + int m_res ) +{ + LDAPRequest *lr; + int incparent, rc; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + Debug0( LDAP_DEBUG_TRACE, "ldap_send_server_request\n" ); + + incparent = 0; + ld->ld_errno = LDAP_SUCCESS; /* optimistic */ + + LDAP_CONN_LOCK_IF(m_noconn); + if ( lc == NULL ) { + if ( srvlist == NULL ) { + lc = ld->ld_defconn; + } else { + lc = find_connection( ld, *srvlist, 1 ); + if ( lc == NULL ) { + if ( (bind != NULL) && (parentreq != NULL) ) { + /* Remember the bind in the parent */ + incparent = 1; + ++parentreq->lr_outrefcnt; + } + lc = ldap_new_connection( ld, srvlist, 0, + 1, bind, 1, m_res ); + } + } + } + + /* async connect... */ + if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) { + ber_socket_t sd = AC_SOCKET_ERROR; + struct timeval tv = { 0 }; + + ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd ); + + /* poll ... */ + switch ( ldap_int_poll( ld, sd, &tv, 1 ) ) { + case 0: + /* go on! */ + lc->lconn_status = LDAP_CONNST_CONNECTED; + break; + + case -2: + /* async only occurs if a network timeout is set */ + + /* honor network timeout */ + LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); + if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec ) + { + /* caller will have to call again */ + ld->ld_errno = LDAP_X_CONNECTING; + } + LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); + /* fallthru */ + + default: + /* error */ + break; + } + } + + if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) { + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = LDAP_SERVER_DOWN; + } + + ber_free( ber, 1 ); + if ( incparent ) { + /* Forget about the bind */ + --parentreq->lr_outrefcnt; + } + LDAP_CONN_UNLOCK_IF(m_noconn); + return( -1 ); + } + + use_connection( ld, lc ); + +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP( ld )) { + BerElement tmpber = *ber; + ber_rewind( &tmpber ); + LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); + rc = ber_write( &tmpber, ld->ld_options.ldo_peer, + sizeof( struct sockaddr_storage ), 0 ); + LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + LDAP_CONN_UNLOCK_IF(m_noconn); + return rc; + } + } +#endif + + /* If we still have an incomplete write, try to finish it before + * dealing with the new request. If we don't finish here, return + * LDAP_BUSY and let the caller retry later. We only allow a single + * request to be in WRITING state. + */ + rc = 0; + if ( ld->ld_requests != NULL ) { + TAvlnode *node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_RIGHT ); + LDAPRequest *lr; + + assert( node != NULL ); + lr = node->avl_data; + if ( lr->lr_status == LDAP_REQST_WRITING && + ldap_int_flush_request( ld, lr ) < 0 ) { + rc = -1; + } + } + if ( rc ) { + ber_free( ber, 1 ); + LDAP_CONN_UNLOCK_IF(m_noconn); + return rc; + } + + lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) ); + if ( lr == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + ldap_free_connection( ld, lc, 0, 0 ); + ber_free( ber, 1 ); + if ( incparent ) { + /* Forget about the bind */ + --parentreq->lr_outrefcnt; + } + LDAP_CONN_UNLOCK_IF(m_noconn); + return( -1 ); + } + lr->lr_msgid = msgid; + lr->lr_status = LDAP_REQST_INPROGRESS; + lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */ + lr->lr_ber = ber; + lr->lr_conn = lc; + 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; + lr->lr_parent = parentreq; + lr->lr_refnext = parentreq->lr_child; + parentreq->lr_child = lr; + } else { /* original request */ + lr->lr_origid = lr->lr_msgid; + } + + /* Extract requestDN for future reference */ +#ifdef LDAP_CONNECTIONLESS + if ( !LDAP_IS_UDP(ld) ) +#endif + { + BerElement tmpber = *ber; + ber_int_t bint; + ber_tag_t tag, rtag; + + ber_reset( &tmpber, 1 ); + rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag ); + switch ( tag ) { + case LDAP_REQ_BIND: + rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint ); + break; + case LDAP_REQ_DELETE: + break; + default: + rtag = ber_scanf( &tmpber, "{" /*}*/ ); + case LDAP_REQ_ABANDON: + break; + } + if ( tag != LDAP_REQ_ABANDON ) { + ber_skip_tag( &tmpber, &lr->lr_dn.bv_len ); + lr->lr_dn.bv_val = tmpber.ber_ptr; + } + } + + rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error ); + assert( rc == LDAP_SUCCESS ); + + ld->ld_errno = LDAP_SUCCESS; + if ( ldap_int_flush_request( ld, lr ) == -1 ) { + msgid = -1; + } + + LDAP_CONN_UNLOCK_IF(m_noconn); + return( msgid ); +} + +/* return 0 if no StartTLS ext, 1 if present, 2 if critical */ +static int +find_tls_ext( LDAPURLDesc *srv ) +{ + int i, crit; + char *ext; + + if ( !srv->lud_exts ) + return 0; + + for (i=0; srv->lud_exts[i]; i++) { + crit = 0; + ext = srv->lud_exts[i]; + if ( ext[0] == '!') { + ext++; + crit = 1; + } + if ( !strcasecmp( ext, "StartTLS" ) || + !strcasecmp( ext, "X-StartTLS" ) || + !strcmp( ext, LDAP_EXOP_START_TLS )) { + return crit + 1; + } + } + return 0; +} + +/* + * always protected by conn_mutex + * optionally protected by req_mutex and res_mutex + */ +LDAPConn * +ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, + int connect, LDAPreqinfo *bind, int m_req, int m_res ) +{ + LDAPConn *lc; + int async = 0; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + Debug3( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n", + use_ldsb, connect, (bind != NULL) ); + /* + * make a new LDAP server connection + * XXX open connection synchronously for now + */ + lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) ); + if ( lc == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return( NULL ); + } + + if ( use_ldsb ) { + assert( ld->ld_sb != NULL ); + lc->lconn_sb = ld->ld_sb; + + } else { + lc->lconn_sb = ber_sockbuf_alloc(); + if ( lc->lconn_sb == NULL ) { + LDAP_FREE( (char *)lc ); + ld->ld_errno = LDAP_NO_MEMORY; + return( NULL ); + } + } + + if ( connect ) { + LDAPURLDesc **srvp, *srv = NULL; + + async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC ); + + for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) { + int rc; + + rc = ldap_int_open_connection( ld, lc, *srvp, async ); + if ( rc != -1 ) { + srv = *srvp; + + /* If we fully connected, async is moot */ + if ( rc == 0 ) + async = 0; + + if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) { + ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params ); + } + + break; + } + } + + if ( srv == NULL ) { + if ( !use_ldsb ) { + ber_sockbuf_free( lc->lconn_sb ); + } + LDAP_FREE( (char *)lc ); + ld->ld_errno = LDAP_SERVER_DOWN; + return( NULL ); + } + + lc->lconn_server = ldap_url_dup( srv ); + if ( !lc->lconn_server ) { + if ( !use_ldsb ) + ber_sockbuf_free( lc->lconn_sb ); + LDAP_FREE( (char *)lc ); + ld->ld_errno = LDAP_NO_MEMORY; + return( NULL ); + } + } + + lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED; + lc->lconn_next = ld->ld_conns; + ld->ld_conns = lc; + + if ( connect ) { +#ifdef HAVE_TLS + if ( lc->lconn_server->lud_exts ) { + int rc, ext = find_tls_ext( lc->lconn_server ); + if ( ext ) { + LDAPConn *savedefconn; + + savedefconn = ld->ld_defconn; + ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; + + LDAP_REQ_UNLOCK_IF(m_req); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + LDAP_RES_UNLOCK_IF(m_res); + rc = ldap_start_tls_s( ld, NULL, NULL ); + LDAP_RES_LOCK_IF(m_res); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + LDAP_REQ_LOCK_IF(m_req); + ld->ld_defconn = savedefconn; + --lc->lconn_refcnt; + + if ( rc != LDAP_SUCCESS && ext == 2 ) { + ldap_free_connection( ld, lc, 1, 0 ); + return NULL; + } + } + } +#endif + } + + if ( bind != NULL ) { + int err = 0; + LDAPConn *savedefconn; + + /* Set flag to prevent additional referrals + * from being processed on this + * connection until the bind has completed + */ + lc->lconn_rebind_inprogress = 1; + /* V3 rebind function */ + if ( ld->ld_rebind_proc != NULL) { + LDAPURLDesc *srvfunc; + + srvfunc = ldap_url_dup( *srvlist ); + if ( srvfunc == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + err = -1; + } else { + savedefconn = ld->ld_defconn; + ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; + + Debug0( LDAP_DEBUG_TRACE, "Call application rebind_proc\n" ); + LDAP_REQ_UNLOCK_IF(m_req); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + LDAP_RES_UNLOCK_IF(m_res); + err = (*ld->ld_rebind_proc)( ld, + bind->ri_url, bind->ri_request, bind->ri_msgid, + ld->ld_rebind_params ); + LDAP_RES_LOCK_IF(m_res); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + LDAP_REQ_LOCK_IF(m_req); + + ld->ld_defconn = savedefconn; + --lc->lconn_refcnt; + + if ( err != 0 ) { + err = -1; + ldap_free_connection( ld, lc, 1, 0 ); + lc = NULL; + } + ldap_free_urldesc( srvfunc ); + } + + } else { + int msgid, rc; + struct berval passwd = BER_BVNULL; + + savedefconn = ld->ld_defconn; + ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; + + Debug0( LDAP_DEBUG_TRACE, + "anonymous rebind via ldap_sasl_bind("")\n" ); + + LDAP_REQ_UNLOCK_IF(m_req); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + LDAP_RES_UNLOCK_IF(m_res); + rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd, + NULL, NULL, &msgid ); + if ( rc != LDAP_SUCCESS ) { + err = -1; + + } else { + for ( err = 1; err > 0; ) { + struct timeval tv = { 0, 100000 }; + LDAPMessage *res = NULL; + + switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) { + case -1: + err = -1; + break; + + case 0: +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_yield(); +#endif + break; + + case LDAP_RES_BIND: + rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 ); + if ( rc != LDAP_SUCCESS ) { + err = -1; + + } else if ( err != LDAP_SUCCESS ) { + err = -1; + } + /* else err == LDAP_SUCCESS == 0 */ + break; + + default: + Debug3( LDAP_DEBUG_TRACE, + "ldap_new_connection %p: " + "unexpected response %d " + "from BIND request id=%d\n", + (void *) ld, ldap_msgtype( res ), msgid ); + err = -1; + break; + } + } + } + LDAP_RES_LOCK_IF(m_res); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + LDAP_REQ_LOCK_IF(m_req); + ld->ld_defconn = savedefconn; + --lc->lconn_refcnt; + + if ( err != 0 ) { + ldap_free_connection( ld, lc, 1, 0 ); + lc = NULL; + } + } + if ( lc != NULL ) + lc->lconn_rebind_inprogress = 0; + } + return( lc ); +} + + +/* protected by ld_conn_mutex */ +static LDAPConn * +find_connection( LDAP *ld, LDAPURLDesc *srv, int any ) +/* + * return an existing connection (if any) to the server srv + * if "any" is non-zero, check for any server in the "srv" chain + */ +{ + LDAPConn *lc; + LDAPURLDesc *lcu, *lsu; + int lcu_port, lsu_port; + int found = 0; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { + lcu = lc->lconn_server; + lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme, + lcu->lud_port ); + + for ( lsu = srv; lsu != NULL; lsu = lsu->lud_next ) { + lsu_port = ldap_pvt_url_scheme_port( lsu->lud_scheme, + lsu->lud_port ); + + if ( lsu_port == lcu_port + && strcmp( lcu->lud_scheme, lsu->lud_scheme ) == 0 + && lcu->lud_host != NULL && lsu->lud_host != NULL + && strcasecmp( lsu->lud_host, lcu->lud_host ) == 0 ) + { + found = 1; + break; + } + + if ( !any ) break; + } + if ( found ) + break; + } + return lc; +} + + + +/* protected by ld_conn_mutex */ +static void +use_connection( LDAP *ld, LDAPConn *lc ) +{ + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + ++lc->lconn_refcnt; + lc->lconn_lastused = time( NULL ); +} + + +/* protected by ld_conn_mutex */ +void +ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) +{ + LDAPConn *tmplc, *prevlc; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + Debug2( LDAP_DEBUG_TRACE, + "ldap_free_connection %d %d\n", + force, unbind ); + + if ( force || --lc->lconn_refcnt <= 0 ) { + /* remove from connections list first */ + + for ( prevlc = NULL, 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; + } + if ( ld->ld_defconn == lc ) { + ld->ld_defconn = NULL; + } + break; + } + prevlc = tmplc; + } + + /* process connection callbacks */ + { + struct ldapoptions *lo; + ldaplist *ll; + ldap_conncb *cb; + + lo = &ld->ld_options; + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, lc->lconn_sb, cb ); + } + } + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + lo = LDAP_INT_GLOBAL_OPT(); + LDAP_MUTEX_LOCK( &lo->ldo_mutex ); + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, lc->lconn_sb, cb ); + } + } + LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); + } + + if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { + ldap_mark_select_clear( ld, lc->lconn_sb ); + if ( unbind ) { + ldap_send_unbind( ld, lc->lconn_sb, + NULL, NULL ); + } + } + + if ( lc->lconn_ber != NULL ) { + ber_free( lc->lconn_ber, 1 ); + } + + ldap_int_sasl_close( ld, lc ); + + ldap_free_urllist( lc->lconn_server ); + + /* FIXME: is this at all possible? + * ldap_ld_free() in unbind.c calls ldap_free_connection() + * with force == 1 __after__ explicitly calling + * ldap_tavl_free on ld->ld_requests */ + if ( force ) { + ldap_tavl_free( ld->ld_requests, ldap_do_free_request ); + ld->ld_requests = NULL; + } + + if ( lc->lconn_sb != ld->ld_sb ) { + ber_sockbuf_free( lc->lconn_sb ); + } else { + ber_int_sb_close( lc->lconn_sb ); + } + + if ( lc->lconn_rebind_queue != NULL) { + int i; + for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) { + LDAP_VFREE( lc->lconn_rebind_queue[i] ); + } + LDAP_FREE( lc->lconn_rebind_queue ); + } + + LDAP_FREE( lc ); + + Debug0( LDAP_DEBUG_TRACE, + "ldap_free_connection: actually freed\n" ); + + } else { + lc->lconn_lastused = time( NULL ); + Debug1( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n", + lc->lconn_refcnt ); + } +} + + +/* Protects self with ld_conn_mutex */ +#ifdef LDAP_DEBUG +void +ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all ) +{ + LDAPConn *lc; + char timebuf[32]; + + Debug2( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "" ); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) { + if ( lc->lconn_server != NULL ) { + Debug3( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n", + ( lc->lconn_server->lud_host == NULL ) ? "(null)" + : lc->lconn_server->lud_host, + lc->lconn_server->lud_port, ( lc->lconn_sb == + ld->ld_sb ) ? " (default)" : "" ); + } + if ( lc->lconn_sb != NULL ) { + char from[LDAP_IPADDRLEN]; + struct berval frombv = BER_BVC(from); + ber_socket_t sb; + if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sb ) == 1 ) { + Sockaddr sin; + socklen_t len = sizeof( sin ); + if ( getsockname( sb, (struct sockaddr *)&sin, &len ) == 0 ) { + ldap_pvt_sockaddrstr( &sin, &frombv ); + Debug1( LDAP_DEBUG_TRACE, "* from: %s\n", + ( from == NULL ) ? "(null)" : from ); + } + } + } + Debug2( LDAP_DEBUG_TRACE, " refcnt: %d status: %s\n", lc->lconn_refcnt, + ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) + ? "NeedSocket" : + ( lc->lconn_status == LDAP_CONNST_CONNECTING ) + ? "Connecting" : "Connected" ); + Debug2( LDAP_DEBUG_TRACE, " last used: %s%s\n", + ldap_pvt_ctime( &lc->lconn_lastused, timebuf ), + lc->lconn_rebind_inprogress ? " rebind in progress" : "" ); + if ( lc->lconn_rebind_inprogress ) { + if ( lc->lconn_rebind_queue != NULL) { + int i; + + for ( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) { + int j; + for( j = 0; lc->lconn_rebind_queue[i][j] != 0; j++ ) { + Debug3( LDAP_DEBUG_TRACE, " queue %d entry %d - %s\n", + i, j, lc->lconn_rebind_queue[i][j] ); + } + } + } else { + Debug0( LDAP_DEBUG_TRACE, " queue is empty\n" ); + } + } + Debug0( LDAP_DEBUG_TRACE, "\n" ); + if ( !all ) { + break; + } + } + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); +} + + +/* protected by req_mutex and res_mutex */ +void +ldap_dump_requests_and_responses( LDAP *ld ) +{ + LDAPMessage *lm, *l; + TAvlnode *node; + int i; + + Debug1( LDAP_DEBUG_TRACE, "** ld %p Outstanding Requests:\n", + (void *)ld ); + node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_LEFT ); + if ( node == NULL ) { + Debug0( LDAP_DEBUG_TRACE, " Empty\n" ); + } + for ( i = 0 ; node != NULL; i++, node = ldap_tavl_next( node, TAVL_DIR_RIGHT ) ) { + LDAPRequest *lr = node->avl_data; + + Debug3( LDAP_DEBUG_TRACE, " * msgid %d, origid %d, status %s\n", + lr->lr_msgid, lr->lr_origid, + ( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" : + ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" : + ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" : + ( lr->lr_status == LDAP_REQST_WRITING ) ? "Writing" : + ( lr->lr_status == LDAP_REQST_COMPLETED ) ? "RequestCompleted" + : "InvalidStatus" ); + Debug2( LDAP_DEBUG_TRACE, " outstanding referrals %d, parent count %d\n", + lr->lr_outrefcnt, lr->lr_parentcnt ); + } + Debug3( LDAP_DEBUG_TRACE, " ld %p request count %d (abandoned %lu)\n", + (void *)ld, i, ld->ld_nabandoned ); + Debug1( LDAP_DEBUG_TRACE, "** ld %p Response Queue:\n", (void *)ld ); + if ( ( lm = ld->ld_responses ) == NULL ) { + Debug0( LDAP_DEBUG_TRACE, " Empty\n" ); + } + for ( i = 0; lm != NULL; lm = lm->lm_next, i++ ) { + Debug2( LDAP_DEBUG_TRACE, " * msgid %d, type %lu\n", + lm->lm_msgid, (unsigned long)lm->lm_msgtype ); + if ( lm->lm_chain != NULL ) { + Debug0( LDAP_DEBUG_TRACE, " chained responses:\n" ); + for ( l = lm->lm_chain; l != NULL; l = l->lm_chain ) { + Debug2( LDAP_DEBUG_TRACE, + " * msgid %d, type %lu\n", + l->lm_msgid, + (unsigned long)l->lm_msgtype ); + } + } + } + Debug2( LDAP_DEBUG_TRACE, " ld %p response count %d\n", (void *)ld, i ); +} +#endif /* LDAP_DEBUG */ + +/* protected by req_mutex */ +void +ldap_do_free_request( void *arg ) +{ + LDAPRequest *lr = arg; + + Debug3( LDAP_DEBUG_TRACE, "ldap_do_free_request: " + "asked to free lr %p msgid %d refcnt %d\n", + (void *) lr, lr->lr_msgid, lr->lr_refcnt ); + /* if lr_refcnt > 0, the request has been looked up + * by ldap_find_request_by_msgid(); if in the meanwhile + * the request is free()'d by someone else, just decrease + * the reference count; later on, it will be freed. */ + if ( lr->lr_refcnt > 0 ) { + assert( lr->lr_refcnt == 1 ); + lr->lr_refcnt = -lr->lr_refcnt; + return; + } + + if ( lr->lr_ber != NULL ) { + ber_free( lr->lr_ber, 1 ); + lr->lr_ber = NULL; + } + + if ( lr->lr_res_error != NULL ) { + LDAP_FREE( lr->lr_res_error ); + lr->lr_res_error = NULL; + } + + if ( lr->lr_res_matched != NULL ) { + LDAP_FREE( lr->lr_res_matched ); + lr->lr_res_matched = NULL; + } + + LDAP_FREE( lr ); +} + +int +ldap_req_cmp( const void *l, const void *r ) +{ + const LDAPRequest *left = l, *right = r; + return left->lr_msgid - right->lr_msgid; +} + +/* protected by req_mutex */ +static void +ldap_free_request_int( LDAP *ld, LDAPRequest *lr ) +{ + LDAPRequest *removed; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + removed = ldap_tavl_delete( &ld->ld_requests, lr, ldap_req_cmp ); + assert( !removed || removed == lr ); + Debug3( LDAP_DEBUG_TRACE, "ldap_free_request_int: " + "lr %p msgid %d%s removed\n", + (void *) lr, lr->lr_msgid, removed ? "" : " not" ); + + ldap_do_free_request( lr ); +} + +/* protected by req_mutex */ +void +ldap_free_request( LDAP *ld, LDAPRequest *lr ) +{ + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + Debug2( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n", + lr->lr_origid, lr->lr_msgid ); + + /* free all referrals (child requests) */ + while ( lr->lr_child ) { + ldap_free_request( ld, lr->lr_child ); + } + + if ( lr->lr_parent != NULL ) { + LDAPRequest **lrp; + + --lr->lr_parent->lr_outrefcnt; + for ( lrp = &lr->lr_parent->lr_child; + *lrp && *lrp != lr; + lrp = &(*lrp)->lr_refnext ); + + if ( *lrp == lr ) { + *lrp = lr->lr_refnext; + } + } + ldap_free_request_int( ld, lr ); +} + +/* + * call first time with *cntp = -1 + * when returns *cntp == -1, no referrals are left + * + * NOTE: may replace *refsp, or shuffle the contents + * of the original array. + */ +static int ldap_int_nextref( + LDAP *ld, + char ***refsp, + int *cntp, + void *params ) +{ + assert( refsp != NULL ); + assert( *refsp != NULL ); + assert( cntp != NULL ); + + if ( *cntp < -1 ) { + *cntp = -1; + return -1; + } + + (*cntp)++; + + if ( (*refsp)[ *cntp ] == NULL ) { + *cntp = -1; + } + + return 0; +} + +/* + * Chase v3 referrals + * + * Parameters: + * (IN) ld = LDAP connection handle + * (IN) lr = LDAP Request structure + * (IN) refs = array of pointers to referral strings that we will chase + * The array will be free'd by this function when no longer needed + * (IN) sref != 0 if following search reference + * (OUT) errstrp = Place to return a string of referrals which could not be followed + * (OUT) hadrefp = 1 if successfully followed referral + * + * Return value - number of referrals followed + * + * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) + */ +int +ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp ) +{ + char *unfollowed; + int unfollowedcnt = 0; + LDAPRequest *origreq; + LDAPURLDesc *srv = NULL; + BerElement *ber; + char **refarray = NULL; + LDAPConn *lc; + int rc, count, i, j, id; + LDAPreqinfo rinfo; + LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + Debug0( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n" ); + + ld->ld_errno = LDAP_SUCCESS; /* optimistic */ + *hadrefp = 0; + + unfollowed = NULL; + rc = count = 0; + + /* If no referrals in array, return */ + if ( (refs == NULL) || ( (refs)[0] == NULL) ) { + rc = 0; + goto done; + } + + /* Check for hop limit exceeded */ + if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { + Debug1( LDAP_DEBUG_ANY, + "more than %d referral hops (dropping)\n", ld->ld_refhoplimit ); + ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED; + rc = -1; + goto done; + } + + /* find original request */ + for ( origreq = lr; + origreq->lr_parent != NULL; + origreq = origreq->lr_parent ) + { + /* empty */ ; + } + + refarray = refs; + refs = NULL; + + /* parse out & follow referrals */ + /* NOTE: if nextref_proc == ldap_int_nextref, params is ignored */ + i = -1; + for ( nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ); + i != -1; + nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ) ) + { + + /* Parse the referral URL */ + rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); + if ( rc != LDAP_URL_SUCCESS ) { + /* ldap_url_parse_ext() returns LDAP_URL_* errors + * which do not map on API errors */ + ld->ld_errno = LDAP_PARAM_ERROR; + rc = -1; + goto done; + } + + if( srv->lud_crit_exts ) { + int ok = 0; +#ifdef HAVE_TLS + /* If StartTLS is the only critical ext, OK. */ + if ( find_tls_ext( srv ) == 2 && srv->lud_crit_exts == 1 ) + ok = 1; +#endif + if ( !ok ) { + /* we do not support any other extensions */ + ld->ld_errno = LDAP_NOT_SUPPORTED; + rc = -1; + goto done; + } + } + + /* check connection for re-bind in progress */ + if (( lc = find_connection( ld, srv, 1 )) != NULL ) { + /* See if we've already requested this DN with this conn */ + LDAPRequest *lp; + int looped = 0; + ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; + for ( lp = origreq; lp; ) { + if ( lp->lr_conn == lc + && len == lp->lr_dn.bv_len + && len + && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) == 0 ) + { + looped = 1; + break; + } + if ( lp == origreq ) { + lp = lp->lr_child; + } else { + lp = lp->lr_refnext; + } + } + if ( looped ) { + ldap_free_urllist( srv ); + srv = NULL; + ld->ld_errno = LDAP_CLIENT_LOOP; + rc = -1; + continue; + } + + if ( lc->lconn_rebind_inprogress ) { + /* We are already chasing a referral or search reference and a + * bind on that connection is in progress. We must queue + * referrals on that connection, so we don't get a request + * going out before the bind operation completes. This happens + * if two search references come in one behind the other + * for the same server with different contexts. + */ + Debug1( LDAP_DEBUG_TRACE, + "ldap_chase_v3referrals: queue referral "%s"\n", + refarray[i] ); + if( lc->lconn_rebind_queue == NULL ) { + /* Create a referral list */ + lc->lconn_rebind_queue = + (char ***) LDAP_MALLOC( sizeof(void *) * 2); + + if( lc->lconn_rebind_queue == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + rc = -1; + goto done; + } + + lc->lconn_rebind_queue[0] = refarray; + lc->lconn_rebind_queue[1] = NULL; + refarray = NULL; + + } else { + /* Count how many referral arrays we already have */ + for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) { + /* empty */; + } + + /* Add the new referral to the list */ + lc->lconn_rebind_queue = (char ***) LDAP_REALLOC( + lc->lconn_rebind_queue, sizeof(void *) * (j + 2)); + + if( lc->lconn_rebind_queue == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + rc = -1; + goto done; + } + lc->lconn_rebind_queue[j] = refarray; + lc->lconn_rebind_queue[j+1] = NULL; + refarray = NULL; + } + + /* We have queued the referral/reference, now just return */ + rc = 0; + *hadrefp = 1; + count = 1; /* Pretend we already followed referral */ + goto done; + } + } + /* Re-encode the request with the new starting point of the search. + * Note: In the future we also need to replace the filter if one + * was provided with the search reference + */ + + /* For references we don't want old dn if new dn empty */ + if ( sref && srv->lud_dn == NULL ) { + srv->lud_dn = LDAP_STRDUP( "" ); + } + + LDAP_NEXT_MSGID( ld, id ); + ber = re_encode_request( ld, origreq->lr_ber, id, + sref, srv, &rinfo.ri_request ); + + if( ber == NULL ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + rc = -1; + goto done; + } + + Debug2( LDAP_DEBUG_TRACE, + "ldap_chase_v3referral: msgid %d, url "%s"\n", + lr->lr_msgid, refarray[i] ); + + /* Send the new request to the server - may require a bind */ + rinfo.ri_msgid = origreq->lr_origid; + rinfo.ri_url = refarray[i]; + rc = ldap_send_server_request( ld, ber, id, + origreq, &srv, NULL, &rinfo, 0, 1 ); + if ( rc < 0 ) { + /* Failure, try next referral in the list */ + Debug3( LDAP_DEBUG_ANY, "Unable to chase referral "%s" (%d: %s)\n", + refarray[i], ld->ld_errno, ldap_err2string( ld->ld_errno ) ); + unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i] ); + ldap_free_urllist( srv ); + srv = NULL; + ld->ld_errno = LDAP_REFERRAL; + } else { + /* Success, no need to try this referral list further */ + rc = 0; + ++count; + *hadrefp = 1; + + /* check if there is a queue of referrals that came in during bind */ + if ( lc == NULL) { + lc = find_connection( ld, srv, 1 ); + if ( lc == NULL ) { + ld->ld_errno = LDAP_OPERATIONS_ERROR; + rc = -1; + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + goto done; + } + } + + if ( lc->lconn_rebind_queue != NULL ) { + /* Release resources of previous list */ + LDAP_VFREE( refarray ); + refarray = NULL; + ldap_free_urllist( srv ); + srv = NULL; + + /* Pull entries off end of queue so list always null terminated */ + for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++ ) + ; + refarray = lc->lconn_rebind_queue[j - 1]; + lc->lconn_rebind_queue[j-1] = NULL; + /* we pulled off last entry from queue, free queue */ + if ( j == 1 ) { + LDAP_FREE( lc->lconn_rebind_queue ); + lc->lconn_rebind_queue = NULL; + } + /* restart the loop the with new referral list */ + i = -1; + continue; + } + break; /* referral followed, break out of for loop */ + } + } /* end for loop */ +done: + LDAP_VFREE( refarray ); + ldap_free_urllist( srv ); + LDAP_FREE( *errstrp ); + + if( rc == 0 ) { + *errstrp = NULL; + LDAP_FREE( unfollowed ); + return count; + } else { + *errstrp = unfollowed; + return rc; + } +} + +/* + * XXX merging of errors in this routine needs to be improved + * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) + */ +int +ldap_chase_referrals( LDAP *ld, + LDAPRequest *lr, + char **errstrp, + int sref, + int *hadrefp ) +{ + int rc, count, id; + unsigned len; + char *p, *ref, *unfollowed; + LDAPRequest *origreq; + LDAPURLDesc *srv; + BerElement *ber; + LDAPreqinfo rinfo; + LDAPConn *lc; + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + Debug0( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n" ); + + ld->ld_errno = LDAP_SUCCESS; /* optimistic */ + *hadrefp = 0; + + if ( *errstrp == NULL ) { + return( 0 ); + } + + len = strlen( *errstrp ); + for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { + if ( 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( 0 ); + } + + if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { + Debug1( LDAP_DEBUG_ANY, + "more than %d referral hops (dropping)\n", + ld->ld_refhoplimit ); + /* XXX report as error in ld->ld_errno? */ + return( 0 ); + } + + /* find original request */ + for ( origreq = lr; origreq->lr_parent != NULL; + origreq = origreq->lr_parent ) { + /* empty */; + } + + unfollowed = NULL; + rc = count = 0; + + /* parse out & follow referrals */ + for ( ref = p; rc == 0 && ref != NULL; ref = p ) { + p = strchr( ref, '\n' ); + if ( p != NULL ) { + *p++ = '\0'; + } + + rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); + if ( rc != LDAP_URL_SUCCESS ) { + Debug2( LDAP_DEBUG_TRACE, + "ignoring %s referral <%s>\n", + ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect" ); + rc = ldap_append_referral( ld, &unfollowed, ref ); + *hadrefp = 1; + continue; + } + + Debug1( LDAP_DEBUG_TRACE, + "chasing LDAP referral: <%s>\n", ref ); + + *hadrefp = 1; + + /* See if we've already been here */ + if (( lc = find_connection( ld, srv, 1 )) != NULL ) { + LDAPRequest *lp; + int looped = 0; + ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; + for ( lp = lr; lp; lp = lp->lr_parent ) { + if ( lp->lr_conn == lc + && len == lp->lr_dn.bv_len ) + { + if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) ) + continue; + looped = 1; + break; + } + } + if ( looped ) { + ldap_free_urllist( srv ); + ld->ld_errno = LDAP_CLIENT_LOOP; + rc = -1; + continue; + } + } + + LDAP_NEXT_MSGID( ld, id ); + ber = re_encode_request( ld, origreq->lr_ber, + id, sref, srv, &rinfo.ri_request ); + + if ( ber == NULL ) { + ldap_free_urllist( srv ); + return -1 ; + } + + /* copy the complete referral for rebind process */ + rinfo.ri_url = LDAP_STRDUP( ref ); + + rinfo.ri_msgid = origreq->lr_origid; + + rc = ldap_send_server_request( ld, ber, id, + lr, &srv, NULL, &rinfo, 0, 1 ); + LDAP_FREE( rinfo.ri_url ); + + if( rc >= 0 ) { + ++count; + } else { + Debug3( LDAP_DEBUG_ANY, + "Unable to chase referral "%s" (%d: %s)\n", + ref, ld->ld_errno, ldap_err2string( ld->ld_errno ) ); + rc = ldap_append_referral( ld, &unfollowed, ref ); + } + + ldap_free_urllist(srv); + } + + LDAP_FREE( *errstrp ); + *errstrp = unfollowed; + + return(( rc == 0 ) ? count : rc ); +} + + +int +ldap_append_referral( LDAP *ld, char **referralsp, char *s ) +{ + int first; + + if ( *referralsp == NULL ) { + first = 1; + *referralsp = (char *)LDAP_MALLOC( strlen( s ) + LDAP_REF_STR_LEN + + 1 ); + } else { + first = 0; + *referralsp = (char *)LDAP_REALLOC( *referralsp, + strlen( *referralsp ) + strlen( s ) + 2 ); + } + + if ( *referralsp == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return( -1 ); + } + + if ( first ) { + strcpy( *referralsp, LDAP_REF_STR ); + } else { + strcat( *referralsp, "\n" ); + } + strcat( *referralsp, s ); + + return( 0 ); +} + + + +static BerElement * +re_encode_request( LDAP *ld, + BerElement *origber, + ber_int_t msgid, + int sref, + LDAPURLDesc *srv, + int *type ) +{ + /* + * XXX this routine knows way too much about how the lber library works! + */ + ber_int_t along; + ber_tag_t tag; + ber_tag_t rtag; + ber_int_t ver; + ber_int_t scope; + int rc; + BerElement tmpber, *ber; + struct berval dn; + + Debug2( LDAP_DEBUG_TRACE, + "re_encode_request: new msgid %ld, new dn <%s>\n", + (long) msgid, + ( srv == NULL || srv->lud_dn == NULL) ? "NONE" : srv->lud_dn ); + + tmpber = *origber; + + /* + * all LDAP requests are sequences that start with a message id. + * For all except delete, this is followed by a sequence that is + * tagged with the operation code. For delete, the provided DN + * is not wrapped by a sequence. + */ + rtag = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag ); + + if ( rtag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return( NULL ); + } + + assert( tag != 0); + if ( tag == LDAP_REQ_BIND ) { + /* bind requests have a version number before the DN & other stuff */ + rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn ); + + } else if ( tag == LDAP_REQ_DELETE ) { + /* delete requests don't have a DN wrapping sequence */ + rtag = ber_scanf( &tmpber, "m", &dn ); + + } else if ( tag == LDAP_REQ_SEARCH ) { + /* search requests need to be re-scope-ed */ + rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope ); + + if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) { + /* use the scope provided in reference */ + scope = srv->lud_scope; + + } else if ( sref ) { + /* use scope implied by previous operation + * base -> base + * one -> base + * subtree -> subtree + * subordinate -> subtree + */ + switch( scope ) { + default: + case LDAP_SCOPE_BASE: + case LDAP_SCOPE_ONELEVEL: + scope = LDAP_SCOPE_BASE; + break; + case LDAP_SCOPE_SUBTREE: + case LDAP_SCOPE_SUBORDINATE: + scope = LDAP_SCOPE_SUBTREE; + break; + } + } + + } else { + rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn ); + } + + if( rtag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + return NULL; + } + + /* restore character zero'd out by ber_scanf*/ + dn.bv_val[dn.bv_len] = tmpber.ber_tag; + + if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return NULL; + } + + if ( srv->lud_dn ) { + ber_str2bv( srv->lud_dn, 0, 0, &dn ); + } + + if ( tag == LDAP_REQ_BIND ) { + rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn ); + } else if ( tag == LDAP_REQ_DELETE ) { + rc = ber_printf( ber, "{itON}", msgid, tag, &dn ); + } else if ( tag == LDAP_REQ_SEARCH ) { + rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope ); + } else { + rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn ); + } + + if ( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return NULL; + } + + 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, /*{{*/ "N}N}" ) == -1 ) ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return NULL; + } + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_PACKETS ) { + Debug0( LDAP_DEBUG_ANY, "re_encode_request new request is:\n" ); + ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 ); + } +#endif /* LDAP_DEBUG */ + + *type = tag; /* return request type */ + return ber; +} + + +/* protected by req_mutex */ +LDAPRequest * +ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid ) +{ + LDAPRequest *lr, needle = {0}; + needle.lr_msgid = msgid; + + lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp ); + if ( lr != NULL && lr->lr_status != LDAP_REQST_COMPLETED ) { + /* lr_refcnt is only negative when we removed it from ld_requests + * already, it is positive if we have sub-requests (referrals) */ + assert( lr->lr_refcnt >= 0 ); + lr->lr_refcnt++; + Debug3( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: " + "msgid %d, lr %p lr->lr_refcnt = %d\n", + msgid, (void *) lr, lr->lr_refcnt ); + return lr; + } + + Debug2( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: " + "msgid %d, lr %p\n", msgid, (void *) lr ); + return NULL; +} + +/* protected by req_mutex */ +void +ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit ) +{ + LDAPRequest *lr; + + lr = ldap_tavl_find( ld->ld_requests, lrx, ldap_req_cmp ); + Debug2( LDAP_DEBUG_TRACE, "ldap_return_request: " + "lrx %p, lr %p\n", (void *) lrx, (void *) lr ); + if ( lr ) { + assert( lr == lrx ); + if ( lr->lr_refcnt > 0 ) { + lr->lr_refcnt--; + } else if ( lr->lr_refcnt < 0 ) { + lr->lr_refcnt++; + if ( lr->lr_refcnt == 0 ) { + lr = NULL; + } + } + } + Debug3( LDAP_DEBUG_TRACE, "ldap_return_request: " + "lrx->lr_msgid %d, lrx->lr_refcnt is now %d, lr is %s present\n", + lrx->lr_msgid, lrx->lr_refcnt, lr ? "still" : "not" ); + /* The request is not tracked anymore */ + if ( lr == NULL ) { + ldap_free_request_int( ld, lrx ); + } else if ( freeit ) { + ldap_free_request( ld, lrx ); + } +} diff --git a/libs/ldap/libldap/result.c b/libs/ldap/libldap/result.c new file mode 100644 index 00000000000..31cf5b980da --- /dev/null +++ b/libs/ldap/libldap/result.c @@ -0,0 +1,1401 @@ +/* result.c - wait for an ldap result */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ +/* This notice applies to changes, created by or for Novell, Inc., + * to preexisting works for which notices appear elsewhere in this file. + * + * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Modification to OpenLDAP source by Novell, Inc. + * April 2000 sfs Add code to process V3 referrals and search results + *--- + * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +/* + * LDAPv3 (RFC 4511) + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED { ... }, + * matchedDN LDAPDN, + * diagnosticMessage LDAPString, + * referral [3] Referral OPTIONAL + * } + * Referral ::= SEQUENCE OF LDAPURL (one or more) + * LDAPURL ::= LDAPString (limited to URL chars) + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#include "ldap-int.h" +#include "ldap_log.h" +#include "lutil.h" + +static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); +static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); +static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, + LDAPMessage **result )); +static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid, + int all, LDAPConn *lc, LDAPMessage **result )); +static ber_tag_t build_result_ber LDAP_P(( LDAP *ld, BerElement **bp, LDAPRequest *lr )); +static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); +static LDAPMessage * chkResponseList LDAP_P(( LDAP *ld, int msgid, int all)); + +#define LDAP_MSG_X_KEEP_LOOKING (-2) + + +/* + * ldap_result - wait for an ldap result response to a message from the + * ldap server. If msgid is LDAP_RES_ANY (-1), any message will be + * accepted. If msgid is LDAP_RES_UNSOLICITED (0), any unsolicited + * message is accepted. Otherwise ldap_result will wait for a response + * with msgid. If all is LDAP_MSG_ONE (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. In general, this is only useful for search responses, + * which can be of three message types (zero or more entries, zero or + * search references, followed by an ldap result). An extension to + * LDAPv3 allows partial extended responses to be returned in response + * to any request. The type of the first message received is returned. + * When waiting, any messages that have been abandoned/discarded are + * discarded. + * + * Example: + * ldap_result( s, msgid, all, timeout, result ) + */ +int +ldap_result( + LDAP *ld, + int msgid, + int all, + struct timeval *timeout, + LDAPMessage **result ) +{ + int rc; + + assert( ld != NULL ); + assert( result != NULL ); + + Debug2( LDAP_DEBUG_TRACE, "ldap_result ld %p msgid %d\n", (void *)ld, msgid ); + + if (ld->ld_errno == LDAP_LOCAL_ERROR || ld->ld_errno == LDAP_SERVER_DOWN) + return -1; + + LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); + rc = wait4msg( ld, msgid, all, timeout, result ); + LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); + + return rc; +} + +/* protected by res_mutex */ +static LDAPMessage * +chkResponseList( + LDAP *ld, + int msgid, + int all) +{ + LDAPMessage *lm, **lastlm, *nextlm; + int cnt = 0; + + /* + * 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. + */ + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); + + Debug3( LDAP_DEBUG_TRACE, + "ldap_chkResponseList ld %p msgid %d all %d\n", + (void *)ld, msgid, all ); + + lastlm = &ld->ld_responses; + for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { + nextlm = lm->lm_next; + ++cnt; + + if ( ldap_abandoned( ld, lm->lm_msgid ) ) { + Debug2( LDAP_DEBUG_ANY, + "response list msg abandoned, " + "msgid %d message type %s\n", + lm->lm_msgid, ldap_int_msgtype2str( lm->lm_msgtype ) ); + + switch ( lm->lm_msgtype ) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_REFERENCE: + case LDAP_RES_INTERMEDIATE: + break; + + default: + /* there's no need to keep the id + * in the abandoned list any longer */ + ldap_mark_abandoned( ld, lm->lm_msgid ); + break; + } + + /* Remove this entry from list */ + *lastlm = nextlm; + + ldap_msgfree( lm ); + + continue; + } + + if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { + LDAPMessage *tmp; + + if ( all == LDAP_MSG_ONE || + all == LDAP_MSG_RECEIVED || + msgid == LDAP_RES_UNSOLICITED ) + { + break; + } + + tmp = lm->lm_chain_tail; + if ( tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY || + tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE || + tmp->lm_msgtype == LDAP_RES_INTERMEDIATE ) + { + tmp = NULL; + } + + if ( tmp == NULL ) { + lm = NULL; + } + + break; + } + lastlm = &lm->lm_next; + } + + if ( lm != NULL ) { + /* Found an entry, remove it from the list */ + if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { + *lastlm = lm->lm_chain; + lm->lm_chain->lm_next = lm->lm_next; + lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain; + lm->lm_chain = NULL; + lm->lm_chain_tail = NULL; + } else { + *lastlm = lm->lm_next; + } + lm->lm_next = NULL; + } + +#ifdef LDAP_DEBUG + if ( lm == NULL) { + Debug1( LDAP_DEBUG_TRACE, + "ldap_chkResponseList returns ld %p NULL\n", (void *)ld ); + } else { + Debug3( LDAP_DEBUG_TRACE, + "ldap_chkResponseList returns ld %p msgid %d, type 0x%02lx\n", + (void *)ld, lm->lm_msgid, (unsigned long)lm->lm_msgtype ); + } +#endif + + return lm; +} + +/* protected by res_mutex */ +static int +wait4msg( + LDAP *ld, + ber_int_t msgid, + int all, + struct timeval *timeout, + LDAPMessage **result ) +{ + int rc; + struct timeval tv = { 0 }, + tv0 = { 0 }, + start_time_tv = { 0 }, + *tvp = NULL; + LDAPConn *lc; + + assert( ld != NULL ); + assert( result != NULL ); + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); + + if ( timeout == NULL && ld->ld_options.ldo_tm_api.tv_sec >= 0 ) { + tv = ld->ld_options.ldo_tm_api; + timeout = &tv; + } + +#ifdef LDAP_DEBUG + if ( timeout == NULL ) { + Debug2( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (infinite timeout)\n", + (void *)ld, msgid ); + } else { + Debug3( LDAP_DEBUG_TRACE, "wait4msg ld %p msgid %d (timeout %ld usec)\n", + (void *)ld, msgid, (long)timeout->tv_sec * 1000000 + timeout->tv_usec ); + } +#endif /* LDAP_DEBUG */ + + if ( timeout != NULL && timeout->tv_sec != -1 ) { + tv0 = *timeout; + tv = *timeout; + tvp = &tv; +#ifdef HAVE_GETTIMEOFDAY + gettimeofday( &start_time_tv, NULL ); +#else /* ! HAVE_GETTIMEOFDAY */ + start_time_tv.tv_sec = time( NULL ); + start_time_tv.tv_usec = 0; +#endif /* ! HAVE_GETTIMEOFDAY */ + } + + rc = LDAP_MSG_X_KEEP_LOOKING; + while ( rc == LDAP_MSG_X_KEEP_LOOKING ) { +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_TRACE ) { + Debug3( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n", + (void *)ld, msgid, all ); + ldap_dump_connection( ld, ld->ld_conns, 1 ); + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + ldap_dump_requests_and_responses( ld ); + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + } +#endif /* LDAP_DEBUG */ + + if ( ( *result = chkResponseList( ld, msgid, all ) ) != NULL ) { + rc = (*result)->lm_msgtype; + + } else { + int lc_ready = 0; + + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { + if ( ber_sockbuf_ctrl( lc->lconn_sb, + LBER_SB_OPT_DATA_READY, NULL ) ) + { + lc_ready = 2; /* ready at ber level, not socket level */ + break; + } + } + + if ( !lc_ready ) { + int err; + rc = ldap_int_select( ld, tvp ); + if ( rc == -1 ) { + err = sock_errno(); +#ifdef LDAP_DEBUG + Debug1( LDAP_DEBUG_TRACE, + "ldap_int_select returned -1: errno %d\n", + err ); +#endif + } + + if ( rc == 0 || ( rc == -1 && ( + !LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART) + || err != EINTR ) ) ) + { + ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : + LDAP_TIMEOUT); + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + return( rc ); + } + + if ( rc == -1 ) { + rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */ + + } else { + lc_ready = 1; + } + } + if ( lc_ready ) { + LDAPConn *lnext; + int serviced = 0; + rc = LDAP_MSG_X_KEEP_LOOKING; + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + if ( ld->ld_requests != NULL ) { + TAvlnode *node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_RIGHT ); + LDAPRequest *lr; + + assert( node != NULL ); + lr = node->avl_data; + if ( lr->lr_status == LDAP_REQST_WRITING && + ldap_is_write_ready( ld, lr->lr_conn->lconn_sb ) ) { + serviced = 1; + ldap_int_flush_request( ld, lr ); + } + } + for ( lc = ld->ld_conns; + rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL; + lc = lnext ) + { + if ( lc->lconn_status == LDAP_CONNST_CONNECTED && + ldap_is_read_ready( ld, lc->lconn_sb ) ) + { + serviced = 1; + /* Don't let it get freed out from under us */ + ++lc->lconn_refcnt; + rc = try_read1msg( ld, msgid, all, lc, result ); + lnext = lc->lconn_next; + + /* Only take locks if we're really freeing */ + if ( lc->lconn_refcnt <= 1 ) { + ldap_free_connection( ld, lc, 0, 1 ); + } else { + --lc->lconn_refcnt; + } + } else { + lnext = lc->lconn_next; + } + } + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + /* Quit looping if no one handled any socket events */ + if (!serviced && lc_ready == 1) + rc = -1; + } + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + } + + if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) { + struct timeval curr_time_tv = { 0 }, + delta_time_tv = { 0 }; + +#ifdef HAVE_GETTIMEOFDAY + gettimeofday( &curr_time_tv, NULL ); +#else /* ! HAVE_GETTIMEOFDAY */ + curr_time_tv.tv_sec = time( NULL ); + curr_time_tv.tv_usec = 0; +#endif /* ! HAVE_GETTIMEOFDAY */ + + /* delta_time = tmp_time - start_time */ + delta_time_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec; + delta_time_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec; + if ( delta_time_tv.tv_usec < 0 ) { + delta_time_tv.tv_sec--; + delta_time_tv.tv_usec += 1000000; + } + + /* tv0 < delta_time ? */ + if ( ( tv0.tv_sec < delta_time_tv.tv_sec ) || + ( ( tv0.tv_sec == delta_time_tv.tv_sec ) && ( tv0.tv_usec < delta_time_tv.tv_usec ) ) ) + { + rc = 0; /* timed out */ + ld->ld_errno = LDAP_TIMEOUT; + break; + } + + /* tv0 -= delta_time */ + tv0.tv_sec -= delta_time_tv.tv_sec; + tv0.tv_usec -= delta_time_tv.tv_usec; + if ( tv0.tv_usec < 0 ) { + tv0.tv_sec--; + tv0.tv_usec += 1000000; + } + + tv.tv_sec = tv0.tv_sec; + tv.tv_usec = tv0.tv_usec; + + Debug3( LDAP_DEBUG_TRACE, "wait4msg ld %p %ld s %ld us to go\n", + (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec ); + + start_time_tv.tv_sec = curr_time_tv.tv_sec; + start_time_tv.tv_usec = curr_time_tv.tv_usec; + } + } + + return( rc ); +} + + +/* protected by res_mutex, conn_mutex and req_mutex */ +static ber_tag_t +try_read1msg( + LDAP *ld, + ber_int_t msgid, + int all, + LDAPConn *lc, + LDAPMessage **result ) +{ + BerElement *ber; + LDAPMessage *newmsg, *l, *prev; + ber_int_t id; + ber_tag_t tag; + ber_len_t len; + int foundit = 0; + LDAPRequest *lr, *tmplr, dummy_lr = { 0 }; + BerElement tmpber; + int rc, refer_cnt, hadref, simple_request, err; + ber_int_t lderr = -1; + +#ifdef LDAP_CONNECTIONLESS + LDAPMessage *tmp = NULL, *chain_head = NULL; + int moremsgs = 0, isv2 = 0; +#endif + + assert( ld != NULL ); + assert( lc != NULL ); + + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); + LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); + + Debug3( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n", + (void *)ld, msgid, all ); + +retry: + if ( lc->lconn_ber == NULL ) { + lc->lconn_ber = ldap_alloc_ber_with_options( ld ); + + if ( lc->lconn_ber == NULL ) { + return -1; + } + } + + ber = lc->lconn_ber; + assert( LBER_VALID (ber) ); + + /* get the next message */ + sock_errset(0); +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP(ld) ) { + struct sockaddr_storage from; + if ( ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr_storage) ) < 0 ) + goto fail; + if ( ld->ld_options.ldo_version == LDAP_VERSION2 ) isv2 = 1; + } +nextresp3: +#endif + tag = ber_get_next( lc->lconn_sb, &len, ber ); + switch ( tag ) { + case LDAP_TAG_MESSAGE: + /* + * We read a complete message. + * The connection should no longer need this ber. + */ + lc->lconn_ber = NULL; + break; + + default: + /* + * We read a BerElement that isn't LDAP or the stream has desync'd. + * In either case, anything we read from now on is probably garbage, + * just drop the connection. + */ + ber_free( ber, 1 ); + lc->lconn_ber = NULL; + /* FALLTHRU */ + + case LBER_DEFAULT: +fail: + err = sock_errno(); +#ifdef LDAP_DEBUG + Debug1( LDAP_DEBUG_CONNS, + "ber_get_next failed, errno=%d.\n", err ); +#endif + if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING; + if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING; + ld->ld_errno = LDAP_SERVER_DOWN; + if ( !LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_KEEPCONN )) { + --lc->lconn_refcnt; + } + lc->lconn_status = 0; + return -1; + } + + /* message id */ + if ( ber_get_int( ber, &id ) == LBER_ERROR ) { + ber_free( ber, 1 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return( -1 ); + } + + /* id == 0 iff unsolicited notification message (RFC 4511) */ + + /* id < 0 is invalid, just toss it. FIXME: should we disconnect? */ + if ( id < 0 ) { + goto retry_ber; + } + + /* if it's been abandoned, toss it */ + if ( id > 0 ) { + if ( ldap_abandoned( ld, id ) ) { + /* the message type */ + tag = ber_peek_tag( ber, &len ); + switch ( tag ) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_REFERENCE: + case LDAP_RES_INTERMEDIATE: + case LBER_ERROR: + break; + + default: + /* there's no need to keep the id + * in the abandoned list any longer */ + ldap_mark_abandoned( ld, id ); + break; + } + + Debug3( LDAP_DEBUG_ANY, + "abandoned/discarded ld %p msgid %d message type %s\n", + (void *)ld, id, ldap_int_msgtype2str( tag ) ); + +retry_ber: + ber_free( ber, 1 ); + if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { + goto retry; + } + return( LDAP_MSG_X_KEEP_LOOKING ); /* continue looking */ + } + + lr = ldap_find_request_by_msgid( ld, id ); + if ( lr == NULL ) { + const char *msg = "unknown"; + + /* the message type */ + tag = ber_peek_tag( ber, &len ); + switch ( tag ) { + case LBER_ERROR: + break; + + default: + msg = ldap_int_msgtype2str( tag ); + break; + } + + Debug3( LDAP_DEBUG_ANY, + "no request for response on ld %p msgid %d message type %s (tossing)\n", + (void *)ld, id, msg ); + + goto retry_ber; + } + +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP(ld) && isv2 ) { + ber_scanf(ber, "x{"); + } +nextresp2: + ; +#endif + } + + /* the message type */ + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return( -1 ); + } + + Debug3( LDAP_DEBUG_TRACE, + "read1msg: ld %p msgid %d message type %s\n", + (void *)ld, id, ldap_int_msgtype2str( tag ) ); + + if ( id == 0 ) { + /* unsolicited notification message (RFC 4511) */ + if ( tag != LDAP_RES_EXTENDED ) { + /* toss it */ + goto retry_ber; + + /* strictly speaking, it's an error; from RFC 4511: + +4.4. Unsolicited Notification + + An unsolicited notification is an LDAPMessage sent from the server to + the client that is not in response to any LDAPMessage received by the + server. It is used to signal an extraordinary condition in the + server or in the LDAP session between the client and the server. The + notification is of an advisory nature, and the server will not expect + any response to be returned from the client. + + The unsolicited notification is structured as an LDAPMessage in which + the messageID is zero and protocolOp is set to the extendedResp + choice using the ExtendedResponse type (See Section 4.12). The + responseName field of the ExtendedResponse always contains an LDAPOID + that is unique for this notification. + + * however, since unsolicited responses + * are of advisory nature, better + * toss it, right now + */ + +#if 0 + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return( -1 ); +#endif + } + + lr = &dummy_lr; + } + + id = lr->lr_origid; + refer_cnt = 0; + hadref = simple_request = 0; + rc = LDAP_MSG_X_KEEP_LOOKING; /* default is to keep looking (no response found) */ + lr->lr_res_msgtype = tag; + + /* + * Check for V3 search reference + */ + if ( tag == LDAP_RES_SEARCH_REFERENCE ) { + if ( ld->ld_version > LDAP_VERSION2 ) { + /* This is a V3 search reference */ + if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || + lr->lr_parent != NULL ) + { + char **refs = NULL; + tmpber = *ber; + + /* Get the referral list */ + if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) { + rc = LDAP_DECODING_ERROR; + + } else { + /* Note: refs array is freed by ldap_chase_v3referrals */ + refer_cnt = ldap_chase_v3referrals( ld, lr, refs, + 1, &lr->lr_res_error, &hadref ); + if ( refer_cnt > 0 ) { + /* successfully chased reference */ + /* If haven't got end search, set chasing referrals */ + if ( lr->lr_status != LDAP_REQST_COMPLETED ) { + lr->lr_status = LDAP_REQST_CHASINGREFS; + Debug1( LDAP_DEBUG_TRACE, + "read1msg: search ref chased, " + "mark request chasing refs, " + "id = %d\n", + lr->lr_msgid ); + } + } + } + } + } + + } else if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) { + /* All results that just return a status, i.e. don't return data + * go through the following code. This code also chases V2 referrals + * and checks if all referrals have been chased. + */ + char *lr_res_error = NULL; + + tmpber = *ber; /* struct copy */ + if ( ber_scanf( &tmpber, "{eAA", &lderr, + &lr->lr_res_matched, &lr_res_error ) + != LBER_ERROR ) + { + if ( lr_res_error != NULL ) { + if ( lr->lr_res_error != NULL ) { + (void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error ); + LDAP_FREE( (char *)lr_res_error ); + + } else { + lr->lr_res_error = lr_res_error; + } + lr_res_error = NULL; + } + + /* Do we need to check for referrals? */ + if ( tag != LDAP_RES_BIND && + ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) || + lr->lr_parent != NULL )) + { + char **refs = NULL; + ber_len_t len; + + /* Check if V3 referral */ + if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) { + if ( ld->ld_version > LDAP_VERSION2 ) { + /* Get the referral list */ + if ( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) { + rc = LDAP_DECODING_ERROR; + lr->lr_status = LDAP_REQST_COMPLETED; + Debug2( LDAP_DEBUG_TRACE, + "read1msg: referral decode error, " + "mark request completed, ld %p msgid %d\n", + (void *)ld, lr->lr_msgid ); + + } else { + /* Chase the referral + * refs array is freed by ldap_chase_v3referrals + */ + refer_cnt = ldap_chase_v3referrals( ld, lr, refs, + 0, &lr->lr_res_error, &hadref ); + lr->lr_status = LDAP_REQST_COMPLETED; + Debug3( LDAP_DEBUG_TRACE, + "read1msg: referral %s chased, " + "mark request completed, ld %p msgid %d\n", + refer_cnt > 0 ? "" : "not", + (void *)ld, lr->lr_msgid); + if ( refer_cnt < 0 ) { + refer_cnt = 0; + } + } + } + } else { + switch ( lderr ) { + case LDAP_SUCCESS: + case LDAP_COMPARE_TRUE: + case LDAP_COMPARE_FALSE: + break; + + default: + if ( lr->lr_res_error == NULL ) { + break; + } + + /* pedantic, should never happen */ + if ( lr->lr_res_error[ 0 ] == '\0' ) { + LDAP_FREE( lr->lr_res_error ); + lr->lr_res_error = NULL; + break; + } + + /* V2 referrals are in error string */ + refer_cnt = ldap_chase_referrals( ld, lr, + &lr->lr_res_error, -1, &hadref ); + lr->lr_status = LDAP_REQST_COMPLETED; + Debug1( LDAP_DEBUG_TRACE, + "read1msg: V2 referral chased, " + "mark request completed, id = %d\n", + lr->lr_msgid ); + break; + } + } + } + + /* save errno, message, and matched string */ + if ( !hadref || lr->lr_res_error == NULL ) { + lr->lr_res_errno = + lderr == LDAP_PARTIAL_RESULTS + ? LDAP_SUCCESS : lderr; + + } else if ( ld->ld_errno != LDAP_SUCCESS ) { + lr->lr_res_errno = ld->ld_errno; + + } else { + lr->lr_res_errno = LDAP_PARTIAL_RESULTS; + } + } + + /* in any case, don't leave any lr_res_error 'round */ + if ( lr_res_error ) { + LDAP_FREE( lr_res_error ); + } + + Debug2( LDAP_DEBUG_TRACE, + "read1msg: ld %p %d new referrals\n", + (void *)ld, refer_cnt ); + + if ( refer_cnt != 0 ) { /* chasing referrals */ + ber_free( ber, 1 ); + ber = NULL; + if ( refer_cnt < 0 ) { + ldap_return_request( ld, lr, 0 ); + return( -1 ); /* fatal error */ + } + lr->lr_res_errno = LDAP_SUCCESS; /* successfully chased referral */ + if ( lr->lr_res_matched ) { + LDAP_FREE( lr->lr_res_matched ); + lr->lr_res_matched = NULL; + } + + } else { + if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { + /* request without any referrals */ + simple_request = ( hadref ? 0 : 1 ); + + } else { + /* request with referrals or child request */ + ber_free( ber, 1 ); + ber = NULL; + } + + lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */ + Debug2( LDAP_DEBUG_TRACE, + "read1msg: mark request completed, ld %p msgid %d\n", + (void *)ld, lr->lr_msgid ); + tmplr = lr; + while ( lr->lr_parent != NULL ) { + merge_error_info( ld, lr->lr_parent, lr ); + + lr = lr->lr_parent; + if ( --lr->lr_outrefcnt > 0 ) { + break; /* not completely done yet */ + } + } + /* ITS#6744: Original lr was refcounted when we retrieved it, + * must release it now that we're working with the parent + */ + if ( tmplr->lr_parent ) { + ldap_return_request( ld, tmplr, 0 ); + } + + /* Check if all requests are finished, lr is now parent */ + tmplr = lr; + if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) { + for ( tmplr = lr->lr_child; + tmplr != NULL; + tmplr = tmplr->lr_refnext ) + { + if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break; + } + } + + /* This is the parent request if the request has referrals */ + if ( lr->lr_outrefcnt <= 0 && + lr->lr_parent == NULL && + tmplr == NULL ) + { + id = lr->lr_msgid; + tag = lr->lr_res_msgtype; + Debug2( LDAP_DEBUG_TRACE, "request done: ld %p msgid %d\n", + (void *)ld, id ); + Debug3( 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 ) { + ber_free( ber, 1 ); + ber = NULL; + if ( build_result_ber( ld, &ber, lr ) + == LBER_ERROR ) + { + rc = -1; /* fatal error */ + } + } + + if ( lr != &dummy_lr ) { + ldap_return_request( ld, lr, 1 ); + } + lr = NULL; + } + + /* + * RFC 4511 unsolicited (id == 0) responses + * shouldn't necessarily end the connection + */ + if ( lc != NULL && id != 0 && + !LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_KEEPCONN )) { + --lc->lconn_refcnt; + lc = NULL; + } + } + } + + if ( lr != NULL ) { + if ( lr != &dummy_lr ) { + ldap_return_request( ld, lr, 0 ); + } + lr = NULL; + } + + if ( ber == NULL ) { + return( rc ); + } + + /* try to handle unsolicited responses as appropriate */ + if ( id == 0 && msgid > LDAP_RES_UNSOLICITED ) { + int is_nod = 0; + + tag = ber_peek_tag( &tmpber, &len ); + + /* we have a res oid */ + if ( tag == LDAP_TAG_EXOP_RES_OID ) { + static struct berval bv_nod = BER_BVC( LDAP_NOTICE_OF_DISCONNECTION ); + struct berval resoid = BER_BVNULL; + + if ( ber_scanf( &tmpber, "m", &resoid ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return -1; + } + + assert( !BER_BVISEMPTY( &resoid ) ); + + is_nod = ber_bvcmp( &resoid, &bv_nod ) == 0; + + tag = ber_peek_tag( &tmpber, &len ); + } + +#if 0 /* don't need right now */ + /* we have res data */ + if ( tag == LDAP_TAG_EXOP_RES_VALUE ) { + struct berval resdata; + + if ( ber_scanf( &tmpber, "m", &resdata ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + /* use it... */ + } +#endif + + /* handle RFC 4511 "Notice of Disconnection" locally */ + + if ( is_nod ) { + if ( tag == LDAP_TAG_EXOP_RES_VALUE ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return -1; + } + + /* get rid of the connection... */ + if ( lc != NULL && + !LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_KEEPCONN )) { + --lc->lconn_refcnt; + } + + /* need to return -1, because otherwise + * a valid result is expected */ + ld->ld_errno = lderr; + return -1; + } + } + + /* make a new ldap message */ + newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) ); + if ( newmsg == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return( -1 ); + } + newmsg->lm_msgid = (int)id; + newmsg->lm_msgtype = tag; + newmsg->lm_ber = ber; + newmsg->lm_chain_tail = newmsg; + +#ifdef LDAP_CONNECTIONLESS + /* CLDAP replies all fit in a single datagram. In LDAPv2 RFC1798 + * the responses are all a sequence wrapped in one message. In + * LDAPv3 each response is in its own message. The datagram must + * end with a SearchResult. We can't just parse each response in + * separate calls to try_read1msg because the header info is only + * present at the beginning of the datagram, not at the beginning + * of each response. So parse all the responses at once and queue + * them up, then pull off the first response to return to the + * caller when all parsing is complete. + */ + if ( LDAP_IS_UDP(ld) ) { + /* If not a result, look for more */ + if ( tag != LDAP_RES_SEARCH_RESULT ) { + int ok = 0; + moremsgs = 1; + if (isv2) { + /* LDAPv2: dup the current ber, skip past the current + * response, and see if there are any more after it. + */ + ber = ber_dup( ber ); + ber_scanf( ber, "x" ); + if ( ber_peek_tag( ber, &len ) != LBER_DEFAULT ) { + /* There's more - dup the ber buffer so they can all be + * individually freed by ldap_msgfree. + */ + struct berval bv; + ber_get_option( ber, LBER_OPT_BER_REMAINING_BYTES, &len ); + bv.bv_val = LDAP_MALLOC( len ); + if ( bv.bv_val ) { + ok = 1; + ber_read( ber, bv.bv_val, len ); + bv.bv_len = len; + ber_init2( ber, &bv, ld->ld_lberoptions ); + } + } + } else { + /* LDAPv3: Just allocate a new ber. Since this is a buffered + * datagram, if the sockbuf is readable we still have data + * to parse. + */ + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return -1; + } + + if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) ok = 1; + } + /* set up response chain */ + if ( tmp == NULL ) { + newmsg->lm_next = ld->ld_responses; + ld->ld_responses = newmsg; + chain_head = newmsg; + } else { + tmp->lm_chain = newmsg; + } + chain_head->lm_chain_tail = newmsg; + tmp = newmsg; + /* "ok" means there's more to parse */ + if ( ok ) { + if ( isv2 ) { + goto nextresp2; + + } else { + goto nextresp3; + } + } else { + /* got to end of datagram without a SearchResult. Free + * our dup'd ber, but leave any buffer alone. For v2 case, + * the previous response is still using this buffer. For v3, + * the new ber has no buffer to free yet. + */ + ber_free( ber, 0 ); + return -1; + } + } else if ( moremsgs ) { + /* got search result, and we had multiple responses in 1 datagram. + * stick the result onto the end of the chain, and then pull the + * first response off the head of the chain. + */ + tmp->lm_chain = newmsg; + chain_head->lm_chain_tail = newmsg; + *result = chkResponseList( ld, msgid, all ); + ld->ld_errno = LDAP_SUCCESS; + return( (*result)->lm_msgtype ); + } + } +#endif /* LDAP_CONNECTIONLESS */ + + /* is this the one we're looking for? */ + if ( msgid == LDAP_RES_ANY || id == msgid ) { + if ( all == LDAP_MSG_ONE + || ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT + && newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY + && newmsg->lm_msgtype != LDAP_RES_INTERMEDIATE + && newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) ) + { + *result = newmsg; + ld->ld_errno = LDAP_SUCCESS; + return( tag ); + + } else if ( newmsg->lm_msgtype == LDAP_RES_SEARCH_RESULT) { + foundit = 1; /* return the chain later */ + } + } + + /* + * 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; + for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) { + if ( l->lm_msgid == newmsg->lm_msgid ) { + break; + } + prev = l; + } + + /* not part of an existing search response */ + if ( l == NULL ) { + if ( foundit ) { + *result = newmsg; + goto exit; + } + + newmsg->lm_next = ld->ld_responses; + ld->ld_responses = newmsg; + goto exit; + } + + Debug3( LDAP_DEBUG_TRACE, "adding response ld %p msgid %d type %ld:\n", + (void *)ld, newmsg->lm_msgid, (long) newmsg->lm_msgtype ); + + /* part of a search response - add to end of list of entries */ + l->lm_chain_tail->lm_chain = newmsg; + l->lm_chain_tail = newmsg; + + /* return the whole chain if that's what we were looking for */ + if ( foundit ) { + if ( prev == NULL ) { + ld->ld_responses = l->lm_next; + } else { + prev->lm_next = l->lm_next; + } + *result = l; + } + +exit: + if ( foundit ) { + ld->ld_errno = LDAP_SUCCESS; + return( tag ); + } + if ( lc && ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) { + goto retry; + } + return( LDAP_MSG_X_KEEP_LOOKING ); /* continue looking */ +} + + +static ber_tag_t +build_result_ber( LDAP *ld, BerElement **bp, LDAPRequest *lr ) +{ + ber_len_t len; + ber_tag_t tag; + ber_int_t along; + BerElement *ber; + + *bp = NULL; + ber = ldap_alloc_ber_with_options( ld ); + + if( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return LBER_ERROR; + } + + if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid, + 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 ) + { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( LBER_ERROR ); + } + + ber_reset( ber, 1 ); + + if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return( LBER_ERROR ); + } + + if ( ber_get_enum( ber, &along ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return( LBER_ERROR ); + } + + tag = ber_peek_tag( ber, &len ); + + if ( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 1 ); + return( LBER_ERROR ); + } + + *bp = ber; + return tag; +} + + +/* + * Merge error information in "lr" with "parentr" error code and string. + */ +static void +merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) +{ + if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { + parentr->lr_res_errno = lr->lr_res_errno; + if ( lr->lr_res_error != NULL ) { + (void)ldap_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 ) { + LDAP_FREE( parentr->lr_res_error ); + } + parentr->lr_res_error = lr->lr_res_error; + lr->lr_res_error = NULL; + if ( LDAP_NAME_ERROR( lr->lr_res_errno ) ) { + if ( parentr->lr_res_matched != NULL ) { + LDAP_FREE( parentr->lr_res_matched ); + } + parentr->lr_res_matched = lr->lr_res_matched; + lr->lr_res_matched = NULL; + } + } + + Debug1( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ", + parentr->lr_msgid ); + Debug3( LDAP_DEBUG_TRACE, "result errno %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 : "" ); +} + + + +int +ldap_msgtype( LDAPMessage *lm ) +{ + assert( lm != NULL ); + return ( lm != NULL ) ? (int)lm->lm_msgtype : -1; +} + + +int +ldap_msgid( LDAPMessage *lm ) +{ + assert( lm != NULL ); + + return ( lm != NULL ) ? lm->lm_msgid : -1; +} + + +const char * +ldap_int_msgtype2str( ber_tag_t tag ) +{ + switch( tag ) { + case LDAP_RES_ADD: return "add"; + case LDAP_RES_BIND: return "bind"; + case LDAP_RES_COMPARE: return "compare"; + case LDAP_RES_DELETE: return "delete"; + case LDAP_RES_EXTENDED: return "extended-result"; + case LDAP_RES_INTERMEDIATE: return "intermediate"; + case LDAP_RES_MODIFY: return "modify"; + case LDAP_RES_RENAME: return "rename"; + case LDAP_RES_SEARCH_ENTRY: return "search-entry"; + case LDAP_RES_SEARCH_REFERENCE: return "search-reference"; + case LDAP_RES_SEARCH_RESULT: return "search-result"; + } + return "unknown"; +} + +int +ldap_msgfree( LDAPMessage *lm ) +{ + LDAPMessage *next; + int type = 0; + + Debug0( LDAP_DEBUG_TRACE, "ldap_msgfree\n" ); + + for ( ; lm != NULL; lm = next ) { + next = lm->lm_chain; + type = lm->lm_msgtype; + ber_free( lm->lm_ber, 1 ); + LDAP_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 rc = 0; + + assert( ld != NULL ); + + Debug2( LDAP_DEBUG_TRACE, "ldap_msgdelete ld=%p msgid=%d\n", + (void *)ld, msgid ); + + LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); + prev = NULL; + for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { + if ( lm->lm_msgid == msgid ) { + break; + } + prev = lm; + } + + if ( lm == NULL ) { + rc = -1; + + } else { + if ( prev == NULL ) { + ld->ld_responses = lm->lm_next; + } else { + prev->lm_next = lm->lm_next; + } + } + LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); + if ( lm ) { + switch ( ldap_msgfree( lm ) ) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_REFERENCE: + case LDAP_RES_INTERMEDIATE: + rc = -1; + break; + + default: + break; + } + } + + return rc; +} + + +/* + * ldap_abandoned + * + * return the location of the message id in the array of abandoned + * message ids, or -1 + */ +static int +ldap_abandoned( LDAP *ld, ber_int_t msgid ) +{ + int ret, idx; + assert( msgid >= 0 ); + + LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); + ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx ); + LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); + return ret; +} + +/* + * ldap_mark_abandoned + */ +static int +ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) +{ + int ret, idx; + + assert( msgid >= 0 ); + LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); + ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx ); + if (ret <= 0) { /* error or already deleted by another thread */ + LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); + return ret; + } + /* still in abandoned array, so delete */ + ret = ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned, + msgid, idx ); + LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); + return ret; +} diff --git a/libs/ldap/libldap/sasl.c b/libs/ldap/libldap/sasl.c new file mode 100644 index 00000000000..32974c6c8e2 --- /dev/null +++ b/libs/ldap/libldap/sasl.c @@ -0,0 +1,867 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING -- passwd + * krbv42ldap [1] OCTET STRING -- OBSOLETE + * krbv42dsa [2] OCTET STRING -- OBSOLETE + * sasl [3] SaslCredentials -- LDAPv3 + * } + * } + * + * BindResponse ::= SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 + * } + * + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +BerElement * +ldap_build_bind_req( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t *msgidp ) +{ + BerElement *ber; + int rc; + + if( mechanism == LDAP_SASL_SIMPLE ) { + if( dn == NULL && cred != NULL && cred->bv_len ) { + /* use default binddn */ + dn = ld->ld_defbinddn; + } + + } else if( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return( NULL ); + } + + if ( dn == NULL ) { + dn = ""; + } + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + LDAP_NEXT_MSGID( ld, *msgidp ); + if( mechanism == LDAP_SASL_SIMPLE ) { + /* simple bind */ + rc = ber_printf( ber, "{it{istON}" /*}*/, + *msgidp, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SIMPLE, + cred ); + + } else if ( cred == NULL || cred->bv_val == NULL ) { + /* SASL bind w/o credentials */ + rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/, + *msgidp, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SASL, + mechanism ); + + } else { + /* SASL bind w/ credentials */ + rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/, + *msgidp, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SASL, + mechanism, cred ); + } + + if( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +/* + * ldap_sasl_bind - bind to the ldap server (and X.500). + * The dn (usually NULL), mechanism, and credentials are provided. + * The message id of the request initiated is provided upon successful + * (LDAP_SUCCESS) return. + * + * Example: + * ldap_sasl_bind( ld, NULL, "mechanism", + * cred, NULL, NULL, &msgid ) + */ + +int +ldap_sasl_bind( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( msgidp != NULL ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + ber = ldap_build_bind_req( ld, dn, mechanism, cred, sctrls, cctrls, &id ); + if( !ber ) + return ld->ld_errno; + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id ); + + if(*msgidp < 0) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + + +int +ldap_sasl_bind_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct berval **servercredp ) +{ + int rc, msgid; + LDAPMessage *result; + struct berval *scredp = NULL; + + Debug0( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n" ); + + /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ + if( servercredp != NULL ) { + if (ld->ld_version < LDAP_VERSION3) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + *servercredp = NULL; + } + + rc = ldap_sasl_bind( ld, dn, mechanism, cred, sctrls, cctrls, &msgid ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld)) { + return( rc ); + } +#endif + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) { + return( ld->ld_errno ); /* ldap_result sets ld_errno */ + } + + /* parse the results */ + scredp = NULL; + if( servercredp != NULL ) { + rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 ); + } + + if ( rc != LDAP_SUCCESS ) { + ldap_msgfree( result ); + return( rc ); + } + + rc = ldap_result2error( ld, result, 1 ); + + if ( rc == LDAP_SUCCESS || rc == LDAP_SASL_BIND_IN_PROGRESS ) { + if( servercredp != NULL ) { + *servercredp = scredp; + scredp = NULL; + } + } + + if ( scredp != NULL ) { + ber_bvfree(scredp); + } + + return rc; +} + + +/* +* Parse BindResponse: +* +* BindResponse ::= [APPLICATION 1] SEQUENCE { +* COMPONENTS OF LDAPResult, +* serverSaslCreds [7] OCTET STRING OPTIONAL } +* +* LDAPResult ::= SEQUENCE { +* resultCode ENUMERATED, +* matchedDN LDAPDN, +* errorMessage LDAPString, +* referral [3] Referral OPTIONAL } +*/ + +int +ldap_parse_sasl_bind_result( + LDAP *ld, + LDAPMessage *res, + struct berval **servercredp, + int freeit ) +{ + ber_int_t errcode; + struct berval* scred; + + ber_tag_t tag; + BerElement *ber; + + Debug0( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( res != NULL ); + + if( servercredp != NULL ) { + if( ld->ld_version < LDAP_VERSION2 ) { + return LDAP_NOT_SUPPORTED; + } + *servercredp = NULL; + } + + if( res->lm_msgtype != LDAP_RES_BIND ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + scred = NULL; + + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + if ( ld->ld_matched ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + /* parse results */ + + ber = ber_dup( res->lm_ber ); + + if( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + if ( ld->ld_version < LDAP_VERSION2 ) { + tag = ber_scanf( ber, "{iA}", + &errcode, &ld->ld_error ); + + if( tag == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } + + } else { + ber_len_t len; + + tag = ber_scanf( ber, "{eAA" /*}*/, + &errcode, &ld->ld_matched, &ld->ld_error ); + + if( tag == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } + + tag = ber_peek_tag(ber, &len); + + if( tag == LDAP_TAG_REFERRAL ) { + /* skip 'em */ + if( ber_scanf( ber, "x" ) == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } + + tag = ber_peek_tag(ber, &len); + } + + if( tag == LDAP_TAG_SASL_RES_CREDS ) { + if( ber_scanf( ber, "O", &scred ) == LBER_ERROR ) { + ber_free( ber, 0 ); + ld->ld_errno = LDAP_DECODING_ERROR; + return ld->ld_errno; + } + } + } + + ber_free( ber, 0 ); + + if ( servercredp != NULL ) { + *servercredp = scred; + + } else if ( scred != NULL ) { + ber_bvfree( scred ); + } + + ld->ld_errno = errcode; + + if ( freeit ) { + ldap_msgfree( res ); + } + + return( LDAP_SUCCESS ); +} + +int +ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) +{ + /* we need to query the server for supported mechs anyway */ + LDAPMessage *res, *e; + char *attrs[] = { "supportedSASLMechanisms", NULL }; + char **values, *mechlist; + int rc; + + Debug0( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_getmech\n" ); + + rc = ldap_search_s( ld, "", LDAP_SCOPE_BASE, + NULL, attrs, 0, &res ); + + if ( rc != LDAP_SUCCESS ) { + return ld->ld_errno; + } + + e = ldap_first_entry( ld, res ); + if ( e == NULL ) { + ldap_msgfree( res ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = LDAP_NO_SUCH_OBJECT; + } + return ld->ld_errno; + } + + values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); + if ( values == NULL ) { + ldap_msgfree( res ); + ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE; + return ld->ld_errno; + } + + mechlist = ldap_charray2str( values, " " ); + if ( mechlist == NULL ) { + LDAP_VFREE( values ); + ldap_msgfree( res ); + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + LDAP_VFREE( values ); + ldap_msgfree( res ); + + *pmechlist = mechlist; + + return LDAP_SUCCESS; +} + +/* + * ldap_sasl_interactive_bind - interactive SASL authentication + * + * This routine uses interactive callbacks. + * + * LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. LDAP_SASL_BIND_IN_PROGRESS is returned if further + * calls are needed. + */ +int +ldap_sasl_interactive_bind( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *mechs, + LDAPControl **serverControls, + LDAPControl **clientControls, + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults, + LDAPMessage *result, + const char **rmech, + int *msgid ) +{ + char *smechs = NULL; + int rc; + +#ifdef LDAP_CONNECTIONLESS + if( LDAP_IS_UDP(ld) ) { + /* Just force it to simple bind, silly to make the user + * ask all the time. No, we don't ever actually bind, but I'll + * let the final bind handler take care of saving the cdn. + */ + rc = ldap_simple_bind( ld, dn, NULL ); + rc = rc < 0 ? rc : 0; + goto done; + } else +#endif + + /* First time */ + if ( !result ) { + +#ifdef HAVE_CYRUS_SASL + if( mechs == NULL || *mechs == '\0' ) { + mechs = ld->ld_options.ldo_def_sasl_mech; + } +#endif + + if( mechs == NULL || *mechs == '\0' ) { + /* FIXME: this needs to be asynchronous too; + * perhaps NULL should be disallowed for async usage? + */ + rc = ldap_pvt_sasl_getmechs( ld, &smechs ); + if( rc != LDAP_SUCCESS ) { + goto done; + } + + Debug1( LDAP_DEBUG_TRACE, + "ldap_sasl_interactive_bind: server supports: %s\n", + smechs ); + + mechs = smechs; + + } else { + Debug1( LDAP_DEBUG_TRACE, + "ldap_sasl_interactive_bind: user selected: %s\n", + mechs ); + } + } + rc = ldap_int_sasl_bind( ld, dn, mechs, + serverControls, clientControls, + flags, interact, defaults, result, rmech, msgid ); + +done: + if ( smechs ) LDAP_FREE( smechs ); + + return rc; +} + +/* + * ldap_sasl_interactive_bind_s - interactive SASL authentication + * + * This routine uses interactive callbacks. + * + * LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. + */ +int +ldap_sasl_interactive_bind_s( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *mechs, + LDAPControl **serverControls, + LDAPControl **clientControls, + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults ) +{ + const char *rmech = NULL; + LDAPMessage *result = NULL; + int rc, msgid; + + do { + rc = ldap_sasl_interactive_bind( ld, dn, mechs, + serverControls, clientControls, + flags, interact, defaults, result, &rmech, &msgid ); + + ldap_msgfree( result ); + + if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) + break; + +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld)) { + break; + } +#endif + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) { + return( ld->ld_errno ); /* ldap_result sets ld_errno */ + } + } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); + + return rc; +} + +#ifdef HAVE_CYRUS_SASL + +#ifdef HAVE_SASL_SASL_H +#include <sasl/sasl.h> +#else +#include <sasl.h> +#endif + +#endif /* HAVE_CYRUS_SASL */ + +static int +sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod ); + +static int +sb_sasl_generic_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct sb_sasl_generic_data *p; + struct sb_sasl_generic_install *i; + + assert( sbiod != NULL ); + + i = (struct sb_sasl_generic_install *)arg; + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) + return -1; + p->ops = i->ops; + p->ops_private = i->ops_private; + p->sbiod = sbiod; + p->flags = 0; + ber_pvt_sb_buf_init( &p->sec_buf_in ); + ber_pvt_sb_buf_init( &p->buf_in ); + ber_pvt_sb_buf_init( &p->buf_out ); + + sbiod->sbiod_pvt = p; + + p->ops->init( p, &p->min_send, &p->max_send, &p->max_recv ); + + if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, p->min_send ) < 0 ) { + sb_sasl_generic_remove( sbiod ); + sock_errset(ENOMEM); + return -1; + } + + return 0; +} + +static int +sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct sb_sasl_generic_data *p; + + assert( sbiod != NULL ); + + p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; + + p->ops->fini(p); + + ber_pvt_sb_buf_destroy( &p->sec_buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_out ); + LBER_FREE( p ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static ber_len_t +sb_sasl_generic_pkt_length( + struct sb_sasl_generic_data *p, + const unsigned char *buf, + int debuglevel ) +{ + ber_len_t size; + + assert( buf != NULL ); + + size = buf[0] << 24 + | buf[1] << 16 + | buf[2] << 8 + | buf[3]; + + if ( size > p->max_recv ) { + /* somebody is trying to mess me up. */ + ber_log_printf( LDAP_DEBUG_ANY, debuglevel, + "sb_sasl_generic_pkt_length: " + "received illegal packet length of %lu bytes\n", + (unsigned long)size ); + size = 16; /* this should lead to an error. */ + } + + return size + 4; /* include the size !!! */ +} + +/* Drop a processed packet from the input buffer */ +static void +sb_sasl_generic_drop_packet ( + struct sb_sasl_generic_data *p, + int debuglevel ) +{ + ber_slen_t len; + + len = p->sec_buf_in.buf_ptr - p->sec_buf_in.buf_end; + if ( len > 0 ) + AC_MEMCPY( p->sec_buf_in.buf_base, p->sec_buf_in.buf_base + + p->sec_buf_in.buf_end, len ); + + if ( len >= 4 ) { + p->sec_buf_in.buf_end = sb_sasl_generic_pkt_length(p, + (unsigned char *) p->sec_buf_in.buf_base, debuglevel); + } + else { + p->sec_buf_in.buf_end = 0; + } + p->sec_buf_in.buf_ptr = len; +} + +static ber_slen_t +sb_sasl_generic_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_generic_data *p; + ber_slen_t ret, bufptr; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; + + /* Are there anything left in the buffer? */ + ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); + bufptr = ret; + len -= ret; + + if ( len == 0 ) + return bufptr; + + p->ops->reset_buf( p, &p->buf_in ); + + /* Read the length of the packet */ + while ( p->sec_buf_in.buf_ptr < 4 ) { + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + + p->sec_buf_in.buf_ptr, + 4 - p->sec_buf_in.buf_ptr ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return bufptr ? bufptr : ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* The new packet always starts at p->sec_buf_in.buf_base */ + ret = sb_sasl_generic_pkt_length(p, (unsigned char *) p->sec_buf_in.buf_base, + sbiod->sbiod_sb->sb_debug ); + + /* Grow the packet buffer if necessary */ + if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) && + ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) + { + sock_errset(ENOMEM); + return -1; + } + p->sec_buf_in.buf_end = ret; + + /* Did we read the whole encrypted packet? */ + while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { + /* No, we have got only a part of it */ + ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; + + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + + p->sec_buf_in.buf_ptr, ret ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return bufptr ? bufptr : ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* Decode the packet */ + ret = p->ops->decode( p, &p->sec_buf_in, &p->buf_in ); + + /* Drop the packet from the input buffer */ + sb_sasl_generic_drop_packet( p, sbiod->sbiod_sb->sb_debug ); + + if ( ret != 0 ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_generic_read: failed to decode packet\n" ); + sock_errset(EIO); + return -1; + } + + bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); + + return bufptr; +} + +static ber_slen_t +sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_generic_data *p; + int ret; + ber_len_t len2; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; + + /* Is there anything left in the buffer? */ + if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + if ( ret < 0 ) return ret; + + /* Still have something left?? */ + if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { + sock_errset(EAGAIN); + return -1; + } + } + + len2 = p->max_send - 100; /* For safety margin */ + len2 = len > len2 ? len2 : len; + + /* If we're just retrying a partial write, tell the + * caller it's done. Let them call again if there's + * still more left to write. + */ + if ( p->flags & LDAP_PVT_SASL_PARTIAL_WRITE ) { + p->flags ^= LDAP_PVT_SASL_PARTIAL_WRITE; + return len2; + } + + /* now encode the next packet. */ + p->ops->reset_buf( p, &p->buf_out ); + + ret = p->ops->encode( p, buf, len2, &p->buf_out ); + + if ( ret != 0 ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_generic_write: failed to encode packet\n" ); + sock_errset(EIO); + return -1; + } + + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + + if ( ret < 0 ) { + /* error? */ + int err = sock_errno(); + /* caller can retry this */ + if ( err == EAGAIN || err == EWOULDBLOCK || err == EINTR ) + p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; + return ret; + } else if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { + /* partial write? pretend nothing got written */ + p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; + sock_errset(EAGAIN); + len2 = -1; + } + + /* return number of bytes encoded, not written, to ensure + * no byte is encoded twice (even if only sent once). + */ + return len2; +} + +static int +sb_sasl_generic_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct sb_sasl_generic_data *p; + + p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) return 1; + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +Sockbuf_IO ldap_pvt_sockbuf_io_sasl_generic = { + sb_sasl_generic_setup, /* sbi_setup */ + sb_sasl_generic_remove, /* sbi_remove */ + sb_sasl_generic_ctrl, /* sbi_ctrl */ + sb_sasl_generic_read, /* sbi_read */ + sb_sasl_generic_write, /* sbi_write */ + NULL /* sbi_close */ +}; + +int ldap_pvt_sasl_generic_install( + Sockbuf *sb, + struct sb_sasl_generic_install *install_arg ) +{ + Debug0( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_generic_install\n" ); + + /* don't install the stuff unless security has been negotiated */ + + if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, + &ldap_pvt_sockbuf_io_sasl_generic ) ) + { +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_APPLICATION, (void *)"sasl_generic_" ); +#endif + ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl_generic, + LBER_SBIOD_LEVEL_APPLICATION, install_arg ); + } + + return LDAP_SUCCESS; +} + +void ldap_pvt_sasl_generic_remove( Sockbuf *sb ) +{ + ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_sasl_generic, + LBER_SBIOD_LEVEL_APPLICATION ); +#ifdef LDAP_DEBUG + ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_APPLICATION ); +#endif +} diff --git a/libs/ldap/libldap/sasl_w.c b/libs/ldap/libldap/sasl_w.c new file mode 100644 index 00000000000..3639ae7cf1a --- /dev/null +++ b/libs/ldap/libldap/sasl_w.c @@ -0,0 +1,349 @@ +/* + * Copyright 2022 Hans Leidekker for CodeWeavers + * + * SSPI based replacement for Cyrus SASL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <windef.h> +#include <winerror.h> +#include <sspi.h> +#include <rpc.h> +#include <sasl.h> + +struct connection +{ + char *servername; + CredHandle cred_handle; + CtxtHandle ctxt_handle; + sasl_interact_t prompts[4]; + unsigned int max_token; + unsigned int trailer_size; + sasl_ssf_t ssf; + char *buf; + unsigned buf_size; +}; + +int sasl_client_init( const sasl_callback_t *callbacks ) +{ + return SASL_OK; +} + +static int grow_buffer( struct connection *conn, unsigned int min_size ) +{ + char *tmp; + unsigned int new_size = max( conn->buf_size * 2, min_size ); + if (conn->buf_size >= min_size) return SASL_OK; + if (!(tmp = realloc( conn->buf, new_size ))) return SASL_NOMEM; + conn->buf = tmp; + conn->buf_size = new_size; + return SASL_OK; +} + +int sasl_decode( sasl_conn_t *handle, const char *input, unsigned int inputlen, const char **output, + unsigned int *outputlen ) +{ + struct connection *conn = (struct connection *)handle; + unsigned int len; + SecBuffer bufs[2] = + { + { conn->trailer_size, SECBUFFER_TOKEN, NULL }, + { inputlen - conn->trailer_size - sizeof(len), SECBUFFER_DATA, NULL } + }; + SecBufferDesc buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(bufs), bufs }; + SECURITY_STATUS status; + int ret; + + if (inputlen < sizeof(len) + conn->trailer_size) return SASL_FAIL; + + if ((ret = grow_buffer( conn, inputlen - sizeof(len) )) < 0) return ret; + memcpy( conn->buf, input + sizeof(len), inputlen - sizeof(len) ); + bufs[0].pvBuffer = conn->buf; + bufs[1].pvBuffer = conn->buf + conn->trailer_size; + + status = DecryptMessage( &conn->ctxt_handle, &buf_desc, 0, NULL ); + if (status == SEC_E_OK) + { + *output = bufs[1].pvBuffer; + *outputlen = bufs[1].cbBuffer; + } + + return (status == SEC_E_OK) ? SASL_OK : SASL_FAIL; +} + +int sasl_encode( sasl_conn_t *handle, const char *input, unsigned int inputlen, const char **output, + unsigned int *outputlen ) +{ + struct connection *conn = (struct connection *)handle; + SecBuffer bufs[2] = + { + { inputlen, SECBUFFER_DATA, NULL }, + { conn->trailer_size, SECBUFFER_TOKEN, NULL } + }; + SecBufferDesc buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(bufs), bufs }; + SECURITY_STATUS status; + unsigned int len; + int ret; + + if ((ret = grow_buffer( conn, sizeof(len) + inputlen + conn->trailer_size )) < 0) return ret; + memcpy( conn->buf + sizeof(len) + conn->trailer_size, input, inputlen ); + bufs[0].pvBuffer = conn->buf + sizeof(len) + conn->trailer_size; + bufs[1].pvBuffer = conn->buf + sizeof(len); + + status = EncryptMessage( &conn->ctxt_handle, 0, &buf_desc, 0 ); + if (status == SEC_E_OK) + { + len = htonl( bufs[0].cbBuffer + bufs[1].cbBuffer ); + memcpy( conn->buf, &len, sizeof(len) ); + *output = conn->buf; + *outputlen = sizeof(len) + bufs[0].cbBuffer + bufs[1].cbBuffer; + } + + return (status == SEC_E_OK) ? SASL_OK : SASL_FAIL; +} + +const char *sasl_errstring( int saslerr, const char *langlist, const char **outlang ) +{ + return NULL; +} + +void sasl_set_mutex( void *mutex_alloc, void *mutex_lock, void *mutex_unlock, void *mutex_free ) +{ +} + +static int check_callback( const sasl_callback_t *callbacks, unsigned long id ) +{ + const sasl_callback_t *ptr = callbacks; + while (ptr->id) + { + if (ptr->id == id) return 1; + ptr++; + } + return 0; +} + +int sasl_client_new( const char *service, const char *server, const char *localport, const char *remoteport, + const sasl_callback_t *prompt, unsigned int flags, sasl_conn_t **ret ) +{ + struct connection *conn; + SECURITY_STATUS status; + SecPkgInfoA *info; + + if (!check_callback( prompt, SASL_CB_AUTHNAME ) || !check_callback( prompt, SASL_CB_GETREALM ) || + !check_callback( prompt, SASL_CB_PASS )) return SASL_BADPARAM; + + if (!(conn = calloc( 1, sizeof(*conn) ))) return SASL_NOMEM; + if (!(conn->servername = strdup( server ))) + { + free( conn ); + return SASL_NOMEM; + } + + status = QuerySecurityPackageInfoA( (SEC_CHAR *)"Negotiate", &info ); + if (status != SEC_E_OK) + { + free( conn->servername ); + free( conn ); + return SASL_FAIL; + } + conn->max_token = conn->buf_size = info->cbMaxToken; + FreeContextBuffer( info ); + + if (!(conn->buf = malloc( conn->buf_size ))) + { + free( conn->servername ); + free( conn ); + return SASL_NOMEM; + } + + conn->prompts[0].id = SASL_CB_AUTHNAME; + conn->prompts[1].id = SASL_CB_GETREALM; + conn->prompts[2].id = SASL_CB_PASS; + conn->prompts[3].id = SASL_CB_LIST_END; + + *ret = (sasl_conn_t *)conn; + return SASL_OK; +} + +void sasl_dispose( sasl_conn_t **handle_ptr ) +{ + struct connection *conn = *(struct connection **)handle_ptr; + + DeleteSecurityContext( &conn->ctxt_handle ); + FreeCredentialsHandle( &conn->cred_handle ); + free( conn->servername ); + free( conn->buf ); + free( conn ); +} + +static unsigned short *get_prompt_result( const sasl_interact_t *prompts, unsigned long id, unsigned long *len ) +{ + const sasl_interact_t *ptr = prompts; + while (ptr->id != SASL_CB_LIST_END) + { + if (ptr->id == id) + { + *len = ptr->len; + return (unsigned short *)ptr->result; + } + ptr++; + } +} + +static int fill_auth_identity( const sasl_interact_t *prompts, SEC_WINNT_AUTH_IDENTITY_W *id ) +{ + if (!(id->User = get_prompt_result( prompts, SASL_CB_AUTHNAME, &id->UserLength ))) + return SASL_BADPARAM; + if (!(id->Domain = get_prompt_result( prompts, SASL_CB_GETREALM, &id->DomainLength ))) + return SASL_BADPARAM; + if (!(id->Password = get_prompt_result( prompts, SASL_CB_PASS, &id->PasswordLength ))) + return SASL_BADPARAM; + + id->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + return SASL_OK; +} + +int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_t **prompts, + const char **clientout, unsigned int *clientoutlen, const char **mech ) +{ + struct connection *conn = (struct connection *)handle; + SEC_WINNT_AUTH_IDENTITY_W id; + SecBuffer out_bufs[] = + { + { conn->buf_size, SECBUFFER_TOKEN, conn->buf }, + { 0, SECBUFFER_ALERT, NULL } + }; + SecBufferDesc out_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(out_bufs), out_bufs }; + ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY; + SECURITY_STATUS status; + int ret; + + if (!*prompts) + { + *prompts = conn->prompts; + return SASL_INTERACT; + } + if ((ret = fill_auth_identity( conn->prompts, &id )) < 0) return ret; + + status = AcquireCredentialsHandleA( NULL, (SEC_CHAR *)"Negotiate", SECPKG_CRED_OUTBOUND, NULL, + (SEC_WINNT_AUTH_IDENTITY_A *)&id, NULL, NULL, &conn->cred_handle, NULL ); + if (status != SEC_E_OK) return SASL_FAIL; + + status = InitializeSecurityContextA( &conn->cred_handle, NULL, (SEC_CHAR *)conn->servername, flags, + 0, 0, NULL, 0, &conn->ctxt_handle, &out_buf_desc, &attrs, NULL ); + if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) + { + *clientout = out_bufs[0].pvBuffer; + *clientoutlen = out_bufs[0].cbBuffer; + *mech = "GSS-SPNEGO"; + return (status == SEC_I_CONTINUE_NEEDED) ? SASL_CONTINUE : SASL_OK; + } + + return SASL_FAIL; +} + +int sasl_client_step( sasl_conn_t *handle, const char *serverin, unsigned int serverinlen, + sasl_interact_t **prompts, const char **clientout, unsigned int *clientoutlen ) +{ + struct connection *conn = (struct connection *)handle; + SecBuffer in_bufs[] = + { + { serverinlen, SECBUFFER_TOKEN, (void *)serverin }, + { 0, SECBUFFER_EMPTY, NULL } + }; + SecBuffer out_bufs[] = + { + { conn->buf_size, SECBUFFER_TOKEN, conn->buf }, + { 0, SECBUFFER_ALERT, NULL } + }; + SecBufferDesc in_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(in_bufs), in_bufs }; + SecBufferDesc out_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(out_bufs), out_bufs }; + ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY; + SECURITY_STATUS status; + + status = InitializeSecurityContextA( NULL, &conn->ctxt_handle, (SEC_CHAR *)conn->servername, flags, 0, 0, + &in_buf_desc, 0, &conn->ctxt_handle, &out_buf_desc, &attrs, NULL ); + if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) + { + *clientout = out_bufs[0].pvBuffer; + *clientoutlen = out_bufs[0].cbBuffer; + if (status == SEC_I_CONTINUE_NEEDED) return SASL_CONTINUE; + else + { + SecPkgContext_KeyInfoA key; + SecPkgContext_Sizes sizes; + + status = QueryContextAttributesA( &conn->ctxt_handle, SECPKG_ATTR_KEY_INFO, &key ); + if (status != SEC_E_OK) return SASL_FAIL; + FreeContextBuffer( key.sSignatureAlgorithmName ); + FreeContextBuffer( key.sEncryptAlgorithmName ); + conn->ssf = key.KeySize; + + status = QueryContextAttributesA( &conn->ctxt_handle, SECPKG_ATTR_SIZES, &sizes ); + if (status != SEC_E_OK) return SASL_FAIL; + conn->trailer_size = sizes.cbSecurityTrailer; + return SASL_OK; + } + } + + return SASL_FAIL; +} + +int sasl_getprop( sasl_conn_t *handle, int propnum, const void **pvalue ) +{ + struct connection *conn = (struct connection *)handle; + + switch (propnum) + { + case SASL_SSF: + *(sasl_ssf_t **)pvalue = &conn->ssf; + return SASL_OK; + case SASL_MAXOUTBUF: + *(unsigned int *)pvalue = conn->max_token; + return SASL_OK; + default: + break; + } + + return SASL_FAIL; +} + +int sasl_setprop( sasl_conn_t *handle, int propnum, const void *value ) +{ + switch (propnum) + { + case SASL_SEC_PROPS: + case SASL_AUTH_EXTERNAL: + return SASL_OK; + default: + break; + } + return SASL_FAIL; +} + +const char *sasl_errdetail( sasl_conn_t *handle ) +{ + return NULL; +} + +const char **sasl_global_listmech( void ) +{ + static const char *mechs[] = { "GSS-SPNEGO", NULL }; + return mechs; +} diff --git a/libs/ldap/libldap/schema.c b/libs/ldap/libldap/schema.c new file mode 100644 index 00000000000..2c477bde734 --- /dev/null +++ b/libs/ldap/libldap/schema.c @@ -0,0 +1,3400 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * schema.c: parsing routines used by servers and clients to process + * schema definitions + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +#include <ldap_schema.h> + +static const char EndOfInput[] = "end of input"; + +static const char * +choose_name( char *names[], const char *fallback ) +{ + return (names != NULL && names[0] != NULL) ? names[0] : fallback; +} + +LDAP_CONST char * +ldap_syntax2name( LDAPSyntax * syn ) +{ + if (!syn) return NULL; + return( syn->syn_oid ); +} + +LDAP_CONST char * +ldap_matchingrule2name( LDAPMatchingRule * mr ) +{ + if (!mr) return NULL; + return( choose_name( mr->mr_names, mr->mr_oid ) ); +} + +LDAP_CONST char * +ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru ) +{ + if (!mru) return NULL; + return( choose_name( mru->mru_names, mru->mru_oid ) ); +} + +LDAP_CONST char * +ldap_attributetype2name( LDAPAttributeType * at ) +{ + if (!at) return NULL; + return( choose_name( at->at_names, at->at_oid ) ); +} + +LDAP_CONST char * +ldap_objectclass2name( LDAPObjectClass * oc ) +{ + if (!oc) return NULL; + return( choose_name( oc->oc_names, oc->oc_oid ) ); +} + +LDAP_CONST char * +ldap_contentrule2name( LDAPContentRule * cr ) +{ + if (!cr) return NULL; + return( choose_name( cr->cr_names, cr->cr_oid ) ); +} + +LDAP_CONST char * +ldap_nameform2name( LDAPNameForm * nf ) +{ + if (!nf) return NULL; + return( choose_name( nf->nf_names, nf->nf_oid ) ); +} + +LDAP_CONST char * +ldap_structurerule2name( LDAPStructureRule * sr ) +{ + if (!sr) return NULL; + return( choose_name( sr->sr_names, NULL ) ); +} + +/* + * When pretty printing the entities we will be appending to a buffer. + * Since checking for overflow, realloc'ing and checking if no error + * is extremely boring, we will use a protection layer that will let + * us blissfully ignore the error until the end. This layer is + * implemented with the help of the next type. + */ + +typedef struct safe_string { + char * val; + ber_len_t size; + ber_len_t pos; + int at_whsp; +} safe_string; + +static safe_string * +new_safe_string(int size) +{ + safe_string * ss; + + ss = LDAP_MALLOC(sizeof(safe_string)); + if ( !ss ) + return(NULL); + + ss->val = LDAP_MALLOC(size); + if ( !ss->val ) { + LDAP_FREE(ss); + return(NULL); + } + + ss->size = size; + ss->pos = 0; + ss->at_whsp = 0; + + return ss; +} + +static void +safe_string_free(safe_string * ss) +{ + if ( !ss ) + return; + LDAP_FREE(ss->val); + LDAP_FREE(ss); +} + +#if 0 /* unused */ +static char * +safe_string_val(safe_string * ss) +{ + ss->val[ss->pos] = '\0'; + return(ss->val); +} +#endif + +static char * +safe_strdup(safe_string * ss) +{ + char *ret = LDAP_MALLOC(ss->pos+1); + if (!ret) + return NULL; + AC_MEMCPY(ret, ss->val, ss->pos); + ret[ss->pos] = '\0'; + return ret; +} + +static int +append_to_safe_string(safe_string * ss, char * s) +{ + int l = strlen(s); + char * temp; + + /* + * Some runaway process is trying to append to a string that + * overflowed and we could not extend. + */ + if ( !ss->val ) + return -1; + + /* We always make sure there is at least one position available */ + if ( ss->pos + l >= ss->size-1 ) { + ss->size *= 2; + if ( ss->pos + l >= ss->size-1 ) { + ss->size = ss->pos + l + 1; + } + + temp = LDAP_REALLOC(ss->val, ss->size); + if ( !temp ) { + /* Trouble, out of memory */ + LDAP_FREE(ss->val); + return -1; + } + ss->val = temp; + } + strncpy(&ss->val[ss->pos], s, l); + ss->pos += l; + if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) ) + ss->at_whsp = 1; + else + ss->at_whsp = 0; + + return 0; +} + +static int +print_literal(safe_string *ss, char *s) +{ + return(append_to_safe_string(ss,s)); +} + +static int +print_whsp(safe_string *ss) +{ + if ( ss->at_whsp ) + return(append_to_safe_string(ss,"")); + else + return(append_to_safe_string(ss," ")); +} + +static int +print_numericoid(safe_string *ss, char *s) +{ + if ( s ) + return(append_to_safe_string(ss,s)); + else + return(append_to_safe_string(ss,"")); +} + +/* This one is identical to print_qdescr */ +static int +print_qdstring(safe_string *ss, char *s) +{ + print_whsp(ss); + print_literal(ss,"'"); + append_to_safe_string(ss,s); + print_literal(ss,"'"); + return(print_whsp(ss)); +} + +static int +print_qdescr(safe_string *ss, char *s) +{ + print_whsp(ss); + print_literal(ss,"'"); + append_to_safe_string(ss,s); + print_literal(ss,"'"); + return(print_whsp(ss)); +} + +static int +print_qdescrlist(safe_string *ss, char **sa) +{ + char **sp; + int ret = 0; + + for (sp=sa; *sp; sp++) { + ret = print_qdescr(ss,*sp); + } + /* If the list was empty, we return zero that is potentially + * incorrect, but since we will be still appending things, the + * overflow will be detected later. Maybe FIX. + */ + return(ret); +} + +static int +print_qdescrs(safe_string *ss, char **sa) +{ + /* The only way to represent an empty list is as a qdescrlist + * so, if the list is empty we treat it as a long list. + * Really, this is what the syntax mandates. We should not + * be here if the list was empty, but if it happens, a label + * has already been output and we cannot undo it. + */ + if ( !sa[0] || ( sa[0] && sa[1] ) ) { + print_whsp(ss); + print_literal(ss,"("/*)*/); + print_qdescrlist(ss,sa); + print_literal(ss,/*(*/")"); + return(print_whsp(ss)); + } else { + return(print_qdescr(ss,*sa)); + } +} + +static int +print_woid(safe_string *ss, char *s) +{ + print_whsp(ss); + append_to_safe_string(ss,s); + return print_whsp(ss); +} + +static int +print_oidlist(safe_string *ss, char **sa) +{ + char **sp; + + for (sp=sa; *(sp+1); sp++) { + print_woid(ss,*sp); + print_literal(ss,"$"); + } + return(print_woid(ss,*sp)); +} + +static int +print_oids(safe_string *ss, char **sa) +{ + if ( sa[0] && sa[1] ) { + print_literal(ss,"("/*)*/); + print_oidlist(ss,sa); + print_whsp(ss); + return(print_literal(ss,/*(*/")")); + } else { + return(print_woid(ss,*sa)); + } +} + +static int +print_noidlen(safe_string *ss, char *s, int l) +{ + char buf[64]; + int ret; + + ret = print_numericoid(ss,s); + if ( l ) { + snprintf(buf, sizeof buf, "{%d}",l); + ret = print_literal(ss,buf); + } + return(ret); +} + +static int +print_ruleid(safe_string *ss, int rid) +{ + char buf[64]; + snprintf(buf, sizeof buf, "%d", rid); + return print_literal(ss,buf); +} + +static int +print_ruleids(safe_string *ss, int n, int *rids) +{ + int i; + + if( n == 1 ) { + print_ruleid(ss,rids[0]); + return print_whsp(ss); + } else { + print_literal(ss,"("/*)*/); + for( i=0; i<n; i++ ) { + print_whsp(ss); + print_ruleid(ss,rids[i]); + } + print_whsp(ss); + return print_literal(ss,/*(*/")"); + } +} + + +static int +print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions) +{ + LDAPSchemaExtensionItem **ext; + + if ( extensions ) { + print_whsp(ss); + for ( ext = extensions; *ext != NULL; ext++ ) { + print_literal(ss, (*ext)->lsei_name); + print_whsp(ss); + /* Should be print_qdstrings */ + print_qdescrs(ss, (*ext)->lsei_values); + print_whsp(ss); + } + } + + return 0; +} + +char * +ldap_syntax2str( LDAPSyntax * syn ) +{ + struct berval bv; + if (ldap_syntax2bv( syn, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv ) +{ + safe_string * ss; + + if ( !syn || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, syn->syn_oid); + print_whsp(ss); + + if ( syn->syn_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,syn->syn_desc); + } + + print_whsp(ss); + + print_extensions(ss, syn->syn_extensions); + + print_literal(ss,/*(*/ ")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_matchingrule2str( LDAPMatchingRule * mr ) +{ + struct berval bv; + if (ldap_matchingrule2bv( mr, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv ) +{ + safe_string * ss; + + if ( !mr || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"(" /*)*/); + print_whsp(ss); + + print_numericoid(ss, mr->mr_oid); + print_whsp(ss); + + if ( mr->mr_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,mr->mr_names); + } + + if ( mr->mr_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,mr->mr_desc); + } + + if ( mr->mr_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( mr->mr_syntax_oid ) { + print_literal(ss,"SYNTAX"); + print_whsp(ss); + print_literal(ss, mr->mr_syntax_oid); + print_whsp(ss); + } + + print_whsp(ss); + + print_extensions(ss, mr->mr_extensions); + + print_literal(ss,/*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru ) +{ + struct berval bv; + if (ldap_matchingruleuse2bv( mru, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv ) +{ + safe_string * ss; + + if ( !mru || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"(" /*)*/); + print_whsp(ss); + + print_numericoid(ss, mru->mru_oid); + print_whsp(ss); + + if ( mru->mru_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,mru->mru_names); + } + + if ( mru->mru_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,mru->mru_desc); + } + + if ( mru->mru_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( mru->mru_applies_oids ) { + print_literal(ss,"APPLIES"); + print_whsp(ss); + print_oids(ss, mru->mru_applies_oids); + print_whsp(ss); + } + + print_whsp(ss); + + print_extensions(ss, mru->mru_extensions); + + print_literal(ss,/*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_objectclass2str( LDAPObjectClass * oc ) +{ + struct berval bv; + if (ldap_objectclass2bv( oc, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv ) +{ + safe_string * ss; + + if ( !oc || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, oc->oc_oid); + print_whsp(ss); + + if ( oc->oc_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,oc->oc_names); + } + + if ( oc->oc_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,oc->oc_desc); + } + + if ( oc->oc_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( oc->oc_sup_oids ) { + print_literal(ss,"SUP"); + print_whsp(ss); + print_oids(ss,oc->oc_sup_oids); + print_whsp(ss); + } + + switch (oc->oc_kind) { + case LDAP_SCHEMA_ABSTRACT: + print_literal(ss,"ABSTRACT"); + break; + case LDAP_SCHEMA_STRUCTURAL: + print_literal(ss,"STRUCTURAL"); + break; + case LDAP_SCHEMA_AUXILIARY: + print_literal(ss,"AUXILIARY"); + break; + default: + print_literal(ss,"KIND-UNKNOWN"); + break; + } + print_whsp(ss); + + if ( oc->oc_at_oids_must ) { + print_literal(ss,"MUST"); + print_whsp(ss); + print_oids(ss,oc->oc_at_oids_must); + print_whsp(ss); + } + + if ( oc->oc_at_oids_may ) { + print_literal(ss,"MAY"); + print_whsp(ss); + print_oids(ss,oc->oc_at_oids_may); + print_whsp(ss); + } + + print_whsp(ss); + + print_extensions(ss, oc->oc_extensions); + + print_literal(ss, /*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_contentrule2str( LDAPContentRule * cr ) +{ + struct berval bv; + if (ldap_contentrule2bv( cr, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv ) +{ + safe_string * ss; + + if ( !cr || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, cr->cr_oid); + print_whsp(ss); + + if ( cr->cr_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,cr->cr_names); + } + + if ( cr->cr_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,cr->cr_desc); + } + + if ( cr->cr_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( cr->cr_oc_oids_aux ) { + print_literal(ss,"AUX"); + print_whsp(ss); + print_oids(ss,cr->cr_oc_oids_aux); + print_whsp(ss); + } + + if ( cr->cr_at_oids_must ) { + print_literal(ss,"MUST"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_must); + print_whsp(ss); + } + + if ( cr->cr_at_oids_may ) { + print_literal(ss,"MAY"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_may); + print_whsp(ss); + } + + if ( cr->cr_at_oids_not ) { + print_literal(ss,"NOT"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_not); + print_whsp(ss); + } + + print_whsp(ss); + print_extensions(ss, cr->cr_extensions); + + print_literal(ss, /*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_structurerule2str( LDAPStructureRule * sr ) +{ + struct berval bv; + if (ldap_structurerule2bv( sr, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv ) +{ + safe_string * ss; + + if ( !sr || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_ruleid(ss, sr->sr_ruleid); + print_whsp(ss); + + if ( sr->sr_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,sr->sr_names); + } + + if ( sr->sr_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,sr->sr_desc); + } + + if ( sr->sr_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + print_literal(ss,"FORM"); + print_whsp(ss); + print_woid(ss,sr->sr_nameform); + print_whsp(ss); + + if ( sr->sr_nsup_ruleids ) { + print_literal(ss,"SUP"); + print_whsp(ss); + print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids); + print_whsp(ss); + } + + print_whsp(ss); + print_extensions(ss, sr->sr_extensions); + + print_literal(ss, /*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + + +char * +ldap_nameform2str( LDAPNameForm * nf ) +{ + struct berval bv; + if (ldap_nameform2bv( nf, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv ) +{ + safe_string * ss; + + if ( !nf || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, nf->nf_oid); + print_whsp(ss); + + if ( nf->nf_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,nf->nf_names); + } + + if ( nf->nf_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,nf->nf_desc); + } + + if ( nf->nf_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + print_literal(ss,"OC"); + print_whsp(ss); + print_woid(ss,nf->nf_objectclass); + print_whsp(ss); + + print_literal(ss,"MUST"); + print_whsp(ss); + print_oids(ss,nf->nf_at_oids_must); + print_whsp(ss); + + + if ( nf->nf_at_oids_may ) { + print_literal(ss,"MAY"); + print_whsp(ss); + print_oids(ss,nf->nf_at_oids_may); + print_whsp(ss); + } + + print_whsp(ss); + print_extensions(ss, nf->nf_extensions); + + print_literal(ss, /*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +char * +ldap_attributetype2str( LDAPAttributeType * at ) +{ + struct berval bv; + if (ldap_attributetype2bv( at, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv ) +{ + safe_string * ss; + + if ( !at || !bv ) + return NULL; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, at->at_oid); + print_whsp(ss); + + if ( at->at_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,at->at_names); + } + + if ( at->at_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,at->at_desc); + } + + if ( at->at_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( at->at_sup_oid ) { + print_literal(ss,"SUP"); + print_woid(ss,at->at_sup_oid); + } + + if ( at->at_equality_oid ) { + print_literal(ss,"EQUALITY"); + print_woid(ss,at->at_equality_oid); + } + + if ( at->at_ordering_oid ) { + print_literal(ss,"ORDERING"); + print_woid(ss,at->at_ordering_oid); + } + + if ( at->at_substr_oid ) { + print_literal(ss,"SUBSTR"); + print_woid(ss,at->at_substr_oid); + } + + if ( at->at_syntax_oid ) { + print_literal(ss,"SYNTAX"); + print_whsp(ss); + print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len); + print_whsp(ss); + } + + if ( at->at_single_value == LDAP_SCHEMA_YES ) { + print_literal(ss,"SINGLE-VALUE"); + print_whsp(ss); + } + + if ( at->at_collective == LDAP_SCHEMA_YES ) { + print_literal(ss,"COLLECTIVE"); + print_whsp(ss); + } + + if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) { + print_literal(ss,"NO-USER-MODIFICATION"); + print_whsp(ss); + } + + if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) { + print_literal(ss,"USAGE"); + print_whsp(ss); + switch (at->at_usage) { + case LDAP_SCHEMA_DIRECTORY_OPERATION: + print_literal(ss,"directoryOperation"); + break; + case LDAP_SCHEMA_DISTRIBUTED_OPERATION: + print_literal(ss,"distributedOperation"); + break; + case LDAP_SCHEMA_DSA_OPERATION: + print_literal(ss,"dSAOperation"); + break; + default: + print_literal(ss,"UNKNOWN"); + break; + } + } + + print_whsp(ss); + + print_extensions(ss, at->at_extensions); + + print_literal(ss,/*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + +/* + * Now come the parsers. There is one parser for each entity type: + * objectclasses, attributetypes, etc. + * + * Each of them is written as a recursive-descent parser, except that + * none of them is really recursive. But the idea is kept: there + * is one routine per non-terminal that either gobbles lexical tokens + * or calls lower-level routines, etc. + * + * The scanner is implemented in the routine get_token. Actually, + * get_token is more than a scanner and will return tokens that are + * in fact non-terminals in the grammar. So you can see the whole + * approach as the combination of a low-level bottom-up recognizer + * combined with a scanner and a number of top-down parsers. Or just + * consider that the real grammars recognized by the parsers are not + * those of the standards. As a matter of fact, our parsers are more + * liberal than the spec when there is no ambiguity. + * + * The difference is pretty academic (modulo bugs or incorrect + * interpretation of the specs). + */ + +typedef enum tk_t { + TK_NOENDQUOTE = -2, + TK_OUTOFMEM = -1, + TK_EOS = 0, + TK_UNEXPCHAR = 1, + TK_BAREWORD = 2, + TK_QDSTRING = 3, + TK_LEFTPAREN = 4, + TK_RIGHTPAREN = 5, + TK_DOLLAR = 6, + TK_QDESCR = TK_QDSTRING +} tk_t; + +static tk_t +get_token( const char ** sp, char ** token_val ) +{ + tk_t kind; + const char * p; + const char * q; + char * res; + + *token_val = NULL; + switch (**sp) { + case '\0': + kind = TK_EOS; + (*sp)++; + break; + case '(': + kind = TK_LEFTPAREN; + (*sp)++; + break; + case ')': + kind = TK_RIGHTPAREN; + (*sp)++; + break; + case '$': + kind = TK_DOLLAR; + (*sp)++; + break; + case ''': + kind = TK_QDSTRING; + (*sp)++; + p = *sp; + while ( **sp != ''' && **sp != '\0' ) + (*sp)++; + if ( **sp == ''' ) { + q = *sp; + res = LDAP_MALLOC(q-p+1); + if ( !res ) { + kind = TK_OUTOFMEM; + } else { + strncpy(res,p,q-p); + res[q-p] = '\0'; + *token_val = res; + } + (*sp)++; + } else { + kind = TK_NOENDQUOTE; + } + break; + default: + kind = TK_BAREWORD; + p = *sp; + while ( !LDAP_SPACE(**sp) && + **sp != '(' && + **sp != ')' && + **sp != '$' && + **sp != ''' && + /* for suggested minimum upper bound on the number + * of characters (RFC 4517) */ + **sp != '{' && + **sp != '\0' ) + (*sp)++; + q = *sp; + res = LDAP_MALLOC(q-p+1); + if ( !res ) { + kind = TK_OUTOFMEM; + } else { + strncpy(res,p,q-p); + res[q-p] = '\0'; + *token_val = res; + } + break; +/* kind = TK_UNEXPCHAR; */ +/* break; */ + } + + return kind; +} + +/* Gobble optional whitespace */ +static void +parse_whsp(const char **sp) +{ + while (LDAP_SPACE(**sp)) + (*sp)++; +} + +/* TBC:!! + * General note for all parsers: to guarantee the algorithm halts they + * must always advance the pointer even when an error is found. For + * this one is not that important since an error here is fatal at the + * upper layers, but it is a simple strategy that will not get in + * endless loops. + */ + +/* Parse a sequence of dot-separated decimal strings */ +char * +ldap_int_parse_numericoid(const char **sp, int *code, const int flags) +{ + char * res = NULL; + const char * start = *sp; + int len; + int quoted = 0; + + /* Netscape puts the SYNTAX value in quotes (incorrectly) */ + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == ''' ) { + quoted = 1; + (*sp)++; + start++; + } + /* Each iteration of this loop gets one decimal string */ + while (**sp) { + if ( !LDAP_DIGIT(**sp) ) { + /* + * Initial char is not a digit or char after dot is + * not a digit + */ + *code = LDAP_SCHERR_NODIGIT; + return NULL; + } + (*sp)++; + while ( LDAP_DIGIT(**sp) ) + (*sp)++; + if ( **sp != '.' ) + break; + /* Otherwise, gobble the dot and loop again */ + (*sp)++; + } + /* Now *sp points at the char past the numericoid. Perfect. */ + len = *sp - start; + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { + if ( **sp == ''' ) { + (*sp)++; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + return NULL; + } + } + if (flags & LDAP_SCHEMA_SKIP) { + res = (char *)start; + } else { + res = LDAP_MALLOC(len+1); + if (!res) { + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + strncpy(res,start,len); + res[len] = '\0'; + } + return(res); +} + +/* Parse a sequence of dot-separated decimal strings */ +int +ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid) +{ + *ruleid=0; + + if ( !LDAP_DIGIT(**sp) ) { + *code = LDAP_SCHERR_NODIGIT; + return -1; + } + *ruleid = (**sp) - '0'; + (*sp)++; + + while ( LDAP_DIGIT(**sp) ) { + *ruleid *= 10; + *ruleid += (**sp) - '0'; + (*sp)++; + } + + return 0; +} + +/* Parse a qdescr or a list of them enclosed in () */ +static char ** +parse_qdescrs(const char **sp, int *code) +{ + char ** res; + char ** res1; + tk_t kind; + char * sval; + int size; + int pos; + + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_LEFTPAREN ) { + /* Let's presume there will be at least 2 entries */ + size = 3; + res = LDAP_CALLOC(3,sizeof(char *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + pos = 0; + while (1) { + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_RIGHTPAREN ) + break; + if ( kind == TK_QDESCR ) { + if ( pos == size-2 ) { + size++; + res1 = LDAP_REALLOC(res,size*sizeof(char *)); + if ( !res1 ) { + LDAP_VFREE(res); + LDAP_FREE(sval); + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + res = res1; + } + res[pos++] = sval; + res[pos] = NULL; + parse_whsp(sp); + } else { + LDAP_VFREE(res); + LDAP_FREE(sval); + *code = LDAP_SCHERR_UNEXPTOKEN; + return(NULL); + } + } + parse_whsp(sp); + return(res); + } else if ( kind == TK_QDESCR ) { + res = LDAP_CALLOC(2,sizeof(char *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + res[0] = sval; + res[1] = NULL; + parse_whsp(sp); + return res; + } else { + LDAP_FREE(sval); + *code = LDAP_SCHERR_BADNAME; + return NULL; + } +} + +/* Parse a woid */ +static char * +parse_woid(const char **sp, int *code) +{ + char * sval; + tk_t kind; + + parse_whsp(sp); + kind = get_token(sp, &sval); + if ( kind != TK_BAREWORD ) { + LDAP_FREE(sval); + *code = LDAP_SCHERR_UNEXPTOKEN; + return NULL; + } + parse_whsp(sp); + return sval; +} + +/* Parse a noidlen */ +static char * +parse_noidlen(const char **sp, int *code, int *len, int flags) +{ + char * sval; + const char *savepos; + int quoted = 0; + int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED ); + int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ); + + *len = 0; + /* Netscape puts the SYNTAX value in quotes (incorrectly) */ + if ( allow_quoted && **sp == ''' ) { + quoted = 1; + (*sp)++; + } + savepos = *sp; + sval = ldap_int_parse_numericoid(sp, code, 0); + if ( !sval ) { + if ( allow_oidmacro + && *sp == savepos + && *code == LDAP_SCHERR_NODIGIT ) + { + if ( get_token(sp, &sval) != TK_BAREWORD ) { + if ( sval != NULL ) { + LDAP_FREE(sval); + } + return NULL; + } + } else { + return NULL; + } + } + if ( **sp == '{' /*}*/ ) { + (*sp)++; + *len = atoi(*sp); + while ( LDAP_DIGIT(**sp) ) + (*sp)++; + if ( **sp != /*{*/ '}' ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + return NULL; + } + (*sp)++; + } + if ( allow_quoted && quoted ) { + if ( **sp == ''' ) { + (*sp)++; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + return NULL; + } + } + return sval; +} + +/* + * Next routine will accept a qdstring in place of an oid if + * allow_quoted is set. This is necessary to interoperate with + * Netscape Directory server that will improperly quote each oid (at + * least those of the descr kind) in the SUP clause. + */ + +/* Parse a woid or a $-separated list of them enclosed in () */ +static char ** +parse_oids(const char **sp, int *code, const int allow_quoted) +{ + char ** res; + char ** res1; + tk_t kind; + char * sval; + int size; + int pos; + + /* + * Strictly speaking, doing this here accepts whsp before the + * ( at the beginning of an oidlist, but this is harmless. Also, + * we are very liberal in what we accept as an OID. Maybe + * refine later. + */ + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_LEFTPAREN ) { + /* Let's presume there will be at least 2 entries */ + size = 3; + res = LDAP_CALLOC(3,sizeof(char *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + pos = 0; + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_BAREWORD || + ( allow_quoted && kind == TK_QDSTRING ) ) { + res[pos++] = sval; + res[pos] = NULL; + } else if ( kind == TK_RIGHTPAREN ) { + /* FIXME: be liberal in what we accept... */ + parse_whsp(sp); + LDAP_FREE(res); + return NULL; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + parse_whsp(sp); + while (1) { + kind = get_token(sp,&sval); + if ( kind == TK_RIGHTPAREN ) + break; + if ( kind == TK_DOLLAR ) { + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_BAREWORD || + ( allow_quoted && + kind == TK_QDSTRING ) ) { + if ( pos == size-2 ) { + size++; + res1 = LDAP_REALLOC(res,size*sizeof(char *)); + if ( !res1 ) { + LDAP_FREE(sval); + LDAP_VFREE(res); + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + res = res1; + } + res[pos++] = sval; + res[pos] = NULL; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + parse_whsp(sp); + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + } + parse_whsp(sp); + return(res); + } else if ( kind == TK_BAREWORD || + ( allow_quoted && kind == TK_QDSTRING ) ) { + res = LDAP_CALLOC(2,sizeof(char *)); + if ( !res ) { + LDAP_FREE(sval); + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + res[0] = sval; + res[1] = NULL; + parse_whsp(sp); + return res; + } else { + LDAP_FREE(sval); + *code = LDAP_SCHERR_BADNAME; + return NULL; + } +} + +static int +add_extension(LDAPSchemaExtensionItem ***extensions, + char * name, char ** values) +{ + int n; + LDAPSchemaExtensionItem **tmp, *ext; + + ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem)); + if ( !ext ) + return 1; + ext->lsei_name = name; + ext->lsei_values = values; + + if ( !*extensions ) { + *extensions = + LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *)); + if ( !*extensions ) { + LDAP_FREE( ext ); + return 1; + } + n = 0; + } else { + for ( n=0; (*extensions)[n] != NULL; n++ ) + ; + tmp = LDAP_REALLOC(*extensions, + (n+2)*sizeof(LDAPSchemaExtensionItem *)); + if ( !tmp ) { + LDAP_FREE( ext ); + return 1; + } + *extensions = tmp; + } + (*extensions)[n] = ext; + (*extensions)[n+1] = NULL; + return 0; +} + +static void +free_extensions(LDAPSchemaExtensionItem **extensions) +{ + LDAPSchemaExtensionItem **ext; + + if ( extensions ) { + for ( ext = extensions; *ext != NULL; ext++ ) { + LDAP_FREE((*ext)->lsei_name); + LDAP_VFREE((*ext)->lsei_values); + LDAP_FREE(*ext); + } + LDAP_FREE(extensions); + } +} + +void +ldap_syntax_free( LDAPSyntax * syn ) +{ + if ( !syn ) return; + LDAP_FREE(syn->syn_oid); + if (syn->syn_names) LDAP_VFREE(syn->syn_names); + if (syn->syn_desc) LDAP_FREE(syn->syn_desc); + free_extensions(syn->syn_extensions); + LDAP_FREE(syn); +} + +LDAPSyntax * +ldap_str2syntax( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + LDAPSyntax * syn; + char ** ext_vals; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + syn = LDAP_CALLOC(1,sizeof(LDAPSyntax)); + + if ( !syn ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + LDAP_FREE(sval); + *code = LDAP_SCHERR_NOLEFTPAREN; + ldap_syntax_free(syn); + return NULL; + } + + parse_whsp(&ss); + syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !syn->syn_oid ) { + *errp = ss; + ldap_syntax_free(syn); + return NULL; + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal and accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_syntax_free(syn); + return NULL; + case TK_RIGHTPAREN: + return syn; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_syntax_free(syn); + return(NULL); + } + seen_name = 1; + syn->syn_names = parse_qdescrs(&ss,code); + if ( !syn->syn_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_syntax_free(syn); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_syntax_free(syn); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_syntax_free(syn); + return NULL; + } + syn->syn_desc = sval; + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_syntax_free(syn); + return NULL; + } + if ( add_extension(&syn->syn_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_syntax_free(syn); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_syntax_free(syn); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_syntax_free(syn); + return NULL; + } + } +} + +void +ldap_matchingrule_free( LDAPMatchingRule * mr ) +{ + if (!mr) return; + LDAP_FREE(mr->mr_oid); + if (mr->mr_names) LDAP_VFREE(mr->mr_names); + if (mr->mr_desc) LDAP_FREE(mr->mr_desc); + if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid); + free_extensions(mr->mr_extensions); + LDAP_FREE(mr); +} + +LDAPMatchingRule * +ldap_str2matchingrule( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_syntax = 0; + LDAPMatchingRule * mr; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule)); + + if ( !mr ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_matchingrule_free(mr); + return NULL; + } + + parse_whsp(&ss); + savepos = ss; + mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags); + if ( !mr->mr_oid ) { + if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "SYNTAX") || + !strncasecmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else { + /* Non-numerical OID, ignore */ + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_matchingrule_free(mr); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal and accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_matchingrule_free(mr); + return NULL; + case TK_RIGHTPAREN: + if( !seen_syntax ) { + *code = LDAP_SCHERR_MISSING; + ldap_matchingrule_free(mr); + return NULL; + } + return mr; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingrule_free(mr); + return(NULL); + } + seen_name = 1; + mr->mr_names = parse_qdescrs(&ss,code); + if ( !mr->mr_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_matchingrule_free(mr); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingrule_free(mr); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingrule_free(mr); + return NULL; + } + mr->mr_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingrule_free(mr); + return(NULL); + } + seen_obsolete = 1; + mr->mr_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"SYNTAX") ) { + LDAP_FREE(sval); + if ( seen_syntax ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingrule_free(mr); + return(NULL); + } + seen_syntax = 1; + parse_whsp(&ss); + mr->mr_syntax_oid = + ldap_int_parse_numericoid(&ss,code,flags); + if ( !mr->mr_syntax_oid ) { + *errp = ss; + ldap_matchingrule_free(mr); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_matchingrule_free(mr); + return NULL; + } + if ( add_extension(&mr->mr_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingrule_free(mr); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingrule_free(mr); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingrule_free(mr); + return NULL; + } + } +} + +void +ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru ) +{ + if (!mru) return; + LDAP_FREE(mru->mru_oid); + if (mru->mru_names) LDAP_VFREE(mru->mru_names); + if (mru->mru_desc) LDAP_FREE(mru->mru_desc); + if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids); + free_extensions(mru->mru_extensions); + LDAP_FREE(mru); +} + +LDAPMatchingRuleUse * +ldap_str2matchingruleuse( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_applies = 0; + LDAPMatchingRuleUse * mru; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse)); + + if ( !mru ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_matchingruleuse_free(mru); + return NULL; + } + + parse_whsp(&ss); + savepos = ss; + mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags); + if ( !mru->mru_oid ) { + if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "APPLIES") || + !strncasecmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else { + /* Non-numerical OID, ignore */ + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_matchingruleuse_free(mru); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal and accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_matchingruleuse_free(mru); + return NULL; + case TK_RIGHTPAREN: + if( !seen_applies ) { + *code = LDAP_SCHERR_MISSING; + ldap_matchingruleuse_free(mru); + return NULL; + } + return mru; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingruleuse_free(mru); + return(NULL); + } + seen_name = 1; + mru->mru_names = parse_qdescrs(&ss,code); + if ( !mru->mru_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_matchingruleuse_free(mru); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingruleuse_free(mru); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingruleuse_free(mru); + return NULL; + } + mru->mru_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingruleuse_free(mru); + return(NULL); + } + seen_obsolete = 1; + mru->mru_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"APPLIES") ) { + LDAP_FREE(sval); + if ( seen_applies ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_matchingruleuse_free(mru); + return(NULL); + } + seen_applies = 1; + mru->mru_applies_oids = parse_oids(&ss, + code, + flags); + if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_matchingruleuse_free(mru); + return NULL; + } + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_matchingruleuse_free(mru); + return NULL; + } + if ( add_extension(&mru->mru_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingruleuse_free(mru); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingruleuse_free(mru); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_matchingruleuse_free(mru); + return NULL; + } + } +} + +void +ldap_attributetype_free(LDAPAttributeType * at) +{ + if (!at) return; + LDAP_FREE(at->at_oid); + if (at->at_names) LDAP_VFREE(at->at_names); + if (at->at_desc) LDAP_FREE(at->at_desc); + if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid); + if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid); + if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid); + if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid); + if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid); + free_extensions(at->at_extensions); + LDAP_FREE(at); +} + +LDAPAttributeType * +ldap_str2attributetype( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_sup = 0; + int seen_equality = 0; + int seen_ordering = 0; + int seen_substr = 0; + int seen_syntax = 0; + int seen_usage = 0; + LDAPAttributeType * at; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + at = LDAP_CALLOC(1,sizeof(LDAPAttributeType)); + + if ( !at ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + * However, this routine is used by clients to parse the response + * from servers and very well known servers will provide an OID + * in the wrong format or even no OID at all. We do our best to + * extract info from those servers. + */ + parse_whsp(&ss); + savepos = ss; + at->at_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !at->at_oid ) { + if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID + | LDAP_SCHEMA_ALLOW_OID_MACRO ) ) + && (ss == savepos) ) + { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "SUP") || + !strcasecmp(sval, "EQUALITY") || + !strcasecmp(sval, "ORDERING") || + !strcasecmp(sval, "SUBSTR") || + !strcasecmp(sval, "SYNTAX") || + !strcasecmp(sval, "SINGLE-VALUE") || + !strcasecmp(sval, "COLLECTIVE") || + !strcasecmp(sval, "NO-USER-MODIFICATION") || + !strcasecmp(sval, "USAGE") || + !strncasecmp(sval, "X-", 2) ) + { + /* Missing OID, backtrack */ + ss = savepos; + } else if ( flags + & LDAP_SCHEMA_ALLOW_OID_MACRO) + { + /* Non-numerical OID ... */ + int len = ss-savepos; + at->at_oid = LDAP_MALLOC(len+1); + if ( !at->at_oid ) { + ldap_attributetype_free(at); + return NULL; + } + + strncpy(at->at_oid, savepos, len); + at->at_oid[len] = 0; + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal and accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_attributetype_free(at); + return NULL; + case TK_RIGHTPAREN: + return at; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_name = 1; + at->at_names = parse_qdescrs(&ss,code); + if ( !at->at_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + at->at_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_obsolete = 1; + at->at_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"SUP") ) { + LDAP_FREE(sval); + if ( seen_sup ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_sup = 1; + at->at_sup_oid = parse_woid(&ss,code); + if ( !at->at_sup_oid ) { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } else if ( !strcasecmp(sval,"EQUALITY") ) { + LDAP_FREE(sval); + if ( seen_equality ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_equality = 1; + at->at_equality_oid = parse_woid(&ss,code); + if ( !at->at_equality_oid ) { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } else if ( !strcasecmp(sval,"ORDERING") ) { + LDAP_FREE(sval); + if ( seen_ordering ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_ordering = 1; + at->at_ordering_oid = parse_woid(&ss,code); + if ( !at->at_ordering_oid ) { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } else if ( !strcasecmp(sval,"SUBSTR") ) { + LDAP_FREE(sval); + if ( seen_substr ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_substr = 1; + at->at_substr_oid = parse_woid(&ss,code); + if ( !at->at_substr_oid ) { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } else if ( !strcasecmp(sval,"SYNTAX") ) { + LDAP_FREE(sval); + if ( seen_syntax ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_syntax = 1; + parse_whsp(&ss); + savepos = ss; + at->at_syntax_oid = + parse_noidlen(&ss, + code, + &at->at_syntax_len, + flags); + if ( !at->at_syntax_oid ) { + if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) { + kind = get_token(&ss,&sval); + if (kind == TK_BAREWORD) + { + char *sp = strchr(sval, '{'); + at->at_syntax_oid = sval; + if (sp) + { + *sp++ = 0; + at->at_syntax_len = atoi(sp); + while ( LDAP_DIGIT(*sp) ) + sp++; + if ( *sp != '}' ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } + } + } else { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) { + LDAP_FREE(sval); + if ( at->at_single_value ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + at->at_single_value = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"COLLECTIVE") ) { + LDAP_FREE(sval); + if ( at->at_collective ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + at->at_collective = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) { + LDAP_FREE(sval); + if ( at->at_no_user_mod ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + at->at_no_user_mod = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"USAGE") ) { + LDAP_FREE(sval); + if ( seen_usage ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_attributetype_free(at); + return(NULL); + } + seen_usage = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_BAREWORD ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + if ( !strcasecmp(sval,"userApplications") ) + at->at_usage = + LDAP_SCHEMA_USER_APPLICATIONS; + else if ( !strcasecmp(sval,"directoryOperation") ) + at->at_usage = + LDAP_SCHEMA_DIRECTORY_OPERATION; + else if ( !strcasecmp(sval,"distributedOperation") ) + at->at_usage = + LDAP_SCHEMA_DISTRIBUTED_OPERATION; + else if ( !strcasecmp(sval,"dSAOperation") ) + at->at_usage = + LDAP_SCHEMA_DSA_OPERATION; + else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + LDAP_FREE(sval); + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_attributetype_free(at); + return NULL; + } + if ( add_extension(&at->at_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_attributetype_free(at); + return NULL; + } + } +} + +void +ldap_objectclass_free(LDAPObjectClass * oc) +{ + if (!oc) return; + LDAP_FREE(oc->oc_oid); + if (oc->oc_names) LDAP_VFREE(oc->oc_names); + if (oc->oc_desc) LDAP_FREE(oc->oc_desc); + if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); + if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); + if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); + free_extensions(oc->oc_extensions); + LDAP_FREE(oc); +} + +LDAPObjectClass * +ldap_str2objectclass( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_sup = 0; + int seen_kind = 0; + int seen_must = 0; + int seen_may = 0; + LDAPObjectClass * oc; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); + + if ( !oc ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + * However, this routine is used by clients to parse the response + * from servers and very well known servers will provide an OID + * in the wrong format or even no OID at all. We do our best to + * extract info from those servers. + */ + parse_whsp(&ss); + savepos = ss; + oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !oc->oc_oid ) { + if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "SUP") || + !strcasecmp(sval, "ABSTRACT") || + !strcasecmp(sval, "STRUCTURAL") || + !strcasecmp(sval, "AUXILIARY") || + !strcasecmp(sval, "MUST") || + !strcasecmp(sval, "MAY") || + !strncasecmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else if ( flags & + LDAP_SCHEMA_ALLOW_OID_MACRO ) { + /* Non-numerical OID, ignore */ + int len = ss-savepos; + oc->oc_oid = LDAP_MALLOC(len+1); + if ( !oc->oc_oid ) { + ldap_objectclass_free(oc); + return NULL; + } + + strncpy(oc->oc_oid, savepos, len); + oc->oc_oid[len] = 0; + } + } + LDAP_FREE(sval); + *code = 0; + } else { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_objectclass_free(oc); + return NULL; + case TK_RIGHTPAREN: + return oc; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_name = 1; + oc->oc_names = parse_qdescrs(&ss,code); + if ( !oc->oc_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + oc->oc_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_obsolete = 1; + oc->oc_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"SUP") ) { + LDAP_FREE(sval); + if ( seen_sup ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_sup = 1; + oc->oc_sup_oids = parse_oids(&ss, + code, + flags); + if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + *code = 0; + } else if ( !strcasecmp(sval,"ABSTRACT") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_ABSTRACT; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"STRUCTURAL") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"AUXILIARY") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_AUXILIARY; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MUST") ) { + LDAP_FREE(sval); + if ( seen_must ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_must = 1; + oc->oc_at_oids_must = parse_oids(&ss,code,0); + if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + *code = 0; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MAY") ) { + LDAP_FREE(sval); + if ( seen_may ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_may = 1; + oc->oc_at_oids_may = parse_oids(&ss,code,0); + if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + *code = 0; + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + *code = 0; + if ( !ext_vals ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + if ( add_extension(&oc->oc_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + } +} + +void +ldap_contentrule_free(LDAPContentRule * cr) +{ + if (!cr) return; + LDAP_FREE(cr->cr_oid); + if (cr->cr_names) LDAP_VFREE(cr->cr_names); + if (cr->cr_desc) LDAP_FREE(cr->cr_desc); + if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux); + if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must); + if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may); + if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not); + free_extensions(cr->cr_extensions); + LDAP_FREE(cr); +} + +LDAPContentRule * +ldap_str2contentrule( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_aux = 0; + int seen_must = 0; + int seen_may = 0; + int seen_not = 0; + LDAPContentRule * cr; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + cr = LDAP_CALLOC(1,sizeof(LDAPContentRule)); + + if ( !cr ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + */ + parse_whsp(&ss); + savepos = ss; + cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !cr->cr_oid ) { + if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "AUX") || + !strcasecmp(sval, "MUST") || + !strcasecmp(sval, "MAY") || + !strcasecmp(sval, "NOT") || + !strncasecmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else if ( flags & + LDAP_SCHEMA_ALLOW_OID_MACRO ) { + /* Non-numerical OID, ignore */ + int len = ss-savepos; + cr->cr_oid = LDAP_MALLOC(len+1); + if ( !cr->cr_oid ) { + ldap_contentrule_free(cr); + return NULL; + } + + strncpy(cr->cr_oid, savepos, len); + cr->cr_oid[len] = 0; + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_contentrule_free(cr); + return NULL; + case TK_RIGHTPAREN: + return cr; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_name = 1; + cr->cr_names = parse_qdescrs(&ss,code); + if ( !cr->cr_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + cr->cr_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_obsolete = 1; + cr->cr_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"AUX") ) { + LDAP_FREE(sval); + if ( seen_aux ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_aux = 1; + cr->cr_oc_oids_aux = parse_oids(&ss,code,0); + if ( !cr->cr_oc_oids_aux ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MUST") ) { + LDAP_FREE(sval); + if ( seen_must ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_must = 1; + cr->cr_at_oids_must = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MAY") ) { + LDAP_FREE(sval); + if ( seen_may ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_may = 1; + cr->cr_at_oids_may = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"NOT") ) { + LDAP_FREE(sval); + if ( seen_not ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_not = 1; + cr->cr_at_oids_not = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + if ( add_extension(&cr->cr_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + } +} + +void +ldap_structurerule_free(LDAPStructureRule * sr) +{ + if (!sr) return; + if (sr->sr_names) LDAP_VFREE(sr->sr_names); + if (sr->sr_desc) LDAP_FREE(sr->sr_desc); + if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform); + if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids); + free_extensions(sr->sr_extensions); + LDAP_FREE(sr); +} + +LDAPStructureRule * +ldap_str2structurerule( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + int ret; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_nameform = 0; + LDAPStructureRule * sr; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule)); + + if ( !sr ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_structurerule_free(sr); + return NULL; + } + + /* + * Definitions MUST begin with a ruleid. + */ + parse_whsp(&ss); + savepos = ss; + ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid); + if ( ret ) { + *errp = ss; + ldap_structurerule_free(sr); + return NULL; + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_structurerule_free(sr); + return NULL; + case TK_RIGHTPAREN: + if( !seen_nameform ) { + *code = LDAP_SCHERR_MISSING; + ldap_structurerule_free(sr); + return NULL; + } + return sr; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_structurerule_free(sr); + return(NULL); + } + seen_name = 1; + sr->sr_names = parse_qdescrs(&ss,code); + if ( !sr->sr_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_structurerule_free(sr); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_structurerule_free(sr); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_structurerule_free(sr); + return NULL; + } + sr->sr_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_structurerule_free(sr); + return(NULL); + } + seen_obsolete = 1; + sr->sr_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"FORM") ) { + LDAP_FREE(sval); + if ( seen_nameform ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_structurerule_free(sr); + return(NULL); + } + seen_nameform = 1; + sr->sr_nameform = parse_woid(&ss,code); + if ( !sr->sr_nameform ) { + *errp = ss; + ldap_structurerule_free(sr); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_structurerule_free(sr); + return NULL; + } + if ( add_extension(&sr->sr_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_structurerule_free(sr); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_structurerule_free(sr); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_structurerule_free(sr); + return NULL; + } + } +} + +void +ldap_nameform_free(LDAPNameForm * nf) +{ + if (!nf) return; + LDAP_FREE(nf->nf_oid); + if (nf->nf_names) LDAP_VFREE(nf->nf_names); + if (nf->nf_desc) LDAP_FREE(nf->nf_desc); + if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass); + if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must); + if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may); + free_extensions(nf->nf_extensions); + LDAP_FREE(nf); +} + +LDAPNameForm * +ldap_str2nameform( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST unsigned flags ) +{ + tk_t kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_class = 0; + int seen_must = 0; + int seen_may = 0; + LDAPNameForm * nf; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + nf = LDAP_CALLOC(1,sizeof(LDAPNameForm)); + + if ( !nf ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_nameform_free(nf); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + * However, this routine is used by clients to parse the response + * from servers and very well known servers will provide an OID + * in the wrong format or even no OID at all. We do our best to + * extract info from those servers. + */ + parse_whsp(&ss); + savepos = ss; + nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !nf->nf_oid ) { + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = EndOfInput; + ldap_nameform_free(nf); + return NULL; + case TK_RIGHTPAREN: + if( !seen_class || !seen_must ) { + *code = LDAP_SCHERR_MISSING; + ldap_nameform_free(nf); + return NULL; + } + return nf; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_name = 1; + nf->nf_names = parse_qdescrs(&ss,code); + if ( !nf->nf_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_nameform_free(nf); + return NULL; + } + nf->nf_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_obsolete = 1; + nf->nf_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OC") ) { + LDAP_FREE(sval); + if ( seen_class ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_class = 1; + nf->nf_objectclass = parse_woid(&ss,code); + if ( !nf->nf_objectclass ) { + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + } else if ( !strcasecmp(sval,"MUST") ) { + LDAP_FREE(sval); + if ( seen_must ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_must = 1; + nf->nf_at_oids_must = parse_oids(&ss,code,0); + if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MAY") ) { + LDAP_FREE(sval); + if ( seen_may ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_nameform_free(nf); + return(NULL); + } + seen_may = 1; + nf->nf_at_oids_may = parse_oids(&ss,code,0); + if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) { + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_nameform_free(nf); + return NULL; + } + if ( add_extension(&nf->nf_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_nameform_free(nf); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_nameform_free(nf); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_nameform_free(nf); + return NULL; + } + } +} + +static char *const err2text[] = { + N_("Success"), + N_("Out of memory"), + N_("Unexpected token"), + N_("Missing opening parenthesis"), + N_("Missing closing parenthesis"), + N_("Expecting digit"), + N_("Expecting a name"), + N_("Bad description"), + N_("Bad superiors"), + N_("Duplicate option"), + N_("Unexpected end of data"), + N_("Missing required field"), + N_("Out of order field") +}; + +char * +ldap_scherr2str(int code) +{ + if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) { + return _("Unknown error"); + } else { + return _(err2text[code]); + } +} diff --git a/libs/ldap/libldap/search.c b/libs/ldap/libldap/search.c new file mode 100644 index 00000000000..09f2c14ea48 --- /dev/null +++ b/libs/ldap/libldap/search.c @@ -0,0 +1,544 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" +#include "ldap_log.h" + +/* + * ldap_search_ext - initiate an ldap search operation. + * + * Parameters: + * + * ld LDAP descriptor + * base DN of the base object + * scope the search scope - one of + * LDAP_SCOPE_BASE (baseObject), + * LDAP_SCOPE_ONELEVEL (oneLevel), + * LDAP_SCOPE_SUBTREE (subtree), or + * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension + * 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 }; + * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", + * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, + * &msgid ); + */ +int +ldap_search_ext( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + int *msgidp ) +{ + return ldap_pvt_search( ld, base, scope, filter, attrs, + attrsonly, sctrls, cctrls, timeout, sizelimit, -1, msgidp ); +} + +int +ldap_pvt_search( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + int deref, + int *msgidp ) +{ + int rc; + BerElement *ber; + int timelimit; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_search_ext\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + /* + * if timeout is provided, both tv_sec and tv_usec must + * not be zero + */ + if( timeout != NULL ) { + if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) { + return LDAP_PARAM_ERROR; + } + + /* timelimit must be non-zero if timeout is provided */ + timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1; + + } else { + /* no timeout, no timelimit */ + timelimit = -1; + } + + ber = ldap_build_search_req( ld, base, scope, filter, attrs, + attrsonly, sctrls, cctrls, timelimit, sizelimit, deref, &id ); + + if ( ber == NULL ) { + return ld->ld_errno; + } + + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ); + + if( *msgidp < 0 ) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + +int +ldap_search_ext_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + LDAPMessage **res ) +{ + return ldap_pvt_search_s( ld, base, scope, filter, attrs, + attrsonly, sctrls, cctrls, timeout, sizelimit, -1, res ); +} + +int +ldap_pvt_search_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + int deref, + LDAPMessage **res ) +{ + int rc; + int msgid; + + *res = NULL; + + rc = ldap_pvt_search( ld, base, scope, filter, attrs, attrsonly, + sctrls, cctrls, timeout, sizelimit, deref, &msgid ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ); + + if( rc <= 0 ) { + /* error(-1) or timeout(0) */ + if ( ld->ld_errno == LDAP_TIMEOUT ) { + /* cleanup request */ + (void) ldap_abandon( ld, msgid ); + ld->ld_errno = LDAP_TIMEOUT; + } + return( ld->ld_errno ); + } + + if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) { + return( ld->ld_errno ); + } + + return( ldap_result2error( ld, *res, 0 ) ); +} + +/* + * 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 (baseObject), + * LDAP_SCOPE_ONELEVEL (oneLevel), + * LDAP_SCOPE_SUBTREE (subtree), or + * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension + * 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, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", + * attrs, attrsonly ); + */ +int +ldap_search( + LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, + char **attrs, int attrsonly ) +{ + BerElement *ber; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_search\n" ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + ber = ldap_build_search_req( ld, base, scope, filter, attrs, + attrsonly, NULL, NULL, -1, -1, -1, &id ); + + if ( ber == NULL ) { + return( -1 ); + } + + + /* send the message */ + return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id )); +} + + +BerElement * +ldap_build_search_req( + LDAP *ld, + LDAP_CONST char *base, + ber_int_t scope, + LDAP_CONST char *filter, + char **attrs, + ber_int_t attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t timelimit, + ber_int_t sizelimit, + ber_int_t deref, + ber_int_t *idp) +{ + BerElement *ber; + int err; + + /* + * 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 ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + if ( base == NULL ) { + /* no base provided, use session default base */ + base = ld->ld_options.ldo_defbase; + + if ( base == NULL ) { + /* no session default base, use top */ + base = ""; + } + } + + LDAP_NEXT_MSGID( ld, *idp ); +#ifdef LDAP_CONNECTIONLESS + if ( LDAP_IS_UDP(ld) ) { + struct sockaddr_storage sa = {0}; + /* dummy, filled with ldo_peer in request.c */ + err = ber_write( ber, (char *) &sa, sizeof( sa ), 0 ); + } + if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) { + char *dn = ld->ld_options.ldo_cldapdn; + if (!dn) dn = ""; + err = ber_printf( ber, "{ist{seeiib", *idp, dn, + LDAP_REQ_SEARCH, base, (ber_int_t) scope, + (deref < 0) ? ld->ld_deref : deref, + (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, + (timelimit < 0) ? ld->ld_timelimit : timelimit, + attrsonly ); + } else +#endif + { + err = ber_printf( ber, "{it{seeiib", *idp, + LDAP_REQ_SEARCH, base, (ber_int_t) scope, + (deref < 0) ? ld->ld_deref : deref, + (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, + (timelimit < 0) ? ld->ld_timelimit : timelimit, + attrsonly ); + } + + if ( err == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + if( filter == NULL ) { + filter = "(objectclass=*)"; + } + + err = ldap_pvt_put_filter( ber, filter ); + + if ( err == -1 ) { + ld->ld_errno = LDAP_FILTER_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + +#ifdef LDAP_DEBUG + if ( ldap_debug & LDAP_DEBUG_ARGS ) { + char buf[ BUFSIZ ], *ptr = " *"; + + if ( attrs != NULL ) { + int i, len, rest = sizeof( buf ); + + for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) { + ptr = &buf[ sizeof( buf ) - rest ]; + len = snprintf( ptr, rest, " %s", attrs[ i ] ); + rest -= (len >= 0 ? len : (int) sizeof( buf )); + } + + if ( rest <= 0 ) { + AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ], + "...(truncated)", STRLENOF( "...(truncated)" ) + 1 ); + } + ptr = buf; + } + + Debug1( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr ); + } +#endif /* LDAP_DEBUG */ + + if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); + } + + return( ber ); +} + +int +ldap_search_st( + LDAP *ld, LDAP_CONST char *base, int scope, + LDAP_CONST char *filter, char **attrs, + int attrsonly, struct timeval *timeout, LDAPMessage **res ) +{ + int msgid; + + *res = NULL; + + if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) + == -1 ) + return( ld->ld_errno ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ) == -1 || !*res ) + return( ld->ld_errno ); + + if ( ld->ld_errno == LDAP_TIMEOUT ) { + (void) ldap_abandon( ld, msgid ); + ld->ld_errno = LDAP_TIMEOUT; + return( ld->ld_errno ); + } + + return( ldap_result2error( ld, *res, 0 ) ); +} + +int +ldap_search_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res ) +{ + int msgid; + + *res = NULL; + + if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) + == -1 ) + return( ld->ld_errno ); + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, res ) == -1 || !*res ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, *res, 0 ) ); +} + +static char escape[128] = { + 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, + 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, 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, 1 +}; +#define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ]) + +/* + * compute the length of the escaped value + */ +ber_len_t +ldap_bv2escaped_filter_value_len( struct berval *in ) +{ + ber_len_t i, l; + + assert( in != NULL ); + + if ( in->bv_len == 0 ) { + return 0; + } + + for( l = 0, i = 0; i < in->bv_len; l++, i++ ) { + char c = in->bv_val[ i ]; + if ( NEEDFLTESCAPE( c ) ) { + l += 2; + } + } + + return l; +} + +int +ldap_bv2escaped_filter_value( struct berval *in, struct berval *out ) +{ + return ldap_bv2escaped_filter_value_x( in, out, 0, NULL ); +} + +int +ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx ) +{ + ber_len_t i, l; + + assert( in != NULL ); + assert( out != NULL ); + + BER_BVZERO( out ); + + if ( in->bv_len == 0 ) { + return 0; + } + + /* assume we'll escape everything */ + l = ldap_bv2escaped_filter_value_len( in ); + if ( l == in->bv_len ) { + if ( inplace ) { + *out = *in; + } else { + ber_dupbv( out, in ); + } + return 0; + } + out->bv_val = LDAP_MALLOCX( l + 1, ctx ); + if ( out->bv_val == NULL ) { + return -1; + } + + for ( i = 0; i < in->bv_len; i++ ) { + char c = in->bv_val[ i ]; + if ( NEEDFLTESCAPE( c ) ) { + assert( out->bv_len < l - 2 ); + out->bv_val[out->bv_len++] = '\'; + out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)]; + out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c]; + + } else { + assert( out->bv_len < l ); + out->bv_val[out->bv_len++] = c; + } + } + + out->bv_val[out->bv_len] = '\0'; + + return 0; +} diff --git a/libs/ldap/libldap/sortctrl.c b/libs/ldap/libldap/sortctrl.c new file mode 100644 index 00000000000..fee693d01bc --- /dev/null +++ b/libs/ldap/libldap/sortctrl.c @@ -0,0 +1,552 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND + * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT + * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS + * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" + * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION + * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP + * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT + * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ +/* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +#define LDAP_MATCHRULE_IDENTIFIER 0x80L +#define LDAP_REVERSEORDER_IDENTIFIER 0x81L +#define LDAP_ATTRTYPES_IDENTIFIER 0x80L + + + +/* --------------------------------------------------------------------------- + countKeys + + Internal function to determine the number of keys in the string. + + keyString (IN) String of items separated by whitespace. + ---------------------------------------------------------------------------*/ + +static int countKeys(char *keyString) +{ + char *p = keyString; + int count = 0; + + for (;;) + { + while (LDAP_SPACE(*p)) /* Skip leading whitespace */ + p++; + + if (*p == '\0') /* End of string? */ + return count; + + count++; /* Found start of a key */ + + while (!LDAP_SPACE(*p)) /* Skip till next space or end of string. */ + if (*p++ == '\0') + return count; + } +} + + +/* --------------------------------------------------------------------------- + readNextKey + + Internal function to parse the next sort key in the string. + Allocate an LDAPSortKey structure and initialize it with + attribute name, reverse flag, and matching rule OID. + + Each sort key in the string has the format: + [whitespace][-]attribute[:[OID]] + + pNextKey (IN/OUT) Points to the next key in the sortkey string to parse. + The pointer is updated to point to the next character + after the sortkey being parsed. + + key (OUT) Points to the address of an LDAPSortKey structure + which has been allocated by this routine and + initialized with information from the next sortkey. + ---------------------------------------------------------------------------*/ + +static int readNextKey( char **pNextKey, LDAPSortKey **key) +{ + char *p = *pNextKey; + int rev = 0; + char *attrStart; + int attrLen; + char *oidStart = NULL; + int oidLen = 0; + + /* Skip leading white space. */ + while (LDAP_SPACE(*p)) + p++; + + if (*p == '-') /* Check if the reverse flag is present. */ + { + rev=1; + p++; + } + + /* We're now positioned at the start of the attribute. */ + attrStart = p; + + /* Get the length of the attribute until the next whitespace or ":". */ + attrLen = strcspn(p, " \t:"); + p += attrLen; + + if (attrLen == 0) /* If no attribute name was present, quit. */ + return LDAP_PARAM_ERROR; + + if (*p == ':') + { + oidStart = ++p; /* Start of the OID, after the colon */ + oidLen = strcspn(p, " \t"); /* Get length of OID till next whitespace */ + p += oidLen; + } + + *pNextKey = p; /* Update argument to point to next key */ + + /* Allocate an LDAPSortKey structure */ + *key = LDAP_MALLOC(sizeof(LDAPSortKey)); + if (*key == NULL) return LDAP_NO_MEMORY; + + /* Allocate memory for the attribute and copy to it. */ + (*key)->attributeType = LDAP_MALLOC(attrLen+1); + if ((*key)->attributeType == NULL) { + LDAP_FREE(*key); + return LDAP_NO_MEMORY; + } + + strncpy((*key)->attributeType, attrStart, attrLen); + (*key)->attributeType[attrLen] = 0; + + /* If present, allocate memory for the OID and copy to it. */ + if (oidLen) { + (*key)->orderingRule = LDAP_MALLOC(oidLen+1); + if ((*key)->orderingRule == NULL) { + LDAP_FREE((*key)->attributeType); + LDAP_FREE(*key); + return LDAP_NO_MEMORY; + } + strncpy((*key)->orderingRule, oidStart, oidLen); + (*key)->orderingRule[oidLen] = 0; + + } else { + (*key)->orderingRule = NULL; + } + + (*key)->reverseOrder = rev; + + return LDAP_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + ldap_create_sort_keylist + + Create an array of pointers to LDAPSortKey structures, containing the + information specified by the string representation of one or more + sort keys. + + sortKeyList (OUT) Points to a null-terminated array of pointers to + LDAPSortKey structures allocated by this routine. + This memory SHOULD be freed by the calling program + using ldap_free_sort_keylist(). + + keyString (IN) Points to a string of one or more sort keys. + + ---------------------------------------------------------------------------*/ + +int +ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString ) +{ + int numKeys, rc, i; + char *nextKey; + LDAPSortKey **keyList = NULL; + + assert( sortKeyList != NULL ); + assert( keyString != NULL ); + + *sortKeyList = NULL; + + /* Determine the number of sort keys so we can allocate memory. */ + if (( numKeys = countKeys(keyString)) == 0) { + return LDAP_PARAM_ERROR; + } + + /* Allocate the array of pointers. Initialize to NULL. */ + keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*)); + if ( keyList == NULL) return LDAP_NO_MEMORY; + + /* For each sort key in the string, create an LDAPSortKey structure + and add it to the list. + */ + nextKey = keyString; /* Points to the next key in the string */ + for (i=0; i < numKeys; i++) { + rc = readNextKey(&nextKey, &keyList[i]); + + if (rc != LDAP_SUCCESS) { + ldap_free_sort_keylist(keyList); + return rc; + } + } + + *sortKeyList = keyList; + return LDAP_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + ldap_free_sort_keylist + + Frees the sort key structures created by ldap_create_sort_keylist(). + Frees the memory referenced by the LDAPSortKey structures, + the LDAPSortKey structures themselves, and the array of pointers + to the structures. + + keyList (IN) Points to an array of pointers to LDAPSortKey structures. + ---------------------------------------------------------------------------*/ + +void +ldap_free_sort_keylist ( LDAPSortKey **keyList ) +{ + int i; + LDAPSortKey *nextKeyp; + + if (keyList == NULL) return; + + i=0; + while ( 0 != (nextKeyp = keyList[i++]) ) { + if (nextKeyp->attributeType) { + LBER_FREE(nextKeyp->attributeType); + } + + if (nextKeyp->orderingRule != NULL) { + LBER_FREE(nextKeyp->orderingRule); + } + + LBER_FREE(nextKeyp); + } + + LBER_FREE(keyList); +} + + +/* --------------------------------------------------------------------------- + ldap_create_sort_control_value + + Create and encode the value of the server-side sort control. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + keyList (IN) Points to a null-terminated array of pointers to + LDAPSortKey structures, containing a description of + each of the sort keys to be used. The description + consists of an attribute name, ascending/descending flag, + and an optional matching rule (OID) to use. + + value (OUT) Contains the control value; the bv_val member of the berval structure + SHOULD be freed by calling ldap_memfree() when done. + + + Ber encoding + + SortKeyList ::= SEQUENCE OF SEQUENCE { + attributeType AttributeDescription, + orderingRule [0] MatchingRuleId OPTIONAL, + reverseOrder [1] BOOLEAN DEFAULT FALSE } + + ---------------------------------------------------------------------------*/ + +int +ldap_create_sort_control_value( + LDAP *ld, + LDAPSortKey **keyList, + struct berval *value ) +{ + int i; + BerElement *ber = NULL; + ber_tag_t tag; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + if ( ld == NULL ) return LDAP_PARAM_ERROR; + if ( keyList == NULL || value == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return LDAP_PARAM_ERROR; + } + + value->bv_val = NULL; + value->bv_len = 0; + ld->ld_errno = LDAP_SUCCESS; + + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_printf( ber, "{" /*}*/ ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + for ( i = 0; keyList[i] != NULL; i++ ) { + tag = ber_printf( ber, "{s" /*}*/, keyList[i]->attributeType ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + if ( keyList[i]->orderingRule != NULL ) { + tag = ber_printf( ber, "ts", + LDAP_MATCHRULE_IDENTIFIER, + keyList[i]->orderingRule ); + + if ( tag == LBER_ERROR ) { + goto error_return; + } + } + + if ( keyList[i]->reverseOrder ) { + tag = ber_printf( ber, "tb", + LDAP_REVERSEORDER_IDENTIFIER, + keyList[i]->reverseOrder ); + + if ( tag == LBER_ERROR ) { + goto error_return; + } + } + + tag = ber_printf( ber, /*{*/ "N}" ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + } + + tag = ber_printf( ber, /*{*/ "N}" ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + if ( ber_flatten2( ber, value, 1 ) == -1 ) { + ld->ld_errno = LDAP_NO_MEMORY; + } + + if ( 0 ) { +error_return:; + ld->ld_errno = LDAP_ENCODING_ERROR; + } + + if ( ber != NULL ) { + ber_free( ber, 1 ); + } + + return ld->ld_errno; +} + + +/* --------------------------------------------------------------------------- + ldap_create_sort_control + + Create and encode the server-side sort control. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + keyList (IN) Points to a null-terminated array of pointers to + LDAPSortKey structures, containing a description of + each of the sort keys to be used. The description + consists of an attribute name, ascending/descending flag, + and an optional matching rule (OID) to use. + + isCritical (IN) 0 - Indicates the control is not critical to the operation. + non-zero - The control is critical to the operation. + + ctrlp (OUT) Returns a pointer to the LDAPControl created. This control + SHOULD be freed by calling ldap_control_free() when done. + + + Ber encoding + + SortKeyList ::= SEQUENCE OF SEQUENCE { + attributeType AttributeDescription, + orderingRule [0] MatchingRuleId OPTIONAL, + reverseOrder [1] BOOLEAN DEFAULT FALSE } + + ---------------------------------------------------------------------------*/ + +int +ldap_create_sort_control( + LDAP *ld, + LDAPSortKey **keyList, + int isCritical, + LDAPControl **ctrlp ) +{ + struct berval value; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + if ( ld == NULL ) { + return LDAP_PARAM_ERROR; + } + + if ( ctrlp == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST, + isCritical, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { + LDAP_FREE( value.bv_val ); + } + } + + return ld->ld_errno; +} + + +/* --------------------------------------------------------------------------- + ldap_parse_sortedresult_control + + Decode the server-side sort control return information. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + ctrl (IN) The address of the LDAP Control Structure. + + returnCode (OUT) This result parameter is filled in with the sort control + result code. This parameter MUST not be NULL. + + attribute (OUT) If an error occurred the server may return a string + indicating the first attribute in the sortkey list + that was in error. If a string is returned, the memory + should be freed with ldap_memfree. If this parameter is + NULL, no string is returned. + + + Ber encoding for sort control + + SortResult ::= SEQUENCE { + sortResult ENUMERATED { + success (0), -- results are sorted + operationsError (1), -- server internal failure + timeLimitExceeded (3), -- timelimit reached before + -- sorting was completed + strongAuthRequired (8), -- refused to return sorted + -- results via insecure + -- protocol + adminLimitExceeded (11), -- too many matching entries + -- for the server to sort + noSuchAttribute (16), -- unrecognized attribute + -- type in sort key + inappropriateMatching (18), -- unrecognized or inappro- + -- priate matching rule in + -- sort key + insufficientAccessRights (50), -- refused to return sorted + -- results to this client + busy (51), -- too busy to process + unwillingToPerform (53), -- unable to sort + other (80) + }, + attributeType [0] AttributeDescription OPTIONAL } + ---------------------------------------------------------------------------*/ + +int +ldap_parse_sortresponse_control( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *returnCode, + char **attribute ) +{ + BerElement *ber; + ber_tag_t tag, berTag; + ber_len_t berLen; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + if (ld == NULL) { + return LDAP_PARAM_ERROR; + } + + if (ctrl == NULL) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if (attribute) { + *attribute = NULL; + } + + if ( strcmp(LDAP_CONTROL_SORTRESPONSE, ctrl->ldctl_oid) != 0 ) { + /* Not sort result control */ + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + } + + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init(&ctrl->ldctl_value); + + if (ber == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return(ld->ld_errno); + } + + /* Extract the result code from the control. */ + tag = ber_scanf(ber, "{e" /*}*/, returnCode); + + if( tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + + /* If caller wants the attribute name, and if it's present in the control, + extract the attribute name which caused the error. */ + if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen))) + { + tag = ber_scanf(ber, "ta", &berTag, attribute); + + if (tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + } + + ber_free(ber,1); + + ld->ld_errno = LDAP_SUCCESS; + return(ld->ld_errno); +} diff --git a/libs/ldap/libldap/string.c b/libs/ldap/libldap/string.c new file mode 100644 index 00000000000..fa3f6f0b3ee --- /dev/null +++ b/libs/ldap/libldap/string.c @@ -0,0 +1,177 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +/* + * Locale-specific 1-byte character versions + * See utf-8.c for UTF-8 versions + */ + +#include "portable.h" + +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/ctype.h> + +#include "ldap-int.h" + + +#if defined ( HAVE_STRSPN ) +#define int_strspn strspn +#else +static int int_strspn( const char *str, const char *delim ) +{ + int pos; + const char *p=delim; + + for( pos=0; (*str) ; pos++,str++) { + if (*str!=*p) { + for( p=delim; (*p) ; p++ ) { + if (*str==*p) { + break; + } + } + } + + if (*p=='\0') { + return pos; + } + } + return pos; +} +#endif + +#if defined( HAVE_STRPBRK ) +#define int_strpbrk strpbrk +#else +static char *(int_strpbrk)( const char *str, const char *accept ) +{ + const char *p; + + for( ; (*str) ; str++ ) { + for( p=accept; (*p) ; p++) { + if (*str==*p) { + return str; + } + } + } + + return NULL; +} +#endif + +char *(ldap_pvt_strtok)( char *str, const char *delim, char **pos ) +{ + char *p; + + if (pos==NULL) { + return NULL; + } + + if (str==NULL) { + if (*pos==NULL) { + return NULL; + } + + str=*pos; + } + + /* skip any initial delimiters */ + str += int_strspn( str, delim ); + if (*str == '\0') { + return NULL; + } + + p = int_strpbrk( str, delim ); + if (p==NULL) { + *pos = NULL; + + } else { + *p ='\0'; + *pos = p+1; + } + + return str; +} + +char * +ldap_pvt_str2upper( char *str ) +{ + char *s; + + /* to upper */ + if ( str ) { + for ( s = str; *s; s++ ) { + *s = TOUPPER( (unsigned char) *s ); + } + } + + return( str ); +} + +struct berval * +ldap_pvt_str2upperbv( char *str, struct berval *bv ) +{ + char *s = NULL; + + assert( bv != NULL ); + + /* to upper */ + if ( str ) { + for ( s = str; *s; s++ ) { + *s = TOUPPER( (unsigned char) *s ); + } + } + + bv->bv_val = str; + bv->bv_len = (ber_len_t)(s - str); + + return( bv ); +} + +char * +ldap_pvt_str2lower( char *str ) +{ + char *s; + + /* to lower */ + if ( str ) { + for ( s = str; *s; s++ ) { + *s = TOLOWER( (unsigned char) *s ); + } + } + + return( str ); +} + +struct berval * +ldap_pvt_str2lowerbv( char *str, struct berval *bv ) +{ + char *s = NULL; + + assert( bv != NULL ); + + /* to lower */ + if ( str ) { + for ( s = str; *s; s++ ) { + *s = TOLOWER( (unsigned char) *s ); + } + } + + bv->bv_val = str; + bv->bv_len = (ber_len_t)(s - str); + + return( bv ); +} diff --git a/libs/ldap/libldap/tavl.c b/libs/ldap/libldap/tavl.c new file mode 100644 index 00000000000..e87729667fc --- /dev/null +++ b/libs/ldap/libldap/tavl.c @@ -0,0 +1,523 @@ +/* avl.c - routines to implement an avl tree */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2005-2022 The OpenLDAP Foundation. + * Portions Copyright (c) 2005 by Howard Chu, Symas Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Howard Chu for inclusion + * in OpenLDAP software. + */ + +#include "portable.h" + +#include <limits.h> +#include <stdio.h> +#include <ac/stdlib.h> + +#ifdef CSRIMALLOC +#define ber_memalloc malloc +#define ber_memrealloc realloc +#define ber_memfree free +#else +#include "lber.h" +#endif + +#define AVL_INTERNAL +#include "ldap_avl.h" + +/* Maximum tree depth this host's address space could support */ +#define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT) + +static const int avl_bfs[] = {LH, RH}; + +/* + * Threaded AVL trees - for fast in-order traversal of nodes. + */ +/* + * ldap_tavl_insert -- insert a node containing data data into the avl tree + * with root root. fcmp is a function to call to compare the data portion + * of two nodes. it should take two arguments and return <, >, or == 0, + * depending on whether its first argument is <, >, or == its second + * argument (like strcmp, e.g.). fdup is a function to call when a duplicate + * node is inserted. it should return 0, or -1 and its return value + * will be the return value from ldap_avl_insert in the case of a duplicate node. + * the function will be called with the original node's data as its first + * argument and with the incoming duplicate node's data as its second + * argument. this could be used, for example, to keep a count with each + * node. + * + * NOTE: this routine may malloc memory + */ +int +ldap_tavl_insert( TAvlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup ) +{ + TAvlnode *t, *p, *s, *q, *r; + int a, cmp, ncmp; + + if ( *root == NULL ) { + if (( r = (TAvlnode *) ber_memalloc( sizeof( TAvlnode ))) == NULL ) { + return( -1 ); + } + r->avl_link[0] = r->avl_link[1] = NULL; + r->avl_data = data; + r->avl_bf = EH; + r->avl_bits[0] = r->avl_bits[1] = AVL_THREAD; + *root = r; + + return( 0 ); + } + + t = NULL; + s = p = *root; + + /* find insertion point */ + while (1) { + cmp = fcmp( data, p->avl_data ); + if ( cmp == 0 ) + return (*fdup)( p->avl_data, data ); + + cmp = (cmp > 0); + q = ldap_avl_child( p, cmp ); + if (q == NULL) { + /* insert */ + if (( q = (TAvlnode *) ber_memalloc( sizeof( TAvlnode ))) == NULL ) { + return( -1 ); + } + q->avl_link[cmp] = p->avl_link[cmp]; + q->avl_link[!cmp] = p; + q->avl_data = data; + q->avl_bf = EH; + q->avl_bits[0] = q->avl_bits[1] = AVL_THREAD; + + p->avl_link[cmp] = q; + p->avl_bits[cmp] = AVL_CHILD; + break; + } else if ( q->avl_bf ) { + t = p; + s = q; + } + p = q; + } + + /* adjust balance factors */ + cmp = fcmp( data, s->avl_data ) > 0; + r = p = s->avl_link[cmp]; + a = avl_bfs[cmp]; + + while ( p != q ) { + cmp = fcmp( data, p->avl_data ) > 0; + p->avl_bf = avl_bfs[cmp]; + p = p->avl_link[cmp]; + } + + /* checks and balances */ + + if ( s->avl_bf == EH ) { + s->avl_bf = a; + return 0; + } else if ( s->avl_bf == -a ) { + s->avl_bf = EH; + return 0; + } else if ( s->avl_bf == a ) { + cmp = (a > 0); + ncmp = !cmp; + if ( r->avl_bf == a ) { + /* single rotation */ + p = r; + if ( r->avl_bits[ncmp] == AVL_THREAD ) { + r->avl_bits[ncmp] = AVL_CHILD; + s->avl_bits[cmp] = AVL_THREAD; + } else { + s->avl_link[cmp] = r->avl_link[ncmp]; + r->avl_link[ncmp] = s; + } + s->avl_bf = 0; + r->avl_bf = 0; + } else if ( r->avl_bf == -a ) { + /* double rotation */ + p = r->avl_link[ncmp]; + if ( p->avl_bits[cmp] == AVL_THREAD ) { + p->avl_bits[cmp] = AVL_CHILD; + r->avl_bits[ncmp] = AVL_THREAD; + } else { + r->avl_link[ncmp] = p->avl_link[cmp]; + p->avl_link[cmp] = r; + } + if ( p->avl_bits[ncmp] == AVL_THREAD ) { + p->avl_bits[ncmp] = AVL_CHILD; + s->avl_link[cmp] = p; + s->avl_bits[cmp] = AVL_THREAD; + } else { + s->avl_link[cmp] = p->avl_link[ncmp]; + p->avl_link[ncmp] = s; + } + if ( p->avl_bf == a ) { + s->avl_bf = -a; + r->avl_bf = 0; + } else if ( p->avl_bf == -a ) { + s->avl_bf = 0; + r->avl_bf = a; + } else { + s->avl_bf = 0; + r->avl_bf = 0; + } + p->avl_bf = 0; + } + /* Update parent */ + if ( t == NULL ) + *root = p; + else if ( s == t->avl_right ) + t->avl_right = p; + else + t->avl_left = p; + } + + return 0; +} + +void* +ldap_tavl_delete( TAvlnode **root, void* data, AVL_CMP fcmp ) +{ + TAvlnode *p, *q, *r, *top; + int side, side_bf, shorter, nside = -1; + + /* parent stack */ + TAvlnode *pptr[MAX_TREE_DEPTH]; + unsigned char pdir[MAX_TREE_DEPTH]; + int depth = 0; + + if ( *root == NULL ) + return NULL; + + p = *root; + + while (1) { + side = fcmp( data, p->avl_data ); + if ( !side ) + break; + side = ( side > 0 ); + pdir[depth] = side; + pptr[depth++] = p; + + if ( p->avl_bits[side] == AVL_THREAD ) + return NULL; + p = p->avl_link[side]; + } + data = p->avl_data; + + /* If this node has two children, swap so we are deleting a node with + * at most one child. + */ + if ( p->avl_bits[0] == AVL_CHILD && p->avl_bits[1] == AVL_CHILD && + p->avl_link[0] && p->avl_link[1] ) { + + /* find the immediate predecessor <q> */ + q = p->avl_link[0]; + side = depth; + pdir[depth++] = 0; + while (q->avl_bits[1] == AVL_CHILD && q->avl_link[1]) { + pdir[depth] = 1; + pptr[depth++] = q; + q = q->avl_link[1]; + } + /* swap links */ + r = p->avl_link[0]; + p->avl_link[0] = q->avl_link[0]; + q->avl_link[0] = r; + + q->avl_link[1] = p->avl_link[1]; + p->avl_link[1] = q; + + p->avl_bits[0] = q->avl_bits[0]; + p->avl_bits[1] = q->avl_bits[1]; + q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD; + + q->avl_bf = p->avl_bf; + + /* fix stack positions: old parent of p points to q */ + pptr[side] = q; + if ( side ) { + r = pptr[side-1]; + r->avl_link[pdir[side-1]] = q; + } else { + *root = q; + } + /* new parent of p points to p */ + if ( depth-side > 1 ) { + r = pptr[depth-1]; + r->avl_link[1] = p; + } else { + q->avl_link[0] = p; + } + + /* fix right subtree: successor of p points to q */ + r = q->avl_link[1]; + while ( r->avl_bits[0] == AVL_CHILD && r->avl_link[0] ) + r = r->avl_link[0]; + r->avl_link[0] = q; + } + + /* now <p> has at most one child, get it */ + if ( p->avl_link[0] && p->avl_bits[0] == AVL_CHILD ) { + q = p->avl_link[0]; + /* Preserve thread continuity */ + r = p->avl_link[1]; + nside = 1; + } else if ( p->avl_link[1] && p->avl_bits[1] == AVL_CHILD ) { + q = p->avl_link[1]; + r = p->avl_link[0]; + nside = 0; + } else { + q = NULL; + if ( depth > 0 ) + r = p->avl_link[pdir[depth-1]]; + else + r = NULL; + } + + ber_memfree( p ); + + /* Update child thread */ + if ( q ) { + for ( ; q->avl_bits[nside] == AVL_CHILD && q->avl_link[nside]; + q = q->avl_link[nside] ) ; + q->avl_link[nside] = r; + } + + if ( !depth ) { + *root = q; + return data; + } + + /* set the child into p's parent */ + depth--; + p = pptr[depth]; + side = pdir[depth]; + p->avl_link[side] = q; + + if ( !q ) { + p->avl_bits[side] = AVL_THREAD; + p->avl_link[side] = r; + } + + top = NULL; + shorter = 1; + + while ( shorter ) { + p = pptr[depth]; + side = pdir[depth]; + nside = !side; + side_bf = avl_bfs[side]; + + /* case 1: height unchanged */ + if ( p->avl_bf == EH ) { + /* Tree is now heavier on opposite side */ + p->avl_bf = avl_bfs[nside]; + shorter = 0; + + } else if ( p->avl_bf == side_bf ) { + /* case 2: taller subtree shortened, height reduced */ + p->avl_bf = EH; + } else { + /* case 3: shorter subtree shortened */ + if ( depth ) + top = pptr[depth-1]; /* p->parent; */ + else + top = NULL; + /* set <q> to the taller of the two subtrees of <p> */ + q = p->avl_link[nside]; + if ( q->avl_bf == EH ) { + /* case 3a: height unchanged, single rotate */ + if ( q->avl_bits[side] == AVL_THREAD ) { + q->avl_bits[side] = AVL_CHILD; + p->avl_bits[nside] = AVL_THREAD; + } else { + p->avl_link[nside] = q->avl_link[side]; + q->avl_link[side] = p; + } + shorter = 0; + q->avl_bf = side_bf; + p->avl_bf = (- side_bf); + + } else if ( q->avl_bf == p->avl_bf ) { + /* case 3b: height reduced, single rotate */ + if ( q->avl_bits[side] == AVL_THREAD ) { + q->avl_bits[side] = AVL_CHILD; + p->avl_bits[nside] = AVL_THREAD; + } else { + p->avl_link[nside] = q->avl_link[side]; + q->avl_link[side] = p; + } + shorter = 1; + q->avl_bf = EH; + p->avl_bf = EH; + + } else { + /* case 3c: height reduced, balance factors opposite */ + r = q->avl_link[side]; + if ( r->avl_bits[nside] == AVL_THREAD ) { + r->avl_bits[nside] = AVL_CHILD; + q->avl_bits[side] = AVL_THREAD; + } else { + q->avl_link[side] = r->avl_link[nside]; + r->avl_link[nside] = q; + } + + if ( r->avl_bits[side] == AVL_THREAD ) { + r->avl_bits[side] = AVL_CHILD; + p->avl_bits[nside] = AVL_THREAD; + p->avl_link[nside] = r; + } else { + p->avl_link[nside] = r->avl_link[side]; + r->avl_link[side] = p; + } + + if ( r->avl_bf == side_bf ) { + q->avl_bf = (- side_bf); + p->avl_bf = EH; + } else if ( r->avl_bf == (- side_bf)) { + q->avl_bf = EH; + p->avl_bf = side_bf; + } else { + q->avl_bf = EH; + p->avl_bf = EH; + } + r->avl_bf = EH; + q = r; + } + /* a rotation has caused <q> (or <r> in case 3c) to become + * the root. let <p>'s former parent know this. + */ + if ( top == NULL ) { + *root = q; + } else if (top->avl_link[0] == p) { + top->avl_link[0] = q; + } else { + top->avl_link[1] = q; + } + /* end case 3 */ + p = q; + } + if ( !depth ) + break; + depth--; + } /* end while(shorter) */ + + return data; +} + +/* + * ldap_tavl_free -- traverse avltree root, freeing the memory it is using. + * the dfree() is called to free the data portion of each node. The + * number of items actually freed is returned. + */ + +int +ldap_tavl_free( TAvlnode *root, AVL_FREE dfree ) +{ + int nleft, nright; + + if ( root == 0 ) + return( 0 ); + + nleft = ldap_tavl_free( ldap_avl_lchild( root ), dfree ); + + nright = ldap_tavl_free( ldap_avl_rchild( root ), dfree ); + + if ( dfree ) + (*dfree)( root->avl_data ); + ber_memfree( root ); + + return( nleft + nright + 1 ); +} + +/* + * ldap_tavl_find -- search avltree root for a node with data data. the function + * cmp is used to compare things. it is called with data as its first arg + * and the current node data as its second. it should return 0 if they match, + * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2. + */ + +/* + * ldap_tavl_find2 - returns TAvlnode instead of data pointer. + * ldap_tavl_find3 - as above, but returns TAvlnode even if no match is found. + * also set *ret = last comparison result, or -1 if root == NULL. + */ +TAvlnode * +ldap_tavl_find3( TAvlnode *root, const void *data, AVL_CMP fcmp, int *ret ) +{ + int cmp = -1, dir; + TAvlnode *prev = root; + + while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { + prev = root; + dir = cmp > 0; + root = ldap_avl_child( root, dir ); + } + *ret = cmp; + return root ? root : prev; +} + +TAvlnode * +ldap_tavl_find2( TAvlnode *root, const void *data, AVL_CMP fcmp ) +{ + int cmp; + + while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { + cmp = cmp > 0; + root = ldap_avl_child( root, cmp ); + } + return root; +} + +void* +ldap_tavl_find( TAvlnode *root, const void* data, AVL_CMP fcmp ) +{ + int cmp; + + while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) { + cmp = cmp > 0; + root = ldap_avl_child( root, cmp ); + } + + return( root ? root->avl_data : 0 ); +} + +/* Return the leftmost or rightmost node in the tree */ +TAvlnode * +ldap_tavl_end( TAvlnode *root, int dir ) +{ + if ( root ) { + while ( root->avl_bits[dir] == AVL_CHILD ) + root = root->avl_link[dir]; + } + return root; +} + +/* Return the next node in the given direction */ +TAvlnode * +ldap_tavl_next( TAvlnode *root, int dir ) +{ + if ( root ) { + int c = root->avl_bits[dir]; + + root = root->avl_link[dir]; + if ( c == AVL_CHILD ) { + dir ^= 1; + while ( root->avl_bits[dir] == AVL_CHILD ) + root = root->avl_link[dir]; + } + } + return root; +} diff --git a/libs/ldap/libldap/thr_nt.c b/libs/ldap/libldap/thr_nt.c new file mode 100644 index 00000000000..def4da706f8 --- /dev/null +++ b/libs/ldap/libldap/thr_nt.c @@ -0,0 +1,253 @@ +/* thr_nt.c - wrapper around NT threads */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" + +#if defined( HAVE_NT_THREADS ) + +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#include <windows.h> +#include <process.h> + +#include "ldap_pvt_thread.h" /* Get the thread interface */ +#define LDAP_THREAD_IMPLEMENTATION +#include "ldap_thr_debug.h" /* May rename the symbols defined below */ + +typedef struct ldap_int_thread_s { + long tid; + HANDLE thd; +} ldap_int_thread_s; + +#ifndef NT_MAX_THREADS +#define NT_MAX_THREADS 1024 +#endif + +static ldap_int_thread_s tids[NT_MAX_THREADS]; +static int ntids; + + +/* mingw compiler very sensitive about getting prototypes right */ +typedef unsigned __stdcall thrfunc_t(void *); + +int +ldap_int_thread_initialize( void ) +{ + return 0; +} + +int +ldap_int_thread_destroy( void ) +{ + return 0; +} + +int +ldap_int_mutex_firstcreate( ldap_int_thread_mutex_t *mutex ) +{ + if ( *mutex == NULL ) { + HANDLE p = CreateMutex( NULL, 0, NULL ); + if ( InterlockedCompareExchangePointer((PVOID*)mutex, (PVOID)p, NULL) != NULL) + CloseHandle( p ); + } + return 0; +} + +int +ldap_pvt_thread_create( ldap_pvt_thread_t * thread, + int detach, + void *(*start_routine)( void *), + void *arg) +{ + unsigned tid; + HANDLE thd; + int rc = -1; + + thd = (HANDLE) _beginthreadex(NULL, LDAP_PVT_THREAD_STACK_SIZE, (thrfunc_t *) start_routine, + arg, 0, &tid); + + if ( thd ) { + *thread = (ldap_pvt_thread_t) tid; + tids[ntids].tid = tid; + tids[ntids].thd = thd; + ntids++; + rc = 0; + } + return rc; +} + +void +ldap_pvt_thread_exit( void *retval ) +{ + _endthread( ); +} + +int +ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return ) +{ + DWORD status; + int i; + + for (i=0; i<ntids; i++) { + if ( tids[i].tid == thread ) + break; + } + if ( i > ntids ) return -1; + + status = WaitForSingleObject( tids[i].thd, INFINITE ); + for (; i<ntids; i++) { + tids[i] = tids[i+1]; + } + ntids--; + return status == WAIT_FAILED ? -1 : 0; +} + +int +ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) +{ + return 0; +} + +int +ldap_pvt_thread_yield( void ) +{ + Sleep( 0 ); + return 0; +} + +int +ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond ) +{ + *cond = CreateEvent( NULL, FALSE, FALSE, NULL ); + return( 0 ); +} + +int +ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv ) +{ + CloseHandle( *cv ); + return( 0 ); +} + +int +ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) +{ + SetEvent( *cond ); + return( 0 ); +} + +int +ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, + ldap_pvt_thread_mutex_t *mutex ) +{ + SignalObjectAndWait( *mutex, *cond, INFINITE, FALSE ); + WaitForSingleObject( *mutex, INFINITE ); + return( 0 ); +} + +int +ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond ) +{ + while ( WaitForSingleObject( *cond, 0 ) == WAIT_TIMEOUT ) + SetEvent( *cond ); + return( 0 ); +} + +int +ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex ) +{ + *mutex = CreateMutex( NULL, 0, NULL ); + return ( 0 ); +} + +int +ldap_pvt_thread_mutex_recursive_init( ldap_pvt_thread_mutex_t *mutex ) +{ + /* All NT mutexes are recursive */ + return ldap_pvt_thread_mutex_init( mutex ); +} + +int +ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) +{ + CloseHandle( *mutex ); + return ( 0 ); +} + +int +ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex ) +{ + DWORD status; + status = WaitForSingleObject( *mutex, INFINITE ); + return status == WAIT_FAILED ? -1 : 0; +} + +int +ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) +{ + ReleaseMutex( *mutex ); + return ( 0 ); +} + +int +ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mp ) +{ + DWORD status; + status = WaitForSingleObject( *mp, 0 ); + return status == WAIT_FAILED || status == WAIT_TIMEOUT + ? -1 : 0; +} + +ldap_pvt_thread_t +ldap_pvt_thread_self( void ) +{ + return GetCurrentThreadId(); +} + +int +ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *keyp ) +{ + DWORD key = TlsAlloc(); + if ( key != TLS_OUT_OF_INDEXES ) { + *keyp = key; + return 0; + } else { + return -1; + } +} + +int +ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key ) +{ + /* TlsFree returns 0 on failure */ + return( TlsFree( key ) == 0 ); +} + +int +ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data ) +{ + return ( TlsSetValue( key, data ) == 0 ); +} + +int +ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data ) +{ + void *ptr = TlsGetValue( key ); + *data = ptr; + return( ptr ? GetLastError() : 0 ); +} + +#endif diff --git a/libs/ldap/libldap/tls2.c b/libs/ldap/libldap/tls2.c new file mode 100644 index 00000000000..24e60922552 --- /dev/null +++ b/libs/ldap/libldap/tls2.c @@ -0,0 +1,1674 @@ +/* tls.c - Handle tls/ssl. */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* ACKNOWLEDGEMENTS: restructured by Howard Chu. + */ + +#include "portable.h" +#include "ldap_config.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/ctype.h> +#include <ac/time.h> +#include <ac/unistd.h> +#include <ac/param.h> +#include <ac/dirent.h> + +#include "ldap-int.h" + +#ifdef HAVE_TLS + +#include "ldap-tls.h" + +static tls_impl *tls_imp = &ldap_int_tls_impl; +#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ + (void *)tls_imp->ti_sbio ) + +#endif /* HAVE_TLS */ + +/* RFC2459 minimum required set of supported attribute types + * in a certificate DN + */ +typedef struct oid_name { + struct berval oid; + struct berval name; +} oid_name; + +static oid_name oids[] = { + { BER_BVC("2.5.4.3"), BER_BVC("cn") }, + { BER_BVC("2.5.4.4"), BER_BVC("sn") }, + { BER_BVC("2.5.4.6"), BER_BVC("c") }, + { BER_BVC("2.5.4.7"), BER_BVC("l") }, + { BER_BVC("2.5.4.8"), BER_BVC("st") }, + { BER_BVC("2.5.4.10"), BER_BVC("o") }, + { BER_BVC("2.5.4.11"), BER_BVC("ou") }, + { BER_BVC("2.5.4.12"), BER_BVC("title") }, + { BER_BVC("2.5.4.41"), BER_BVC("name") }, + { BER_BVC("2.5.4.42"), BER_BVC("givenName") }, + { BER_BVC("2.5.4.43"), BER_BVC("initials") }, + { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") }, + { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") }, + { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") }, + { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") }, + { BER_BVNULL, BER_BVNULL } +}; + +#ifdef HAVE_TLS + +LDAP_F(int) ldap_pvt_tls_check_hostname LDAP_P(( LDAP *ld, void *s, const char *name_in )); +LDAP_F(int) ldap_pvt_tls_get_peercert LDAP_P(( void *s, struct berval *der )); + +void +ldap_pvt_tls_ctx_free ( void *c ) +{ + if ( !c ) return; + tls_imp->ti_ctx_free( c ); +} + +static void +tls_ctx_ref( tls_ctx *ctx ) +{ + if ( !ctx ) return; + + tls_imp->ti_ctx_ref( ctx ); +} + +#ifdef LDAP_R_COMPILE +/* + * an extra mutex for the default ctx. + */ +static ldap_pvt_thread_mutex_t tls_def_ctx_mutex; +#endif + +void +ldap_int_tls_destroy( struct ldapoptions *lo ) +{ + if ( lo->ldo_tls_ctx ) { + ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); + lo->ldo_tls_ctx = NULL; + } + + if ( lo->ldo_tls_certfile ) { + LDAP_FREE( lo->ldo_tls_certfile ); + lo->ldo_tls_certfile = NULL; + } + if ( lo->ldo_tls_keyfile ) { + LDAP_FREE( lo->ldo_tls_keyfile ); + lo->ldo_tls_keyfile = NULL; + } + if ( lo->ldo_tls_dhfile ) { + LDAP_FREE( lo->ldo_tls_dhfile ); + lo->ldo_tls_dhfile = NULL; + } + if ( lo->ldo_tls_ecname ) { + LDAP_FREE( lo->ldo_tls_ecname ); + lo->ldo_tls_ecname = NULL; + } + if ( lo->ldo_tls_cacertfile ) { + LDAP_FREE( lo->ldo_tls_cacertfile ); + lo->ldo_tls_cacertfile = NULL; + } + if ( lo->ldo_tls_cacertdir ) { + LDAP_FREE( lo->ldo_tls_cacertdir ); + lo->ldo_tls_cacertdir = NULL; + } + if ( lo->ldo_tls_ciphersuite ) { + LDAP_FREE( lo->ldo_tls_ciphersuite ); + lo->ldo_tls_ciphersuite = NULL; + } + if ( lo->ldo_tls_crlfile ) { + LDAP_FREE( lo->ldo_tls_crlfile ); + lo->ldo_tls_crlfile = NULL; + } + /* tls_pin_hashalg and tls_pin share the same buffer */ + if ( lo->ldo_tls_pin_hashalg ) { + LDAP_FREE( lo->ldo_tls_pin_hashalg ); + lo->ldo_tls_pin_hashalg = NULL; + } else { + LDAP_FREE( lo->ldo_tls_pin.bv_val ); + } + BER_BVZERO( &lo->ldo_tls_pin ); +} + +/* + * Tear down the TLS subsystem. Should only be called once. + */ +void +ldap_pvt_tls_destroy( void ) +{ + struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); + + ldap_int_tls_destroy( lo ); + + tls_imp->ti_tls_destroy(); +} + +/* + * Initialize a particular TLS implementation. + * Called once per implementation. + */ +static int +tls_init(tls_impl *impl, int do_threads ) +{ + static int tls_initialized = 0; + + if ( !tls_initialized++ ) { +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex ); +#endif + } + + if ( impl->ti_inited++ ) return 0; + + if ( do_threads ) { +#ifdef LDAP_R_COMPILE + impl->ti_thr_init(); +#endif + } + + return impl->ti_tls_init(); +} + +/* + * Initialize TLS subsystem. Called once per implementation. + */ +int +ldap_pvt_tls_init( int do_threads ) +{ + return tls_init( tls_imp, do_threads ); +} + +/* + * initialize a new TLS context + */ +static int +ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) +{ + int rc = 0; + tls_impl *ti = tls_imp; + struct ldaptls lts = lo->ldo_tls_info; + + if ( lo->ldo_tls_ctx ) + return 0; + + tls_init( ti, 0 ); + + if ( is_server && !lts.lt_certfile && !lts.lt_keyfile && + !lts.lt_cacertfile && !lts.lt_cacertdir && + !lts.lt_cacert.bv_val && !lts.lt_cert.bv_val && + !lts.lt_key.bv_val ) { + /* minimum configuration not provided */ + return LDAP_NOT_SUPPORTED; + } + +#ifdef HAVE_EBCDIC + /* This ASCII/EBCDIC handling is a real pain! */ + if ( lts.lt_ciphersuite ) { + lts.lt_ciphersuite = LDAP_STRDUP( lts.lt_ciphersuite ); + __atoe( lts.lt_ciphersuite ); + } + if ( lts.lt_cacertfile ) { + lts.lt_cacertfile = LDAP_STRDUP( lts.lt_cacertfile ); + __atoe( lts.lt_cacertfile ); + } + if ( lts.lt_certfile ) { + lts.lt_certfile = LDAP_STRDUP( lts.lt_certfile ); + __atoe( lts.lt_certfile ); + } + if ( lts.lt_keyfile ) { + lts.lt_keyfile = LDAP_STRDUP( lts.lt_keyfile ); + __atoe( lts.lt_keyfile ); + } + if ( lts.lt_crlfile ) { + lts.lt_crlfile = LDAP_STRDUP( lts.lt_crlfile ); + __atoe( lts.lt_crlfile ); + } + if ( lts.lt_cacertdir ) { + lts.lt_cacertdir = LDAP_STRDUP( lts.lt_cacertdir ); + __atoe( lts.lt_cacertdir ); + } + if ( lts.lt_dhfile ) { + lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile ); + __atoe( lts.lt_dhfile ); + } + if ( lts.lt_ecname ) { + lts.lt_ecname = LDAP_STRDUP( lts.lt_ecname ); + __atoe( lts.lt_ecname ); + } +#endif + lo->ldo_tls_ctx = ti->ti_ctx_new( lo ); + if ( lo->ldo_tls_ctx == NULL ) { + Debug0( LDAP_DEBUG_ANY, + "TLS: could not allocate default ctx.\n" ); + rc = -1; + goto error_exit; + } + + rc = ti->ti_ctx_init( lo, <s, is_server ); + +error_exit: + if ( rc < 0 && lo->ldo_tls_ctx != NULL ) { + ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); + lo->ldo_tls_ctx = NULL; + } +#ifdef HAVE_EBCDIC + LDAP_FREE( lts.lt_ciphersuite ); + LDAP_FREE( lts.lt_cacertfile ); + LDAP_FREE( lts.lt_certfile ); + LDAP_FREE( lts.lt_keyfile ); + LDAP_FREE( lts.lt_crlfile ); + LDAP_FREE( lts.lt_cacertdir ); + LDAP_FREE( lts.lt_dhfile ); + LDAP_FREE( lts.lt_ecname ); +#endif + return rc; +} + +/* + * initialize the default context + */ +int +ldap_pvt_tls_init_def_ctx( int is_server ) +{ + struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); + int rc; + LDAP_MUTEX_LOCK( &tls_def_ctx_mutex ); + rc = ldap_int_tls_init_ctx( lo, is_server ); + LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex ); + return rc; +} + +static tls_session * +alloc_handle( void *ctx_arg, int is_server ) +{ + tls_ctx *ctx; + tls_session *ssl; + + if ( ctx_arg ) { + ctx = ctx_arg; + } else { + struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); + if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL; + ctx = lo->ldo_tls_ctx; + } + + ssl = tls_imp->ti_session_new( ctx, is_server ); + if ( ssl == NULL ) { + Debug0( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n" ); + return NULL; + } + return ssl; +} + +static int +update_flags( Sockbuf *sb, tls_session * ssl, int rc ) +{ + sb->sb_trans_needs_read = 0; + sb->sb_trans_needs_write = 0; + + return tls_imp->ti_session_upflags( sb, ssl, rc ); +} + +/* + * Call this to do a TLS connect on a sockbuf. ctx_arg can be + * a SSL_CTX * or NULL, in which case the default ctx is used. + * + * Return value: + * + * 0 - Success. Connection is ready for communication. + * <0 - Error. Can't create a TLS stream. + * >0 - Partial success. + * Do a select (using information from lber_pvt_sb_needs_{read,write} + * and call again. + */ + +static int +ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host ) +{ + Sockbuf *sb = conn->lconn_sb; + int err; + tls_session *ssl = NULL; + const char *sni = host; + + if ( HAS_TLS( sb )) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); + } else { + struct ldapoptions *lo; + tls_ctx *ctx; + + ctx = ld->ld_options.ldo_tls_ctx; + + ssl = alloc_handle( ctx, 0 ); + + if ( ssl == NULL ) return -1; + +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); +#endif + ber_sockbuf_add_io( sb, tls_imp->ti_sbio, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); + + lo = LDAP_INT_GLOBAL_OPT(); + if( ctx == NULL ) { + ctx = lo->ldo_tls_ctx; + ld->ld_options.ldo_tls_ctx = ctx; + tls_ctx_ref( ctx ); + } + if ( ld->ld_options.ldo_tls_connect_cb ) + ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx, + ld->ld_options.ldo_tls_connect_arg ); + if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb != + ld->ld_options.ldo_tls_connect_cb ) + lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg ); + } + + /* pass hostname for SNI, but only if it's an actual name + * and not a numeric address + */ + { + int numeric = 1; + unsigned char *c; + for ( c = (unsigned char *)sni; *c; c++ ) { + if ( *c == ':' ) /* IPv6 address */ + break; + if ( *c == '.' ) + continue; + if ( !isdigit( *c )) { + numeric = 0; + break; + } + } + if ( numeric ) + sni = NULL; + } + err = tls_imp->ti_session_connect( ld, ssl, sni ); + +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); +#endif + + if ( err == 0 ) { + err = ldap_pvt_tls_check_hostname( ld, ssl, host ); + } + + if ( err < 0 ) + { + char buf[256], *msg; + if ( update_flags( sb, ssl, err )) { + return 1; + } + + msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); + if ( msg ) { + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + } + ld->ld_error = LDAP_STRDUP( msg ); +#ifdef HAVE_EBCDIC + if ( ld->ld_error ) __etoa(ld->ld_error); +#endif + } + + Debug1( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n", + ld->ld_error ? ld->ld_error : "" ); + + ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, + LBER_SBIOD_LEVEL_TRANSPORT ); +#ifdef LDAP_DEBUG + ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT ); +#endif + return -1; + } + + return 0; +} + +int +ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, const char *host ) +{ + LDAPConn conn = { .lconn_sb = sb }; + return ldap_int_tls_connect( ld, &conn, host ); +} + +/* + * Call this to do a TLS accept on a sockbuf. + * Everything else is the same as with tls_connect. + */ +int +ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) +{ + int err; + tls_session *ssl = NULL; + + if ( HAS_TLS( sb )) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); + } else { + ssl = alloc_handle( ctx_arg, 1 ); + if ( ssl == NULL ) return -1; + +#ifdef LDAP_DEBUG + ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); +#endif + ber_sockbuf_add_io( sb, tls_imp->ti_sbio, + LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); + } + + err = tls_imp->ti_session_accept( ssl ); + +#ifdef HAVE_WINSOCK + errno = WSAGetLastError(); +#endif + + if ( err < 0 ) + { + if ( update_flags( sb, ssl, err )) return 1; + + if ( DebugTest( LDAP_DEBUG_ANY ) ) { + char buf[256], *msg; + msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); + Debug1( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n", + msg ? msg : "(unknown)" ); + } + + ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, + LBER_SBIOD_LEVEL_TRANSPORT ); +#ifdef LDAP_DEBUG + ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, + LBER_SBIOD_LEVEL_TRANSPORT ); +#endif + return -1; + } + return 0; +} + +int +ldap_pvt_tls_inplace ( Sockbuf *sb ) +{ + return HAS_TLS( sb ) ? 1 : 0; +} + +int +ldap_tls_inplace( LDAP *ld ) +{ + Sockbuf *sb = NULL; + + if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) { + sb = ld->ld_defconn->lconn_sb; + + } else if ( ld->ld_sb ) { + sb = ld->ld_sb; + + } else { + return 0; + } + + return ldap_pvt_tls_inplace( sb ); +} + +int +ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn, + LDAPDN_rewrite_dummy *func, unsigned flags ) +{ + tls_session *session = s; + struct berval bvdn; + int rc; + + rc = tls_imp->ti_session_peer_dn( session, &bvdn ); + if ( rc ) return rc; + + rc = ldap_X509dn2bv( &bvdn, dn, + (LDAPDN_rewrite_func *)func, flags); + return rc; +} + +int +ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in ) +{ + tls_session *session = s; + + if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && + ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { + ld->ld_errno = tls_imp->ti_session_chkhost( ld, session, name_in ); + if (ld->ld_errno != LDAP_SUCCESS) { + return ld->ld_errno; + } + } + + /* + * If instructed to do pinning, do it now + */ + if ( !BER_BVISNULL( &ld->ld_options.ldo_tls_pin ) ) { + ld->ld_errno = tls_imp->ti_session_pinning( ld, s, + ld->ld_options.ldo_tls_pin_hashalg, + &ld->ld_options.ldo_tls_pin ); + if (ld->ld_errno != LDAP_SUCCESS) { + return ld->ld_errno; + } + } + + return LDAP_SUCCESS; +} + +int +ldap_pvt_tls_config( LDAP *ld, int option, const char *arg ) +{ + int i; + + switch( option ) { + case LDAP_OPT_X_TLS_CACERTFILE: + case LDAP_OPT_X_TLS_CACERTDIR: + case LDAP_OPT_X_TLS_CERTFILE: + case LDAP_OPT_X_TLS_KEYFILE: + case LDAP_OPT_X_TLS_RANDOM_FILE: + case LDAP_OPT_X_TLS_CIPHER_SUITE: + case LDAP_OPT_X_TLS_DHFILE: + case LDAP_OPT_X_TLS_PEERKEY_HASH: + case LDAP_OPT_X_TLS_ECNAME: + case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ + return ldap_pvt_tls_set_option( ld, option, (void *) arg ); + + case LDAP_OPT_X_TLS_REQUIRE_CERT: + case LDAP_OPT_X_TLS_REQUIRE_SAN: + case LDAP_OPT_X_TLS: + i = -1; + if ( strcasecmp( arg, "never" ) == 0 ) { + i = LDAP_OPT_X_TLS_NEVER ; + + } else if ( strcasecmp( arg, "demand" ) == 0 ) { + i = LDAP_OPT_X_TLS_DEMAND ; + + } else if ( strcasecmp( arg, "allow" ) == 0 ) { + i = LDAP_OPT_X_TLS_ALLOW ; + + } else if ( strcasecmp( arg, "try" ) == 0 ) { + i = LDAP_OPT_X_TLS_TRY ; + + } else if ( ( strcasecmp( arg, "hard" ) == 0 ) || + ( strcasecmp( arg, "on" ) == 0 ) || + ( strcasecmp( arg, "yes" ) == 0) || + ( strcasecmp( arg, "true" ) == 0 ) ) + { + i = LDAP_OPT_X_TLS_HARD ; + } + + if (i >= 0) { + return ldap_pvt_tls_set_option( ld, option, &i ); + } + return -1; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: + case LDAP_OPT_X_TLS_PROTOCOL_MIN: { + char *next; + long l; + l = strtol( arg, &next, 10 ); + if ( l < 0 || l > 0xff || next == arg || + ( *next != '\0' && *next != '.' ) ) + return -1; + i = l << 8; + if (*next == '.') { + arg = next + 1; + l = strtol( arg, &next, 10 ); + if ( l < 0 || l > 0xff || next == arg || *next != '\0' ) + return -1; + i += l; + } + return ldap_pvt_tls_set_option( ld, option, &i ); + } +#ifdef HAVE_OPENSSL + case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ + i = -1; + if ( strcasecmp( arg, "none" ) == 0 ) { + i = LDAP_OPT_X_TLS_CRL_NONE ; + } else if ( strcasecmp( arg, "peer" ) == 0 ) { + i = LDAP_OPT_X_TLS_CRL_PEER ; + } else if ( strcasecmp( arg, "all" ) == 0 ) { + i = LDAP_OPT_X_TLS_CRL_ALL ; + } + if (i >= 0) { + return ldap_pvt_tls_set_option( ld, option, &i ); + } + return -1; +#endif + } + return -1; +} + +int +ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) +{ + struct ldapoptions *lo; + + if( option == LDAP_OPT_X_TLS_PACKAGE ) { + *(char **)arg = LDAP_STRDUP( tls_imp->ti_name ); + return 0; + } + + if( ld != NULL ) { + assert( LDAP_VALID( ld ) ); + + if( !LDAP_VALID( ld ) ) { + return LDAP_OPT_ERROR; + } + + lo = &ld->ld_options; + + } else { + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if ( lo == NULL ) { + return LDAP_NO_MEMORY; + } + } + + switch( option ) { + case LDAP_OPT_X_TLS: + *(int *)arg = lo->ldo_tls_mode; + break; + case LDAP_OPT_X_TLS_CTX: + *(void **)arg = lo->ldo_tls_ctx; + if ( lo->ldo_tls_ctx ) { + tls_ctx_ref( lo->ldo_tls_ctx ); + } + break; + case LDAP_OPT_X_TLS_CACERTFILE: + *(char **)arg = lo->ldo_tls_cacertfile ? + LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL; + break; + case LDAP_OPT_X_TLS_CACERTDIR: + *(char **)arg = lo->ldo_tls_cacertdir ? + LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL; + break; + case LDAP_OPT_X_TLS_CERTFILE: + *(char **)arg = lo->ldo_tls_certfile ? + LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL; + break; + case LDAP_OPT_X_TLS_KEYFILE: + *(char **)arg = lo->ldo_tls_keyfile ? + LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL; + break; + case LDAP_OPT_X_TLS_DHFILE: + *(char **)arg = lo->ldo_tls_dhfile ? + LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL; + break; + case LDAP_OPT_X_TLS_ECNAME: + *(char **)arg = lo->ldo_tls_ecname ? + LDAP_STRDUP( lo->ldo_tls_ecname ) : NULL; + break; + case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ + *(char **)arg = lo->ldo_tls_crlfile ? + LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL; + break; + case LDAP_OPT_X_TLS_REQUIRE_CERT: + *(int *)arg = lo->ldo_tls_require_cert; + break; + case LDAP_OPT_X_TLS_REQUIRE_SAN: + *(int *)arg = lo->ldo_tls_require_san; + break; +#ifdef HAVE_OPENSSL + case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ + *(int *)arg = lo->ldo_tls_crlcheck; + break; +#endif + case LDAP_OPT_X_TLS_CIPHER_SUITE: + *(char **)arg = lo->ldo_tls_ciphersuite ? + LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; + break; + case LDAP_OPT_X_TLS_PROTOCOL_MIN: + *(int *)arg = lo->ldo_tls_protocol_min; + break; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: + *(int *)arg = lo->ldo_tls_protocol_max; + break; + case LDAP_OPT_X_TLS_RANDOM_FILE: + *(char **)arg = lo->ldo_tls_randfile ? + LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; + break; + case LDAP_OPT_X_TLS_SSL_CTX: { + void *retval = 0; + if ( ld != NULL ) { + LDAPConn *conn = ld->ld_defconn; + if ( conn != NULL ) { + Sockbuf *sb = conn->lconn_sb; + retval = ldap_pvt_tls_sb_ctx( sb ); + } + } + *(void **)arg = retval; + break; + } + case LDAP_OPT_X_TLS_CONNECT_CB: + *(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb; + break; + case LDAP_OPT_X_TLS_CONNECT_ARG: + *(void **)arg = lo->ldo_tls_connect_arg; + break; + case LDAP_OPT_X_TLS_VERSION: { + void *sess = NULL; + const char *retval = NULL; + if ( ld != NULL ) { + LDAPConn *conn = ld->ld_defconn; + if ( conn != NULL ) { + Sockbuf *sb = conn->lconn_sb; + sess = ldap_pvt_tls_sb_ctx( sb ); + if ( sess != NULL ) + retval = ldap_pvt_tls_get_version( sess ); + } + } + *(char **)arg = retval ? LDAP_STRDUP( retval ) : NULL; + break; + } + case LDAP_OPT_X_TLS_CIPHER: { + void *sess = NULL; + const char *retval = NULL; + if ( ld != NULL ) { + LDAPConn *conn = ld->ld_defconn; + if ( conn != NULL ) { + Sockbuf *sb = conn->lconn_sb; + sess = ldap_pvt_tls_sb_ctx( sb ); + if ( sess != NULL ) + retval = ldap_pvt_tls_get_cipher( sess ); + } + } + *(char **)arg = retval ? LDAP_STRDUP( retval ) : NULL; + break; + } + case LDAP_OPT_X_TLS_PEERCERT: { + void *sess = NULL; + struct berval *bv = arg; + bv->bv_len = 0; + bv->bv_val = NULL; + if ( ld != NULL ) { + LDAPConn *conn = ld->ld_defconn; + if ( conn != NULL ) { + Sockbuf *sb = conn->lconn_sb; + sess = ldap_pvt_tls_sb_ctx( sb ); + if ( sess != NULL ) + return ldap_pvt_tls_get_peercert( sess, bv ); + } + } + break; + } + case LDAP_OPT_X_TLS_CACERT: { + struct berval *bv = arg; + if ( lo->ldo_tls_cacert.bv_val ) { + ber_dupbv( bv, &lo->ldo_tls_cacert ); + } else { + BER_BVZERO( bv ); + } + break; + } + case LDAP_OPT_X_TLS_CERT: { + struct berval *bv = arg; + if ( lo->ldo_tls_cert.bv_val ) { + ber_dupbv( bv, &lo->ldo_tls_cert ); + } else { + BER_BVZERO( bv ); + } + break; + } + case LDAP_OPT_X_TLS_KEY: { + struct berval *bv = arg; + if ( lo->ldo_tls_key.bv_val ) { + ber_dupbv( bv, &lo->ldo_tls_key ); + } else { + BER_BVZERO( bv ); + } + break; + } + + default: + return -1; + } + return 0; +} + +int +ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) +{ + struct ldapoptions *lo; + + if( ld != NULL ) { + assert( LDAP_VALID( ld ) ); + + if( !LDAP_VALID( ld ) ) { + return LDAP_OPT_ERROR; + } + + lo = &ld->ld_options; + + } else { + /* Get pointer to global option structure */ + lo = LDAP_INT_GLOBAL_OPT(); + if ( lo == NULL ) { + return LDAP_NO_MEMORY; + } + } + + switch( option ) { + case LDAP_OPT_X_TLS: + if ( !arg ) return -1; + + switch( *(int *) arg ) { + case LDAP_OPT_X_TLS_NEVER: + case LDAP_OPT_X_TLS_DEMAND: + case LDAP_OPT_X_TLS_ALLOW: + case LDAP_OPT_X_TLS_TRY: + case LDAP_OPT_X_TLS_HARD: + if (lo != NULL) { + lo->ldo_tls_mode = *(int *)arg; + } + + return 0; + } + return -1; + + case LDAP_OPT_X_TLS_CTX: + if ( lo->ldo_tls_ctx ) + ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); + lo->ldo_tls_ctx = arg; + tls_ctx_ref( lo->ldo_tls_ctx ); + return 0; + case LDAP_OPT_X_TLS_CONNECT_CB: + lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg; + return 0; + case LDAP_OPT_X_TLS_CONNECT_ARG: + lo->ldo_tls_connect_arg = arg; + return 0; + case LDAP_OPT_X_TLS_CACERTFILE: + if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile ); + lo->ldo_tls_cacertfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_CACERTDIR: + if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir ); + lo->ldo_tls_cacertdir = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_CERTFILE: + if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile ); + lo->ldo_tls_certfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_KEYFILE: + if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile ); + lo->ldo_tls_keyfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_DHFILE: + if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile ); + lo->ldo_tls_dhfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_ECNAME: + if ( lo->ldo_tls_ecname ) LDAP_FREE( lo->ldo_tls_ecname ); + lo->ldo_tls_ecname = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ + if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile ); + lo->ldo_tls_crlfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + case LDAP_OPT_X_TLS_REQUIRE_CERT: + if ( !arg ) return -1; + switch( *(int *) arg ) { + case LDAP_OPT_X_TLS_NEVER: + case LDAP_OPT_X_TLS_DEMAND: + case LDAP_OPT_X_TLS_ALLOW: + case LDAP_OPT_X_TLS_TRY: + case LDAP_OPT_X_TLS_HARD: + lo->ldo_tls_require_cert = * (int *) arg; + return 0; + } + return -1; + case LDAP_OPT_X_TLS_REQUIRE_SAN: + if ( !arg ) return -1; + switch( *(int *) arg ) { + case LDAP_OPT_X_TLS_NEVER: + case LDAP_OPT_X_TLS_DEMAND: + case LDAP_OPT_X_TLS_ALLOW: + case LDAP_OPT_X_TLS_TRY: + case LDAP_OPT_X_TLS_HARD: + lo->ldo_tls_require_san = * (int *) arg; + return 0; + } + return -1; +#ifdef HAVE_OPENSSL + case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ + if ( !arg ) return -1; + switch( *(int *) arg ) { + case LDAP_OPT_X_TLS_CRL_NONE: + case LDAP_OPT_X_TLS_CRL_PEER: + case LDAP_OPT_X_TLS_CRL_ALL: + lo->ldo_tls_crlcheck = * (int *) arg; + return 0; + } + return -1; +#endif + case LDAP_OPT_X_TLS_CIPHER_SUITE: + if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); + lo->ldo_tls_ciphersuite = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + return 0; + + case LDAP_OPT_X_TLS_PROTOCOL_MIN: + if ( !arg ) return -1; + lo->ldo_tls_protocol_min = *(int *)arg; + return 0; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: + if ( !arg ) return -1; + lo->ldo_tls_protocol_max = *(int *)arg; + return 0; + case LDAP_OPT_X_TLS_RANDOM_FILE: + if ( ld != NULL ) + return -1; + if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile ); + lo->ldo_tls_randfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL; + break; + case LDAP_OPT_X_TLS_NEWCTX: + if ( !arg ) return -1; + if ( lo->ldo_tls_ctx ) + ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); + lo->ldo_tls_ctx = NULL; + return ldap_int_tls_init_ctx( lo, *(int *)arg ); + case LDAP_OPT_X_TLS_CACERT: + if ( lo->ldo_tls_cacert.bv_val ) + LDAP_FREE( lo->ldo_tls_cacert.bv_val ); + if ( arg ) { + lo->ldo_tls_cacert.bv_len = ((struct berval *)arg)->bv_len; + lo->ldo_tls_cacert.bv_val = LDAP_MALLOC( lo->ldo_tls_cacert.bv_len ); + if ( !lo->ldo_tls_cacert.bv_val ) + return -1; + AC_MEMCPY( lo->ldo_tls_cacert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cacert.bv_len ); + } else { + BER_BVZERO( &lo->ldo_tls_cacert ); + } + break; + case LDAP_OPT_X_TLS_CERT: + if ( lo->ldo_tls_cert.bv_val ) + LDAP_FREE( lo->ldo_tls_cert.bv_val ); + if ( arg ) { + lo->ldo_tls_cert.bv_len = ((struct berval *)arg)->bv_len; + lo->ldo_tls_cert.bv_val = LDAP_MALLOC( lo->ldo_tls_cert.bv_len ); + if ( !lo->ldo_tls_cert.bv_val ) + return -1; + AC_MEMCPY( lo->ldo_tls_cert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cert.bv_len ); + } else { + BER_BVZERO( &lo->ldo_tls_cert ); + } + break; + case LDAP_OPT_X_TLS_KEY: + if ( lo->ldo_tls_key.bv_val ) + LDAP_FREE( lo->ldo_tls_key.bv_val ); + if ( arg ) { + lo->ldo_tls_key.bv_len = ((struct berval *)arg)->bv_len; + lo->ldo_tls_key.bv_val = LDAP_MALLOC( lo->ldo_tls_key.bv_len ); + if ( !lo->ldo_tls_key.bv_val ) + return -1; + AC_MEMCPY( lo->ldo_tls_key.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_key.bv_len ); + } else { + BER_BVZERO( &lo->ldo_tls_key ); + } + break; + case LDAP_OPT_X_TLS_PEERKEY_HASH: { + /* arg = "[hashalg:]pubkey_hash" */ + struct berval bv; + char *p, *pin = arg; + int rc = LDAP_SUCCESS; + + if ( !tls_imp->ti_session_pinning ) return -1; + + if ( !pin || !*pin ) { + if ( lo->ldo_tls_pin_hashalg ) { + LDAP_FREE( lo->ldo_tls_pin_hashalg ); + } else if ( lo->ldo_tls_pin.bv_val ) { + LDAP_FREE( lo->ldo_tls_pin.bv_val ); + } + lo->ldo_tls_pin_hashalg = NULL; + BER_BVZERO( &lo->ldo_tls_pin ); + return rc; + } + + pin = LDAP_STRDUP( pin ); + p = strchr( pin, ':' ); + + /* pubkey (its hash) goes in bv, alg in p */ + if ( p ) { + *p = '\0'; + bv.bv_val = p+1; + p = pin; + } else { + bv.bv_val = pin; + } + + bv.bv_len = strlen(bv.bv_val); + if ( ldap_int_decode_b64_inplace( &bv ) ) { + LDAP_FREE( pin ); + return -1; + } + + if ( ld != NULL ) { + LDAPConn *conn = ld->ld_defconn; + if ( conn != NULL ) { + Sockbuf *sb = conn->lconn_sb; + void *sess = ldap_pvt_tls_sb_ctx( sb ); + if ( sess != NULL ) { + rc = tls_imp->ti_session_pinning( ld, sess, p, &bv ); + } + } + } + + if ( rc == LDAP_SUCCESS ) { + if ( lo->ldo_tls_pin_hashalg ) { + LDAP_FREE( lo->ldo_tls_pin_hashalg ); + } else if ( lo->ldo_tls_pin.bv_val ) { + LDAP_FREE( lo->ldo_tls_pin.bv_val ); + } + lo->ldo_tls_pin_hashalg = p; + lo->ldo_tls_pin = bv; + } else { + LDAP_FREE( pin ); + } + + return rc; + } + default: + return -1; + } + return 0; +} + +int +ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) +{ + Sockbuf *sb; + char *host; + void *ssl; + int ret, async; + struct timeval start_time_tv, tv, tv0; + ber_socket_t sd = AC_SOCKET_ERROR; + + if ( !conn ) + return LDAP_PARAM_ERROR; + + sb = conn->lconn_sb; + if( srv ) { + host = srv->lud_host; + } else { + host = conn->lconn_server->lud_host; + } + + /* avoid NULL host */ + if( host == NULL ) { + host = "localhost"; + } + + (void) tls_init( tls_imp, 0 ); + + /* + * Use non-blocking io during SSL Handshake when a timeout is configured + */ + async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC ); + if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { + if ( !async ) { + /* if async, this has already been set */ + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)1 ); + } + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); + tv = ld->ld_options.ldo_tm_net; + tv0 = tv; +#ifdef HAVE_GETTIMEOFDAY + gettimeofday( &start_time_tv, NULL ); +#else /* ! HAVE_GETTIMEOFDAY */ + time( &start_time_tv.tv_sec ); + start_time_tv.tv_usec = 0; +#endif /* ! HAVE_GETTIMEOFDAY */ + } + + ld->ld_errno = LDAP_SUCCESS; + ret = ldap_int_tls_connect( ld, conn, host ); + + /* this mainly only happens for non-blocking io + * but can also happen when the handshake is too + * big for a single network message. + */ + while ( ret > 0 ) { + if ( async ) { + struct timeval curr_time_tv, delta_tv; + int wr=0; + + if ( sb->sb_trans_needs_read ) { + wr=0; + } else if ( sb->sb_trans_needs_write ) { + wr=1; + } + Debug1( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n", + wr ? "write": "read" ); + + /* This is mostly copied from result.c:wait4msg(), should + * probably be moved into a separate function */ +#ifdef HAVE_GETTIMEOFDAY + gettimeofday( &curr_time_tv, NULL ); +#else /* ! HAVE_GETTIMEOFDAY */ + time( &curr_time_tv.tv_sec ); + curr_time_tv.tv_usec = 0; +#endif /* ! HAVE_GETTIMEOFDAY */ + + /* delta = curr - start */ + delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec; + delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec; + if ( delta_tv.tv_usec < 0 ) { + delta_tv.tv_sec--; + delta_tv.tv_usec += 1000000; + } + + /* tv0 < delta ? */ + if ( ( tv0.tv_sec < delta_tv.tv_sec ) || + ( ( tv0.tv_sec == delta_tv.tv_sec ) && + ( tv0.tv_usec < delta_tv.tv_usec ) ) ) + { + ret = -1; + ld->ld_errno = LDAP_TIMEOUT; + break; + } + /* timeout -= delta_time */ + tv0.tv_sec -= delta_tv.tv_sec; + tv0.tv_usec -= delta_tv.tv_usec; + if ( tv0.tv_usec < 0 ) { + tv0.tv_sec--; + tv0.tv_usec += 1000000; + } + start_time_tv.tv_sec = curr_time_tv.tv_sec; + start_time_tv.tv_usec = curr_time_tv.tv_usec; + tv = tv0; + Debug3( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n", + (void *)ld, (long) tv.tv_sec, (long) tv.tv_usec ); + ret = ldap_int_poll( ld, sd, &tv, wr); + if ( ret < 0 ) { + ld->ld_errno = LDAP_TIMEOUT; + break; + } + } + ret = ldap_int_tls_connect( ld, conn, host ); + } + + if ( ret < 0 ) { + if ( ld->ld_errno == LDAP_SUCCESS ) + ld->ld_errno = LDAP_CONNECT_ERROR; + return (ld->ld_errno); + } + + return LDAP_SUCCESS; +} + +void * +ldap_pvt_tls_sb_ctx( Sockbuf *sb ) +{ + void *p = NULL; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p ); + return p; +} + +int +ldap_pvt_tls_get_strength( void *s ) +{ + tls_session *session = s; + + return tls_imp->ti_session_strength( session ); +} + +int +ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags ) +{ + tls_session *session = s; + struct berval der_dn; + int rc; + + rc = tls_imp->ti_session_my_dn( session, &der_dn ); + if ( rc == LDAP_SUCCESS ) + rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags ); + return rc; +} + +int +ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server ) +{ + tls_session *session = s; + return tls_imp->ti_session_unique( session, buf, is_server ); +} + +int +ldap_pvt_tls_get_endpoint( void *s, struct berval *buf, int is_server ) +{ + tls_session *session = s; + return tls_imp->ti_session_endpoint( session, buf, is_server ); +} + +const char * +ldap_pvt_tls_get_version( void *s ) +{ + tls_session *session = s; + return tls_imp->ti_session_version( session ); +} + +const char * +ldap_pvt_tls_get_cipher( void *s ) +{ + tls_session *session = s; + return tls_imp->ti_session_cipher( session ); +} + +int +ldap_pvt_tls_get_peercert( void *s, struct berval *der ) +{ + tls_session *session = s; + return tls_imp->ti_session_peercert( session, der ); +} +#endif /* HAVE_TLS */ + +int +ldap_start_tls( LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls, + int *msgidp ) +{ + return ldap_extended_operation( ld, LDAP_EXOP_START_TLS, + NULL, serverctrls, clientctrls, msgidp ); +} + +int +ldap_install_tls( LDAP *ld ) +{ +#ifndef HAVE_TLS + return LDAP_NOT_SUPPORTED; +#else + if ( ldap_tls_inplace( ld ) ) { + return LDAP_LOCAL_ERROR; + } + + return ldap_int_tls_start( ld, ld->ld_defconn, NULL ); +#endif +} + +int +ldap_start_tls_s ( LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ +#ifndef HAVE_TLS + return LDAP_NOT_SUPPORTED; +#else + int rc; + char *rspoid = NULL; + struct berval *rspdata = NULL; + + /* XXYYZ: this initiates operation only on default connection! */ + + if ( ldap_tls_inplace( ld ) ) { + return LDAP_LOCAL_ERROR; + } + + rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS, + NULL, serverctrls, clientctrls, &rspoid, &rspdata ); + + if ( rspoid != NULL ) { + LDAP_FREE(rspoid); + } + + if ( rspdata != NULL ) { + ber_bvfree( rspdata ); + } + + if ( rc == LDAP_SUCCESS ) { + rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL ); + } + + return rc; +#endif +} + +/* These tags probably all belong in lber.h, but they're + * not normally encountered when processing LDAP, so maybe + * they belong somewhere else instead. + */ + +#define LBER_TAG_OID ((ber_tag_t) 0x06UL) + +/* Tags for string types used in a DirectoryString. + * + * Note that IA5string is not one of the defined choices for + * DirectoryString in X.520, but it gets used for email AVAs. + */ +#define LBER_TAG_UTF8 ((ber_tag_t) 0x0cUL) +#define LBER_TAG_PRINTABLE ((ber_tag_t) 0x13UL) +#define LBER_TAG_TELETEX ((ber_tag_t) 0x14UL) +#define LBER_TAG_IA5 ((ber_tag_t) 0x16UL) +#define LBER_TAG_UNIVERSAL ((ber_tag_t) 0x1cUL) +#define LBER_TAG_BMP ((ber_tag_t) 0x1eUL) + +static oid_name * +find_oid( struct berval *oid ) +{ + int i; + + for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) { + if ( oids[i].oid.bv_len != oid->bv_len ) continue; + if ( !strcmp( oids[i].oid.bv_val, oid->bv_val )) + return &oids[i]; + } + return NULL; +} + +/* Converts BER Bitstring value to LDAP BitString value (RFC4517) + * + * berValue : IN + * rfc4517Value: OUT + * + * berValue and ldapValue should not be NULL + */ + +#define BITS_PER_BYTE 8 +#define SQUOTE_LENGTH 1 +#define B_CHAR_LENGTH 1 +#define STR_OVERHEAD (2*SQUOTE_LENGTH + B_CHAR_LENGTH) + +static int +der_to_ldap_BitString (struct berval *berValue, + struct berval *ldapValue) +{ + ber_len_t bitPadding=0; + ber_len_t bits, maxBits; + char *tmpStr; + unsigned char byte; + ber_len_t bitLength; + ber_len_t valLen; + unsigned char* valPtr; + + ldapValue->bv_len=0; + ldapValue->bv_val=NULL; + + /* Gets padding and points to binary data */ + valLen=berValue->bv_len; + valPtr=(unsigned char*)berValue->bv_val; + if (valLen) { + bitPadding=(ber_len_t)(valPtr[0]); + valLen--; + valPtr++; + } + /* If Block is non DER encoding fixes to DER encoding */ + if (bitPadding >= BITS_PER_BYTE) { + if (valLen*BITS_PER_BYTE > bitPadding ) { + valLen-=(bitPadding/BITS_PER_BYTE); + bitPadding%=BITS_PER_BYTE; + } else { + valLen=0; + bitPadding=0; + } + } + /* Just in case bad encoding */ + if (valLen*BITS_PER_BYTE < bitPadding ) { + bitPadding=0; + valLen=0; + } + + /* Gets buffer to hold RFC4517 Bit String format */ + bitLength=valLen*BITS_PER_BYTE-bitPadding; + tmpStr=LDAP_MALLOC(bitLength + STR_OVERHEAD + 1); + + if (!tmpStr) + return LDAP_NO_MEMORY; + + ldapValue->bv_val=tmpStr; + ldapValue->bv_len=bitLength + STR_OVERHEAD; + + /* Formatting in '*binary-digit'B format */ + maxBits=BITS_PER_BYTE; + *tmpStr++ ='''; + while(valLen) { + byte=*valPtr; + if (valLen==1) + maxBits-=bitPadding; + for (bits=0; bits<maxBits; bits++) { + if (0x80 & byte) + *tmpStr='1'; + else + *tmpStr='0'; + tmpStr++; + byte<<=1; + } + valPtr++; + valLen--; + } + *tmpStr++ ='''; + *tmpStr++ ='B'; + *tmpStr=0; + + return LDAP_SUCCESS; +} + +/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN. + * x509_name must be raw DER. If func is non-NULL, the + * constructed DN will use numeric OIDs to identify attributeTypes, + * and the func() will be invoked to rewrite the DN with the given + * flags. + * + * Otherwise the DN will use shortNames from a hardcoded table. + */ +int +ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func, + unsigned flags ) +{ + LDAPDN newDN; + LDAPRDN newRDN; + LDAPAVA *newAVA, *baseAVA; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; + char oids[8192], *oidptr = oids, *oidbuf = NULL; + void *ptrs[2048]; + char *dn_end, *rdn_end; + int i, navas, nrdns, rc = LDAP_SUCCESS; + size_t dnsize, oidrem = sizeof(oids), oidsize = 0; + int csize; + ber_tag_t tag; + ber_len_t len; + oid_name *oidname; + + struct berval Oid, Val, oid2, *in = x509_name; + + assert( bv != NULL ); + + bv->bv_len = 0; + bv->bv_val = NULL; + + navas = 0; + nrdns = 0; + + /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs. + * An AVA is a SEQUENCE of attr and value. + * Count the number of AVAs and RDNs + */ + ber_init2( ber, in, LBER_USE_DER ); + tag = ber_peek_tag( ber, &len ); + if ( tag != LBER_SEQUENCE ) + return LDAP_DECODING_ERROR; + + for ( tag = ber_first_element( ber, &len, &dn_end ); + tag == LBER_SET; + tag = ber_next_element( ber, &len, dn_end )) { + nrdns++; + for ( tag = ber_first_element( ber, &len, &rdn_end ); + tag == LBER_SEQUENCE; + tag = ber_next_element( ber, &len, rdn_end )) { + if ( rdn_end > dn_end ) + return LDAP_DECODING_ERROR; + tag = ber_skip_tag( ber, &len ); + ber_skip_data( ber, len ); + navas++; + } + } + + /* Rewind and prepare to extract */ + ber_rewind( ber ); + tag = ber_first_element( ber, &len, &dn_end ); + if ( tag != LBER_SET ) + return LDAP_DECODING_ERROR; + + /* Allocate the DN/RDN/AVA stuff as a single block */ + dnsize = sizeof(LDAPRDN) * (nrdns+1); + dnsize += sizeof(LDAPAVA *) * (navas+nrdns); + dnsize += sizeof(LDAPAVA) * navas; + if (dnsize > sizeof(ptrs)) { + newDN = (LDAPDN)LDAP_MALLOC( dnsize ); + if ( newDN == NULL ) + return LDAP_NO_MEMORY; + } else { + newDN = (LDAPDN)(char *)ptrs; + } + + newDN[nrdns] = NULL; + newRDN = (LDAPRDN)(newDN + nrdns+1); + newAVA = (LDAPAVA *)(newRDN + navas + nrdns); + baseAVA = newAVA; + + for ( i = nrdns - 1; i >= 0; i-- ) { + newDN[i] = newRDN; + + for ( tag = ber_first_element( ber, &len, &rdn_end ); + tag == LBER_SEQUENCE; + tag = ber_next_element( ber, &len, rdn_end )) { + + *newRDN++ = newAVA; + tag = ber_skip_tag( ber, &len ); + tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM ); + if ( tag != LBER_TAG_OID ) { + rc = LDAP_DECODING_ERROR; + goto nomem; + } + + oid2.bv_val = oidptr; + oid2.bv_len = oidrem; + if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) { + rc = LDAP_DECODING_ERROR; + goto nomem; + } + oidname = find_oid( &oid2 ); + if ( !oidname ) { + newAVA->la_attr = oid2; + oidptr += oid2.bv_len + 1; + oidrem -= oid2.bv_len + 1; + + /* Running out of OID buffer space? */ + if (oidrem < 128) { + if ( oidsize == 0 ) { + oidsize = sizeof(oids) * 2; + oidrem = oidsize; + oidbuf = LDAP_MALLOC( oidsize ); + if ( oidbuf == NULL ) goto nomem; + oidptr = oidbuf; + } else { + char *old = oidbuf; + oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 ); + if ( oidbuf == NULL ) goto nomem; + /* Buffer moved! Fix AVA pointers */ + if ( old != oidbuf ) { + LDAPAVA *a; + long dif = oidbuf - old; + + for (a=baseAVA; a<=newAVA; a++){ + if (a->la_attr.bv_val >= old && + a->la_attr.bv_val <= (old + oidsize)) + a->la_attr.bv_val += dif; + } + } + oidptr = oidbuf + oidsize - oidrem; + oidrem += oidsize; + oidsize *= 2; + } + } + } else { + if ( func ) { + newAVA->la_attr = oidname->oid; + } else { + newAVA->la_attr = oidname->name; + } + } + newAVA->la_private = NULL; + newAVA->la_flags = LDAP_AVA_STRING; + tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM ); + switch(tag) { + case LBER_TAG_UNIVERSAL: + /* This uses 32-bit ISO 10646-1 */ + csize = 4; goto to_utf8; + case LBER_TAG_BMP: + /* This uses 16-bit ISO 10646-1 */ + csize = 2; goto to_utf8; + case LBER_TAG_TELETEX: + /* This uses 8-bit, assume ISO 8859-1 */ + csize = 1; +to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value ); + newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; +allocd: + newAVA->la_flags |= LDAP_AVA_FREE_VALUE; + if (rc != LDAP_SUCCESS) goto nomem; + break; + case LBER_TAG_UTF8: + newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; + /* This is already in UTF-8 encoding */ + case LBER_TAG_IA5: + case LBER_TAG_PRINTABLE: + /* These are always 7-bit strings */ + newAVA->la_value = Val; + break; + case LBER_BITSTRING: + /* X.690 bitString value converted to RFC4517 Bit String */ + rc = der_to_ldap_BitString( &Val, &newAVA->la_value ); + goto allocd; + case LBER_DEFAULT: + /* decode error */ + rc = LDAP_DECODING_ERROR; + goto nomem; + default: + /* Not a string type at all */ + newAVA->la_flags = 0; + newAVA->la_value = Val; + break; + } + newAVA++; + } + *newRDN++ = NULL; + tag = ber_next_element( ber, &len, dn_end ); + } + + if ( func ) { + rc = func( newDN, flags, NULL ); + if ( rc != LDAP_SUCCESS ) + goto nomem; + } + + rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL ); + +nomem: + for (;baseAVA < newAVA; baseAVA++) { + if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR) + LDAP_FREE( baseAVA->la_attr.bv_val ); + if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE) + LDAP_FREE( baseAVA->la_value.bv_val ); + } + + if ( oidsize != 0 ) + LDAP_FREE( oidbuf ); + if ( newDN != (LDAPDN)(char *) ptrs ) + LDAP_FREE( newDN ); + return rc; +} diff --git a/libs/ldap/libldap/tls_w.c b/libs/ldap/libldap/tls_w.c new file mode 100644 index 00000000000..137fb58a27a --- /dev/null +++ b/libs/ldap/libldap/tls_w.c @@ -0,0 +1,659 @@ +/* tls_w.c - Handle tls/ssl using Windows SSPI SChannel provider. */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 2008-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ + +#include "portable.h" +#include "ldap_config.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/ctype.h> +#include <ac/time.h> +#include <ac/unistd.h> +#include <ac/param.h> +#include <ac/dirent.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "ldap-int.h" +#include "ldap-tls.h" + +#include <sspi.h> +#include <schannel.h> + +typedef struct tlsw_ctx { + int refcount; + int reqcert; +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_t ref_mutex; +#endif +} tlsw_ctx; + +typedef struct tlsw_session { + CredHandle cred_handle; + CtxtHandle ctxt_handle; + Sockbuf_IO_Desc *sbiod; + struct berval peer_der_dn; +} tlsw_session; + +#ifdef LDAP_R_COMPILE + +static void +tlsw_thr_init( void ) +{ + /* do nothing */ +} +#endif /* LDAP_R_COMPILE */ + +/* + * Initialize TLS subsystem. Should be called only once. + */ +static int +tlsw_init( void ) +{ + struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); + lo->ldo_debug = -1; + /* do nothing */ + return 0; +} + +/* + * Tear down the TLS subsystem. Should only be called once. + */ +static void +tlsw_destroy( void ) +{ + /* do nothing */ +} + +static tls_ctx * +tlsw_ctx_new( struct ldapoptions *lo ) +{ + tlsw_ctx *ctx; + + ctx = ber_memcalloc ( 1, sizeof (*ctx) ); + if ( ctx ) { + ctx->refcount = 1; +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &ctx->ref_mutex ); +#endif + } + return (tls_ctx *)ctx; +} + +static void +tlsw_ctx_ref( tls_ctx *ctx ) +{ + tlsw_ctx *c = (tlsw_ctx *)ctx; + LDAP_MUTEX_LOCK( &c->ref_mutex ); + c->refcount++; + LDAP_MUTEX_UNLOCK( &c->ref_mutex ); +} + +static void +tlsw_ctx_free( tls_ctx *ctx ) +{ + tlsw_ctx *c = (tlsw_ctx *)ctx; + int refcount; + + if ( !c ) return; + + LDAP_MUTEX_LOCK( &c->ref_mutex ); + refcount = --c->refcount; + LDAP_MUTEX_UNLOCK( &c->ref_mutex ); + if ( refcount ) + return; + ber_memfree ( c ); +} + +/* + * initialize a new TLS context + */ +static int +tlsw_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) +{ + tlsw_ctx *ctx = lo->ldo_tls_ctx; + + ctx->reqcert = lo->ldo_tls_require_cert; + return 0; +} + +static tls_session * +tlsw_session_new( tls_ctx * ctx, int is_server ) +{ + tlsw_session *session; + SCHANNEL_CRED cred; + + session = ber_memcalloc ( 1, sizeof (*session) ); + if ( !session ) + return NULL; + + memset( &cred, 0, sizeof(cred) ); + cred.dwVersion = SCHANNEL_CRED_VERSION; /* FIXME set other fields */ + if ( AcquireCredentialsHandleA( NULL, (SEC_CHAR *)UNISP_NAME_A, + is_server ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, + &cred, NULL, NULL, &session->cred_handle, NULL )) { + ber_memfree( session ); + return NULL; + } + return (tls_session *)session; +} + +static int +tlsw_session_accept( tls_session *session ) +{ + return -1; +} + +static ssize_t +tlsw_recv( Sockbuf_IO_Desc *sbiod, void *buf, size_t len ) +{ + tlsw_session *session; + + if ( sbiod == NULL || buf == NULL || len <= 0 ) return 0; + + return LBER_SBIOD_READ_NEXT( sbiod, buf, len ); +} + +static ssize_t +tlsw_send( Sockbuf_IO_Desc *sbiod, const void *buf, size_t len ) +{ + tlsw_session *session; + + if ( sbiod == NULL || buf == NULL || len <= 0 ) return 0; + + return LBER_SBIOD_WRITE_NEXT( sbiod, (char *)buf, len ); +} + +#define TLS_HEADER_SIZE 5 +static int +tlsw_session_connect( LDAP *ld, tls_session *session, const char *name_in ) +{ + tlsw_session *s = (tlsw_session *)session; + SecBuffer in_bufs[] = { { 0, SECBUFFER_TOKEN, NULL }, { 0, SECBUFFER_EMPTY, NULL } }; + SecBuffer out_bufs[] = { { 0, SECBUFFER_TOKEN, NULL }, { 0, SECBUFFER_ALERT, NULL } }; + SecBufferDesc in_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(in_bufs), in_bufs }; + SecBufferDesc out_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(out_bufs), out_bufs }; + ULONG attrs, flags = ISC_REQ_CONFIDENTIALITY | ISC_REQ_STREAM | + ISC_REQ_USE_SUPPLIED_CREDS | ISC_REQ_ALLOCATE_MEMORY; + SECURITY_STATUS status; + ssize_t size, max_token, recv_offset = 0, expected = TLS_HEADER_SIZE; + SecPkgInfoA *info; + + status = QuerySecurityPackageInfoA( UNISP_NAME_A, &info ); + if ( status != SEC_E_OK ) + return -1; + expected = max_token = info->cbMaxToken; + FreeContextBuffer( info ); + + in_bufs[0].cbBuffer = max_token; + in_bufs[0].pvBuffer = ber_memalloc( in_bufs[0].cbBuffer ); + if ( !in_bufs[0].pvBuffer ) + return -1; + + status = InitializeSecurityContextA( &s->cred_handle, NULL, (SEC_CHAR *)name_in, + flags, 0, 0, NULL, 0, &s->ctxt_handle, &out_buf_desc, &attrs, NULL ); + while ( status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE ) + { + if ( status == SEC_I_CONTINUE_NEEDED ) { + size = tlsw_send( s->sbiod, out_bufs[0].pvBuffer, out_bufs[0].cbBuffer ); + if ( size < 0 ) + break; + expected = TLS_HEADER_SIZE; + in_bufs[0].cbBuffer = recv_offset = 0; + } + + while ( expected > 0 ) { + size = tlsw_recv( s->sbiod, (char *)in_bufs[0].pvBuffer + recv_offset, expected ); + if ( size < 0 ) + break; + in_bufs[0].cbBuffer += size; + recv_offset += size; + expected -= size; + } + + out_bufs[0].cbBuffer = max_token; + status = InitializeSecurityContextA( &s->cred_handle, &s->ctxt_handle, (SEC_CHAR *)name_in, + flags, 0, 0, &in_buf_desc, 0, NULL, &out_buf_desc, &attrs, NULL ); + if ( status == SEC_E_INCOMPLETE_MESSAGE ) { + assert( in_bufs[1].BufferType == SECBUFFER_MISSING ); + expected = in_bufs[1].cbBuffer; + in_bufs[1].BufferType = SECBUFFER_EMPTY; + in_bufs[1].cbBuffer = 0; + } + } + + ber_memfree( in_bufs[0].pvBuffer ); + FreeContextBuffer( out_bufs[0].pvBuffer ); + return status == SEC_E_OK ? 0 : -1; +} + +static int +tlsw_session_upflags( Sockbuf *sb, tls_session *session, int rc ) +{ + return -1; +} + +static char * +tlsw_session_errmsg( tls_session *session, int rc, char *buf, size_t len ) +{ + return NULL; +} + +static void +tlsw_x509_cert_dn( struct berval *cert, struct berval *dn, int get_subject ) +{ + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; + ber_tag_t tag; + ber_len_t len; + ber_int_t i; + + ber_init2( ber, cert, LBER_USE_DER ); + tag = ber_skip_tag( ber, &len ); /* Sequence */ + tag = ber_skip_tag( ber, &len ); /* Sequence */ + tag = ber_peek_tag( ber, &len ); /* Context + Constructed (version) */ + if ( tag == 0xa0 ) { /* Version is optional */ + tag = ber_skip_tag( ber, &len ); + tag = ber_get_int( ber, &i ); /* Int: Version */ + } + tag = ber_skip_tag( ber, &len ); /* Int: Serial (can be longer than ber_int_t) */ + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Sequence: Signature */ + ber_skip_data( ber, len ); + if ( !get_subject ) { + tag = ber_peek_tag( ber, &len ); /* Sequence: Issuer DN */ + } else { + tag = ber_skip_tag( ber, &len ); + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Sequence: Validity */ + ber_skip_data( ber, len ); + tag = ber_peek_tag( ber, &len ); /* Sequence: Subject DN */ + } + len = ber_ptrlen( ber ); + dn->bv_val = cert->bv_val + len; + dn->bv_len = cert->bv_len - len; +} + +static int +tlsw_session_my_dn( tls_session *session, struct berval *der_dn ) +{ + return -1; +} + +static int +tlsw_session_peer_dn( tls_session *session, struct berval *der_dn ) +{ + return -1; +} + +static int +tlsw_session_chkhost( LDAP *ld, tls_session *session, const char *name_in ) +{ + return 0; +} + +static int +tlsw_session_strength( tls_session *session ) +{ + return 0; +} + +static int +tlsw_session_unique( tls_session *session, struct berval *buf, int is_server ) +{ + return -1; +} + +static int +tlsw_session_endpoint( tls_session *session, struct berval *buf, int is_server ) +{ + return 0; +} + +static const char * +tlsw_session_version( tls_session *session ) +{ + return NULL; +} + +static const char * +tlsw_session_cipher( tls_session *session ) +{ + return NULL; +} + +static int +tlsw_session_peercert( tls_session *session, struct berval *der ) +{ + return -1; +} + +static int +tlsw_session_pinning( LDAP *ld, tls_session *session, char *hashalg, struct berval *hash ) +{ + return -1; +} + +/* + * TLS support for LBER Sockbufs + */ + +struct buffer +{ + char *buf; + size_t size; + size_t offset; +}; + +struct tls_data { + tlsw_session *session; + struct buffer header; + struct buffer data; + struct buffer trailer; + struct buffer recv; +}; + +static int +tlsw_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct tls_data *tls; + tlsw_session *session = arg; + SECURITY_STATUS status; + + assert( sbiod != NULL ); + + tls = ber_memcalloc( 1, sizeof( *tls ) ); + if ( tls == NULL ) { + return -1; + } + + tls->session = session; + sbiod->sbiod_pvt = tls; + session->sbiod = sbiod; + return 0; +} + +static int +tlsw_sb_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct tls_data *tls; + + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + tls = (struct tls_data *)sbiod->sbiod_pvt; + ber_memfree( tls->header.buf ); + ber_memfree( tls->data.buf ); + ber_memfree( tls->trailer.buf ); + ber_memfree( tls->recv.buf ); + DeleteSecurityContext( &tls->session->ctxt_handle ); + FreeCredentialsHandle( &tls->session->cred_handle ); + ber_memfree( tls->session ); + ber_memfree( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static int +tlsw_sb_close( Sockbuf_IO_Desc *sbiod ) +{ + /* FIXME: send close_notify message */ + return 0; +} + +static int +tlsw_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct tls_data *tls; + + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + + tls = (struct tls_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_GET_SSL ) { + *((tlsw_session **)arg) = tls->session; + return 1; + } + else if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( tls->data.offset > 0 || tls->recv.offset > 0 ) { + return 1; + } + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +static int alloc_buffer( struct buffer *buf, size_t size ) +{ + buf->size = size; + buf->offset = 0; + buf->buf = ber_memalloc( buf->size ); + return buf->buf != NULL; +} + +static int setup_buffers( struct tls_data *tls ) +{ + SecPkgContext_StreamSizes sizes; + SECURITY_STATUS status; + + if ( tls->header.buf ) + return 0; + + status = QueryContextAttributesA( &tls->session->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &sizes ); + if ( status != SEC_E_OK ) + return -1; + + if ( !alloc_buffer( &tls->header, sizes.cbHeader ) ) + return -1; + + if ( !alloc_buffer( &tls->data, sizes.cbMaximumMessage ) ) { + ber_memfree( tls->header.buf ); + return -1; + } + + if ( !alloc_buffer( &tls->trailer, sizes.cbTrailer ) ) { + ber_memfree( tls->header.buf ); + ber_memfree( tls->data.buf ); + return -1; + } + + if ( !alloc_buffer( &tls->recv, sizes.cbMaximumMessage ) ) { + ber_memfree( tls->header.buf ); + ber_memfree( tls->data.buf ); + ber_memfree( tls->trailer.buf ); + return -1; + } + + return 0; +} + +static void init_secbuf( SecBuffer *secbuf, DWORD type, void *buf, DWORD size ) { + secbuf->BufferType = type; + secbuf->cbBuffer = size; + secbuf->pvBuffer = buf; +} + +static ber_len_t remove_data( struct tls_data *tls, ber_len_t len ) +{ + tls->data.offset -= len; + memmove( tls->data.buf, tls->data.buf + len, tls->data.offset ); + return len; +} + +static int grow_buffer( struct buffer *buf, size_t min_size ) +{ + size_t size = max( min_size, buf->size * 2 ); + char *tmp; + + if ( buf->size >= min_size ) + return 0; + + tmp = ber_memrealloc( buf->buf, size ); + if ( !tmp ) + return -1; + buf->buf = tmp; + buf->size = size; + return 0; +} + +static ber_slen_t +tlsw_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *tls = sbiod->sbiod_pvt; + SecBuffer bufs[4]; + SecBufferDesc buf_desc = { SECBUFFER_VERSION, 4, bufs }; + SECURITY_STATUS status = SEC_E_OK; + ssize_t size, expected = max( len, tls->header.size ), ret = -1; + + if ( !len ) + return 0; + if ( setup_buffers( tls ) < 0 ) + return -1; + + if ( tls->data.offset >= len ) { + memcpy( buf, tls->data.buf, len ); + return remove_data( tls, len ); + } + +restart: + if ( grow_buffer( &tls->recv, expected ) < 0 ) + return -1; + while ( tls->recv.offset < expected ) { + size = tlsw_recv( sbiod, tls->recv.buf + tls->recv.offset, expected - tls->recv.offset ); + if ( size < 0 ) + return size; + tls->recv.offset += size; + } + + if ( grow_buffer( &tls->data, tls->data.offset + tls->recv.offset ) < 0 ) + return -1; + memcpy( tls->data.buf + tls->data.offset, tls->recv.buf, tls->recv.offset ); + + init_secbuf( &bufs[0], SECBUFFER_DATA, tls->data.buf + tls->data.offset, tls->recv.offset ); + init_secbuf( &bufs[1], SECBUFFER_EMPTY, NULL, 0 ); + init_secbuf( &bufs[2], SECBUFFER_EMPTY, NULL, 0 ); + init_secbuf( &bufs[3], SECBUFFER_EMPTY, NULL, 0 ); + + status = DecryptMessage( &tls->session->ctxt_handle, &buf_desc, 0, NULL ); + if ( status == SEC_E_OK ) { + assert( bufs[0].BufferType == SECBUFFER_STREAM_HEADER ); + assert( bufs[1].BufferType == SECBUFFER_DATA ); + assert( (char *)bufs[1].pvBuffer == (char *)bufs[0].pvBuffer + tls->header.size ); + + tls->recv.offset = 0; + memmove( tls->data.buf, tls->data.buf + tls->header.size, bufs[1].cbBuffer ); + tls->data.offset += bufs[1].cbBuffer; + if ( tls->data.offset >= len ) { + memcpy( buf, tls->data.buf, len ); + ret = remove_data( tls, len ); + } + } + else if ( status == SEC_E_INCOMPLETE_MESSAGE ) { + assert( bufs[1].BufferType == SECBUFFER_MISSING ); + expected = bufs[1].cbBuffer; + goto restart; + } + + return ret; +} + +static ber_slen_t +tlsw_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *tls = sbiod->sbiod_pvt; + SecBuffer bufs[3]; + SecBufferDesc buf_desc = { SECBUFFER_VERSION, 3, bufs }; + SECURITY_STATUS status; + ssize_t size, ret = len; + unsigned int i; + + if ( !len ) + return 0; + if ( setup_buffers( tls ) < 0 ) + return -1; + + init_secbuf( &bufs[0], SECBUFFER_STREAM_HEADER, tls->header.buf, tls->header.size ); + init_secbuf( &bufs[1], SECBUFFER_DATA, buf, len ); + init_secbuf( &bufs[2], SECBUFFER_STREAM_TRAILER, tls->trailer.buf, tls->trailer.size ); + + status = EncryptMessage( &tls->session->ctxt_handle, 0, &buf_desc, 0 ); + if ( status != SEC_E_OK ) + ret = -1; + else { + for ( i = 0; i < 3; i++ ) { + size = tlsw_send( sbiod, bufs[i].pvBuffer, bufs[i].cbBuffer ); + if ( size < 0 ) { + ret = -1; + break; + } + } + } + + return ret; +} + +static Sockbuf_IO tlsw_sbio = +{ + tlsw_sb_setup, /* sbi_setup */ + tlsw_sb_remove, /* sbi_remove */ + tlsw_sb_ctrl, /* sbi_ctrl */ + tlsw_sb_read, /* sbi_read */ + tlsw_sb_write, /* sbi_write */ + tlsw_sb_close /* sbi_close */ +}; + +tls_impl ldap_int_tls_impl = { + "Windows SSPI SChannel", + + tlsw_init, + tlsw_destroy, + + tlsw_ctx_new, + tlsw_ctx_ref, + tlsw_ctx_free, + tlsw_ctx_init, + + tlsw_session_new, + tlsw_session_connect, + tlsw_session_accept, + tlsw_session_upflags, + tlsw_session_errmsg, + tlsw_session_my_dn, + tlsw_session_peer_dn, + tlsw_session_chkhost, + tlsw_session_strength, + tlsw_session_unique, + tlsw_session_endpoint, + tlsw_session_version, + tlsw_session_cipher, + tlsw_session_peercert, + tlsw_session_pinning, + + &tlsw_sbio, + +#ifdef LDAP_R_COMPILE + tlsw_thr_init, +#else + NULL, +#endif + + 0 +}; diff --git a/libs/ldap/libldap/unbind.c b/libs/ldap/libldap/unbind.c new file mode 100644 index 00000000000..820d48feae8 --- /dev/null +++ b/libs/ldap/libldap/unbind.c @@ -0,0 +1,319 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1990 Regents of the University of Michigan. + * All rights reserved. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* An Unbind Request looks like this: + * + * UnbindRequest ::= [APPLICATION 2] NULL + * + * and has no response. (Source: RFC 4511) + */ + +int +ldap_unbind_ext( + LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int rc; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + /* check client controls */ + rc = ldap_int_client_controls( ld, cctrls ); + if( rc != LDAP_SUCCESS ) return rc; + + return ldap_ld_free( ld, 1, sctrls, cctrls ); +} + +int +ldap_unbind_ext_s( + LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + return ldap_unbind_ext( ld, sctrls, cctrls ); +} + +int +ldap_unbind( LDAP *ld ) +{ + Debug0( LDAP_DEBUG_TRACE, "ldap_unbind\n" ); + + return( ldap_unbind_ext( ld, NULL, NULL ) ); +} + + +int +ldap_ld_free( + LDAP *ld, + int close, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + LDAPMessage *lm, *next; + int err = LDAP_SUCCESS; + + LDAP_MUTEX_LOCK( &ld->ld_ldcmutex ); + /* Someone else is still using this ld. */ + if (ld->ld_ldcrefcnt > 1) { /* but not last thread */ + /* clean up self only */ + ld->ld_ldcrefcnt--; + if ( ld->ld_error != NULL ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + + if ( ld->ld_matched != NULL ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + if ( ld->ld_referrals != NULL) { + LDAP_VFREE(ld->ld_referrals); + ld->ld_referrals = NULL; + } + LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); + LDAP_FREE( (char *) ld ); + return( err ); + } + + /* This ld is the last thread. */ + LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); + + /* free LDAP structure and outstanding requests/responses */ + LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); + ldap_tavl_free( ld->ld_requests, ldap_do_free_request ); + ld->ld_requests = NULL; + LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); + LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); + + /* free and unbind from all open connections */ + while ( ld->ld_conns != NULL ) { + ldap_free_connection( ld, ld->ld_conns, 1, close ); + } + LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); + LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); + for ( lm = ld->ld_responses; lm != NULL; lm = next ) { + next = lm->lm_next; + ldap_msgfree( lm ); + } + + if ( ld->ld_abandoned != NULL ) { + LDAP_FREE( ld->ld_abandoned ); + ld->ld_abandoned = NULL; + } + LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); + + /* Should already be closed by ldap_free_connection which knows not to free + * this one */ + ber_int_sb_destroy( ld->ld_sb ); + LBER_FREE( ld->ld_sb ); + + LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex ); + + /* final close callbacks */ + { + ldaplist *ll, *next; + + for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) { + ldap_conncb *cb = ll->ll_data; + next = ll->ll_next; + cb->lc_del( ld, NULL, cb ); + LDAP_FREE( ll ); + } + } + + if ( ld->ld_error != NULL ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + + if ( ld->ld_matched != NULL ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + if ( ld->ld_referrals != NULL) { + LDAP_VFREE(ld->ld_referrals); + ld->ld_referrals = NULL; + } + + if ( ld->ld_selectinfo != NULL ) { + ldap_free_select_info( ld->ld_selectinfo ); + ld->ld_selectinfo = NULL; + } + + if ( ld->ld_options.ldo_defludp != NULL ) { + ldap_free_urllist( ld->ld_options.ldo_defludp ); + ld->ld_options.ldo_defludp = NULL; + } + + if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ) { + LDAP_FREE( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ); + memset( & ld->ld_options.ldo_local_ip_addrs, 0, + sizeof( ldapsourceip ) ); + } + +#ifdef LDAP_CONNECTIONLESS + if ( ld->ld_options.ldo_peer != NULL ) { + LDAP_FREE( ld->ld_options.ldo_peer ); + ld->ld_options.ldo_peer = NULL; + } + + if ( ld->ld_options.ldo_cldapdn != NULL ) { + LDAP_FREE( ld->ld_options.ldo_cldapdn ); + ld->ld_options.ldo_cldapdn = NULL; + } +#endif + + if ( ld->ld_options.ldo_defbase != NULL ) { + LDAP_FREE( ld->ld_options.ldo_defbase ); + ld->ld_options.ldo_defbase = NULL; + } + +#ifdef HAVE_CYRUS_SASL + if ( ld->ld_options.ldo_def_sasl_mech != NULL ) { + LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); + ld->ld_options.ldo_def_sasl_mech = NULL; + } + + if ( ld->ld_options.ldo_def_sasl_realm != NULL ) { + LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); + ld->ld_options.ldo_def_sasl_realm = NULL; + } + + if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) { + LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); + ld->ld_options.ldo_def_sasl_authcid = NULL; + } + + if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) { + LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); + ld->ld_options.ldo_def_sasl_authzid = NULL; + } +#endif + +#ifdef HAVE_TLS + ldap_int_tls_destroy( &ld->ld_options ); +#endif + + if ( ld->ld_options.ldo_sctrls != NULL ) { + ldap_controls_free( ld->ld_options.ldo_sctrls ); + ld->ld_options.ldo_sctrls = NULL; + } + + if ( ld->ld_options.ldo_cctrls != NULL ) { + ldap_controls_free( ld->ld_options.ldo_cctrls ); + ld->ld_options.ldo_cctrls = NULL; + } + LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex ); + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex ); + ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex ); +#endif +#ifndef NDEBUG + LDAP_TRASH(ld); +#endif + LDAP_FREE( (char *) ld->ldc ); + LDAP_FREE( (char *) ld ); + + return( err ); +} + +int +ldap_destroy( LDAP *ld ) +{ + return ( ldap_ld_free( ld, 1, NULL, NULL ) ); +} + +int +ldap_unbind_s( LDAP *ld ) +{ + return( ldap_unbind_ext( ld, NULL, NULL ) ); +} + +/* FIXME: this function is called only by ldap_free_connection(), + * which, most of the times, is called with ld_req_mutex locked */ +int +ldap_send_unbind( + LDAP *ld, + Sockbuf *sb, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + BerElement *ber; + ber_int_t id; + + Debug0( LDAP_DEBUG_TRACE, "ldap_send_unbind\n" ); + +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld)) + return LDAP_SUCCESS; +#endif + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( ld->ld_errno ); + } + + LDAP_NEXT_MSGID(ld, id); + + /* fill it in */ + if ( ber_printf( ber, "{itn" /*}*/, id, + LDAP_REQ_UNBIND ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( ld->ld_errno ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return ld->ld_errno; + } + + if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( ld->ld_errno ); + } + + ld->ld_errno = LDAP_SUCCESS; + /* send the message */ + if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { + ld->ld_errno = LDAP_SERVER_DOWN; + } + + return( ld->ld_errno ); +} diff --git a/libs/ldap/libldap/url.c b/libs/ldap/libldap/url.c new file mode 100644 index 00000000000..06eb675c2aa --- /dev/null +++ b/libs/ldap/libldap/url.c @@ -0,0 +1,1652 @@ +/* LIBLDAP url.c -- LDAP URL (RFC 4516) related routines */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (c) 1996 Regents of the University of Michigan. + * All rights reserved. + */ + + +/* + * LDAP URLs look like this: + * [p]ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] + * + * where: + * attributes is a comma separated list + * scope is one of these three strings: base one sub (default=base) + * filter is an string-represented filter as in RFC 4515 + * + * e.g., ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension + * + * We also tolerate URLs that look like: <ldapurl> and URL:ldapurl + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> +#include <ac/ctype.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* local functions */ +static const char* skip_url_prefix LDAP_P(( + const char *url, + int *enclosedp, + const char **scheme )); + +int ldap_pvt_url_scheme2proto( const char *scheme ) +{ + assert( scheme != NULL ); + + if( scheme == NULL ) { + return -1; + } + + if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) { + return LDAP_PROTO_TCP; + } + + if( strcmp("ldapi", scheme) == 0 ) { + return LDAP_PROTO_IPC; + } + + if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) { + return LDAP_PROTO_TCP; + } +#ifdef LDAP_CONNECTIONLESS + if( strcmp("cldap", scheme) == 0 ) { + return LDAP_PROTO_UDP; + } +#endif + + return -1; +} + +int ldap_pvt_url_scheme_port( const char *scheme, int port ) +{ + assert( scheme != NULL ); + + if( port ) return port; + if( scheme == NULL ) return port; + + if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) { + return LDAP_PORT; + } + + if( strcmp("ldapi", scheme) == 0 ) { + return -1; + } + + if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) { + return LDAPS_PORT; + } + +#ifdef LDAP_CONNECTIONLESS + if( strcmp("cldap", scheme) == 0 ) { + return LDAP_PORT; + } +#endif + + return -1; +} + +int +ldap_pvt_url_scheme2tls( const char *scheme ) +{ + assert( scheme != NULL ); + + if( scheme == NULL ) { + return -1; + } + + return strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0; +} + +int +ldap_pvt_url_scheme2proxied( const char *scheme ) +{ + assert( scheme != NULL ); + + if( scheme == NULL ) { + return -1; + } + + return strcmp("pldap", scheme) == 0 || strcmp("pldaps", scheme) == 0; +} + +int +ldap_is_ldap_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return 1; +} + +int +ldap_is_ldaps_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return strcmp(scheme, "ldaps") == 0 || strcmp(scheme, "pldaps") == 0; +} + +int +ldap_is_ldapi_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return strcmp(scheme, "ldapi") == 0; +} + +#ifdef LDAP_CONNECTIONLESS +int +ldap_is_ldapc_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return strcmp(scheme, "cldap") == 0; +} +#endif + +static const char* +skip_url_prefix( + const char *url, + int *enclosedp, + const char **scheme ) +{ + /* + * 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 + */ + const char *p; + + if ( url == NULL ) { + return( NULL ); + } + + p = url; + + /* skip leading '<' (if any) */ + if ( *p == '<' ) { + *enclosedp = 1; + ++p; + } else { + *enclosedp = 0; + } + + /* skip leading "URL:" (if any) */ + if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { + p += LDAP_URL_URLCOLON_LEN; + } + + /* check for "ldap://" prefix */ + if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldap://" prefix and return success */ + p += LDAP_URL_PREFIX_LEN; + *scheme = "ldap"; + return( p ); + } + + /* check for "pldap://" prefix */ + if ( strncasecmp( p, PLDAP_URL_PREFIX, PLDAP_URL_PREFIX_LEN ) == 0 ) { + /* skip over "pldap://" prefix and return success */ + p += PLDAP_URL_PREFIX_LEN; + *scheme = "pldap"; + return( p ); + } + + /* check for "ldaps://" prefix */ + if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldaps://" prefix and return success */ + p += LDAPS_URL_PREFIX_LEN; + *scheme = "ldaps"; + return( p ); + } + + /* check for "pldaps://" prefix */ + if ( strncasecmp( p, PLDAPS_URL_PREFIX, PLDAPS_URL_PREFIX_LEN ) == 0 ) { + /* skip over "pldaps://" prefix and return success */ + p += PLDAPS_URL_PREFIX_LEN; + *scheme = "pldaps"; + return( p ); + } + + /* check for "ldapi://" prefix */ + if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldapi://" prefix and return success */ + p += LDAPI_URL_PREFIX_LEN; + *scheme = "ldapi"; + return( p ); + } + +#ifdef LDAP_CONNECTIONLESS + /* check for "cldap://" prefix */ + if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { + /* skip over "cldap://" prefix and return success */ + p += LDAPC_URL_PREFIX_LEN; + *scheme = "cldap"; + return( p ); + } +#endif + + return( NULL ); +} + +int +ldap_pvt_scope2bv( int scope, struct berval *bv ) +{ + switch ( scope ) { + case LDAP_SCOPE_BASE: + BER_BVSTR( bv, "base" ); + break; + + case LDAP_SCOPE_ONELEVEL: + BER_BVSTR( bv, "one" ); + break; + + case LDAP_SCOPE_SUBTREE: + BER_BVSTR( bv, "sub" ); + break; + + case LDAP_SCOPE_SUBORDINATE: + BER_BVSTR( bv, "subordinate" ); + break; + + default: + return LDAP_OTHER; + } + + return LDAP_SUCCESS; +} + +const char * +ldap_pvt_scope2str( int scope ) +{ + struct berval bv; + + if ( ldap_pvt_scope2bv( scope, &bv ) == LDAP_SUCCESS ) { + return bv.bv_val; + } + + return NULL; +} + +int +ldap_pvt_bv2scope( struct berval *bv ) +{ + static struct { + struct berval bv; + int scope; + } v[] = { + { BER_BVC( "one" ), LDAP_SCOPE_ONELEVEL }, + { BER_BVC( "onelevel" ), LDAP_SCOPE_ONELEVEL }, + { BER_BVC( "base" ), LDAP_SCOPE_BASE }, + { BER_BVC( "sub" ), LDAP_SCOPE_SUBTREE }, + { BER_BVC( "subtree" ), LDAP_SCOPE_SUBTREE }, + { BER_BVC( "subord" ), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC( "subordinate" ), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC( "children" ), LDAP_SCOPE_SUBORDINATE }, + { BER_BVNULL, -1 } + }; + int i; + + for ( i = 0; v[ i ].scope != -1; i++ ) { + if ( ber_bvstrcasecmp( bv, &v[ i ].bv ) == 0 ) { + return v[ i ].scope; + } + } + + return( -1 ); +} + +int +ldap_pvt_str2scope( const char *p ) +{ + struct berval bv; + + ber_str2bv( p, 0, 0, &bv ); + + return ldap_pvt_bv2scope( &bv ); +} + +static const char hex[] = "0123456789ABCDEF"; + +#define URLESC_NONE 0x0000U +#define URLESC_COMMA 0x0001U +#define URLESC_SLASH 0x0002U + +static int +hex_escape_len( const char *s, unsigned list ) +{ + int len; + + if ( s == NULL ) { + return 0; + } + + for ( len = 0; s[0]; s++ ) { + switch ( s[0] ) { + /* RFC 2396: reserved */ + case '?': + len += 3; + break; + + case ',': + if ( list & URLESC_COMMA ) { + len += 3; + } else { + len++; + } + break; + + case '/': + if ( list & URLESC_SLASH ) { + len += 3; + } else { + len++; + } + break; + + case ';': + case ':': + case '@': + case '&': + case '=': + case '+': + case '$': + + /* RFC 2396: unreserved mark */ + case '-': + case '_': + case '.': + case '!': + case '~': + case '*': + case ''': + case '(': + case ')': + len++; + break; + + /* RFC 2396: unreserved alphanum */ + default: + if ( !isalnum( (unsigned char) s[0] ) ) { + len += 3; + } else { + len++; + } + break; + } + } + + return len; +} + +static int +hex_escape( char *buf, int len, const char *s, unsigned list ) +{ + int i; + int pos; + + if ( s == NULL ) { + return 0; + } + + for ( pos = 0, i = 0; s[i] && pos < len; i++ ) { + int escape = 0; + + switch ( s[i] ) { + /* RFC 2396: reserved */ + case '?': + escape = 1; + break; + + case ',': + if ( list & URLESC_COMMA ) { + escape = 1; + } + break; + + case '/': + if ( list & URLESC_SLASH ) { + escape = 1; + } + break; + + case ';': + case ':': + case '@': + case '&': + case '=': + case '+': + case '$': + + /* RFC 2396: unreserved mark */ + case '-': + case '_': + case '.': + case '!': + case '~': + case '*': + case ''': + case '(': + case ')': + break; + + /* RFC 2396: unreserved alphanum */ + default: + if ( !isalnum( (unsigned char) s[i] ) ) { + escape = 1; + } + break; + } + + if ( escape ) { + buf[pos++] = '%'; + buf[pos++] = hex[ (s[i] >> 4) & 0x0f ]; + buf[pos++] = hex[ s[i] & 0x0f ]; + + } else { + buf[pos++] = s[i]; + } + } + + buf[pos] = '\0'; + + return pos; +} + +static int +hex_escape_len_list( char **s, unsigned flags ) +{ + int len; + int i; + + if ( s == NULL ) { + return 0; + } + + len = 0; + for ( i = 0; s[i] != NULL; i++ ) { + if ( len ) { + len++; + } + len += hex_escape_len( s[i], flags ); + } + + return len; +} + +static int +hex_escape_list( char *buf, int len, char **s, unsigned flags ) +{ + int pos; + int i; + + if ( s == NULL ) { + return 0; + } + + pos = 0; + for ( i = 0; s[i] != NULL; i++ ) { + int curlen; + + if ( pos ) { + buf[pos++] = ','; + len--; + } + curlen = hex_escape( &buf[pos], len, s[i], flags ); + len -= curlen; + pos += curlen; + } + + return pos; +} + +static int +desc2str_len( LDAPURLDesc *u ) +{ + int sep = 0; + int len = 0; + int is_ipc = 0; + struct berval scope; + + if ( u == NULL || u->lud_scheme == NULL ) { + return -1; + } + + if ( !strcmp( "ldapi", u->lud_scheme )) { + is_ipc = 1; + } + + if ( u->lud_exts ) { + len += hex_escape_len_list( u->lud_exts, URLESC_COMMA ); + if ( !sep ) { + sep = 5; + } + } + + if ( u->lud_filter ) { + len += hex_escape_len( u->lud_filter, URLESC_NONE ); + if ( !sep ) { + sep = 4; + } + } + + if ( ldap_pvt_scope2bv( u->lud_scope, &scope ) == LDAP_SUCCESS ) { + len += scope.bv_len; + if ( !sep ) { + sep = 3; + } + } + + if ( u->lud_attrs ) { + len += hex_escape_len_list( u->lud_attrs, URLESC_NONE ); + if ( !sep ) { + sep = 2; + } + } + + if ( u->lud_dn && u->lud_dn[0] ) { + len += hex_escape_len( u->lud_dn, URLESC_NONE ); + if ( !sep ) { + sep = 1; + } + }; + + len += sep; + + if ( u->lud_port ) { + unsigned p = u->lud_port; + if ( p > 65535 ) + return -1; + + len += (p > 999 ? 5 + (p > 9999) : p > 99 ? 4 : 2 + (p > 9)); + } + + if ( u->lud_host && u->lud_host[0] ) { + char *ptr; + len += hex_escape_len( u->lud_host, URLESC_SLASH ); + if ( !is_ipc && ( ptr = strchr( u->lud_host, ':' ))) { + if ( strchr( ptr+1, ':' )) + len += 2; /* IPv6, [] */ + } + } + + len += strlen( u->lud_scheme ) + STRLENOF( "://" ); + + return len; +} + +static int +desc2str( LDAPURLDesc *u, char *s, int len ) +{ + int i; + int sep = 0; + int sofar = 0; + int is_v6 = 0; + int is_ipc = 0; + struct berval scope = BER_BVNULL; + char *ptr; + + if ( u == NULL ) { + return -1; + } + + if ( s == NULL ) { + return -1; + } + + if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) { + is_ipc = 1; + } + + ldap_pvt_scope2bv( u->lud_scope, &scope ); + + if ( u->lud_exts ) { + sep = 5; + } else if ( u->lud_filter ) { + sep = 4; + } else if ( !BER_BVISEMPTY( &scope ) ) { + sep = 3; + } else if ( u->lud_attrs ) { + sep = 2; + } else if ( u->lud_dn && u->lud_dn[0] ) { + sep = 1; + } + + if ( !is_ipc && u->lud_host && ( ptr = strchr( u->lud_host, ':' ))) { + if ( strchr( ptr+1, ':' )) + is_v6 = 1; + } + + if ( u->lud_port ) { + sofar = sprintf( s, "%s://%s%s%s:%d", u->lud_scheme, + is_v6 ? "[" : "", + u->lud_host ? u->lud_host : "", + is_v6 ? "]" : "", + u->lud_port ); + len -= sofar; + + } else { + sofar = sprintf( s, "%s://", u->lud_scheme ); + len -= sofar; + if ( u->lud_host && u->lud_host[0] ) { + if ( is_v6 ) { + s[sofar++] = '['; + len--; + } + i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH ); + sofar += i; + len -= i; + if ( is_v6 ) { + s[sofar++] = ']'; + len--; + } + } + } + + assert( len >= 0 ); + + if ( sep < 1 ) { + goto done; + } + + s[sofar++] = '/'; + len--; + + assert( len >= 0 ); + + if ( u->lud_dn && u->lud_dn[0] ) { + i = hex_escape( &s[sofar], len, u->lud_dn, URLESC_NONE ); + sofar += i; + len -= i; + + assert( len >= 0 ); + } + + if ( sep < 2 ) { + goto done; + } + s[sofar++] = '?'; + len--; + + assert( len >= 0 ); + + i = hex_escape_list( &s[sofar], len, u->lud_attrs, URLESC_NONE ); + sofar += i; + len -= i; + + assert( len >= 0 ); + + if ( sep < 3 ) { + goto done; + } + s[sofar++] = '?'; + len--; + + assert( len >= 0 ); + + if ( !BER_BVISNULL( &scope ) ) { + strcpy( &s[sofar], scope.bv_val ); + sofar += scope.bv_len; + len -= scope.bv_len; + } + + assert( len >= 0 ); + + if ( sep < 4 ) { + goto done; + } + s[sofar++] = '?'; + len--; + + assert( len >= 0 ); + + i = hex_escape( &s[sofar], len, u->lud_filter, URLESC_NONE ); + sofar += i; + len -= i; + + assert( len >= 0 ); + + if ( sep < 5 ) { + goto done; + } + s[sofar++] = '?'; + len--; + + assert( len >= 0 ); + + i = hex_escape_list( &s[sofar], len, u->lud_exts, URLESC_COMMA ); + sofar += i; + len -= i; + + assert( len >= 0 ); + +done: + if ( len < 0 ) { + return -1; + } + + return sofar; +} + +char * +ldap_url_desc2str( LDAPURLDesc *u ) +{ + int len; + char *s; + + if ( u == NULL ) { + return NULL; + } + + len = desc2str_len( u ); + if ( len < 0 ) { + return NULL; + } + + /* allocate enough to hex escape everything -- overkill */ + s = LDAP_MALLOC( len + 1 ); + + if ( s == NULL ) { + return NULL; + } + + if ( desc2str( u, s, len ) != len ) { + LDAP_FREE( s ); + return NULL; + } + + s[len] = '\0'; + + return s; +} + +int +ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags ) +{ +/* + * Pick apart the pieces of an LDAP URL. + */ + + LDAPURLDesc *ludp; + char *p, *q, *r; + int i, enclosed, proto, is_v6 = 0; + const char *scheme = NULL; + const char *url_tmp; + char *url; + + int check_dn = 1; + + if( url_in == NULL || ludpp == NULL ) { + return LDAP_URL_ERR_PARAM; + } + +#ifndef LDAP_INT_IN_KERNEL + /* Global options may not be created yet + * We can't test if the global options are initialized + * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate + * the options and cause infinite recursion + */ + Debug1( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in ); +#endif + + *ludpp = NULL; /* pessimistic */ + + url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); + + if ( url_tmp == NULL ) { + return LDAP_URL_ERR_BADSCHEME; + } + + assert( scheme != NULL ); + + proto = ldap_pvt_url_scheme2proto( scheme ); + if ( proto == -1 ) { + return LDAP_URL_ERR_BADSCHEME; + } + + /* make working copy of the remainder of the URL */ + url = LDAP_STRDUP( url_tmp ); + if ( url == NULL ) { + return LDAP_URL_ERR_MEM; + } + + if ( enclosed ) { + p = &url[strlen(url)-1]; + + if( *p != '>' ) { + LDAP_FREE( url ); + return LDAP_URL_ERR_BADENCLOSURE; + } + + *p = '\0'; + } + + /* allocate return struct */ + ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); + + if ( ludp == NULL ) { + LDAP_FREE( url ); + return LDAP_URL_ERR_MEM; + } + + ludp->lud_next = NULL; + ludp->lud_host = NULL; + ludp->lud_port = 0; + ludp->lud_dn = NULL; + ludp->lud_attrs = NULL; + ludp->lud_scope = ( flags & LDAP_PVT_URL_PARSE_NODEF_SCOPE ) ? LDAP_SCOPE_BASE : LDAP_SCOPE_DEFAULT; + ludp->lud_filter = NULL; + ludp->lud_exts = NULL; + + ludp->lud_scheme = LDAP_STRDUP( scheme ); + + if ( ludp->lud_scheme == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + /* scan forward for '/' that marks end of hostport and begin. of dn */ + p = strchr( url, '/' ); + q = NULL; + + if( p != NULL ) { + /* terminate hostport; point to start of dn */ + *p++ = '\0'; + } else { + /* check for Novell kludge, see below */ + p = strchr( url, '?' ); + if ( p ) { + *p++ = '\0'; + q = p; + p = NULL; + } + } + + if ( proto != LDAP_PROTO_IPC ) { + /* IPv6 syntax with [ip address]:port */ + if ( *url == '[' ) { + r = strchr( url, ']' ); + if ( r == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + *r++ = '\0'; + q = strchr( r, ':' ); + if ( q && q != r ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + is_v6 = 1; + } else { + q = strchr( url, ':' ); + } + + if ( q != NULL ) { + char *next; + + *q++ = '\0'; + ldap_pvt_hex_unescape( q ); + + if( *q == '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + + ludp->lud_port = strtol( q, &next, 10 ); + if ( next == q || next[0] != '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + /* check for Novell kludge */ + if ( !p ) { + if ( *next != '\0' ) { + q = &next[1]; + } else { + q = NULL; + } + } + } + + if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) { + if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) { + ludp->lud_port = LDAPS_PORT; + } else { + ludp->lud_port = LDAP_PORT; + } + } + } + + ldap_pvt_hex_unescape( url ); + + /* If [ip address]:port syntax, url is [ip and we skip the [ */ + ludp->lud_host = LDAP_STRDUP( url + is_v6 ); + + if( ludp->lud_host == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + if ( ( flags & LDAP_PVT_URL_PARSE_NOEMPTY_HOST ) + && ludp->lud_host != NULL + && *ludp->lud_host == '\0' ) + { + LDAP_FREE( ludp->lud_host ); + ludp->lud_host = NULL; + } + + /* + * Kludge. ldap://111.222.333.444:389??cn=abc,o=company + * + * On early Novell releases, search references/referrals were returned + * in this format, i.e., the dn was kind of in the scope position, + * but the required slash is missing. The whole thing is illegal syntax, + * but we need to account for it. Fortunately it can't be confused with + * anything real. + */ + if( (p == NULL) && (q != NULL) && (*q == '?') ) { + /* ? immediately followed by question */ + q++; + if( *q != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( q ); + ludp->lud_dn = LDAP_STRDUP( q ); + + } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { + ludp->lud_dn = LDAP_STRDUP( "" ); + + } else { + check_dn = 0; + } + + if ( check_dn && ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + } + + if( p == NULL ) { + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of dn */ + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate dn part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( p ); + ludp->lud_dn = LDAP_STRDUP( p ); + + } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { + ludp->lud_dn = LDAP_STRDUP( "" ); + + } else { + check_dn = 0; + } + + if( check_dn && ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + if( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of attributes */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate attributes part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse attributes */ + ldap_pvt_hex_unescape( p ); + ludp->lud_attrs = ldap_str2charray( p, "," ); + + if( ludp->lud_attrs == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADATTRS; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of scope */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate the scope part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse the scope */ + ldap_pvt_hex_unescape( p ); + ludp->lud_scope = ldap_pvt_str2scope( p ); + + if( ludp->lud_scope == -1 ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADSCOPE; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of filter */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate the filter part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse the filter */ + ldap_pvt_hex_unescape( p ); + + if( ! *p ) { + /* missing filter */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADFILTER; + } + + ludp->lud_filter = LDAP_STRDUP( p ); + + if( ludp->lud_filter == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of extensions */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* extra '?' */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + + /* parse the extensions */ + ludp->lud_exts = ldap_str2charray( p, "," ); + + if( ludp->lud_exts == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADEXTS; + } + + for( i=0; ludp->lud_exts[i] != NULL; i++ ) { + ldap_pvt_hex_unescape( ludp->lud_exts[i] ); + + if( *ludp->lud_exts[i] == '!' ) { + /* count the number of critical extensions */ + ludp->lud_crit_exts++; + } + } + + if( i == 0 ) { + /* must have 1 or more */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADEXTS; + } + + /* no more */ + *ludpp = ludp; + LDAP_FREE( url ); + return LDAP_URL_SUCCESS; +} + +int +ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) +{ + return ldap_url_parse_ext( url_in, ludpp, LDAP_PVT_URL_PARSE_HISTORIC ); +} + +LDAPURLDesc * +ldap_url_dup ( LDAPURLDesc *ludp ) +{ + LDAPURLDesc *dest; + + if ( ludp == NULL ) { + return NULL; + } + + dest = LDAP_MALLOC( sizeof(LDAPURLDesc) ); + if (dest == NULL) + return NULL; + + *dest = *ludp; + dest->lud_scheme = NULL; + dest->lud_host = NULL; + dest->lud_dn = NULL; + dest->lud_filter = NULL; + dest->lud_attrs = NULL; + dest->lud_exts = NULL; + dest->lud_next = NULL; + + if ( ludp->lud_scheme != NULL ) { + dest->lud_scheme = LDAP_STRDUP( ludp->lud_scheme ); + if (dest->lud_scheme == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_host != NULL ) { + dest->lud_host = LDAP_STRDUP( ludp->lud_host ); + if (dest->lud_host == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_dn != NULL ) { + dest->lud_dn = LDAP_STRDUP( ludp->lud_dn ); + if (dest->lud_dn == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_filter != NULL ) { + dest->lud_filter = LDAP_STRDUP( ludp->lud_filter ); + if (dest->lud_filter == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_attrs != NULL ) { + dest->lud_attrs = ldap_charray_dup( ludp->lud_attrs ); + if (dest->lud_attrs == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + if ( ludp->lud_exts != NULL ) { + dest->lud_exts = ldap_charray_dup( ludp->lud_exts ); + if (dest->lud_exts == NULL) { + ldap_free_urldesc(dest); + return NULL; + } + } + + return dest; +} + +LDAPURLDesc * +ldap_url_duplist (LDAPURLDesc *ludlist) +{ + LDAPURLDesc *dest, *tail, *ludp, *newludp; + + dest = NULL; + tail = NULL; + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + newludp = ldap_url_dup(ludp); + if (newludp == NULL) { + ldap_free_urllist(dest); + return NULL; + } + if (tail == NULL) + dest = newludp; + else + tail->lud_next = newludp; + tail = newludp; + } + return dest; +} + +static int +ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags ) + +{ + int i, rc; + LDAPURLDesc *ludp; + char **urls; + + assert( ludlist != NULL ); + assert( url != NULL ); + + *ludlist = NULL; + + if ( sep == NULL ) { + sep = ", "; + } + + urls = ldap_str2charray( url, sep ); + if (urls == NULL) + return LDAP_URL_ERR_MEM; + + /* count the URLs... */ + for (i = 0; urls[i] != NULL; i++) ; + /* ...and put them in the "stack" backward */ + while (--i >= 0) { + rc = ldap_url_parse_ext( urls[i], &ludp, flags ); + if ( rc != 0 ) { + ldap_charray_free( urls ); + ldap_free_urllist( *ludlist ); + *ludlist = NULL; + return rc; + } + ludp->lud_next = *ludlist; + *ludlist = ludp; + } + ldap_charray_free( urls ); + return LDAP_URL_SUCCESS; +} + +int +ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) +{ + return ldap_url_parselist_int( ludlist, url, ", ", LDAP_PVT_URL_PARSE_HISTORIC ); +} + +int +ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags ) +{ + return ldap_url_parselist_int( ludlist, url, sep, flags ); +} + +int +ldap_url_parsehosts( + LDAPURLDesc **ludlist, + const char *hosts, + int port ) +{ + int i; + LDAPURLDesc *ludp; + char **specs, *p; + + assert( ludlist != NULL ); + assert( hosts != NULL ); + + *ludlist = NULL; + + specs = ldap_str2charray(hosts, ", "); + if (specs == NULL) + return LDAP_NO_MEMORY; + + /* count the URLs... */ + for (i = 0; specs[i] != NULL; i++) /* EMPTY */; + + /* ...and put them in the "stack" backward */ + while (--i >= 0) { + ludp = LDAP_CALLOC( 1, sizeof(LDAPURLDesc) ); + if (ludp == NULL) { + ldap_charray_free(specs); + ldap_free_urllist(*ludlist); + *ludlist = NULL; + return LDAP_NO_MEMORY; + } + ludp->lud_port = port; + ludp->lud_host = specs[i]; + p = strchr(ludp->lud_host, ':'); + if (p != NULL) { + /* more than one :, IPv6 address */ + if ( strchr(p+1, ':') != NULL ) { + /* allow [address] and [address]:port */ + if ( *ludp->lud_host == '[' ) { + p = strchr( ludp->lud_host+1, ']' ); + if ( p == NULL ) { + LDAP_FREE(ludp); + ldap_charray_free(specs); + return LDAP_PARAM_ERROR; + } + /* Truncate trailing ']' and shift hostname down 1 char */ + *p = '\0'; + AC_MEMCPY( ludp->lud_host, ludp->lud_host+1, p - ludp->lud_host ); + p++; + if ( *p != ':' ) { + if ( *p != '\0' ) { + LDAP_FREE(ludp); + ldap_charray_free(specs); + return LDAP_PARAM_ERROR; + } + p = NULL; + } + } else { + p = NULL; + } + } + if (p != NULL) { + char *next; + + *p++ = 0; + ldap_pvt_hex_unescape(p); + ludp->lud_port = strtol( p, &next, 10 ); + if ( next == p || next[0] != '\0' ) { + LDAP_FREE(ludp); + ldap_charray_free(specs); + return LDAP_PARAM_ERROR; + } + } + } + ludp->lud_scheme = LDAP_STRDUP("ldap"); + if ( ludp->lud_scheme == NULL ) { + LDAP_FREE(ludp); + ldap_charray_free(specs); + return LDAP_NO_MEMORY; + } + specs[i] = NULL; + ldap_pvt_hex_unescape(ludp->lud_host); + ludp->lud_next = *ludlist; + *ludlist = ludp; + } + + /* this should be an array of NULLs now */ + ldap_charray_free(specs); + return LDAP_SUCCESS; +} + +char * +ldap_url_list2hosts (LDAPURLDesc *ludlist) +{ + LDAPURLDesc *ludp; + int size; + char *s, *p, buf[32]; /* big enough to hold a long decimal # (overkill) */ + + if (ludlist == NULL) + return NULL; + + /* figure out how big the string is */ + size = 1; /* nul-term */ + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + if ( ludp->lud_host == NULL ) continue; + size += strlen(ludp->lud_host) + 1; /* host and space */ + if (strchr(ludp->lud_host, ':')) /* will add [ ] below */ + size += 2; + if (ludp->lud_port != 0) + size += sprintf(buf, ":%d", ludp->lud_port); + } + s = LDAP_MALLOC(size); + if (s == NULL) + return NULL; + + p = s; + for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { + if ( ludp->lud_host == NULL ) continue; + if (strchr(ludp->lud_host, ':')) { + p += sprintf(p, "[%s]", ludp->lud_host); + } else { + strcpy(p, ludp->lud_host); + p += strlen(ludp->lud_host); + } + if (ludp->lud_port != 0) + p += sprintf(p, ":%d", ludp->lud_port); + *p++ = ' '; + } + if (p != s) + p--; /* nuke that extra space */ + *p = '\0'; + return s; +} + +char * +ldap_url_list2urls( + LDAPURLDesc *ludlist ) +{ + LDAPURLDesc *ludp; + int size, sofar; + char *s; + + if ( ludlist == NULL ) { + return NULL; + } + + /* figure out how big the string is */ + for ( size = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) { + int len = desc2str_len( ludp ); + if ( len < 0 ) { + return NULL; + } + size += len + 1; + } + + s = LDAP_MALLOC( size ); + + if ( s == NULL ) { + return NULL; + } + + for ( sofar = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) { + int len; + + len = desc2str( ludp, &s[sofar], size ); + + if ( len < 0 ) { + LDAP_FREE( s ); + return NULL; + } + + sofar += len; + size -= len; + + s[sofar++] = ' '; + size--; + + assert( size >= 0 ); + } + + s[sofar - 1] = '\0'; + + return s; +} + +void +ldap_free_urllist( LDAPURLDesc *ludlist ) +{ + LDAPURLDesc *ludp, *next; + + for (ludp = ludlist; ludp != NULL; ludp = next) { + next = ludp->lud_next; + ldap_free_urldesc(ludp); + } +} + +void +ldap_free_urldesc( LDAPURLDesc *ludp ) +{ + if ( ludp == NULL ) { + return; + } + + if ( ludp->lud_scheme != NULL ) { + LDAP_FREE( ludp->lud_scheme ); + } + + if ( ludp->lud_host != NULL ) { + LDAP_FREE( ludp->lud_host ); + } + + if ( ludp->lud_dn != NULL ) { + LDAP_FREE( ludp->lud_dn ); + } + + if ( ludp->lud_filter != NULL ) { + LDAP_FREE( ludp->lud_filter); + } + + if ( ludp->lud_attrs != NULL ) { + LDAP_VFREE( ludp->lud_attrs ); + } + + if ( ludp->lud_exts != NULL ) { + LDAP_VFREE( ludp->lud_exts ); + } + + LDAP_FREE( ludp ); +} + +static int +ldap_int_is_hexpair( char *s ) +{ + int i; + + for ( i = 0; i < 2; i++ ) { + if ( s[i] >= '0' && s[i] <= '9' ) { + continue; + } + + if ( s[i] >= 'A' && s[i] <= 'F' ) { + continue; + } + + if ( s[i] >= 'a' && s[i] <= 'f' ) { + continue; + } + + return 0; + } + + return 1; +} + +static int +ldap_int_unhex( int c ) +{ + return( c >= '0' && c <= '9' ? c - '0' + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : c - 'a' + 10 ); +} + +void +ldap_pvt_hex_unescape( char *s ) +{ + /* + * Remove URL hex escapes from s... done in place. The basic concept for + * this routine is borrowed from the WWW library HTUnEscape() routine. + */ + char *p, + *save_s = s; + + for ( p = s; *s != '\0'; ++s ) { + if ( *s == '%' ) { + /* + * FIXME: what if '%' is followed + * by non-hexpair chars? + */ + if ( !ldap_int_is_hexpair( s + 1 ) ) { + p = save_s; + break; + } + + if ( *++s == '\0' ) { + break; + } + *p = ldap_int_unhex( *s ) << 4; + if ( *++s == '\0' ) { + break; + } + *p++ += ldap_int_unhex( *s ); + } else { + *p++ = *s; + } + } + + *p = '\0'; +} diff --git a/libs/ldap/libldap/utf-8.c b/libs/ldap/libldap/utf-8.c new file mode 100644 index 00000000000..97dd230669f --- /dev/null +++ b/libs/ldap/libldap/utf-8.c @@ -0,0 +1,562 @@ +/* utf-8.c -- Basic UTF-8 routines */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Basic UTF-8 routines + * + * These routines are "dumb". Though they understand UTF-8, + * they don't grok Unicode. That is, they can push bits, + * but don't have a clue what the bits represent. That's + * good enough for use with the LDAP Client SDK. + * + * These routines are not optimized. + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap_utf8.h" + +#include "ldap-int.h" +#include "ldap_defaults.h" + +/* + * return the number of bytes required to hold the + * NULL-terminated UTF-8 string NOT INCLUDING the + * termination. + */ +ber_len_t ldap_utf8_bytes( const char * p ) +{ + ber_len_t bytes; + + for( bytes=0; p[bytes]; bytes++ ) { + /* EMPTY */ ; + } + + return bytes; +} + +ber_len_t ldap_utf8_chars( const char * p ) +{ + /* could be optimized and could check for invalid sequences */ + ber_len_t chars=0; + + for( ; *p ; LDAP_UTF8_INCR(p) ) { + chars++; + } + + return chars; +} + +/* return offset to next character */ +int ldap_utf8_offset( const char * p ) +{ + return LDAP_UTF8_NEXT(p) - p; +} + +/* + * Returns length indicated by first byte. + */ +const char ldap_utf8_lentab[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 }; + +int ldap_utf8_charlen( const char * p ) +{ + if (!(*p & 0x80)) + return 1; + + return ldap_utf8_lentab[*(const unsigned char *)p ^ 0x80]; +} + +/* + * Make sure the UTF-8 char used the shortest possible encoding + * returns charlen if valid, 0 if not. + * + * Here are the valid UTF-8 encodings, taken from RFC 2279 page 4. + * The table is slightly modified from that of the RFC. + * + * UCS-4 range (hex) UTF-8 sequence (binary) + * 0000 0000-0000 007F 0....... + * 0000 0080-0000 07FF 110++++. 10...... + * 0000 0800-0000 FFFF 1110++++ 10+..... 10...... + * 0001 0000-001F FFFF 11110+++ 10++.... 10...... 10...... + * 0020 0000-03FF FFFF 111110++ 10+++... 10...... 10...... 10...... + * 0400 0000-7FFF FFFF 1111110+ 10++++.. 10...... 10...... 10...... 10...... + * + * The '.' bits are "don't cares". When validating a UTF-8 sequence, + * at least one of the '+' bits must be set, otherwise the character + * should have been encoded in fewer octets. Note that in the two-octet + * case, only the first octet needs to be validated, and this is done + * in the ldap_utf8_lentab[] above. + */ + +/* mask of required bits in second octet */ +#undef c +#define c const char +c ldap_utf8_mintab[] = { + (c)0x20, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, + (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, + (c)0x30, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, (c)0x80, + (c)0x38, (c)0x80, (c)0x80, (c)0x80, (c)0x3c, (c)0x80, (c)0x00, (c)0x00 }; +#undef c + +int ldap_utf8_charlen2( const char * p ) +{ + int i = LDAP_UTF8_CHARLEN( p ); + + if ( i > 2 ) { + if ( !( ldap_utf8_mintab[*p & 0x1f] & p[1] ) ) + i = 0; + } + return i; +} + +/* conv UTF-8 to UCS-4, useful for comparisons */ +ldap_ucs4_t ldap_x_utf8_to_ucs4( const char * p ) +{ + const unsigned char *c = (const unsigned char *) p; + ldap_ucs4_t ch; + int len, i; + static unsigned char mask[] = { + 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + + len = LDAP_UTF8_CHARLEN2(p, len); + + if( len == 0 ) return LDAP_UCS4_INVALID; + + ch = c[0] & mask[len]; + + for(i=1; i < len; i++) { + if ((c[i] & 0xc0) != 0x80) { + return LDAP_UCS4_INVALID; + } + + ch <<= 6; + ch |= c[i] & 0x3f; + } + + return ch; +} + +/* conv UCS-4 to UTF-8, not used */ +int ldap_x_ucs4_to_utf8( ldap_ucs4_t c, char *buf ) +{ + int len=0; + unsigned char* p = (unsigned char *) buf; + + /* not a valid Unicode character */ + if ( c < 0 ) return 0; + + /* Just return length, don't convert */ + if(buf == NULL) { + if( c < 0x80 ) return 1; + else if( c < 0x800 ) return 2; + else if( c < 0x10000 ) return 3; + else if( c < 0x200000 ) return 4; + else if( c < 0x4000000 ) return 5; + else return 6; + } + + if( c < 0x80 ) { + p[len++] = c; + + } else if( c < 0x800 ) { + p[len++] = 0xc0 | ( c >> 6 ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x10000 ) { + p[len++] = 0xe0 | ( c >> 12 ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x200000 ) { + p[len++] = 0xf0 | ( c >> 18 ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else if( c < 0x4000000 ) { + p[len++] = 0xf8 | ( c >> 24 ); + p[len++] = 0x80 | ( (c >> 18) & 0x3f ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + + } else /* if( c < 0x80000000 ) */ { + p[len++] = 0xfc | ( c >> 30 ); + p[len++] = 0x80 | ( (c >> 24) & 0x3f ); + p[len++] = 0x80 | ( (c >> 18) & 0x3f ); + p[len++] = 0x80 | ( (c >> 12) & 0x3f ); + p[len++] = 0x80 | ( (c >> 6) & 0x3f ); + p[len++] = 0x80 | ( c & 0x3f ); + } + + return len; +} + +#define LDAP_UCS_UTF8LEN(c) \ + c < 0 ? 0 : (c < 0x80 ? 1 : (c < 0x800 ? 2 : (c < 0x10000 ? 3 : \ + (c < 0x200000 ? 4 : (c < 0x4000000 ? 5 : 6))))) + +/* Convert a string to UTF-8 format. The input string is expected to + * have characters of 1, 2, or 4 octets (in network byte order) + * corresponding to the ASN.1 T61STRING, BMPSTRING, and UNIVERSALSTRING + * types respectively. (Here T61STRING just means that there is one + * octet per character and characters may use the high bit of the octet. + * The characters are assumed to use ISO mappings, no provision is made + * for converting from T.61 coding rules to Unicode.) + */ + +int +ldap_ucs_to_utf8s( struct berval *ucs, int csize, struct berval *utf8s ) +{ + unsigned char *in, *end; + char *ptr; + ldap_ucs4_t u; + int i, l = 0; + + utf8s->bv_val = NULL; + utf8s->bv_len = 0; + + in = (unsigned char *)ucs->bv_val; + + /* Make sure we stop at an even multiple of csize */ + end = in + ( ucs->bv_len & ~(csize-1) ); + + for (; in < end; ) { + u = *in++; + if (csize > 1) { + u <<= 8; + u |= *in++; + } + if (csize > 2) { + u <<= 8; + u |= *in++; + u <<= 8; + u |= *in++; + } + i = LDAP_UCS_UTF8LEN(u); + if (i == 0) + return LDAP_INVALID_SYNTAX; + l += i; + } + + utf8s->bv_val = LDAP_MALLOC( l+1 ); + if (utf8s->bv_val == NULL) + return LDAP_NO_MEMORY; + utf8s->bv_len = l; + + ptr = utf8s->bv_val; + for (in = (unsigned char *)ucs->bv_val; in < end; ) { + u = *in++; + if (csize > 1) { + u <<= 8; + u |= *in++; + } + if (csize > 2) { + u <<= 8; + u |= *in++; + u <<= 8; + u |= *in++; + } + ptr += ldap_x_ucs4_to_utf8(u, ptr); + } + *ptr = '\0'; + return LDAP_SUCCESS; +} + +/* + * Advance to the next UTF-8 character + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +char* ldap_utf8_next( const char * p ) +{ + int i; + const unsigned char *u = (const unsigned char *) p; + + if( LDAP_UTF8_ISASCII(u) ) { + return (char *) &p[1]; + } + + for( i=1; i<6; i++ ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return (char *) &p[i]; + } + } + + return (char *) &p[i]; +} + +/* + * Advance to the previous UTF-8 character + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +char* ldap_utf8_prev( const char * p ) +{ + int i; + const unsigned char *u = (const unsigned char *) p; + + for( i=-1; i>-6 ; i-- ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return (char *) &p[i]; + } + } + + return (char *) &p[i]; +} + +/* + * Copy one UTF-8 character from src to dst returning + * number of bytes copied. + * + * Ignores length of multibyte character, instead rely on + * continuation markers to find start of next character. + * This allows for "resyncing" of when invalid characters + * are provided provided the start of the next character + * is appears within the 6 bytes examined. + */ +int ldap_utf8_copy( char* dst, const char *src ) +{ + int i; + const unsigned char *u = (const unsigned char *) src; + + dst[0] = src[0]; + + if( LDAP_UTF8_ISASCII(u) ) { + return 1; + } + + for( i=1; i<6; i++ ) { + if ( ( u[i] & 0xc0 ) != 0x80 ) { + return i; + } + dst[i] = src[i]; + } + + return i; +} + +#ifndef UTF8_ALPHA_CTYPE +/* + * UTF-8 ctype routines + * Only deals with characters < 0x80 (ie: US-ASCII) + */ + +int ldap_utf8_isascii( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + return LDAP_ASCII(c); +} + +int ldap_utf8_isdigit( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_DIGIT( c ); +} + +int ldap_utf8_isxdigit( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_HEX(c); +} + +int ldap_utf8_isspace( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + switch(c) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\v': + case '\f': + return 1; + } + + return 0; +} + +/* + * These are not needed by the C SDK and are + * not "good enough" for general use. + */ +int ldap_utf8_isalpha( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_ALPHA(c); +} + +int ldap_utf8_isalnum( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_ALNUM(c); +} + +int ldap_utf8_islower( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_LOWER(c); +} + +int ldap_utf8_isupper( const char * p ) +{ + unsigned c = * (const unsigned char *) p; + + if(!LDAP_ASCII(c)) return 0; + + return LDAP_UPPER(c); +} +#endif + + +/* + * UTF-8 string routines + */ + +/* like strchr() */ +char * (ldap_utf8_strchr)( const char *str, const char *chr ) +{ + for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { + if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { + return (char *) str; + } + } + + return NULL; +} + +/* like strcspn() but returns number of bytes, not characters */ +ber_len_t (ldap_utf8_strcspn)( const char *str, const char *set ) +{ + const char *cstr; + const char *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { + if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { + return cstr - str; + } + } + } + + return cstr - str; +} + +/* like strspn() but returns number of bytes, not characters */ +ber_len_t (ldap_utf8_strspn)( const char *str, const char *set ) +{ + const char *cstr; + const char *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + for( cset = set; ; LDAP_UTF8_INCR(cset) ) { + if( *cset == '\0' ) { + return cstr - str; + } + + if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { + break; + } + } + } + + return cstr - str; +} + +/* like strpbrk(), replaces strchr() as well */ +char *(ldap_utf8_strpbrk)( const char *str, const char *set ) +{ + for( ; *str != '\0'; LDAP_UTF8_INCR(str) ) { + const char *cset; + + for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { + if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( cset ) ) { + return (char *) str; + } + } + } + + return NULL; +} + +/* like strtok_r(), not strtok() */ +char *(ldap_utf8_strtok)(char *str, const char *sep, char **last) +{ + char *begin; + char *end; + + if( last == NULL ) return NULL; + + begin = str ? str : *last; + + begin += ldap_utf8_strspn( begin, sep ); + + if( *begin == '\0' ) { + *last = NULL; + return NULL; + } + + end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; + + if( *end != '\0' ) { + char *next = LDAP_UTF8_NEXT( end ); + *end = '\0'; + end = next; + } + + *last = end; + return begin; +} diff --git a/libs/ldap/libldap/util-int.c b/libs/ldap/libldap/util-int.c new file mode 100644 index 00000000000..07a6f423463 --- /dev/null +++ b/libs/ldap/libldap/util-int.c @@ -0,0 +1,1026 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * Portions Copyright 1998 A. Hartgers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Bart Hartgers for inclusion in + * OpenLDAP Software. + */ + +/* + * util-int.c Various functions to replace missing threadsafe ones. + * Without the real *_r funcs, things will + * work, but might not be threadsafe. + */ + +#include "portable.h" + +#include <ac/stdlib.h> + +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#include "ldap-int.h" + +#ifndef h_errno +/* newer systems declare this in <netdb.h> for you, older ones don't. + * harmless to declare it again (unless defined by a macro). + */ +extern int h_errno; +#endif + +#ifdef HAVE_HSTRERROR +# define HSTRERROR(e) hstrerror(e) +#else +# define HSTRERROR(e) hp_strerror(e) +#endif + +#ifndef LDAP_R_COMPILE +# undef HAVE_REENTRANT_FUNCTIONS +# undef HAVE_CTIME_R +# undef HAVE_GETHOSTBYNAME_R +# undef HAVE_GETHOSTBYADDR_R + +#else +# include <ldap_pvt_thread.h> + ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; + ldap_pvt_thread_mutex_t ldap_int_hostname_mutex; + static ldap_pvt_thread_mutex_t ldap_int_gettime_mutex; + +# if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \ + && defined( CTIME_R_NARGS ) +# define USE_CTIME_R +# else + static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex; +# endif + +/* USE_GMTIME_R and USE_LOCALTIME_R defined in ldap_pvt.h */ + +#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) + /* we use the same mutex for gmtime(3) and localtime(3) + * because implementations may use the same buffer + * for both functions */ + static ldap_pvt_thread_mutex_t ldap_int_gmtime_mutex; +#endif + +# if defined(HAVE_GETHOSTBYNAME_R) && \ + (GETHOSTBYNAME_R_NARGS < 5) || (6 < GETHOSTBYNAME_R_NARGS) + /* Don't know how to handle this version, pretend it's not there */ +# undef HAVE_GETHOSTBYNAME_R +# endif +# if defined(HAVE_GETHOSTBYADDR_R) && \ + (GETHOSTBYADDR_R_NARGS < 7) || (8 < GETHOSTBYADDR_R_NARGS) + /* Don't know how to handle this version, pretend it's not there */ +# undef HAVE_GETHOSTBYADDR_R +# endif +#endif /* LDAP_R_COMPILE */ + +char *ldap_pvt_ctime( const time_t *tp, char *buf ) +{ +#ifdef USE_CTIME_R +# if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2) +# error "CTIME_R_NARGS should be 2 or 3" +# elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT) + return( ctime_r(tp,buf,26) < 0 ? 0 : buf ); +# elif CTIME_R_NARGS > 2 + return ctime_r(tp,buf,26); +# else + return ctime_r(tp,buf); +# endif + +#else + + LDAP_MUTEX_LOCK( &ldap_int_ctime_mutex ); + AC_MEMCPY( buf, ctime(tp), 26 ); + LDAP_MUTEX_UNLOCK( &ldap_int_ctime_mutex ); + + return buf; +#endif +} + +#if !defined( USE_GMTIME_R ) || !defined( USE_LOCALTIME_R ) +int +ldap_pvt_gmtime_lock( void ) +{ +# ifndef LDAP_R_COMPILE + return 0; +# else /* LDAP_R_COMPILE */ + return ldap_pvt_thread_mutex_lock( &ldap_int_gmtime_mutex ); +# endif /* LDAP_R_COMPILE */ +} + +int +ldap_pvt_gmtime_unlock( void ) +{ +# ifndef LDAP_R_COMPILE + return 0; +# else /* LDAP_R_COMPILE */ + return ldap_pvt_thread_mutex_unlock( &ldap_int_gmtime_mutex ); +# endif /* LDAP_R_COMPILE */ +} +#endif /* !USE_GMTIME_R || !USE_LOCALTIME_R */ + +#ifndef USE_GMTIME_R +struct tm * +ldap_pvt_gmtime( const time_t *timep, struct tm *result ) +{ + struct tm *tm_ptr; + + LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); + tm_ptr = gmtime( timep ); + if ( tm_ptr == NULL ) { + result = NULL; + + } else { + *result = *tm_ptr; + } + LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); + + return result; +} +#endif /* !USE_GMTIME_R */ + +#ifndef USE_LOCALTIME_R +struct tm * +ldap_pvt_localtime( const time_t *timep, struct tm *result ) +{ + struct tm *tm_ptr; + + LDAP_MUTEX_LOCK( &ldap_int_gmtime_mutex ); + tm_ptr = localtime( timep ); + if ( tm_ptr == NULL ) { + result = NULL; + + } else { + *result = *tm_ptr; + } + LDAP_MUTEX_UNLOCK( &ldap_int_gmtime_mutex ); + + return result; +} +#endif /* !USE_LOCALTIME_R */ + +static int _ldap_pvt_gt_subs; + +#ifdef _WIN32 +/* Windows SYSTEMTIME only has 10 millisecond resolution, so we + * also need to use a high resolution timer to get nanoseconds. + * This is pretty clunky. + */ +static LARGE_INTEGER _ldap_pvt_gt_freq; +static LARGE_INTEGER _ldap_pvt_gt_prev; +static int _ldap_pvt_gt_offset; + +#define SEC_TO_UNIX_EPOCH 11644473600LL +#define TICKS_PER_SECOND 10000000 +#define BILLION 1000000000LL + +static int +ldap_pvt_gettimensec(int *sec) +{ + LARGE_INTEGER count; + + QueryPerformanceCounter( &count ); + + /* It shouldn't ever go backwards, but multiple CPUs might + * be able to hit in the same tick. + */ + LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); + /* We assume Windows has at least a vague idea of + * when a second begins. So we align our nanosecond count + * with the Windows millisecond count using this offset. + * We retain the submillisecond portion of our own count. + * + * Note - this also assumes that the relationship between + * the PerformanceCounter and SystemTime stays constant; + * that assumption breaks if the SystemTime is adjusted by + * an external action. + */ + if ( !_ldap_pvt_gt_freq.QuadPart ) { + LARGE_INTEGER c2; + ULARGE_INTEGER ut; + FILETIME ft0, ft1; + long long t; + int nsec; + + /* Initialize our offset */ + QueryPerformanceFrequency( &_ldap_pvt_gt_freq ); + + /* Wait for a tick of the system time: 10-15ms */ + GetSystemTimeAsFileTime( &ft0 ); + do { + GetSystemTimeAsFileTime( &ft1 ); + } while ( ft1.dwLowDateTime == ft0.dwLowDateTime ); + + ut.LowPart = ft1.dwLowDateTime; + ut.HighPart = ft1.dwHighDateTime; + QueryPerformanceCounter( &c2 ); + + /* get second and fraction portion of counter */ + t = c2.QuadPart % (_ldap_pvt_gt_freq.QuadPart*10); + + /* convert to nanoseconds */ + t *= BILLION; + nsec = t / _ldap_pvt_gt_freq.QuadPart; + + ut.QuadPart /= 10; + ut.QuadPart %= (10 * BILLION); + _ldap_pvt_gt_offset = nsec - ut.QuadPart; + count = c2; + } + if ( count.QuadPart <= _ldap_pvt_gt_prev.QuadPart ) { + _ldap_pvt_gt_subs++; + } else { + _ldap_pvt_gt_subs = 0; + _ldap_pvt_gt_prev = count; + } + LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); + + /* convert to nanoseconds */ + count.QuadPart %= _ldap_pvt_gt_freq.QuadPart*10; + count.QuadPart *= BILLION; + count.QuadPart /= _ldap_pvt_gt_freq.QuadPart; + count.QuadPart -= _ldap_pvt_gt_offset; + + /* We've extracted the 1s and nanoseconds. + * The 1sec digit is used to detect wraparound in nanosecnds. + */ + if (count.QuadPart < 0) + count.QuadPart += (10 * BILLION); + else if (count.QuadPart >= (10 * BILLION)) + count.QuadPart -= (10 * BILLION); + + *sec = count.QuadPart / BILLION; + return count.QuadPart % BILLION; +} + + +/* emulate POSIX clock_gettime */ +int +ldap_pvt_clock_gettime( int clk_id, struct timespec *tv ) +{ + FILETIME ft; + ULARGE_INTEGER ut; + int sec, sec0; + + GetSystemTimeAsFileTime( &ft ); + ut.LowPart = ft.dwLowDateTime; + ut.HighPart = ft.dwHighDateTime; + + /* convert to sec */ + ut.QuadPart /= TICKS_PER_SECOND; + + tv->tv_nsec = ldap_pvt_gettimensec(&sec); + tv->tv_sec = ut.QuadPart - SEC_TO_UNIX_EPOCH; + + /* check for carry from microseconds */ + sec0 = tv->tv_sec % 10; + if (sec0 < sec || (sec0 == 9 && !sec)) + tv->tv_sec++; + + return 0; +} + +/* emulate POSIX gettimeofday */ +int +ldap_pvt_gettimeofday( struct timeval *tv, void *unused ) +{ + struct timespec ts; + ldap_pvt_clock_gettime( 0, &ts ); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + return 0; +} + + +/* return a broken out time, with nanoseconds + */ +void +ldap_pvt_gettime( struct lutil_tm *tm ) +{ + SYSTEMTIME st; + int sec, sec0; + static const char daysPerMonth[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + GetSystemTime( &st ); + tm->tm_nsec = ldap_pvt_gettimensec(&sec); + tm->tm_usub = _ldap_pvt_gt_subs; + + /* any difference larger than nanoseconds is + * already reflected in st + */ + tm->tm_sec = st.wSecond; + tm->tm_min = st.wMinute; + tm->tm_hour = st.wHour; + tm->tm_mday = st.wDay; + tm->tm_mon = st.wMonth - 1; + tm->tm_year = st.wYear - 1900; + + /* check for carry from nanoseconds */ + sec0 = tm->tm_sec % 10; + if (sec0 < sec || (sec0 == 9 && !sec)) { + tm->tm_sec++; + /* FIXME: we don't handle leap seconds */ + if (tm->tm_sec > 59) { + tm->tm_sec = 0; + tm->tm_min++; + if (tm->tm_min > 59) { + tm->tm_min = 0; + tm->tm_hour++; + if (tm->tm_hour > 23) { + int days = daysPerMonth[tm->tm_mon]; + tm->tm_hour = 0; + tm->tm_mday++; + + /* if it's February of a leap year, + * add 1 day to this month + */ + if (tm->tm_mon == 1 && + ((!(st.wYear % 4) && (st.wYear % 100)) || + !(st.wYear % 400))) + days++; + + if (tm->tm_mday > days) { + tm->tm_mday = 1; + tm->tm_mon++; + if (tm->tm_mon > 11) { + tm->tm_mon = 0; + tm->tm_year++; + } + } + } + } + } + } +} +#else + +#ifdef HAVE_CLOCK_GETTIME +static struct timespec _ldap_pvt_gt_prevTv; +#else +static struct timeval _ldap_pvt_gt_prevTv; +#endif + +void +ldap_pvt_gettime( struct lutil_tm *ltm ) +{ + struct tm tm; + time_t t; +#ifdef HAVE_CLOCK_GETTIME +#define FRAC tv_nsec +#define NSECS(x) x + struct timespec tv; + + clock_gettime( CLOCK_REALTIME, &tv ); +#else +#define FRAC tv_usec +#define NSECS(x) x * 1000 + struct timeval tv; + + gettimeofday( &tv, NULL ); +#endif + t = tv.tv_sec; + + LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex ); + if ( tv.tv_sec < _ldap_pvt_gt_prevTv.tv_sec + || ( tv.tv_sec == _ldap_pvt_gt_prevTv.tv_sec + && tv.FRAC <= _ldap_pvt_gt_prevTv.FRAC )) { + _ldap_pvt_gt_subs++; + } else { + _ldap_pvt_gt_subs = 0; + _ldap_pvt_gt_prevTv = tv; + } + LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex ); + + ltm->tm_usub = _ldap_pvt_gt_subs; + + ldap_pvt_gmtime( &t, &tm ); + + ltm->tm_sec = tm.tm_sec; + ltm->tm_min = tm.tm_min; + ltm->tm_hour = tm.tm_hour; + ltm->tm_mday = tm.tm_mday; + ltm->tm_mon = tm.tm_mon; + ltm->tm_year = tm.tm_year; + ltm->tm_nsec = NSECS(tv.FRAC); +} +#endif + +size_t +ldap_pvt_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod) +{ + struct lutil_tm tm; + int n; + + ldap_pvt_gettime( &tm ); + + n = snprintf( buf, len, + "%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, tm.tm_nsec / 1000, tm.tm_usub, replica, mod ); + + if( n < 0 ) return 0; + return ( (size_t) n < len ) ? n : 0; +} + +#define BUFSTART (1024-32) +#define BUFMAX (32*1024-32) + +#if defined(LDAP_R_COMPILE) +static char *safe_realloc( char **buf, int len ); + +#if !(defined(HAVE_GETHOSTBYNAME_R) && defined(HAVE_GETHOSTBYADDR_R)) +static int copy_hostent( struct hostent *res, + char **buf, struct hostent * src ); +#endif +#endif + +int ldap_pvt_gethostbyname_a( + const char *name, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr ) +{ +#if defined( HAVE_GETHOSTBYNAME_R ) + +# define NEED_SAFE_REALLOC 1 + int r=-1; + int buflen=BUFSTART; + *buf = NULL; + for(;buflen<BUFMAX;) { + if (safe_realloc( buf, buflen )==NULL) + return r; + +#if (GETHOSTBYNAME_R_NARGS < 6) + *result=gethostbyname_r( name, resbuf, *buf, buflen, herrno_ptr ); + r = (*result == NULL) ? -1 : 0; +#else + while((r = gethostbyname_r( name, resbuf, *buf, buflen, result, herrno_ptr )) == ERANGE) { + /* Increase the buffer */ + buflen*=2; + if (safe_realloc(buf, buflen) == NULL) + return -1; + } +#endif + + Debug2( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n", + name, r ); + +#ifdef NETDB_INTERNAL + if ((r<0) && + (*herrno_ptr==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + return r; + } + return -1; +#elif defined( LDAP_R_COMPILE ) +# define NEED_COPY_HOSTENT + struct hostent *he; + int retval; + *buf = NULL; + + LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); + + he = gethostbyname( name ); + + if (he==NULL) { + *herrno_ptr = h_errno; + retval = -1; + } else if (copy_hostent( resbuf, buf, he )<0) { + *herrno_ptr = -1; + retval = -1; + } else { + *result = resbuf; + retval = 0; + } + + LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); + + return retval; +#else + *buf = NULL; + *result = gethostbyname( name ); + + if (*result!=NULL) { + return 0; + } + + *herrno_ptr = h_errno; + + return -1; +#endif +} + +#if !defined( HAVE_GETNAMEINFO ) && !defined( HAVE_HSTRERROR ) +static const char * +hp_strerror( int err ) +{ + switch (err) { + case HOST_NOT_FOUND: return _("Host not found (authoritative)"); + case TRY_AGAIN: return _("Host not found (server fail?)"); + case NO_RECOVERY: return _("Non-recoverable failure"); + case NO_DATA: return _("No data of requested type"); +#ifdef NETDB_INTERNAL + case NETDB_INTERNAL: return STRERROR( errno ); +#endif + } + return _("Unknown resolver error"); +} +#endif + +int ldap_pvt_get_hname( + const struct sockaddr *sa, + int len, + char *name, + int namelen, + char **err ) +{ + int rc; +#if defined( HAVE_GETNAMEINFO ) + + LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); + rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 ); + LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); + if ( rc ) *err = (char *)AC_GAI_STRERROR( rc ); + return rc; + +#else /* !HAVE_GETNAMEINFO */ + char *addr; + int alen; + struct hostent *hp = NULL; +#ifdef HAVE_GETHOSTBYADDR_R + struct hostent hb; + int buflen=BUFSTART, h_errno; + char *buf=NULL; +#endif + +#ifdef LDAP_PF_INET6 + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; + addr = (char *)&sin->sin6_addr; + alen = sizeof(sin->sin6_addr); + } else +#endif + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + addr = (char *)&sin->sin_addr; + alen = sizeof(sin->sin_addr); + } else { + rc = NO_RECOVERY; + *err = (char *)HSTRERROR( rc ); + return rc; + } +#if defined( HAVE_GETHOSTBYADDR_R ) + for(;buflen<BUFMAX;) { + if (safe_realloc( &buf, buflen )==NULL) { + *err = (char *)STRERROR( ENOMEM ); + return ENOMEM; + } +#if (GETHOSTBYADDR_R_NARGS < 8) + hp=gethostbyaddr_r( addr, alen, sa->sa_family, + &hb, buf, buflen, &h_errno ); + rc = (hp == NULL) ? -1 : 0; +#else + rc = gethostbyaddr_r( addr, alen, sa->sa_family, + &hb, buf, buflen, + &hp, &h_errno ); +#endif +#ifdef NETDB_INTERNAL + if ((rc<0) && + (h_errno==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + break; + } + if (hp) { + strncpy( name, hp->h_name, namelen ); + } else { + *err = (char *)HSTRERROR( h_errno ); + } + LDAP_FREE(buf); +#else /* HAVE_GETHOSTBYADDR_R */ + + LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); + hp = gethostbyaddr( addr, alen, sa->sa_family ); + if (hp) { + strncpy( name, hp->h_name, namelen ); + rc = 0; + } else { + rc = h_errno; + *err = (char *)HSTRERROR( h_errno ); + } + LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); + +#endif /* !HAVE_GETHOSTBYADDR_R */ + return rc; +#endif /* !HAVE_GETNAMEINFO */ +} + +int ldap_pvt_gethostbyaddr_a( + const char *addr, + int len, + int type, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr ) +{ +#if defined( HAVE_GETHOSTBYADDR_R ) + +# undef NEED_SAFE_REALLOC +# define NEED_SAFE_REALLOC + int r=-1; + int buflen=BUFSTART; + *buf = NULL; + for(;buflen<BUFMAX;) { + if (safe_realloc( buf, buflen )==NULL) + return r; +#if (GETHOSTBYADDR_R_NARGS < 8) + *result=gethostbyaddr_r( addr, len, type, + resbuf, *buf, buflen, herrno_ptr ); + r = (*result == NULL) ? -1 : 0; +#else + r = gethostbyaddr_r( addr, len, type, + resbuf, *buf, buflen, + result, herrno_ptr ); +#endif + +#ifdef NETDB_INTERNAL + if ((r<0) && + (*herrno_ptr==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + return r; + } + return -1; +#elif defined( LDAP_R_COMPILE ) +# undef NEED_COPY_HOSTENT +# define NEED_COPY_HOSTENT + struct hostent *he; + int retval; + *buf = NULL; + + LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); + he = gethostbyaddr( addr, len, type ); + + if (he==NULL) { + *herrno_ptr = h_errno; + retval = -1; + } else if (copy_hostent( resbuf, buf, he )<0) { + *herrno_ptr = -1; + retval = -1; + } else { + *result = resbuf; + retval = 0; + } + LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); + + return retval; + +#else /* gethostbyaddr() */ + *buf = NULL; + *result = gethostbyaddr( addr, len, type ); + + if (*result!=NULL) { + return 0; + } + return -1; +#endif +} +/* + * ldap_int_utils_init() should be called before any other function. + */ + +void ldap_int_utils_init( void ) +{ + static int done=0; + if (done) + return; + done=1; + +#ifdef LDAP_R_COMPILE +#if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS ) + ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex ); +#endif +#if !defined( USE_GMTIME_R ) && !defined( USE_LOCALTIME_R ) + ldap_pvt_thread_mutex_init( &ldap_int_gmtime_mutex ); +#endif + ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex ); + + ldap_pvt_thread_mutex_init( &ldap_int_hostname_mutex ); + + ldap_pvt_thread_mutex_init( &ldap_int_gettime_mutex ); + +#endif + + /* call other module init functions here... */ +} + +#if defined( NEED_COPY_HOSTENT ) +# undef NEED_SAFE_REALLOC +#define NEED_SAFE_REALLOC + +static char *cpy_aliases( + char ***tgtio, + char *buf, + char **src ) +{ + int len; + char **tgt=*tgtio; + for( ; (*src) ; src++ ) { + len = strlen( *src ) + 1; + AC_MEMCPY( buf, *src, len ); + *tgt++=buf; + buf+=len; + } + *tgtio=tgt; + return buf; +} + +static char *cpy_addresses( + char ***tgtio, + char *buf, + char **src, + int len ) +{ + char **tgt=*tgtio; + for( ; (*src) ; src++ ) { + AC_MEMCPY( buf, *src, len ); + *tgt++=buf; + buf+=len; + } + *tgtio=tgt; + return buf; +} + +static int copy_hostent( + struct hostent *res, + char **buf, + struct hostent * src ) +{ + char **p; + char **tp; + char *tbuf; + int name_len; + int n_alias=0; + int total_alias_len=0; + int n_addr=0; + int total_addr_len=0; + int total_len; + + /* calculate the size needed for the buffer */ + name_len = strlen( src->h_name ) + 1; + + if( src->h_aliases != NULL ) { + for( p = src->h_aliases; (*p) != NULL; p++ ) { + total_alias_len += strlen( *p ) + 1; + n_alias++; + } + } + + if( src->h_addr_list != NULL ) { + for( p = src->h_addr_list; (*p) != NULL; p++ ) { + n_addr++; + } + total_addr_len = n_addr * src->h_length; + } + + total_len = (n_alias + n_addr + 2) * sizeof( char * ) + + total_addr_len + total_alias_len + name_len; + + if (safe_realloc( buf, total_len )) { + tp = (char **) *buf; + tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * ); + AC_MEMCPY( res, src, sizeof( struct hostent ) ); + /* first the name... */ + AC_MEMCPY( tbuf, src->h_name, name_len ); + res->h_name = tbuf; tbuf+=name_len; + /* now the aliases */ + res->h_aliases = tp; + if ( src->h_aliases != NULL ) { + tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); + } + *tp++=NULL; + /* finally the addresses */ + res->h_addr_list = tp; + if ( src->h_addr_list != NULL ) { + tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); + } + *tp++=NULL; + return 0; + } + return -1; +} +#endif + +#if defined( NEED_SAFE_REALLOC ) +static char *safe_realloc( char **buf, int len ) +{ + char *tmpbuf; + tmpbuf = LDAP_REALLOC( *buf, len ); + if (tmpbuf) { + *buf=tmpbuf; + } + return tmpbuf; +} +#endif + +char * ldap_pvt_get_fqdn( char *name ) +{ +#ifdef HAVE_GETADDRINFO + struct addrinfo hints, *res; +#else + char *ha_buf; + struct hostent *hp, he_buf; + int local_h_errno; +#endif + int rc; + char *fqdn, hostbuf[MAXHOSTNAMELEN+1]; + + if( name == NULL ) { + if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { + hostbuf[MAXHOSTNAMELEN] = '\0'; + name = hostbuf; + } else { + name = "localhost"; + } + } + +#ifdef HAVE_GETADDRINFO + memset( &hints, 0, sizeof( hints )); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + + LDAP_MUTEX_LOCK( &ldap_int_resolv_mutex ); + rc = getaddrinfo( name, NULL, &hints, &res ); + LDAP_MUTEX_UNLOCK( &ldap_int_resolv_mutex ); + if ( rc == 0 && res->ai_canonname ) { + fqdn = LDAP_STRDUP( res->ai_canonname ); + } else { + fqdn = LDAP_STRDUP( name ); + } + if ( rc == 0 ) + freeaddrinfo( res ); +#else + rc = ldap_pvt_gethostbyname_a( name, + &he_buf, &ha_buf, &hp, &local_h_errno ); + + if( rc < 0 || hp == NULL || hp->h_name == NULL ) { + fqdn = LDAP_STRDUP( name ); + } else { + fqdn = LDAP_STRDUP( hp->h_name ); + } + + LDAP_FREE( ha_buf ); +#endif + return fqdn; +} + +#if ( defined( HAVE_GETADDRINFO ) || defined( HAVE_GETNAMEINFO ) ) \ + && !defined( HAVE_GAI_STRERROR ) +char *ldap_pvt_gai_strerror (int code) { + static struct { + int code; + const char *msg; + } values[] = { +#ifdef EAI_ADDRFAMILY + { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, +#endif + { EAI_AGAIN, N_("Temporary failure in name resolution") }, + { EAI_BADFLAGS, N_("Bad value for ai_flags") }, + { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, + { EAI_FAMILY, N_("ai_family not supported") }, + { EAI_MEMORY, N_("Memory allocation failure") }, +#ifdef EAI_NODATA + { EAI_NODATA, N_("No address associated with hostname") }, +#endif + { EAI_NONAME, N_("Name or service not known") }, + { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, + { EAI_SOCKTYPE, N_("ai_socktype not supported") }, +#ifdef EAI_SYSTEM + { EAI_SYSTEM, N_("System error") }, +#endif + { 0, NULL } + }; + + int i; + + for ( i = 0; values[i].msg != NULL; i++ ) { + if ( values[i].code == code ) { + return (char *) _(values[i].msg); + } + } + + return _("Unknown error"); +} +#endif + +/* format a socket address as a string */ + +#ifdef HAVE_TCPD +# include <tcpd.h> +# define SOCKADDR_STRING_UNKNOWN STRING_UNKNOWN +#else /* ! TCP Wrappers */ +# define SOCKADDR_STRING_UNKNOWN "unknown" +#endif /* ! TCP Wrappers */ + +void +ldap_pvt_sockaddrstr( Sockaddr *sa, struct berval *addrbuf ) +{ + char *addr; + switch( sa->sa_addr.sa_family ) { +#ifdef LDAP_PF_LOCAL + case AF_LOCAL: + addrbuf->bv_len = snprintf( addrbuf->bv_val, addrbuf->bv_len, + "PATH=%s", sa->sa_un_addr.sun_path ); + break; +#endif +#ifdef LDAP_PF_INET6 + case AF_INET6: + strcpy(addrbuf->bv_val, "IP="); + if ( IN6_IS_ADDR_V4MAPPED(&sa->sa_in6_addr.sin6_addr) ) { +#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) + addr = (char *)inet_ntop( AF_INET, + ((struct in_addr *)&sa->sa_in6_addr.sin6_addr.s6_addr[12]), + addrbuf->bv_val+3, addrbuf->bv_len-3 ); +#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ + addr = inet_ntoa( *((struct in_addr *) + &sa->sa_in6_addr.sin6_addr.s6_addr[12]) ); +#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ + if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; + if ( addr != addrbuf->bv_val+3 ) { + addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "%s:%d", addr, + (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + 3; + } else { + int len = strlen( addr ); + addrbuf->bv_len = sprintf( addr+len, ":%d", + (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + len + 3; + } + } else { + addr = (char *)inet_ntop( AF_INET6, + &sa->sa_in6_addr.sin6_addr, + addrbuf->bv_val+4, addrbuf->bv_len-4 ); + if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; + if ( addr != addrbuf->bv_val+4 ) { + addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "[%s]:%d", addr, + (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + 3; + } else { + int len = strlen( addr ); + addrbuf->bv_val[3] = '['; + addrbuf->bv_len = sprintf( addr+len, "]:%d", + (unsigned) ntohs( sa->sa_in6_addr.sin6_port ) ) + len + 4; + } + } + break; +#endif /* LDAP_PF_INET6 */ + case AF_INET: + strcpy(addrbuf->bv_val, "IP="); +#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) + addr = (char *)inet_ntop( AF_INET, &sa->sa_in_addr.sin_addr, + addrbuf->bv_val+3, addrbuf->bv_len-3 ); +#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ + addr = inet_ntoa( sa->sa_in_addr.sin_addr ); +#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ + if ( !addr ) addr = SOCKADDR_STRING_UNKNOWN; + if ( addr != addrbuf->bv_val+3 ) { + addrbuf->bv_len = sprintf( addrbuf->bv_val+3, "%s:%d", addr, + (unsigned) ntohs( sa->sa_in_addr.sin_port ) ) + 3; + } else { + int len = strlen( addr ); + addrbuf->bv_len = sprintf( addr+len, ":%d", + (unsigned) ntohs( sa->sa_in_addr.sin_port ) ) + len + 3; + } + break; + default: + addrbuf->bv_val[0] = '\0'; + } +} diff --git a/libs/ldap/libldap/vlvctrl.c b/libs/ldap/libldap/vlvctrl.c new file mode 100644 index 00000000000..5dfeace6e84 --- /dev/null +++ b/libs/ldap/libldap/vlvctrl.c @@ -0,0 +1,361 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software http://www.openldap.org/. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * http://www.OpenLDAP.org/license.html. + */ +/* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND + * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT + * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS + * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" + * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION + * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP + * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT + * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + *--- + * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License + * can be found in the file "build/LICENSE-2.0.1" in this distribution + * of OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +#define LDAP_VLVBYINDEX_IDENTIFIER 0xa0L +#define LDAP_VLVBYVALUE_IDENTIFIER 0x81L +#define LDAP_VLVCONTEXT_IDENTIFIER 0x04L + + +/*--- + ldap_create_vlv_control + + Create and encode the Virtual List View control. + + ld (IN) An LDAP session handle. + + vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents + are used to construct the value of the control + that is created. + + value (OUT) A struct berval that contains the value to be assigned to the ldctl_value member + of an LDAPControl structure that contains the + VirtualListViewRequest control. + The bv_val member of the berval structure + SHOULD be freed when it is no longer in use by + calling ldap_memfree(). + + + Ber encoding + + VirtualListViewRequest ::= SEQUENCE { + beforeCount INTEGER (0 .. maxInt), + afterCount INTEGER (0 .. maxInt), + CHOICE { + byoffset [0] SEQUENCE, { + offset INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt) } + [1] greaterThanOrEqual assertionValue } + contextID OCTET STRING OPTIONAL } + + + Note: The first time the VLV control is created, the ldvlv_context + field of the LDAPVLVInfo structure should be set to NULL. + The context obtained from calling ldap_parse_vlv_control() + should be used as the context in the next ldap_create_vlv_control + call. + + ---*/ + +int +ldap_create_vlv_control_value( + LDAP *ld, + LDAPVLVInfo *vlvinfop, + struct berval *value ) +{ + ber_tag_t tag; + BerElement *ber; + + if ( ld == NULL || vlvinfop == NULL || value == NULL ) { + if ( ld ) + ld->ld_errno = LDAP_PARAM_ERROR; + return LDAP_PARAM_ERROR; + } + + assert( LDAP_VALID( ld ) ); + + value->bv_val = NULL; + value->bv_len = 0; + ld->ld_errno = LDAP_SUCCESS; + + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_printf( ber, "{ii" /*}*/, + vlvinfop->ldvlv_before_count, + vlvinfop->ldvlv_after_count ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + if ( vlvinfop->ldvlv_attrvalue == NULL ) { + tag = ber_printf( ber, "t{iiN}", + LDAP_VLVBYINDEX_IDENTIFIER, + vlvinfop->ldvlv_offset, + vlvinfop->ldvlv_count ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + } else { + tag = ber_printf( ber, "tO", + LDAP_VLVBYVALUE_IDENTIFIER, + vlvinfop->ldvlv_attrvalue ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + } + + if ( vlvinfop->ldvlv_context ) { + tag = ber_printf( ber, "tO", + LDAP_VLVCONTEXT_IDENTIFIER, + vlvinfop->ldvlv_context ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + } + + tag = ber_printf( ber, /*{*/ "N}" ); + if ( tag == LBER_ERROR ) { + goto error_return; + } + + if ( ber_flatten2( ber, value, 1 ) == -1 ) { + ld->ld_errno = LDAP_NO_MEMORY; + } + + if ( 0 ) { +error_return:; + ld->ld_errno = LDAP_ENCODING_ERROR; + } + + if ( ber != NULL ) { + ber_free( ber, 1 ); + } + + return ld->ld_errno; +} + +/*--- + ldap_create_vlv_control + + Create and encode the Virtual List View control. + + ld (IN) An LDAP session handle. + + vlvinfop (IN) The address of an LDAPVLVInfo structure whose contents + are used to construct the value of the control + that is created. + + ctrlp (OUT) A result parameter that will be assigned the address + of an LDAPControl structure that contains the + VirtualListViewRequest control created by this function. + The memory occupied by the LDAPControl structure + SHOULD be freed when it is no longer in use by + calling ldap_control_free(). + + + Ber encoding + + VirtualListViewRequest ::= SEQUENCE { + beforeCount INTEGER (0 .. maxInt), + afterCount INTEGER (0 .. maxInt), + CHOICE { + byoffset [0] SEQUENCE, { + offset INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt) } + [1] greaterThanOrEqual assertionValue } + contextID OCTET STRING OPTIONAL } + + + Note: The first time the VLV control is created, the ldvlv_context + field of the LDAPVLVInfo structure should be set to NULL. + The context obtained from calling ldap_parse_vlv_control() + should be used as the context in the next ldap_create_vlv_control + call. + + ---*/ + +int +ldap_create_vlv_control( + LDAP *ld, + LDAPVLVInfo *vlvinfop, + LDAPControl **ctrlp ) +{ + struct berval value; + + if ( ctrlp == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + + ld->ld_errno = ldap_control_create( LDAP_CONTROL_VLVREQUEST, + 1, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { + LDAP_FREE( value.bv_val ); + } + } + + return ld->ld_errno; +} + + +/*--- + ldap_parse_vlvresponse_control + + Decode the Virtual List View control return information. + + ld (IN) An LDAP session handle. + + ctrl (IN) The address of the LDAPControl structure. + + target_posp (OUT) This result parameter is filled in with the list + index of the target entry. If this parameter is + NULL, the target position is not returned. + + list_countp (OUT) This result parameter is filled in with the server's + estimate of the size of the list. If this parameter + is NULL, the size is not returned. + + contextp (OUT) This result parameter is filled in with the address + of a struct berval that contains the server- + generated context identifier if one was returned by + the server. If the server did not return a context + identifier, this parameter will be set to NULL, even + if an error occurred. + The returned context SHOULD be used in the next call + to create a VLV sort control. The struct berval + returned SHOULD be disposed of by calling ber_bvfree() + when it is no longer needed. If NULL is passed for + contextp, the context identifier is not returned. + + errcodep (OUT) This result parameter is filled in with the VLV + result code. If this parameter is NULL, the result + code is not returned. + + + Ber encoding + + VirtualListViewResponse ::= SEQUENCE { + targetPosition INTEGER (0 .. maxInt), + contentCount INTEGER (0 .. maxInt), + virtualListViewResult ENUMERATED { + success (0), + operationsError (1), + unwillingToPerform (53), + insufficientAccessRights (50), + busy (51), + timeLimitExceeded (3), + adminLimitExceeded (11), + sortControlMissing (60), + offsetRangeError (61), + other (80) }, + contextID OCTET STRING OPTIONAL } + +---*/ + +int +ldap_parse_vlvresponse_control( + LDAP *ld, + LDAPControl *ctrl, + ber_int_t *target_posp, + ber_int_t *list_countp, + struct berval **contextp, + ber_int_t *errcodep ) +{ + BerElement *ber; + ber_int_t pos, count, err; + ber_tag_t tag, berTag; + ber_len_t berLen; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + + if (contextp) { + *contextp = NULL; /* Make sure we return a NULL if error occurs. */ + } + + if (ctrl == NULL) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) { + /* Not VLV Response control */ + ld->ld_errno = LDAP_CONTROL_NOT_FOUND; + return(ld->ld_errno); + } + + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init(&ctrl->ldctl_value); + + if (ber == NULL) { + ld->ld_errno = LDAP_NO_MEMORY; + return(ld->ld_errno); + } + + /* Extract the data returned in the control. */ + tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err); + + if( tag == LBER_ERROR) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + + + /* Since the context is the last item encoded, if caller doesn't want + it returned, don't decode it. */ + if (contextp) { + if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) { + tag = ber_scanf(ber, "tO", &berTag, contextp); + + if( tag == LBER_ERROR) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + } + } + + ber_free(ber, 1); + + /* Return data to the caller for items that were requested. */ + if (target_posp) *target_posp = pos; + if (list_countp) *list_countp = count; + if (errcodep) *errcodep = err; + + ld->ld_errno = LDAP_SUCCESS; + return(ld->ld_errno); +}
From: Hans Leidekker hans@codeweavers.com
--- dlls/wldap32/tests/parse.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/dlls/wldap32/tests/parse.c b/dlls/wldap32/tests/parse.c index 8ed95dd03f2..704ce0766a1 100644 --- a/dlls/wldap32/tests/parse.c +++ b/dlls/wldap32/tests/parse.c @@ -67,14 +67,6 @@ static void test_ldap_parse_sort_control( LDAP *ld ) ok( !ret, "ldap_search_ext_sA failed %#lx\n", ret ); ok( res != NULL, "expected res != NULL\n" );
- if (GetProcAddress(GetModuleHandleA("wldap32.dll"), "ber_init")) - { - ret = ldap_parse_resultA( NULL, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); - ok( ret == LDAP_PARAM_ERROR, "ldap_parse_resultA failed %#lx\n", ret ); - } - else - win_skip("Test would crash on older wldap32 versions\n"); - result = ~0u; ret = ldap_parse_resultA( ld, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); ok( !ret, "ldap_parse_resultA failed %#lx\n", ret ); @@ -127,7 +119,7 @@ static void test_ldap_set_optionW( LDAP *ld ) }
ret = ldap_set_optionW( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); - ok( !ret || broken(ret == LDAP_PARAM_ERROR) /* nt4, win2k */, "ldap_set_optionW failed %#lx\n", ret ); + ok( !ret, "ldap_set_optionW failed %#lx\n", ret );
ret = ldap_set_optionW( ld, LDAP_OPT_REFERRALS, (void *)&oldvalue ); ok( !ret, "ldap_set_optionW failed %#lx\n", ret );
From: Hans Leidekker hans@codeweavers.com
This server supports secure connections. --- dlls/wldap32/tests/parse.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/dlls/wldap32/tests/parse.c b/dlls/wldap32/tests/parse.c index 704ce0766a1..f30912324ba 100644 --- a/dlls/wldap32/tests/parse.c +++ b/dlls/wldap32/tests/parse.c @@ -57,7 +57,8 @@ static void test_ldap_parse_sort_control( LDAP *ld ) ctrls[1] = NULL; timeout.tv_sec = 20; timeout.tv_usec = 0; - ret = ldap_search_ext_sA( ld, (char *)"", LDAP_SCOPE_ONELEVEL, (char *)"(ou=*)", NULL, 0, ctrls, NULL, &timeout, 10, &res ); + ret = ldap_search_ext_sA( ld, (char *)"dc=debian,dc=org", LDAP_SCOPE_ONELEVEL, (char *)"(uid=*)", NULL, 0, + ctrls, NULL, &timeout, 10, &res ); if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) { skip("test server can't be reached\n"); @@ -140,8 +141,8 @@ static void test_ldap_bind_sA( void ) ULONG ret; int version;
- ld = ldap_initA( (char *)"ldap.forumsys.com", 389 ); - ok( ld != NULL, "ldap_init failed\n" ); + ld = ldap_sslinitA( (char *)"db.debian.org", 636, 1 ); + ok( ld != NULL, "ldap_sslinit failed\n" );
version = LDAP_VERSION3; ret = ldap_set_optionW( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); @@ -155,9 +156,16 @@ static void test_ldap_bind_sA( void ) ret = ldap_connect( ld, NULL ); ok( !ret, "ldap_connect failed %#lx\n", ret );
- ret = ldap_bind_sA( ld, (char *)"CN=read-only-admin,DC=example,DC=com", (char *)"password", LDAP_AUTH_SIMPLE ); - ok( !ret, "ldap_bind_s failed %#lx\n", ret ); + ret = ldap_bind_sA( ld, (char *)"uid=winetest,ou=users,dc=debian,dc=org", (char *)"winetest", + LDAP_AUTH_SIMPLE ); + ok( ret == LDAP_INVALID_CREDENTIALS, "ldap_bind_s returned %#lx\n", ret ); + ldap_unbind( ld ); + + ld = ldap_sslinitA( (char *)"db.debian.org", 389, 0 ); + ok( ld != NULL, "ldap_sslinit failed\n" );
+ ret = ldap_connect( ld, NULL ); + ok( !ret, "ldap_connect failed %#lx\n", ret ); ldap_unbind( ld ); }
@@ -171,7 +179,7 @@ static void test_ldap_server_control( void ) LDAPControlW *ctrls[2], mask; LDAPMessage *res;
- ld = ldap_initA( (char *)"ldap.forumsys.com", 389 ); + ld = ldap_initA( (char *)"db.debian.org", 389 ); ok( ld != NULL, "ldap_init failed\n" );
version = LDAP_VERSION3; @@ -197,7 +205,7 @@ static void test_ldap_server_control( void ) ok( ret == LDAP_PARAM_ERROR, "ldap_set_optionW should fail: %#lx\n", ret );
res = NULL; - ret = ldap_search_sA( ld, (char *)"OU=scientists,DC=example,DC=com", LDAP_SCOPE_BASE, (char *)"(objectclass=*)", NULL, FALSE, &res ); + ret = ldap_search_sA( ld, (char *)"dc=debian,dc=org", LDAP_SCOPE_BASE, (char *)"(objectclass=*)", NULL, FALSE, &res ); ok( !ret, "ldap_search_sA failed %#lx\n", ret ); ok( res != NULL, "expected res != NULL\n" );
@@ -215,7 +223,7 @@ static void test_ldap_paged_search(void) BerElement *ber; WCHAR *attr;
- ld = ldap_initA( (char *)"ldap.forumsys.com", 389 ); + ld = ldap_initA( (char *)"db.debian.org", 389 ); ok( ld != NULL, "ldap_init failed\n" );
version = LDAP_VERSION3; @@ -272,7 +280,7 @@ START_TEST (parse) test_ldap_server_control(); test_ldap_bind_sA();
- ld = ldap_initA((char *)"ldap.itd.umich.edu", 389 ); + ld = ldap_initA( (char *)"db.debian.org", 389 ); ok( ld != NULL, "ldap_init failed\n" );
test_ldap_parse_sort_control( ld );
From: Hans Leidekker hans@codeweavers.com
--- dlls/wldap32/add.c | 75 -------------- dlls/wldap32/ber.c | 177 -------------------------------- dlls/wldap32/bind.c | 123 ---------------------- dlls/wldap32/compare.c | 73 ------------- dlls/wldap32/control.c | 96 ----------------- dlls/wldap32/delete.c | 67 ------------ dlls/wldap32/dn.c | 60 ----------- dlls/wldap32/error.c | 57 ----------- dlls/wldap32/extended.c | 61 ----------- dlls/wldap32/init.c | 125 ----------------------- dlls/wldap32/misc.c | 221 ---------------------------------------- dlls/wldap32/modify.c | 75 -------------- dlls/wldap32/modrdn.c | 64 ------------ dlls/wldap32/option.c | 29 ------ dlls/wldap32/page.c | 17 ---- dlls/wldap32/parse.c | 95 ----------------- dlls/wldap32/rename.c | 41 +------- dlls/wldap32/search.c | 117 --------------------- dlls/wldap32/value.c | 84 --------------- 19 files changed, 1 insertion(+), 1656 deletions(-)
diff --git a/dlls/wldap32/add.c b/dlls/wldap32/add.c index 282fd327ba3..2afe4fa2b33 100644 --- a/dlls/wldap32/add.c +++ b/dlls/wldap32/add.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_addA (WLDAP32.@) - * - * See ldap_addW. */ ULONG CDECL ldap_addA( LDAP *ld, char *dn, LDAPModA **attrs ) { @@ -57,23 +55,6 @@ exit:
/*********************************************************************** * ldap_addW (WLDAP32.@) - * - * Add an entry to a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to add. - * attrs [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to add. - * - * RETURNS - * Success: Message ID of the add operation. - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_addW( LDAP *ld, WCHAR *dn, LDAPModW **attrs ) { @@ -88,8 +69,6 @@ ULONG CDECL ldap_addW( LDAP *ld, WCHAR *dn, LDAPModW **attrs )
/*********************************************************************** * ldap_add_extA (WLDAP32.@) - * - * See ldap_add_extW. */ ULONG CDECL ldap_add_extA( LDAP *ld, char *dn, LDAPModA **attrs, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) @@ -120,26 +99,6 @@ exit:
/*********************************************************************** * ldap_add_extW (WLDAP32.@) - * - * Add an entry to a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to add. - * attrs [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to add. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the add operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. The serverctrls and clientctrls parameters are - * optional and should be set to NULL if not used. */ ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -173,8 +132,6 @@ exit:
/*********************************************************************** * ldap_add_ext_sA (WLDAP32.@) - * - * See ldap_add_ext_sW. */ ULONG CDECL ldap_add_ext_sA( LDAP *ld, char *dn, LDAPModA **attrs, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) @@ -205,24 +162,6 @@ exit:
/*********************************************************************** * ldap_add_ext_sW (WLDAP32.@) - * - * Add an entry to a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to add. - * attrs [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to add. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The serverctrls and clientctrls parameters are optional and - * should be set to NULL if not used. */ ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) @@ -256,8 +195,6 @@ exit:
/*********************************************************************** * ldap_add_sA (WLDAP32.@) - * - * See ldap_add_sW. */ ULONG CDECL ldap_add_sA( LDAP *ld, char *dn, LDAPModA **attrs ) { @@ -282,18 +219,6 @@ exit:
/*********************************************************************** * ldap_add_sW (WLDAP32.@) - * - * Add an entry to a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to add. - * attrs [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to add. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_add_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs ) { diff --git a/dlls/wldap32/ber.c b/dlls/wldap32/ber.c index f3b18e530b4..82ab6116455 100644 --- a/dlls/wldap32/ber.c +++ b/dlls/wldap32/ber.c @@ -33,18 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ber_alloc_t (WLDAP32.@) - * - * Allocate a berelement structure. - * - * PARAMS - * options [I] Must be LBER_USE_DER. - * - * RETURNS - * Success: Pointer to an allocated berelement structure. - * Failure: NULL - * - * NOTES - * Free the berelement structure with ber_free. */ BerElement * CDECL ber_alloc_t( int options ) { @@ -62,86 +50,32 @@ BerElement * CDECL ber_alloc_t( int options ) return ret; }
- /*********************************************************************** * ber_bvdup (WLDAP32.@) - * - * Copy a berval structure. - * - * PARAMS - * berval [I] Pointer to the berval structure to be copied. - * - * RETURNS - * Success: Pointer to a copy of the berval structure. - * Failure: NULL - * - * NOTES - * Free the copy with ber_bvfree. */ BERVAL * CDECL ber_bvdup( BERVAL *berval ) { return bervalWtoW( berval ); }
- /*********************************************************************** * ber_bvecfree (WLDAP32.@) - * - * Free an array of berval structures. - * - * PARAMS - * berval [I] Pointer to an array of berval structures. - * - * RETURNS - * Nothing. - * - * NOTES - * Use this function only to free an array of berval structures - * returned by a call to ber_scanf with a 'V' in the format string. */ void CDECL ber_bvecfree( BERVAL **berval ) { bvarrayfreeW( berval ); }
- /*********************************************************************** * ber_bvfree (WLDAP32.@) - * - * Free a berval structure. - * - * PARAMS - * berval [I] Pointer to a berval structure. - * - * RETURNS - * Nothing. - * - * NOTES - * Use this function only to free berval structures allocated by - * an LDAP API. */ void CDECL ber_bvfree( BERVAL *berval ) { free( berval ); }
- /*********************************************************************** * ber_first_element (WLDAP32.@) - * - * Return the tag of the first element in a set or sequence. - * - * PARAMS - * berelement [I] Pointer to a berelement structure. - * len [O] Receives the length of the first element. - * opaque [O] Receives a pointer to a cookie. - * - * RETURNS - * Success: Tag of the first element. - * Failure: LBER_DEFAULT (no more data). - * - * NOTES - * len and cookie should be passed to ber_next_element. */ ULONG CDECL ber_first_element( BerElement *ber, ULONG *len, char **opaque ) { @@ -149,22 +83,8 @@ ULONG CDECL ber_first_element( BerElement *ber, ULONG *len, char **opaque ) return LDAP_CALL( ber_first_element, ¶ms ); }
- /*********************************************************************** * ber_flatten (WLDAP32.@) - * - * Flatten a berelement structure into a berval structure. - * - * PARAMS - * berelement [I] Pointer to a berelement structure. - * berval [O] Pointer to a berval structure. - * - * RETURNS - * Success: 0 - * Failure: LBER_ERROR - * - * NOTES - * Free the berval structure with ber_bvfree. */ int CDECL ber_flatten( BerElement *ber, BERVAL **berval ) { @@ -181,22 +101,8 @@ int CDECL ber_flatten( BerElement *ber, BERVAL **berval ) return 0; }
- /*********************************************************************** * ber_free (WLDAP32.@) - * - * Free a berelement structure. - * - * PARAMS - * berelement [I] Pointer to the berelement structure to be freed. - * buf [I] Flag. - * - * RETURNS - * Nothing. - * - * NOTES - * Set buf to 0 if the berelement was allocated with ldap_first_attribute - * or ldap_next_attribute, otherwise set it to 1. */ void CDECL ber_free( BerElement *ber, int freebuf ) { @@ -205,21 +111,8 @@ void CDECL ber_free( BerElement *ber, int freebuf ) free( ber ); }
- /*********************************************************************** * ber_init (WLDAP32.@) - * - * Initialise a berelement structure from a berval structure. - * - * PARAMS - * berval [I] Pointer to a berval structure. - * - * RETURNS - * Success: Pointer to a berelement structure. - * Failure: NULL - * - * NOTES - * Call ber_free to free the returned berelement structure. */ BerElement * CDECL ber_init( BERVAL *berval ) { @@ -244,24 +137,8 @@ BerElement * CDECL ber_init( BERVAL *berval ) return ret; }
- /*********************************************************************** * ber_next_element (WLDAP32.@) - * - * Return the tag of the next element in a set or sequence. - * - * PARAMS - * berelement [I] Pointer to a berelement structure. - * len [I/O] Receives the length of the next element. - * opaque [I/O] Pointer to a cookie. - * - * RETURNS - * Success: Tag of the next element. - * Failure: LBER_DEFAULT (no more data). - * - * NOTES - * len and cookie are initialized by ber_first_element and should - * be passed on in subsequent calls to ber_next_element. */ ULONG CDECL ber_next_element( BerElement *ber, ULONG *len, char *opaque ) { @@ -269,19 +146,8 @@ ULONG CDECL ber_next_element( BerElement *ber, ULONG *len, char *opaque ) return LDAP_CALL( ber_next_element, ¶ms ); }
- /*********************************************************************** * ber_peek_tag (WLDAP32.@) - * - * Return the tag of the next element. - * - * PARAMS - * berelement [I] Pointer to a berelement structure. - * len [O] Receives the length of the next element. - * - * RETURNS - * Success: Tag of the next element. - * Failure: LBER_DEFAULT (no more data). */ ULONG CDECL ber_peek_tag( BerElement *ber, ULONG *len ) { @@ -289,19 +155,8 @@ ULONG CDECL ber_peek_tag( BerElement *ber, ULONG *len ) return LDAP_CALL( ber_peek_tag, ¶ms ); }
- /*********************************************************************** * ber_skip_tag (WLDAP32.@) - * - * Skip the current tag and return the tag of the next element. - * - * PARAMS - * berelement [I] Pointer to a berelement structure. - * len [O] Receives the length of the skipped element. - * - * RETURNS - * Success: Tag of the next element. - * Failure: LBER_DEFAULT (no more data). */ ULONG CDECL ber_skip_tag( BerElement *ber, ULONG *len ) { @@ -309,24 +164,8 @@ ULONG CDECL ber_skip_tag( BerElement *ber, ULONG *len ) return LDAP_CALL( ber_skip_tag, ¶ms ); }
- /*********************************************************************** * ber_printf (WLDAP32.@) - * - * Encode a berelement structure. - * - * PARAMS - * berelement [I/O] Pointer to a berelement structure. - * fmt [I] Format string. - * ... [I] Values to encode. - * - * RETURNS - * Success: Non-negative number. - * Failure: LBER_ERROR - * - * NOTES - * berelement must have been allocated with ber_alloc_t. This function - * can be called multiple times to append data. */ int WINAPIV ber_printf( BerElement *ber, char *fmt, ... ) { @@ -402,24 +241,8 @@ int WINAPIV ber_printf( BerElement *ber, char *fmt, ... ) return ret; }
- /*********************************************************************** * ber_scanf (WLDAP32.@) - * - * Decode a berelement structure. - * - * PARAMS - * berelement [I/O] Pointer to a berelement structure. - * fmt [I] Format string. - * ... [I] Pointers to values to be decoded. - * - * RETURNS - * Success: Non-negative number. - * Failure: LBER_ERROR - * - * NOTES - * berelement must have been allocated with ber_init. This function - * can be called multiple times to decode data. */ ULONG WINAPIV ber_scanf( BerElement *ber, char *fmt, ... ) { diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index 160a3d1ed30..beb7626b8b1 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -33,8 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_bindA (WLDAP32.@) - * - * See ldap_bindW. */ ULONG CDECL ldap_bindA( LDAP *ld, char *dn, char *cred, ULONG method ) { @@ -58,21 +56,6 @@ exit:
/*********************************************************************** * ldap_bindW (WLDAP32.@) - * - * Authenticate with an LDAP server (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * cred [I] Credentials (e.g. password string). - * method [I] Authentication method. - * - * RETURNS - * Success: Message ID of the bind operation. - * Failure: An LDAP error code. - * - * NOTES - * Only LDAP_AUTH_SIMPLE is supported (just like native). */ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { @@ -111,8 +94,6 @@ exit:
/*********************************************************************** * ldap_bind_sA (WLDAP32.@) - * - * See ldap_bind_sW. */ ULONG CDECL ldap_bind_sA( LDAP *ld, char *dn, char *cred, ULONG method ) { @@ -143,18 +124,6 @@ exit:
/*********************************************************************** * ldap_bind_sW (WLDAP32.@) - * - * Authenticate with an LDAP server (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * cred [I] Credentials (e.g. password string). - * method [I] Authentication method. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { @@ -236,8 +205,6 @@ exit:
/*********************************************************************** * ldap_sasl_bindA (WLDAP32.@) - * - * See ldap_sasl_bindW. */ ULONG CDECL ldap_sasl_bindA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, LDAPControlA **serverctrls, LDAPControlA **clientctrls, int *message ) @@ -268,25 +235,6 @@ exit:
/*********************************************************************** * ldap_sasl_bindW (WLDAP32.@) - * - * Authenticate with an LDAP server using SASL (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * mechanism [I] Authentication method. - * cred [I] Credentials. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the bind operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The serverctrls and clientctrls parameters are optional and should - * be set to NULL if not used. */ ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, int *message ) @@ -323,8 +271,6 @@ exit:
/*********************************************************************** * ldap_sasl_bind_sA (WLDAP32.@) - * - * See ldap_sasl_bind_sW. */ ULONG CDECL ldap_sasl_bind_sA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, LDAPControlA **serverctrls, LDAPControlA **clientctrls, BERVAL **serverdata ) @@ -355,25 +301,6 @@ exit:
/*********************************************************************** * ldap_sasl_bind_sW (WLDAP32.@) - * - * Authenticate with an LDAP server using SASL (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * mechanism [I] Authentication method. - * cred [I] Credentials. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * serverdata [O] Authentication response from the server. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The serverctrls and clientctrls parameters are optional and should - * be set to NULL if not used. */ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, BERVAL **serverdata ) @@ -418,8 +345,6 @@ exit:
/*********************************************************************** * ldap_simple_bindA (WLDAP32.@) - * - * See ldap_simple_bindW. */ ULONG CDECL ldap_simple_bindA( LDAP *ld, char *dn, char *passwd ) { @@ -443,20 +368,6 @@ exit:
/*********************************************************************** * ldap_simple_bindW (WLDAP32.@) - * - * Authenticate with an LDAP server (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * passwd [I] Password string. - * - * RETURNS - * Success: Message ID of the bind operation. - * Failure: An LDAP error code. - * - * NOTES - * Set dn and passwd to NULL to bind as an anonymous user. */ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { @@ -494,8 +405,6 @@ exit:
/*********************************************************************** * ldap_simple_bind_sA (WLDAP32.@) - * - * See ldap_simple_bind_sW. */ ULONG CDECL ldap_simple_bind_sA( LDAP *ld, char *dn, char *passwd ) { @@ -519,20 +428,6 @@ exit:
/*********************************************************************** * ldap_simple_bind_sW (WLDAP32.@) - * - * Authenticate with an LDAP server (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to bind as. - * passwd [I] Password string. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Set dn and passwd to NULL to bind as an anonymous user. */ ULONG CDECL ldap_simple_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { @@ -565,15 +460,6 @@ exit:
/*********************************************************************** * ldap_unbind (WLDAP32.@) - * - * Close LDAP connection and free resources (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_unbind( LDAP *ld ) { @@ -596,15 +482,6 @@ ULONG CDECL ldap_unbind( LDAP *ld )
/*********************************************************************** * ldap_unbind_s (WLDAP32.@) - * - * Close LDAP connection and free resources (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_unbind_s( LDAP *ld ) { diff --git a/dlls/wldap32/compare.c b/dlls/wldap32/compare.c index 87aa5e388d2..37b87c11c39 100644 --- a/dlls/wldap32/compare.c +++ b/dlls/wldap32/compare.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_compareA (WLDAP32.@) - * - * See ldap_compareW. */ ULONG CDECL ldap_compareA( LDAP *ld, char *dn, char *attr, char *value ) { @@ -58,18 +56,6 @@ exit:
/*********************************************************************** * ldap_compareW (WLDAP32.@) - * - * Check if an attribute has a certain value (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to compare value for. - * attr [I] Attribute to compare value for. - * value [I] Value to compare. - * - * RETURNS - * Success: Message ID of the compare operation. - * Failure: An LDAP error code. */ ULONG CDECL ldap_compareW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value ) { @@ -84,8 +70,6 @@ ULONG CDECL ldap_compareW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value )
/*********************************************************************** * ldap_compare_extA (WLDAP32.@) - * - * See ldap_compare_extW. */ ULONG CDECL ldap_compare_extA( LDAP *ld, char *dn, char *attr, char *value, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, @@ -119,27 +103,6 @@ exit:
/*********************************************************************** * ldap_compare_extW (WLDAP32.@) - * - * Check if an attribute has a certain value (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to compare value for. - * attr [I] Attribute to compare value for. - * value [I] string encoded value to compare. - * data [I] berval encoded value to compare. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the compare operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Set value to compare strings or data to compare binary values. If - * both are non-NULL, data will be used. The serverctrls and clientctrls - * parameters are optional and should be set to NULL if not used. */ ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -188,8 +151,6 @@ exit:
/*********************************************************************** * ldap_compare_ext_sA (WLDAP32.@) - * - * See ldap_compare_ext_sW. */ ULONG CDECL ldap_compare_ext_sA( LDAP *ld, char *dn, char *attr, char *value, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) @@ -222,26 +183,6 @@ exit:
/*********************************************************************** * ldap_compare_ext_sW (WLDAP32.@) - * - * Check if an attribute has a certain value (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to compare value for. - * attr [I] Attribute to compare value for. - * value [I] string encoded value to compare. - * data [I] berval encoded value to compare. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Set value to compare strings or data to compare binary values. If - * both are non-NULL, data will be used. The serverctrls and clientctrls - * parameters are optional and should be set to NULL if not used. */ ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) @@ -288,8 +229,6 @@ exit:
/*********************************************************************** * ldap_compare_sA (WLDAP32.@) - * - * See ldap_compare_sW. */ ULONG CDECL ldap_compare_sA( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ) { @@ -315,18 +254,6 @@ exit:
/*********************************************************************** * ldap_compare_sW (WLDAP32.@) - * - * Check if an attribute has a certain value (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of entry to compare value for. - * attr [I] Attribute to compare value for. - * value [I] Value to compare. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_compare_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value ) { diff --git a/dlls/wldap32/control.c b/dlls/wldap32/control.c index 9601fb6a96a..a825ada48ce 100644 --- a/dlls/wldap32/control.c +++ b/dlls/wldap32/control.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_control_freeA (WLDAP32.@) - * - * See ldap_control_freeW. */ ULONG CDECL ldap_control_freeA( LDAPControlA *control ) { @@ -43,14 +41,6 @@ ULONG CDECL ldap_control_freeA( LDAPControlA *control )
/*********************************************************************** * ldap_control_freeW (WLDAP32.@) - * - * Free an LDAPControl structure. - * - * PARAMS - * control [I] LDAPControl structure to free. - * - * RETURNS - * LDAP_SUCCESS */ ULONG CDECL ldap_control_freeW( LDAPControlW *control ) { @@ -61,8 +51,6 @@ ULONG CDECL ldap_control_freeW( LDAPControlW *control )
/*********************************************************************** * ldap_controls_freeA (WLDAP32.@) - * - * See ldap_controls_freeW. */ ULONG CDECL ldap_controls_freeA( LDAPControlA **controls ) { @@ -73,14 +61,6 @@ ULONG CDECL ldap_controls_freeA( LDAPControlA **controls )
/*********************************************************************** * ldap_controls_freeW (WLDAP32.@) - * - * Free an array of LDAPControl structures. - * - * PARAMS - * controls [I] Array of LDAPControl structures to free. - * - * RETURNS - * LDAP_SUCCESS */ ULONG CDECL ldap_controls_freeW( LDAPControlW **controls ) { @@ -91,8 +71,6 @@ ULONG CDECL ldap_controls_freeW( LDAPControlW **controls )
/*********************************************************************** * ldap_create_sort_controlA (WLDAP32.@) - * - * See ldap_create_sort_controlW. */ ULONG CDECL ldap_create_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkey, UCHAR critical, LDAPControlA **control ) { @@ -121,25 +99,6 @@ ULONG CDECL ldap_create_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkey, UCHAR c
/*********************************************************************** * ldap_create_sort_controlW (WLDAP32.@) - * - * Create a control for server sorted search results. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * sortkey [I] Array of LDAPSortKey structures, each specifying an - * attribute to use as a sort key, a matching rule and - * the sort order (ascending or descending). - * critical [I] Tells the server this control is critical to the - * search operation. - * control [O] LDAPControl created. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Pass the created control as a server control in subsequent calls - * to ldap_search_ext(_s) to obtain sorted search results. */ ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR critical, LDAPControlW **control ) { @@ -172,8 +131,6 @@ ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR c
/*********************************************************************** * ldap_create_vlv_controlA (WLDAP32.@) - * - * See ldap_create_vlv_controlW. */ INT CDECL ldap_create_vlv_controlA( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, LDAPControlA **control ) { @@ -198,25 +155,6 @@ INT CDECL ldap_create_vlv_controlA( LDAP *ld, LDAPVLVInfo *info, UCHAR critical,
/*********************************************************************** * ldap_create_vlv_controlW (WLDAP32.@) - * - * Create a virtual list view control. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * info [I] LDAPVLVInfo structure specifying a list view window. - * critical [I] Tells the server this control is critical to the - * search operation. - * control [O] LDAPControl created. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Pass the created control in conjunction with a sort control as - * server controls in subsequent calls to ldap_search_ext(_s). The - * server will then return a sorted, contiguous subset of results - * that meets the criteria specified in the LDAPVLVInfo structure. */ INT CDECL ldap_create_vlv_controlW( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, LDAPControlW **control ) { @@ -259,8 +197,6 @@ static inline void bv_val_dup( const struct berval *src, struct berval *dst )
/*********************************************************************** * ldap_encode_sort_controlA (WLDAP32.@) - * - * See ldap_encode_sort_controlW. */ ULONG CDECL ldap_encode_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkeys, LDAPControlA *ret, BOOLEAN critical ) { @@ -279,25 +215,6 @@ ULONG CDECL ldap_encode_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkeys, LDAPCo
/*********************************************************************** * ldap_encode_sort_controlW (WLDAP32.@) - * - * Create a control for server sorted search results. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * sortkey [I] Array of LDAPSortKey structures, each specifying an - * attribute to use as a sort key, a matching rule and - * the sort order (ascending or descending). - * critical [I] Tells the server this control is critical to the - * search operation. - * control [O] LDAPControl created. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * This function is obsolete. Use its equivalent - * ldap_create_sort_control instead. */ ULONG CDECL ldap_encode_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkeys, LDAPControlW *ret, BOOLEAN critical ) { @@ -316,8 +233,6 @@ ULONG CDECL ldap_encode_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkeys, LDAPCo
/*********************************************************************** * ldap_free_controlsA (WLDAP32.@) - * - * See ldap_free_controlsW. */ ULONG CDECL ldap_free_controlsA( LDAPControlA **controls ) { @@ -326,17 +241,6 @@ ULONG CDECL ldap_free_controlsA( LDAPControlA **controls )
/*********************************************************************** * ldap_free_controlsW (WLDAP32.@) - * - * Free an array of LDAPControl structures. - * - * PARAMS - * controls [I] Array of LDAPControl structures to free. - * - * RETURNS - * LDAP_SUCCESS - * - * NOTES - * Obsolete, use ldap_controls_freeW. */ ULONG CDECL ldap_free_controlsW( LDAPControlW **controls ) { diff --git a/dlls/wldap32/delete.c b/dlls/wldap32/delete.c index 41f8bfe3921..325aac4a580 100644 --- a/dlls/wldap32/delete.c +++ b/dlls/wldap32/delete.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_deleteA (WLDAP32.@) - * - * See ldap_deleteW. */ ULONG CDECL ldap_deleteA( LDAP *ld, char *dn ) { @@ -51,21 +49,6 @@ ULONG CDECL ldap_deleteA( LDAP *ld, char *dn )
/*********************************************************************** * ldap_deleteW (WLDAP32.@) - * - * Delete an entry from a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to delete. - * - * RETURNS - * Success: Message ID of the add operation. - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_deleteW( LDAP *ld, WCHAR *dn ) { @@ -80,8 +63,6 @@ ULONG CDECL ldap_deleteW( LDAP *ld, WCHAR *dn )
/*********************************************************************** * ldap_delete_extA (WLDAP32.@) - * - * See ldap_delete_extW. */ ULONG CDECL ldap_delete_extA( LDAP *ld, char *dn, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) @@ -109,24 +90,6 @@ exit:
/*********************************************************************** * ldap_delete_extW (WLDAP32.@) - * - * Delete an entry from a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to delete. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the delete operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. The serverctrls and clientctrls parameters are - * optional and should be set to NULL if not used. */ ULONG CDECL ldap_delete_extW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -157,8 +120,6 @@ exit:
/*********************************************************************** * ldap_delete_ext_sA (WLDAP32.@) - * - * See ldap_delete_ext_sW. */ ULONG CDECL ldap_delete_ext_sA( LDAP *ld, char *dn, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { @@ -185,22 +146,6 @@ exit:
/*********************************************************************** * ldap_delete_ext_sW (WLDAP32.@) - * - * Delete an entry from a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to delete. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The serverctrls and clientctrls parameters are optional and - * should be set to NULL if not used. */ ULONG CDECL ldap_delete_ext_sW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { @@ -230,8 +175,6 @@ exit:
/*********************************************************************** * ldap_delete_sA (WLDAP32.@) - * - * See ldap_delete_sW. */ ULONG CDECL ldap_delete_sA( LDAP *ld, char *dn ) { @@ -250,16 +193,6 @@ ULONG CDECL ldap_delete_sA( LDAP *ld, char *dn )
/*********************************************************************** * ldap_delete_sW (WLDAP32.@) - * - * Delete an entry from a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to delete. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_delete_sW( LDAP *ld, WCHAR *dn ) { diff --git a/dlls/wldap32/dn.c b/dlls/wldap32/dn.c index d18ff88d9aa..14c4617726a 100644 --- a/dlls/wldap32/dn.c +++ b/dlls/wldap32/dn.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_dn2ufnA (WLDAP32.@) - * - * See ldap_dn2ufnW. */ char * CDECL ldap_dn2ufnA( char *dn ) { @@ -53,18 +51,6 @@ char * CDECL ldap_dn2ufnA( char *dn )
/*********************************************************************** * ldap_dn2ufnW (WLDAP32.@) - * - * Convert a DN to a user-friendly name. - * - * PARAMS - * dn [I] DN to convert. - * - * RETURNS - * Success: Pointer to a string containing the user-friendly name. - * Failure: NULL - * - * NOTES - * Free the string with ldap_memfree. */ WCHAR * CDECL ldap_dn2ufnW( WCHAR *dn ) { @@ -88,8 +74,6 @@ WCHAR * CDECL ldap_dn2ufnW( WCHAR *dn )
/*********************************************************************** * ldap_explode_dnA (WLDAP32.@) - * - * See ldap_explode_dnW. */ char ** CDECL ldap_explode_dnA( char *dn, ULONG notypes ) { @@ -110,20 +94,6 @@ char ** CDECL ldap_explode_dnA( char *dn, ULONG notypes )
/*********************************************************************** * ldap_explode_dnW (WLDAP32.@) - * - * Break up a DN into its components. - * - * PARAMS - * dn [I] DN to break up. - * notypes [I] Remove attribute type information from the components. - * - * RETURNS - * Success: Pointer to a NULL-terminated array that contains the DN - * components. - * Failure: NULL - * - * NOTES - * Free the string array with ldap_value_free. */ WCHAR ** CDECL ldap_explode_dnW( WCHAR *dn, ULONG notypes ) { @@ -146,8 +116,6 @@ WCHAR ** CDECL ldap_explode_dnW( WCHAR *dn, ULONG notypes )
/*********************************************************************** * ldap_get_dnA (WLDAP32.@) - * - * See ldap_get_dnW. */ char * CDECL ldap_get_dnA( LDAP *ld, LDAPMessage *entry ) { @@ -167,19 +135,6 @@ char * CDECL ldap_get_dnA( LDAP *ld, LDAPMessage *entry )
/*********************************************************************** * ldap_get_dnW (WLDAP32.@) - * - * Retrieve the DN from a given LDAP message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] LDAPMessage structure to retrieve the DN from. - * - * RETURNS - * Success: Pointer to a string that contains the DN. - * Failure: NULL - * - * NOTES - * Free the string with ldap_memfree. */ WCHAR * CDECL ldap_get_dnW( LDAP *ld, LDAPMessage *entry ) { @@ -201,8 +156,6 @@ WCHAR * CDECL ldap_get_dnW( LDAP *ld, LDAPMessage *entry )
/*********************************************************************** * ldap_ufn2dnA (WLDAP32.@) - * - * See ldap_ufn2dnW. */ ULONG CDECL ldap_ufn2dnA( char *ufn, char **dn ) { @@ -231,19 +184,6 @@ ULONG CDECL ldap_ufn2dnA( char *ufn, char **dn )
/*********************************************************************** * ldap_ufn2dnW (WLDAP32.@) - * - * Convert a user-friendly name to a DN. - * - * PARAMS - * ufn [I] User-friendly name to convert. - * dn [O] Receives a pointer to a string containing the DN. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Free the string with ldap_memfree. */ ULONG CDECL ldap_ufn2dnW( WCHAR *ufn, WCHAR **dn ) { diff --git a/dlls/wldap32/error.c b/dlls/wldap32/error.c index a72babf830d..c2c7a6d9979 100644 --- a/dlls/wldap32/error.c +++ b/dlls/wldap32/error.c @@ -60,8 +60,6 @@ ULONG map_error( int error )
/*********************************************************************** * ldap_err2stringA (WLDAP32.@) - * - * See ldap_err2stringW. */ char * CDECL ldap_err2stringA( ULONG err ) { @@ -79,19 +77,6 @@ char * CDECL ldap_err2stringA( ULONG err )
/*********************************************************************** * ldap_err2stringW (WLDAP32.@) - * - * Convert an error code into a string describing the error. - * - * PARAMS - * err [I] Error code to convert. - * - * RETURNS - * Success: Pointer to a string containing the error description. - * Failure: NULL - * - * NOTES - * The returned string is statically allocated, you must not - * free this string. */ WCHAR * CDECL ldap_err2stringW( ULONG err ) { @@ -109,18 +94,6 @@ WCHAR * CDECL ldap_err2stringW( ULONG err )
/*********************************************************************** * ldap_perror (WLDAP32.@) - * - * Print a given error string. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * msg [I] Error string. - * - * RETURNS - * Nothing. - * - * NOTES - * Like native, this function does nothing. */ void CDECL ldap_perror( LDAP *ld, const PCHAR msg ) { @@ -129,20 +102,6 @@ void CDECL ldap_perror( LDAP *ld, const PCHAR msg )
/*********************************************************************** * ldap_result2error (WLDAP32.@) - * - * Parse an LDAP message and return the error obtained from it. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] Pointer to an LDAPMessage structure. - * free [I] Ask for the LDAPMessage structure to be freed. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * If not asked for, use ldap_msgfree to free the LDAPMessage. */ ULONG CDECL ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG free ) { @@ -160,14 +119,6 @@ ULONG CDECL ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG free )
/*********************************************************************** * LdapGetLastError (WLDAP32.@) - * - * Return the last error set by an LDAP function call. - * - * PARAMS - * None. - * - * RETURNS - * An LDAP error code. */ ULONG CDECL LdapGetLastError( void ) { @@ -278,14 +229,6 @@ static const ULONG errormap[] = {
/*********************************************************************** * LdapMapErrorToWin32 (WLDAP32.@) - * - * Map an LDAP error code to a Win32 error code. - * - * PARAMS - * err [I] An LDAP error code. - * - * RETURNS - * A Win32 error code. */ ULONG CDECL LdapMapErrorToWin32( ULONG err ) { diff --git a/dlls/wldap32/extended.c b/dlls/wldap32/extended.c index e693ae034f1..8c49c1d6b20 100644 --- a/dlls/wldap32/extended.c +++ b/dlls/wldap32/extended.c @@ -31,20 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_close_extended_op (WLDAP32.@) - * - * Close an extended operation. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * msgid [I] Message ID of the operation to be closed. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Contrary to native, OpenLDAP does not require us to close - * extended operations, so this is a no-op. */ ULONG CDECL ldap_close_extended_op( LDAP *ld, ULONG msgid ) { @@ -56,8 +42,6 @@ ULONG CDECL ldap_close_extended_op( LDAP *ld, ULONG msgid )
/*********************************************************************** * ldap_extended_operationA (WLDAP32.@) - * - * See ldap_extended_operationW. */ ULONG CDECL ldap_extended_operationA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) @@ -85,28 +69,6 @@ exit:
/*********************************************************************** * ldap_extended_operationW (WLDAP32.@) - * - * Perform an extended operation (asynchronous mode). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * oid [I] OID of the extended operation. - * data [I] Data needed by the operation. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the extended operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The data parameter should be set to NULL if the operation - * requires no data. Call ldap_result with the message ID to - * get the result of the operation or ldap_abandon to cancel - * the operation. The serverctrls and clientctrls parameters - * are optional and should be set to NULL if not used. Call - * ldap_close_extended_op to close the operation. */ ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -140,8 +102,6 @@ exit:
/*********************************************************************** * ldap_extended_operation_sA (WLDAP32.@) - * - * See ldap_extended_operation_sW. */ ULONG CDECL ldap_extended_operation_sA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, char **retoid, struct berval **retdata ) @@ -176,27 +136,6 @@ exit:
/*********************************************************************** * ldap_extended_operation_sW (WLDAP32.@) - * - * Perform an extended operation (synchronous mode). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * oid [I] OID of the extended operation. - * data [I] Data needed by the operation. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * retoid [O] OID of the server response message. - * retdata [O] Data returned by the server. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The data parameter should be set to NULL if the operation - * requires no data. The serverctrls, clientctrls, retoid and - * and retdata parameters are also optional. Set to NULL if not - * used. Free retoid and retdata after use with ldap_memfree. */ ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, WCHAR **retoid, struct berval **retdata ) diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index bd9c8cb4277..c128039bf5c 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -212,8 +212,6 @@ static LDAP *create_context( const char *url )
/*********************************************************************** * cldap_openA (WLDAP32.@) - * - * See cldap_openW. */ LDAP * CDECL cldap_openA( char *hostname, ULONG portnumber ) { @@ -232,24 +230,6 @@ LDAP * CDECL cldap_openA( char *hostname, ULONG portnumber )
/*********************************************************************** * cldap_openW (WLDAP32.@) - * - * Initialize an LDAP context and create a UDP connection. - * - * PARAMS - * hostname [I] Name of the host to connect to. - * portnumber [I] Port number to use. - * - * RETURNS - * Success: Pointer to an LDAP context. - * Failure: NULL - * - * NOTES - * The hostname string can be a space separated string of hostnames, - * in which case the LDAP runtime will try to connect to the hosts - * in order, until a connection can be made. A hostname may have a - * trailing port number (separated from the hostname by a ':'), which - * will take precedence over the port number supplied as a parameter - * to this function. */ LDAP * CDECL cldap_openW( WCHAR *hostname, ULONG portnumber ) { @@ -271,21 +251,6 @@ exit:
/*********************************************************************** * ldap_connect (WLDAP32.@) - * - * Connect to an LDAP server. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * timeout [I] Pointer to an l_timeval structure specifying the - * timeout in seconds. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The timeout parameter may be NULL in which case a default timeout - * value will be used. */ ULONG CDECL ldap_connect( LDAP *ld, struct l_timeval *timeout ) { @@ -297,8 +262,6 @@ ULONG CDECL ldap_connect( LDAP *ld, struct l_timeval *timeout )
/*********************************************************************** * ldap_initA (WLDAP32.@) - * - * See ldap_initW. */ LDAP * CDECL ldap_initA( const PCHAR hostname, ULONG portnumber ) { @@ -317,25 +280,6 @@ LDAP * CDECL ldap_initA( const PCHAR hostname, ULONG portnumber )
/*********************************************************************** * ldap_initW (WLDAP32.@) - * - * Initialize an LDAP context and create a TCP connection. - * - * PARAMS - * hostname [I] Name of the host to connect to. - * portnumber [I] Port number to use. - * - * RETURNS - * Success: Pointer to an LDAP context. - * Failure: NULL - * - * NOTES - * The hostname string can be a space separated string of hostnames, - * in which case the LDAP runtime will try to connect to the hosts - * in order, until a connection can be made. A hostname may have a - * trailing port number (separated from the hostname by a ':'), which - * will take precedence over the port number supplied as a parameter - * to this function. The connection will not be made until the first - * LDAP function that needs it is called. */ LDAP * CDECL ldap_initW( const PWCHAR hostname, ULONG portnumber ) { @@ -357,8 +301,6 @@ exit:
/*********************************************************************** * ldap_openA (WLDAP32.@) - * - * See ldap_openW. */ LDAP * CDECL ldap_openA( char *hostname, ULONG portnumber ) { @@ -377,24 +319,6 @@ LDAP * CDECL ldap_openA( char *hostname, ULONG portnumber )
/*********************************************************************** * ldap_openW (WLDAP32.@) - * - * Initialize an LDAP context and create a TCP connection. - * - * PARAMS - * hostname [I] Name of the host to connect to. - * portnumber [I] Port number to use. - * - * RETURNS - * Success: Pointer to an LDAP context. - * Failure: NULL - * - * NOTES - * The hostname string can be a space separated string of hostnames, - * in which case the LDAP runtime will try to connect to the hosts - * in order, until a connection can be made. A hostname may have a - * trailing port number (separated from the hostname by a ':'), which - * will take precedence over the port number supplied as a parameter - * to this function. */ LDAP * CDECL ldap_openW( WCHAR *hostname, ULONG portnumber ) { @@ -416,8 +340,6 @@ exit:
/*********************************************************************** * ldap_sslinitA (WLDAP32.@) - * - * See ldap_sslinitW. */ LDAP * CDECL ldap_sslinitA( char *hostname, ULONG portnumber, int secure ) { @@ -436,26 +358,6 @@ LDAP * CDECL ldap_sslinitA( char *hostname, ULONG portnumber, int secure )
/*********************************************************************** * ldap_sslinitW (WLDAP32.@) - * - * Initialize an LDAP context and create a secure TCP connection. - * - * PARAMS - * hostname [I] Name of the host to connect to. - * portnumber [I] Port number to use. - * secure [I] Ask the server to create an SSL connection. - * - * RETURNS - * Success: Pointer to an LDAP context. - * Failure: NULL - * - * NOTES - * The hostname string can be a space separated string of hostnames, - * in which case the LDAP runtime will try to connect to the hosts - * in order, until a connection can be made. A hostname may have a - * trailing port number (separated from the hostname by a ':'), which - * will take precedence over the port number supplied as a parameter - * to this function. The connection will not be made until the first - * LDAP function that needs it is called. */ LDAP * CDECL ldap_sslinitW( WCHAR *hostname, ULONG portnumber, int secure ) { @@ -482,8 +384,6 @@ exit:
/*********************************************************************** * ldap_start_tls_sA (WLDAP32.@) - * - * See ldap_start_tls_sW. */ ULONG CDECL ldap_start_tls_sA( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) @@ -508,22 +408,6 @@ exit:
/*********************************************************************** * ldap_start_tls_s (WLDAP32.@) - * - * Start TLS encryption on an LDAP connection. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * retval [I] Return value from the server. - * result [I] Response message from the server. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * LDAP function that needs it is called. */ ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) @@ -565,15 +449,6 @@ ULONG CDECL ldap_startup( LDAP_VERSION_INFO *version, HANDLE *instance )
/*********************************************************************** * ldap_stop_tls_s (WLDAP32.@) - * - * Stop TLS encryption on an LDAP connection. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * - * RETURNS - * Success: TRUE - * Failure: FALSE */ BOOLEAN CDECL ldap_stop_tls_s( LDAP *ld ) { diff --git a/dlls/wldap32/misc.c b/dlls/wldap32/misc.c index 697f1d3ad5e..135d79a6d58 100644 --- a/dlls/wldap32/misc.c +++ b/dlls/wldap32/misc.c @@ -32,16 +32,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_abandon (WLDAP32.@) - * - * Cancel an asynchronous operation. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * msgid [I] ID of the operation to cancel. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_abandon( LDAP *ld, ULONG msgid ) { @@ -57,8 +47,6 @@ ULONG CDECL ldap_abandon( LDAP *ld, ULONG msgid )
/*********************************************************************** * ldap_check_filterA (WLDAP32.@) - * - * See ldap_check_filterW. */ ULONG CDECL ldap_check_filterA( LDAP *ld, char *filter ) { @@ -78,16 +66,6 @@ ULONG CDECL ldap_check_filterA( LDAP *ld, char *filter )
/*********************************************************************** * ldap_check_filterW (WLDAP32.@) - * - * Check filter syntax. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * filter [I] Filter string. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_check_filterW( LDAP *ld, WCHAR *filter ) { @@ -108,16 +86,6 @@ ULONG CDECL ldap_cleanup( HANDLE instance )
/*********************************************************************** * ldap_conn_from_msg (WLDAP32.@) - * - * Get the LDAP context for a given message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] LDAP message. - * - * RETURNS - * Success: Pointer to an LDAP context. - * Failure: NULL */ LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res ) { @@ -129,16 +97,6 @@ LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res )
/*********************************************************************** * ldap_count_entries (WLDAP32.@) - * - * Count the number of entries returned from a search. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] LDAP message. - * - * RETURNS - * Success: The number of entries. - * Failure: ~0u */ ULONG CDECL ldap_count_entries( LDAP *ld, LDAPMessage *res ) { @@ -154,16 +112,6 @@ ULONG CDECL ldap_count_entries( LDAP *ld, LDAPMessage *res )
/*********************************************************************** * ldap_count_references (WLDAP32.@) - * - * Count the number of references returned from a search. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] LDAP message. - * - * RETURNS - * Success: The number of references. - * Failure: ~0u */ ULONG CDECL ldap_count_references( LDAP *ld, LDAPMessage *res ) { @@ -216,8 +164,6 @@ static void escape_filter_element( char *src, ULONG srclen, char *dst )
/*********************************************************************** * ldap_escape_filter_elementA (WLDAP32.@) - * - * See ldap_escape_filter_elementW. */ ULONG CDECL ldap_escape_filter_elementA( char *src, ULONG srclen, char *dst, ULONG dstlen ) { @@ -234,18 +180,6 @@ ULONG CDECL ldap_escape_filter_elementA( char *src, ULONG srclen, char *dst, ULO
/*********************************************************************** * ldap_escape_filter_elementW (WLDAP32.@) - * - * Escape binary data for safe passing in filters. - * - * PARAMS - * src [I] Filter element to be escaped. - * srclen [I] Length in bytes of the filter element. - * dst [O] Destination buffer for the escaped filter element. - * dstlen [I] Length in bytes of the destination buffer. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_escape_filter_elementW( char *src, ULONG srclen, WCHAR *dst, ULONG dstlen ) { @@ -261,8 +195,6 @@ ULONG CDECL ldap_escape_filter_elementW( char *src, ULONG srclen, WCHAR *dst, UL
/*********************************************************************** * ldap_first_attributeA (WLDAP32.@) - * - * See ldap_first_attributeW. */ char * CDECL ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **ber ) { @@ -285,20 +217,6 @@ char * CDECL ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **b
/*********************************************************************** * ldap_first_attributeW (WLDAP32.@) - * - * Get the first attribute for a given entry. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] Entry to retrieve attribute for. - * ptr [O] Position pointer. - * - * RETURNS - * Success: Name of the first attribute. - * Failure: NULL - * - * NOTES - * Use ldap_memfree to free the returned string. */ WCHAR * CDECL ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement **ptr ) { @@ -329,19 +247,6 @@ WCHAR * CDECL ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement **
/*********************************************************************** * ldap_first_entry (WLDAP32.@) - * - * Get the first entry from a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] Search result message. - * - * RETURNS - * Success: The first entry. - * Failure: NULL - * - * NOTES - * The returned entry will be freed when the message is freed. */ LDAPMessage * CDECL ldap_first_entry( LDAP *ld, LDAPMessage *res ) { @@ -363,16 +268,6 @@ LDAPMessage * CDECL ldap_first_entry( LDAP *ld, LDAPMessage *res )
/*********************************************************************** * ldap_first_reference (WLDAP32.@) - * - * Get the first reference from a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * res [I] Search result message. - * - * RETURNS - * Success: The first reference. - * Failure: NULL */ LDAPMessage * CDECL ldap_first_reference( LDAP *ld, LDAPMessage *res ) { @@ -394,8 +289,6 @@ LDAPMessage * CDECL ldap_first_reference( LDAP *ld, LDAPMessage *res )
/*********************************************************************** * ldap_memfreeA (WLDAP32.@) - * - * See ldap_memfreeW. */ void CDECL ldap_memfreeA( char *block ) { @@ -405,11 +298,6 @@ void CDECL ldap_memfreeA( char *block )
/*********************************************************************** * ldap_memfreeW (WLDAP32.@) - * - * Free a block of memory. - * - * PARAMS - * block [I] Pointer to memory block to be freed. */ void CDECL ldap_memfreeW( WCHAR *block ) { @@ -419,11 +307,6 @@ void CDECL ldap_memfreeW( WCHAR *block )
/*********************************************************************** * ldap_msgfree (WLDAP32.@) - * - * Free a message. - * - * PARAMS - * res [I] Message to be freed. */ ULONG CDECL ldap_msgfree( LDAPMessage *res ) { @@ -446,8 +329,6 @@ ULONG CDECL ldap_msgfree( LDAPMessage *res )
/*********************************************************************** * ldap_next_attributeA (WLDAP32.@) - * - * See ldap_next_attributeW. */ char * CDECL ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr ) { @@ -470,21 +351,6 @@ char * CDECL ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr
/*********************************************************************** * ldap_next_attributeW (WLDAP32.@) - * - * Get the next attribute for a given entry. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] Entry to retrieve attribute for. - * ptr [I/O] Position pointer. - * - * RETURNS - * Success: The name of the next attribute. - * Failure: NULL - * - * NOTES - * Free the returned string after each iteration with ldap_memfree. - * When done iterating and when ptr != NULL, call ber_free( ptr, 0 ). */ WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *ptr ) { @@ -507,19 +373,6 @@ WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *pt
/*********************************************************************** * ldap_next_entry (WLDAP32.@) - * - * Get the next entry from a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] Entry returned by a previous call. - * - * RETURNS - * Success: The next entry. - * Failure: NULL - * - * NOTES - * The returned entry will be freed when the message is freed. */ LDAPMessage * CDECL ldap_next_entry( LDAP *ld, LDAPMessage *entry ) { @@ -548,19 +401,6 @@ LDAPMessage * CDECL ldap_next_entry( LDAP *ld, LDAPMessage *entry )
/*********************************************************************** * ldap_next_reference (WLDAP32.@) - * - * Get the next reference from a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] Entry returned by a previous call. - * - * RETURNS - * Success: The next reference. - * Failure: NULL - * - * NOTES - * The returned entry will be freed when the message is freed. */ LDAPMessage * CDECL ldap_next_reference( LDAP *ld, LDAPMessage *entry ) { @@ -588,39 +428,6 @@ LDAPMessage * CDECL ldap_next_reference( LDAP *ld, LDAPMessage *entry )
/*********************************************************************** * ldap_result (WLDAP32.@) - * - * Get the result of an asynchronous operation. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * msgid [I] Message ID of the operation. - * all [I] How many results should be returned? - * timeout [I] How long to wait for the results? - * res [O] Result message for the operation. - * - * RETURNS - * Success: One of the following values: - * - * LDAP_RES_ADD - * LDAP_RES_BIND - * LDAP_RES_COMPARE - * LDAP_RES_DELETE - * LDAP_RES_EXTENDED - * LDAP_RES_MODIFY - * LDAP_RES_MODRDN - * LDAP_RES_REFERRAL - * LDAP_RES_SEARCH_ENTRY - * LDAP_RES_SEARCH_RESULT - * - * Failure: ~0u - * - * This function returns 0 when the timeout has expired. - * - * NOTES - * A NULL timeout pointer causes the function to block waiting - * for results to arrive. A timeout value of 0 causes the function - * to immediately return any available results. Free returned results - * with ldap_msgfree. */ ULONG CDECL ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res ) { @@ -654,20 +461,6 @@ ULONG CDECL ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *tim
/*********************************************************************** * LdapUnicodeToUTF8 (WLDAP32.@) - * - * Convert a wide character string to a UTF8 string. - * - * PARAMS - * src [I] Wide character string to convert. - * srclen [I] Size of string to convert, in characters. - * dst [O] Pointer to a buffer that receives the converted string. - * dstlen [I] Size of the destination buffer in characters. - * - * RETURNS - * The number of characters written into the destination buffer. - * - * NOTES - * Set dstlen to zero to ask for the required buffer size. */ int CDECL LdapUnicodeToUTF8( const WCHAR *src, int srclen, char *dst, int dstlen ) { @@ -676,20 +469,6 @@ int CDECL LdapUnicodeToUTF8( const WCHAR *src, int srclen, char *dst, int dstlen
/*********************************************************************** * LdapUTF8ToUnicode (WLDAP32.@) - * - * Convert a UTF8 string to a wide character string. - * - * PARAMS - * src [I] UTF8 string to convert. - * srclen [I] Size of string to convert, in characters. - * dst [O] Pointer to a buffer that receives the converted string. - * dstlen [I] Size of the destination buffer in characters. - * - * RETURNS - * The number of characters written into the destination buffer. - * - * NOTES - * Set dstlen to zero to ask for the required buffer size. */ int CDECL LdapUTF8ToUnicode( const char *src, int srclen, WCHAR *dst, int dstlen ) { diff --git a/dlls/wldap32/modify.c b/dlls/wldap32/modify.c index 7c7f2c61293..553437a0b22 100644 --- a/dlls/wldap32/modify.c +++ b/dlls/wldap32/modify.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_modifyA (WLDAP32.@) - * - * See ldap_modifyW. */ ULONG CDECL ldap_modifyA( LDAP *ld, char *dn, LDAPModA **mods ) { @@ -57,23 +55,6 @@ exit:
/*********************************************************************** * ldap_modifyW (WLDAP32.@) - * - * Change an entry in a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * mods [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to change. - * - * RETURNS - * Success: Message ID of the modify operation. - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_modifyW( LDAP *ld, WCHAR *dn, LDAPModW **mods ) { @@ -88,8 +69,6 @@ ULONG CDECL ldap_modifyW( LDAP *ld, WCHAR *dn, LDAPModW **mods )
/*********************************************************************** * ldap_modify_extA (WLDAP32.@) - * - * See ldap_modify_extW. */ ULONG CDECL ldap_modify_extA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) @@ -120,26 +99,6 @@ exit:
/*********************************************************************** * ldap_modify_extW (WLDAP32.@) - * - * Change an entry in a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * mods [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to change. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the modify operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. The serverctrls and clientctrls parameters are - * optional and should be set to NULL if not used. */ ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -173,8 +132,6 @@ exit:
/*********************************************************************** * ldap_modify_ext_sA (WLDAP32.@) - * - * See ldap_modify_ext_sW. */ ULONG CDECL ldap_modify_ext_sA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) @@ -205,24 +162,6 @@ exit:
/*********************************************************************** * ldap_modify_ext_sW (WLDAP32.@) - * - * Change an entry in a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * mods [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to change. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * The serverctrls and clientctrls parameters are optional and - * should be set to NULL if not used. */ ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) @@ -256,8 +195,6 @@ exit:
/*********************************************************************** * ldap_modify_sA (WLDAP32.@) - * - * See ldap_modify_sW. */ ULONG CDECL ldap_modify_sA( LDAP *ld, char *dn, LDAPModA **mods ) { @@ -282,18 +219,6 @@ exit:
/*********************************************************************** * ldap_modify_sW (WLDAP32.@) - * - * Change an entry in a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * attrs [I] Pointer to an array of LDAPModW structures, each - * specifying an attribute and its values to change. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_modify_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods ) { diff --git a/dlls/wldap32/modrdn.c b/dlls/wldap32/modrdn.c index 97e06a1975c..999e5b5df62 100644 --- a/dlls/wldap32/modrdn.c +++ b/dlls/wldap32/modrdn.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_modrdnA (WLDAP32.@) - * - * See ldap_modrdnW. */ ULONG CDECL ldap_modrdnA( LDAP *ld, char *dn, char *newdn ) { @@ -56,22 +54,6 @@ exit:
/*********************************************************************** * ldap_modrdnW (WLDAP32.@) - * - * Change the RDN of a directory entry (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newdn [I] New DN for the entry. - * - * RETURNS - * Success: Message ID of the modrdn operation. - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_modrdnW( LDAP *ld, WCHAR *dn, WCHAR *newdn ) { @@ -81,8 +63,6 @@ ULONG CDECL ldap_modrdnW( LDAP *ld, WCHAR *dn, WCHAR *newdn )
/*********************************************************************** * ldap_modrdn2A (WLDAP32.@) - * - * See ldap_modrdn2W. */ ULONG CDECL ldap_modrdn2A( LDAP *ld, char *dn, char *newdn, int delete ) { @@ -106,23 +86,6 @@ exit:
/*********************************************************************** * ldap_modrdn2W (WLDAP32.@) - * - * Change the RDN of a directory entry (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newdn [I] New DN for the entry. - * delete [I] Delete old DN? - * - * RETURNS - * Success: Message ID of the modrdn operation. - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { @@ -152,8 +115,6 @@ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete )
/*********************************************************************** * ldap_modrdn2_sA (WLDAP32.@) - * - * See ldap_modrdn2_sW. */ ULONG CDECL ldap_modrdn2_sA( LDAP *ld, char *dn, char *newdn, int delete ) { @@ -177,18 +138,6 @@ exit:
/*********************************************************************** * ldap_modrdn2_sW (WLDAP32.@) - * - * Change the RDN of a directory entry (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newdn [I] New DN for the entry. - * delete [I] Delete old DN? - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { @@ -213,8 +162,6 @@ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete )
/*********************************************************************** * ldap_modrdn_sA (WLDAP32.@) - * - * See ldap_modrdn_sW. */ ULONG CDECL ldap_modrdn_sA( LDAP *ld, char *dn, char *newdn ) { @@ -238,17 +185,6 @@ exit:
/*********************************************************************** * ldap_modrdn_sW (WLDAP32.@) - * - * Change the RDN of a directory entry (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newdn [I] New DN for the entry. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_modrdn_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn ) { diff --git a/dlls/wldap32/option.c b/dlls/wldap32/option.c index efd0d4586b9..d848522fa56 100644 --- a/dlls/wldap32/option.c +++ b/dlls/wldap32/option.c @@ -35,8 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_get_optionA (WLDAP32.@) - * - * See ldap_get_optionW. */ ULONG CDECL ldap_get_optionA( LDAP *ld, int option, void *value ) { @@ -154,17 +152,6 @@ ULONG CDECL ldap_get_optionA( LDAP *ld, int option, void *value )
/*********************************************************************** * ldap_get_optionW (WLDAP32.@) - * - * Retrieve option values for a given LDAP context. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * option [I] Option to get values for. - * value [O] Pointer to option values. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) { @@ -289,8 +276,6 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value )
/*********************************************************************** * ldap_set_optionA (WLDAP32.@) - * - * See ldap_set_optionW. */ ULONG CDECL ldap_set_optionA( LDAP *ld, int option, void *value ) { @@ -435,20 +420,6 @@ static BOOL is_supported_server_ctrls( LDAP *ld, LDAPControlU **ctrls )
/*********************************************************************** * ldap_set_optionW (WLDAP32.@) - * - * Set option values for a given LDAP context. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * option [I] Option to set values for. - * value [I] Pointer to option values. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Set value to LDAP_OPT_ON or LDAP_OPT_OFF for on/off options. */ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) { diff --git a/dlls/wldap32/page.c b/dlls/wldap32/page.c index e36d0ad5615..fab2b83366a 100644 --- a/dlls/wldap32/page.c +++ b/dlls/wldap32/page.c @@ -36,8 +36,6 @@ static struct berval null_cookieW = { 0, NULL };
/*********************************************************************** * ldap_create_page_controlA (WLDAP32.@) - * - * See ldap_create_page_controlW. */ ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct berval *cookie, UCHAR critical, LDAPControlA **control ) @@ -110,21 +108,6 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c
/*********************************************************************** * ldap_create_page_controlW (WLDAP32.@) - * - * Create a control for paged search results. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * pagesize [I] Number of entries to return per page. - * cookie [I] Used by the server to track its location in the - * search results. - * critical [I] Tells the server this control is critical to the - * search operation. - * control [O] LDAPControl created. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_create_page_controlW( LDAP *ld, ULONG pagesize, struct berval *cookie, UCHAR critical, LDAPControlW **control ) diff --git a/dlls/wldap32/parse.c b/dlls/wldap32/parse.c index 88e801b3053..bcd0e61607a 100644 --- a/dlls/wldap32/parse.c +++ b/dlls/wldap32/parse.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_parse_extended_resultA (WLDAP32.@) - * - * See ldap_parse_extended_resultW. */ ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, LDAPMessage *result, char **oid, struct berval **data, BOOLEAN free ) @@ -58,23 +56,6 @@ ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, LDAPMessage *result, char **o
/*********************************************************************** * ldap_parse_extended_resultW (WLDAP32.@) - * - * Parse the result of an extended operation. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * result [I] Result message from an extended operation. - * oid [O] OID of the extended operation. - * data [O] Result data. - * free [I] Free the result message? - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Free the OID and result data with ldap_memfree. Pass a nonzero - * value for 'free' or call ldap_msgfree to free the result message. */ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR **oid, struct berval **data, BOOLEAN free ) @@ -112,8 +93,6 @@ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR **
/*********************************************************************** * ldap_parse_referenceA (WLDAP32.@) - * - * See ldap_parse_referenceW. */ ULONG CDECL ldap_parse_referenceA( LDAP *ld, LDAPMessage *message, char ***referrals ) { @@ -137,20 +116,6 @@ ULONG CDECL ldap_parse_referenceA( LDAP *ld, LDAPMessage *message, char ***refer
/*********************************************************************** * ldap_parse_referenceW (WLDAP32.@) - * - * Return any referrals from a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * result [I] Result message. - * referrals [O] Array of referral URLs. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Free the referrals with ldap_value_free. */ ULONG CDECL ldap_parse_referenceW( LDAP *ld, LDAPMessage *message, WCHAR ***referrals ) { @@ -176,8 +141,6 @@ ULONG CDECL ldap_parse_referenceW( LDAP *ld, LDAPMessage *message, WCHAR ***refe
/*********************************************************************** * ldap_parse_resultA (WLDAP32.@) - * - * See ldap_parse_resultW. */ ULONG CDECL ldap_parse_resultA( LDAP *ld, LDAPMessage *result, ULONG *retcode, char **matched, char **error, char ***referrals, LDAPControlA ***serverctrls, BOOLEAN free ) @@ -207,28 +170,6 @@ ULONG CDECL ldap_parse_resultA( LDAP *ld, LDAPMessage *result, ULONG *retcode, c
/*********************************************************************** * ldap_parse_resultW (WLDAP32.@) - * - * Parse a result message. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * result [I] Result message. - * retcode [O] Return code for the server operation. - * matched [O] DNs matched in the operation. - * error [O] Error message for the operation. - * referrals [O] Referrals found in the result message. - * serverctrls [O] Controls used in the operation. - * free [I] Free the result message? - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Free the DNs and error message with ldap_memfree. Free - * the referrals with ldap_value_free and the controls with - * ldap_controls_free. Pass a nonzero value for 'free' or call - * ldap_msgfree to free the result message. */ ULONG CDECL ldap_parse_resultW( LDAP *ld, LDAPMessage *result, ULONG *retcode, WCHAR **matched, WCHAR **error, WCHAR ***referrals, LDAPControlW ***serverctrls, BOOLEAN free ) @@ -262,8 +203,6 @@ ULONG CDECL ldap_parse_resultW( LDAP *ld, LDAPMessage *result, ULONG *retcode, W
/*********************************************************************** * ldap_parse_sort_controlA (WLDAP32.@) - * - * See ldap_parse_sort_controlW. */ ULONG CDECL ldap_parse_sort_controlA( LDAP *ld, LDAPControlA **control, ULONG *result, char **attr ) { @@ -286,21 +225,6 @@ ULONG CDECL ldap_parse_sort_controlA( LDAP *ld, LDAPControlA **control, ULONG *r
/*********************************************************************** * ldap_parse_sort_controlW (WLDAP32.@) - * - * Parse a sort control. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * control [I] Control obtained from a result message. - * result [O] Result code. - * attr [O] Failing attribute. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * If the function fails, free the failing attribute with ldap_memfree. */ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *result, WCHAR **attr ) { @@ -349,8 +273,6 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r
/*********************************************************************** * ldap_parse_vlv_controlA (WLDAP32.@) - * - * See ldap_parse_vlv_controlW. */ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targetpos, ULONG *listcount, struct berval **context, int *errcode ) @@ -370,23 +292,6 @@ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targ
/*********************************************************************** * ldap_parse_vlv_controlW (WLDAP32.@) - * - * Parse a virtual list view control. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * control [I] Controls obtained from a result message. - * targetpos [O] Position of the target in the result list. - * listcount [O] Estimate of the number of results in the list. - * context [O] Server side context. - * errcode [O] Error code from the listview operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Free the server context with ber_bvfree. */ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targetpos, ULONG *listcount, struct berval **context, int *errcode ) diff --git a/dlls/wldap32/rename.c b/dlls/wldap32/rename.c index f6b343521c5..58a2f2101b3 100644 --- a/dlls/wldap32/rename.c +++ b/dlls/wldap32/rename.c @@ -31,8 +31,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_rename_extA (WLDAP32.@) - * - * See ldap_rename_extW. */ ULONG CDECL ldap_rename_extA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) @@ -65,27 +63,6 @@ exit:
/*********************************************************************** * ldap_rename_extW (WLDAP32.@) - * - * Change the DN of a directory entry (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newrdn [I] New RDN for the entry. - * newparent [I] New parent for the entry. - * delete [I] Delete old RDN? - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * message [O] Message ID of the operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) @@ -120,8 +97,6 @@ exit:
/*********************************************************************** * ldap_rename_ext_sA (WLDAP32.@) - * - * See ldap_rename_ext_sW. */ ULONG CDECL ldap_rename_ext_sA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) @@ -151,23 +126,9 @@ exit: controlarrayfreeW( clientctrlsW ); return ret; } + /*********************************************************************** * ldap_rename_ext_sW (WLDAP32.@) - * - * Change the DN of a directory entry (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * dn [I] DN of the entry to change. - * newrdn [I] New RDN for the entry. - * newparent [I] New parent for the entry. - * delete [I] Delete old RDN? - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) diff --git a/dlls/wldap32/search.c b/dlls/wldap32/search.c index a673851b148..738344de685 100644 --- a/dlls/wldap32/search.c +++ b/dlls/wldap32/search.c @@ -32,8 +32,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_searchA (WLDAP32.@) - * - * See ldap_searchW. */ ULONG CDECL ldap_searchA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly ) { @@ -59,26 +57,6 @@ exit:
/*********************************************************************** * ldap_searchW (WLDAP32.@) - * - * Search a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * base [I] Starting point for the search. - * scope [I] Search scope. One of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. - * filter [I] Search filter. - * attrs [I] Attributes to return. - * attrsonly [I] Return no values, only attributes. - * - * RETURNS - * Success: Message ID of the search operation. - * Failure: ~0u - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_searchW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly ) { @@ -92,8 +70,6 @@ ULONG CDECL ldap_searchW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCH
/*********************************************************************** * ldap_search_extA (WLDAP32.@) - * - * See ldap_search_extW. */ ULONG CDECL ldap_search_extA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message ) @@ -127,31 +103,6 @@ exit:
/*********************************************************************** * ldap_search_extW (WLDAP32.@) - * - * Search a directory tree (asynchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * base [I] Starting point for the search. - * scope [I] Search scope. One of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. - * filter [I] Search filter. - * attrs [I] Attributes to return. - * attrsonly [I] Return no values, only attributes. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * timelimit [I] Timeout in seconds. - * sizelimit [I] Maximum number of entries to return. Zero means unlimited. - * message [O] Message ID of the search operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_result with the message ID to get the result of - * the operation. Cancel the operation by calling ldap_abandon - * with the message ID. */ ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, ULONG sizelimit, @@ -192,8 +143,6 @@ exit:
/*********************************************************************** * ldap_search_ext_sA (WLDAP32.@) - * - * See ldap_search_ext_sW. */ ULONG CDECL ldap_search_ext_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, struct l_timeval *timeout, @@ -228,29 +177,6 @@ exit:
/*********************************************************************** * ldap_search_ext_sW (WLDAP32.@) - * - * Search a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * base [I] Starting point for the search. - * scope [I] Search scope. One of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. - * filter [I] Search filter. - * attrs [I] Attributes to return. - * attrsonly [I] Return no values, only attributes. - * serverctrls [I] Array of LDAP server controls. - * clientctrls [I] Array of LDAP client controls. - * timeout [I] Timeout in seconds. - * sizelimit [I] Maximum number of entries to return. Zero means unlimited. - * res [O] Results of the search operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_msgfree to free the results. */ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, struct l_timeval *timeout, @@ -311,8 +237,6 @@ exit:
/*********************************************************************** * ldap_search_sA (WLDAP32.@) - * - * See ldap_search_sW. */ ULONG CDECL ldap_search_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, LDAPMessage **res ) @@ -340,25 +264,6 @@ exit:
/*********************************************************************** * ldap_search_sW (WLDAP32.@) - * - * Search a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * base [I] Starting point for the search. - * scope [I] Search scope. One of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. - * filter [I] Search filter. - * attrs [I] Attributes to return. - * attrsonly [I] Return no values, only attributes. - * res [O] Results of the search operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_msgfree to free the results. */ ULONG CDECL ldap_search_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, LDAPMessage **res ) @@ -370,8 +275,6 @@ ULONG CDECL ldap_search_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, W
/*********************************************************************** * ldap_search_stA (WLDAP32.@) - * - * See ldap_search_stW. */ ULONG CDECL ldap_search_stA( LDAP *ld, const PCHAR base, ULONG scope, const PCHAR filter, char **attrs, ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ) @@ -399,26 +302,6 @@ exit:
/*********************************************************************** * ldap_search_stW (WLDAP32.@) - * - * Search a directory tree (synchronous operation). - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * base [I] Starting point for the search. - * scope [I] Search scope. One of LDAP_SCOPE_BASE, - * LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE. - * filter [I] Search filter. - * attrs [I] Attributes to return. - * attrsonly [I] Return no values, only attributes. - * timeout [I] Timeout in seconds. - * res [O] Results of the search operation. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. - * - * NOTES - * Call ldap_msgfree to free the results. */ ULONG CDECL ldap_search_stW( LDAP *ld, const PWCHAR base, ULONG scope, const PWCHAR filter, WCHAR **attrs, ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ) diff --git a/dlls/wldap32/value.c b/dlls/wldap32/value.c index 219f6a6d2f5..a825b57da8d 100644 --- a/dlls/wldap32/value.c +++ b/dlls/wldap32/value.c @@ -32,19 +32,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
/*********************************************************************** * ldap_count_values_len (WLDAP32.@) - * - * Count the number of values in an array of berval structures. - * - * PARAMS - * values [I] Pointer to an array of berval structures. - * - * RETURNS - * Success: The number of values counted. - * Failure: 0 - * - * NOTES - * Call ldap_count_values_len with the result of a call to - * ldap_get_values_len. */ ULONG CDECL ldap_count_values_len( struct berval **values ) { @@ -60,8 +47,6 @@ ULONG CDECL ldap_count_values_len( struct berval **values )
/*********************************************************************** * ldap_count_valuesA (WLDAP32.@) - * - * See ldap_count_valuesW. */ ULONG CDECL ldap_count_valuesA( char **values ) { @@ -77,19 +62,6 @@ ULONG CDECL ldap_count_valuesA( char **values )
/*********************************************************************** * ldap_count_valuesW (WLDAP32.@) - * - * Count the number of values in a string array. - * - * PARAMS - * values [I] Pointer to an array of strings. - * - * RETURNS - * Success: The number of values counted. - * Failure: 0 - * - * NOTES - * Call ldap_count_valuesW with the result of a call to - * ldap_get_valuesW. */ ULONG CDECL ldap_count_valuesW( WCHAR **values ) { @@ -105,8 +77,6 @@ ULONG CDECL ldap_count_valuesW( WCHAR **values )
/*********************************************************************** * ldap_get_valuesA (WLDAP32.@) - * - * See ldap_get_valuesW. */ char ** CDECL ldap_get_valuesA( LDAP *ld, LDAPMessage *entry, char *attr ) { @@ -170,22 +140,6 @@ static char **bv2str_array( struct bervalU **bv )
/*********************************************************************** * ldap_get_valuesW (WLDAP32.@) - * - * Retrieve string values for a given attribute. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * entry [I] Entry to retrieve values from. - * attr [I] Attribute to retrieve values for. - * - * RETURNS - * Success: Pointer to a character array holding the values. - * Failure: NULL - * - * NOTES - * Call ldap_get_valuesW with the result of a call to - * ldap_first_entry or ldap_next_entry. Free the returned - * array with a call to ldap_value_freeW. */ WCHAR ** CDECL ldap_get_valuesW( LDAP *ld, LDAPMessage *entry, WCHAR *attr ) { @@ -214,8 +168,6 @@ WCHAR ** CDECL ldap_get_valuesW( LDAP *ld, LDAPMessage *entry, WCHAR *attr )
/*********************************************************************** * ldap_get_values_lenA (WLDAP32.@) - * - * See ldap_get_values_lenW. */ struct berval ** CDECL ldap_get_values_lenA( LDAP *ld, LDAPMessage *message, char *attr ) { @@ -234,22 +186,6 @@ struct berval ** CDECL ldap_get_values_lenA( LDAP *ld, LDAPMessage *message, cha
/*********************************************************************** * ldap_get_values_lenW (WLDAP32.@) - * - * Retrieve binary values for a given attribute. - * - * PARAMS - * ld [I] Pointer to an LDAP context. - * message [I] Entry to retrieve values from. - * attr [I] Attribute to retrieve values for. - * - * RETURNS - * Success: Pointer to a berval array holding the values. - * Failure: NULL - * - * NOTES - * Call ldap_get_values_lenW with the result of a call to - * ldap_first_entry or ldap_next_entry. Free the returned - * array with a call to ldap_value_free_len. */ struct berval ** CDECL ldap_get_values_lenW( LDAP *ld, LDAPMessage *message, WCHAR *attr ) { @@ -276,15 +212,6 @@ struct berval ** CDECL ldap_get_values_lenW( LDAP *ld, LDAPMessage *message, WCH
/*********************************************************************** * ldap_value_free_len (WLDAP32.@) - * - * Free an array of berval structures. - * - * PARAMS - * values [I] Array of berval structures. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_value_free_len( struct berval **values ) { @@ -296,8 +223,6 @@ ULONG CDECL ldap_value_free_len( struct berval **values )
/*********************************************************************** * ldap_value_freeA (WLDAP32.@) - * - * See ldap_value_freeW. */ ULONG CDECL ldap_value_freeA( char **values ) { @@ -309,15 +234,6 @@ ULONG CDECL ldap_value_freeA( char **values )
/*********************************************************************** * ldap_value_freeW (WLDAP32.@) - * - * Free an array of string values. - * - * PARAMS - * values [I] Array of string values. - * - * RETURNS - * Success: LDAP_SUCCESS - * Failure: An LDAP error code. */ ULONG CDECL ldap_value_freeW( WCHAR **values ) {
From: Hans Leidekker hans@codeweavers.com
--- dlls/wldap32/ber.c | 30 +++++++++--------- dlls/wldap32/bind.c | 4 +-- dlls/wldap32/error.c | 4 +-- dlls/wldap32/init.c | 2 +- dlls/wldap32/misc.c | 18 +++++------ dlls/wldap32/page.c | 20 ++++++------ dlls/wldap32/value.c | 4 +-- dlls/wldap32/winldap_private.h | 19 +++++++++++ dlls/wldap32/wldap32.spec | 58 +++++++++++++++++----------------- 9 files changed, 89 insertions(+), 70 deletions(-)
diff --git a/dlls/wldap32/ber.c b/dlls/wldap32/ber.c index 82ab6116455..0d8f0dfe010 100644 --- a/dlls/wldap32/ber.c +++ b/dlls/wldap32/ber.c @@ -34,9 +34,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); /*********************************************************************** * ber_alloc_t (WLDAP32.@) */ -BerElement * CDECL ber_alloc_t( int options ) +WLDAP32_BerElement * CDECL WLDAP32_ber_alloc_t( int options ) { - BerElement *ret; + WLDAP32_BerElement *ret; struct ber_alloc_t_params params;
if (!(ret = malloc( sizeof(*ret) ))) return NULL; @@ -53,7 +53,7 @@ BerElement * CDECL ber_alloc_t( int options ) /*********************************************************************** * ber_bvdup (WLDAP32.@) */ -BERVAL * CDECL ber_bvdup( BERVAL *berval ) +BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL *berval ) { return bervalWtoW( berval ); } @@ -61,7 +61,7 @@ BERVAL * CDECL ber_bvdup( BERVAL *berval ) /*********************************************************************** * ber_bvecfree (WLDAP32.@) */ -void CDECL ber_bvecfree( BERVAL **berval ) +void CDECL WLDAP32_ber_bvecfree( BERVAL **berval ) { bvarrayfreeW( berval ); } @@ -69,7 +69,7 @@ void CDECL ber_bvecfree( BERVAL **berval ) /*********************************************************************** * ber_bvfree (WLDAP32.@) */ -void CDECL ber_bvfree( BERVAL *berval ) +void CDECL WLDAP32_ber_bvfree( BERVAL *berval ) { free( berval ); } @@ -77,7 +77,7 @@ void CDECL ber_bvfree( BERVAL *berval ) /*********************************************************************** * ber_first_element (WLDAP32.@) */ -ULONG CDECL ber_first_element( BerElement *ber, ULONG *len, char **opaque ) +ULONG CDECL WLDAP32_ber_first_element( WLDAP32_BerElement *ber, ULONG *len, char **opaque ) { struct ber_first_element_params params = { BER(ber), (unsigned int *)len, opaque }; return LDAP_CALL( ber_first_element, ¶ms ); @@ -86,7 +86,7 @@ ULONG CDECL ber_first_element( BerElement *ber, ULONG *len, char **opaque ) /*********************************************************************** * ber_flatten (WLDAP32.@) */ -int CDECL ber_flatten( BerElement *ber, BERVAL **berval ) +int CDECL WLDAP32_ber_flatten( WLDAP32_BerElement *ber, BERVAL **berval ) { struct bervalU *bervalU; struct berval *bervalW; @@ -104,7 +104,7 @@ int CDECL ber_flatten( BerElement *ber, BERVAL **berval ) /*********************************************************************** * ber_free (WLDAP32.@) */ -void CDECL ber_free( BerElement *ber, int freebuf ) +void CDECL WLDAP32_ber_free( WLDAP32_BerElement *ber, int freebuf ) { struct ber_free_params params = { BER(ber), freebuf }; LDAP_CALL( ber_free, ¶ms ); @@ -114,10 +114,10 @@ void CDECL ber_free( BerElement *ber, int freebuf ) /*********************************************************************** * ber_init (WLDAP32.@) */ -BerElement * CDECL ber_init( BERVAL *berval ) +WLDAP32_BerElement * CDECL WLDAP32_ber_init( BERVAL *berval ) { struct bervalU *bervalU; - BerElement *ret; + WLDAP32_BerElement *ret; struct ber_init_params params;
if (!(ret = malloc( sizeof(*ret) ))) return NULL; @@ -140,7 +140,7 @@ BerElement * CDECL ber_init( BERVAL *berval ) /*********************************************************************** * ber_next_element (WLDAP32.@) */ -ULONG CDECL ber_next_element( BerElement *ber, ULONG *len, char *opaque ) +ULONG CDECL WLDAP32_ber_next_element( WLDAP32_BerElement *ber, ULONG *len, char *opaque ) { struct ber_next_element_params params = { BER(ber), (unsigned int *)len, opaque }; return LDAP_CALL( ber_next_element, ¶ms ); @@ -149,7 +149,7 @@ ULONG CDECL ber_next_element( BerElement *ber, ULONG *len, char *opaque ) /*********************************************************************** * ber_peek_tag (WLDAP32.@) */ -ULONG CDECL ber_peek_tag( BerElement *ber, ULONG *len ) +ULONG CDECL WLDAP32_ber_peek_tag( WLDAP32_BerElement *ber, ULONG *len ) { struct ber_peek_tag_params params = { BER(ber), (unsigned int *)len }; return LDAP_CALL( ber_peek_tag, ¶ms ); @@ -158,7 +158,7 @@ ULONG CDECL ber_peek_tag( BerElement *ber, ULONG *len ) /*********************************************************************** * ber_skip_tag (WLDAP32.@) */ -ULONG CDECL ber_skip_tag( BerElement *ber, ULONG *len ) +ULONG CDECL WLDAP32_ber_skip_tag( WLDAP32_BerElement *ber, ULONG *len ) { struct ber_skip_tag_params params = { BER(ber), (unsigned int *)len }; return LDAP_CALL( ber_skip_tag, ¶ms ); @@ -167,7 +167,7 @@ ULONG CDECL ber_skip_tag( BerElement *ber, ULONG *len ) /*********************************************************************** * ber_printf (WLDAP32.@) */ -int WINAPIV ber_printf( BerElement *ber, char *fmt, ... ) +int WINAPIV WLDAP32_ber_printf( WLDAP32_BerElement *ber, char *fmt, ... ) { va_list list; int ret = 0; @@ -244,7 +244,7 @@ int WINAPIV ber_printf( BerElement *ber, char *fmt, ... ) /*********************************************************************** * ber_scanf (WLDAP32.@) */ -ULONG WINAPIV ber_scanf( BerElement *ber, char *fmt, ... ) +ULONG WINAPIV WLDAP32_ber_scanf( WLDAP32_BerElement *ber, char *fmt, ... ) { va_list list; int ret = 0; diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index beb7626b8b1..1fe2bc23fda 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -461,7 +461,7 @@ exit: /*********************************************************************** * ldap_unbind (WLDAP32.@) */ -ULONG CDECL ldap_unbind( LDAP *ld ) +ULONG CDECL WLDAP32_ldap_unbind( LDAP *ld ) { ULONG ret;
@@ -483,7 +483,7 @@ ULONG CDECL ldap_unbind( LDAP *ld ) /*********************************************************************** * ldap_unbind_s (WLDAP32.@) */ -ULONG CDECL ldap_unbind_s( LDAP *ld ) +ULONG CDECL WLDAP32_ldap_unbind_s( LDAP *ld ) { ULONG ret;
diff --git a/dlls/wldap32/error.c b/dlls/wldap32/error.c index c2c7a6d9979..2b3d0166eb5 100644 --- a/dlls/wldap32/error.c +++ b/dlls/wldap32/error.c @@ -95,7 +95,7 @@ WCHAR * CDECL ldap_err2stringW( ULONG err ) /*********************************************************************** * ldap_perror (WLDAP32.@) */ -void CDECL ldap_perror( LDAP *ld, const PCHAR msg ) +void CDECL WLDAP32_ldap_perror( LDAP *ld, const PCHAR msg ) { TRACE( "(%p, %s)\n", ld, debugstr_a(msg) ); } @@ -103,7 +103,7 @@ void CDECL ldap_perror( LDAP *ld, const PCHAR msg ) /*********************************************************************** * ldap_result2error (WLDAP32.@) */ -ULONG CDECL ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG free ) +ULONG CDECL WLDAP32_ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG free ) { int error;
diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index c128039bf5c..88fa55b77f7 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -252,7 +252,7 @@ exit: /*********************************************************************** * ldap_connect (WLDAP32.@) */ -ULONG CDECL ldap_connect( LDAP *ld, struct l_timeval *timeout ) +ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout ) { TRACE( "(%p, %p)\n", ld, timeout );
diff --git a/dlls/wldap32/misc.c b/dlls/wldap32/misc.c index 135d79a6d58..c8dcf614683 100644 --- a/dlls/wldap32/misc.c +++ b/dlls/wldap32/misc.c @@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); /*********************************************************************** * ldap_abandon (WLDAP32.@) */ -ULONG CDECL ldap_abandon( LDAP *ld, ULONG msgid ) +ULONG CDECL WLDAP32_ldap_abandon( LDAP *ld, ULONG msgid ) { TRACE( "(%p, %#lx)\n", ld, msgid );
@@ -98,7 +98,7 @@ LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res ) /*********************************************************************** * ldap_count_entries (WLDAP32.@) */ -ULONG CDECL ldap_count_entries( LDAP *ld, LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_count_entries( LDAP *ld, LDAPMessage *res ) { TRACE( "(%p, %p)\n", ld, res );
@@ -113,7 +113,7 @@ ULONG CDECL ldap_count_entries( LDAP *ld, LDAPMessage *res ) /*********************************************************************** * ldap_count_references (WLDAP32.@) */ -ULONG CDECL ldap_count_references( LDAP *ld, LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_count_references( LDAP *ld, LDAPMessage *res ) { TRACE( "(%p, %p)\n", ld, res );
@@ -248,7 +248,7 @@ WCHAR * CDECL ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement ** /*********************************************************************** * ldap_first_entry (WLDAP32.@) */ -LDAPMessage * CDECL ldap_first_entry( LDAP *ld, LDAPMessage *res ) +LDAPMessage * CDECL WLDAP32_ldap_first_entry( LDAP *ld, LDAPMessage *res ) { void *msgU;
@@ -269,7 +269,7 @@ LDAPMessage * CDECL ldap_first_entry( LDAP *ld, LDAPMessage *res ) /*********************************************************************** * ldap_first_reference (WLDAP32.@) */ -LDAPMessage * CDECL ldap_first_reference( LDAP *ld, LDAPMessage *res ) +LDAPMessage * CDECL WLDAP32_ldap_first_reference( LDAP *ld, LDAPMessage *res ) { void *msgU;
@@ -308,7 +308,7 @@ void CDECL ldap_memfreeW( WCHAR *block ) /*********************************************************************** * ldap_msgfree (WLDAP32.@) */ -ULONG CDECL ldap_msgfree( LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_msgfree( LDAPMessage *res ) { LDAPMessage *entry, *list = res;
@@ -374,7 +374,7 @@ WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *pt /*********************************************************************** * ldap_next_entry (WLDAP32.@) */ -LDAPMessage * CDECL ldap_next_entry( LDAP *ld, LDAPMessage *entry ) +LDAPMessage * CDECL WLDAP32_ldap_next_entry( LDAP *ld, LDAPMessage *entry ) { LDAPMessage *msg = NULL; void *msgU; @@ -402,7 +402,7 @@ LDAPMessage * CDECL ldap_next_entry( LDAP *ld, LDAPMessage *entry ) /*********************************************************************** * ldap_next_reference (WLDAP32.@) */ -LDAPMessage * CDECL ldap_next_reference( LDAP *ld, LDAPMessage *entry ) +LDAPMessage * CDECL WLDAP32_ldap_next_reference( LDAP *ld, LDAPMessage *entry ) { LDAPMessage *msg = NULL; void *msgU; @@ -429,7 +429,7 @@ LDAPMessage * CDECL ldap_next_reference( LDAP *ld, LDAPMessage *entry ) /*********************************************************************** * ldap_result (WLDAP32.@) */ -ULONG CDECL ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res ) +ULONG CDECL WLDAP32_ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res ) { LDAPMessage *msg; struct timevalU timeval; diff --git a/dlls/wldap32/page.c b/dlls/wldap32/page.c index fab2b83366a..fd574eca2e7 100644 --- a/dlls/wldap32/page.c +++ b/dlls/wldap32/page.c @@ -60,22 +60,22 @@ ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct berval * static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR critical, LDAPControlW **control ) { LDAPControlW *ctrl; - BerElement *ber; + WLDAP32_BerElement *ber; struct berval *berval, *vec[2]; int ret, len; char *val;
- if (!(ber = ber_alloc_t( LBER_USE_DER ))) return LDAP_NO_MEMORY; + if (!(ber = WLDAP32_ber_alloc_t( LBER_USE_DER ))) return LDAP_NO_MEMORY;
vec[1] = NULL; if (cookie) vec[0] = cookie; else vec[0] = &null_cookieW; - len = ber_printf( ber, (char *)"{iV}", pagesize, vec ); + len = WLDAP32_ber_printf( ber, (char *)"{iV}", pagesize, vec );
- ret = ber_flatten( ber, &berval ); - ber_free( ber, 1 ); + ret = WLDAP32_ber_flatten( ber, &berval ); + WLDAP32_ber_free( ber, 1 );
if (len == LBER_ERROR) return LDAP_ENCODING_ERROR; if (ret == -1) return LDAP_NO_MEMORY; @@ -85,7 +85,7 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c
len = berval->bv_len; memcpy( val, berval->bv_val, len ); - ber_bvfree( berval ); + WLDAP32_ber_bvfree( berval );
if (!(ctrl = malloc( sizeof(*ctrl) ))) { @@ -218,7 +218,7 @@ ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret { ULONG ret, count; LDAPControlW *control = NULL; - BerElement *ber; + WLDAP32_BerElement *ber; struct berval *cookie = NULL; int tag; ULONG i; @@ -234,9 +234,9 @@ ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret } if (!control) return LDAP_CONTROL_NOT_FOUND;
- if (!(ber = ber_init( &control->ldctl_value ))) return LDAP_NO_MEMORY; + if (!(ber = WLDAP32_ber_init( &control->ldctl_value ))) return LDAP_NO_MEMORY;
- tag = ber_scanf( ber, (char *)"{iO}", &count, &cookie ); + tag = WLDAP32_ber_scanf( ber, (char *)"{iO}", &count, &cookie ); if (tag == LBER_ERROR) ret = LDAP_DECODING_ERROR; else { @@ -245,7 +245,7 @@ ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret ret = LDAP_SUCCESS; }
- ber_free( ber, 1 ); + WLDAP32_ber_free( ber, 1 ); return ret; }
diff --git a/dlls/wldap32/value.c b/dlls/wldap32/value.c index a825b57da8d..3d2149a41d3 100644 --- a/dlls/wldap32/value.c +++ b/dlls/wldap32/value.c @@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); /*********************************************************************** * ldap_count_values_len (WLDAP32.@) */ -ULONG CDECL ldap_count_values_len( struct berval **values ) +ULONG CDECL WLDAP32_ldap_count_values_len( struct berval **values ) { ULONG ret = 0; struct berval **ptr = values; @@ -213,7 +213,7 @@ struct berval ** CDECL ldap_get_values_lenW( LDAP *ld, LDAPMessage *message, WCH /*********************************************************************** * ldap_value_free_len (WLDAP32.@) */ -ULONG CDECL ldap_value_free_len( struct berval **values ) +ULONG CDECL WLDAP32_ldap_value_free_len( struct berval **values ) { TRACE( "(%p)\n", values );
diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h index b8b6daf5a50..c2b47dcda50 100644 --- a/dlls/wldap32/winldap_private.h +++ b/dlls/wldap32/winldap_private.h @@ -24,6 +24,11 @@ #include "winnls.h" #include "libldap.h"
+typedef struct WLDAP32_berelement +{ + char *opaque; +} WLDAP32_BerElement; + typedef struct ldapsearch { WCHAR *dn; @@ -43,6 +48,20 @@ typedef struct ldapsearch #define MSG(entry) (entry->Request) #define BER(ber) (ber->opaque)
+WLDAP32_BerElement * CDECL WLDAP32_ber_alloc_t( int ); +BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL * ); +void CDECL WLDAP32_ber_bvecfree( BERVAL ** ); +void CDECL WLDAP32_ber_bvfree( BERVAL * ); +ULONG CDECL WLDAP32_ber_first_element( WLDAP32_BerElement *, ULONG *, char ** ); +int CDECL WLDAP32_ber_flatten( WLDAP32_BerElement *, BERVAL ** ); +void CDECL WLDAP32_ber_free( WLDAP32_BerElement *, int ); +WLDAP32_BerElement * CDECL WLDAP32_ber_init( BERVAL * ); +ULONG CDECL WLDAP32_ber_next_element( WLDAP32_BerElement *, ULONG *, char * ); +ULONG CDECL WLDAP32_ber_peek_tag( WLDAP32_BerElement *, ULONG * ); +ULONG CDECL WLDAP32_ber_skip_tag( WLDAP32_BerElement *, ULONG * ); +int WINAPIV WLDAP32_ber_printf( WLDAP32_BerElement *, char *, ... ); +ULONG WINAPIV WLDAP32_ber_scanf( WLDAP32_BerElement *, char *, ... ); + ULONG map_error( int ) DECLSPEC_HIDDEN;
static inline char *strdupU( const char *src ) diff --git a/dlls/wldap32/wldap32.spec b/dlls/wldap32/wldap32.spec index 63271615eb8..33e630dea87 100644 --- a/dlls/wldap32/wldap32.spec +++ b/dlls/wldap32/wldap32.spec @@ -1,20 +1,20 @@ - 10 cdecl ldap_abandon(ptr long) + 10 cdecl ldap_abandon(ptr long) WLDAP32_ldap_abandon 11 cdecl ldap_add(ptr str ptr) ldap_addA 12 cdecl ldap_get_optionW(ptr long ptr) - 13 cdecl ldap_unbind(ptr) + 13 cdecl ldap_unbind(ptr) WLDAP32_ldap_unbind 14 cdecl ldap_set_optionW(ptr long ptr) 16 cdecl LdapGetLastError() 17 cdecl cldap_open(str long) cldap_openA 18 cdecl LdapMapErrorToWin32(long) 19 cdecl ldap_compare(ptr str str str) ldap_compareA 20 cdecl ldap_delete(ptr str) ldap_deleteA - 21 cdecl ldap_result2error(ptr ptr long) + 21 cdecl ldap_result2error(ptr ptr long) WLDAP32_ldap_result2error 22 cdecl ldap_err2string(long) ldap_err2stringA 23 cdecl ldap_modify(ptr str ptr) ldap_modifyA 24 cdecl ldap_modrdn(ptr str ptr) ldap_modrdnA 25 cdecl ldap_open(str long) ldap_openA - 26 cdecl ldap_first_entry(ptr ptr) - 27 cdecl ldap_next_entry(ptr ptr) + 26 cdecl ldap_first_entry(ptr ptr) WLDAP32_ldap_first_entry + 27 cdecl ldap_next_entry(ptr ptr) WLDAP32_ldap_next_entry 28 cdecl cldap_openW(wstr long) 29 cdecl LdapUTF8ToUnicode(str long ptr long) 30 cdecl ldap_get_dn(ptr ptr) ldap_get_dnA @@ -23,17 +23,17 @@ 33 cdecl ldap_next_attribute(ptr ptr ptr) ldap_next_attributeA 34 cdecl ldap_get_values(ptr ptr str) ldap_get_valuesA 35 cdecl ldap_get_values_len(ptr ptr str) ldap_get_values_lenA - 36 cdecl ldap_count_entries(ptr ptr) + 36 cdecl ldap_count_entries(ptr ptr) WLDAP32_ldap_count_entries 37 cdecl ldap_count_values(ptr) ldap_count_valuesA 38 cdecl ldap_value_free(ptr) ldap_value_freeA 39 cdecl ldap_explode_dn(str long) ldap_explode_dnA - 40 cdecl ldap_result(ptr long long ptr ptr) - 41 cdecl ldap_msgfree(ptr) + 40 cdecl ldap_result(ptr long long ptr ptr) WLDAP32_ldap_result + 41 cdecl ldap_msgfree(ptr) WLDAP32_ldap_msgfree 42 cdecl ldap_addW(ptr wstr ptr) 43 cdecl ldap_search(ptr str long str ptr long) ldap_searchA 44 cdecl ldap_add_s(ptr str ptr) ldap_add_sA 45 cdecl ldap_bind_s(ptr str str long) ldap_bind_sA - 46 cdecl ldap_unbind_s(ptr) + 46 cdecl ldap_unbind_s(ptr) WLDAP32_ldap_unbind_s 47 cdecl ldap_delete_s(ptr str) ldap_delete_sA 48 cdecl ldap_modify_s(ptr str ptr) ldap_modify_sA 49 cdecl ldap_modrdn_s(ptr str ptr) ldap_modrdn_sA @@ -41,7 +41,7 @@ 51 cdecl ldap_search_st(ptr str long str ptr long ptr ptr) ldap_search_stA 52 cdecl ldap_compare_s(ptr str str str) ldap_compare_sA 53 cdecl LdapUnicodeToUTF8(wstr long ptr long) - 54 cdecl ber_bvfree(ptr) + 54 cdecl ber_bvfree(ptr) WLDAP32_ber_bvfree 55 cdecl cldap_openA(str long) 56 cdecl ldap_addA(ptr str ptr) 57 cdecl ldap_add_ext(ptr str ptr ptr ptr ptr) ldap_add_extA @@ -64,25 +64,25 @@ 74 cdecl ldap_close_extended_op(ptr long) 75 cdecl ldap_compareA(ptr str str str) 76 cdecl ldap_compareW(ptr wstr wstr wstr) - 77 cdecl ldap_count_values_len(ptr) + 77 cdecl ldap_count_values_len(ptr) WLDAP32_ldap_count_values_len 78 cdecl ldap_compare_ext(ptr str str str ptr ptr ptr ptr) ldap_compare_extA - 79 cdecl ldap_value_free_len(ptr) + 79 cdecl ldap_value_free_len(ptr) WLDAP32_ldap_value_free_len 80 cdecl ldap_compare_extA(ptr str str str ptr ptr ptr ptr) 81 cdecl ldap_compare_extW(ptr wstr wstr wstr ptr ptr ptr ptr) - 82 cdecl ldap_perror(ptr ptr) + 82 cdecl ldap_perror(ptr ptr) WLDAP32_ldap_perror 83 cdecl ldap_compare_ext_s(ptr str str str ptr ptr ptr) ldap_compare_ext_sA 84 cdecl ldap_compare_ext_sA(ptr str str str ptr ptr ptr) 85 cdecl ldap_compare_ext_sW(ptr wstr wstr wstr ptr ptr ptr) 86 cdecl ldap_compare_sA(ptr str str str) 87 cdecl ldap_compare_sW(ptr wstr wstr wstr) - 88 cdecl ldap_connect(ptr ptr) + 88 cdecl ldap_connect(ptr ptr) WLDAP32_ldap_connect 89 cdecl ldap_control_free(ptr) ldap_control_freeA 90 cdecl ldap_control_freeA(ptr) 91 cdecl ldap_control_freeW(ptr) 92 cdecl ldap_controls_free(ptr) ldap_controls_freeA 93 cdecl ldap_controls_freeA(ptr) 94 cdecl ldap_controls_freeW(ptr) - 95 cdecl ldap_count_references(ptr ptr) + 95 cdecl ldap_count_references(ptr ptr) WLDAP32_ldap_count_references 96 cdecl ldap_count_valuesA(ptr) 97 cdecl ldap_count_valuesW(ptr) 98 cdecl ldap_create_page_control(ptr long ptr long ptr) ldap_create_page_controlA @@ -115,7 +115,7 @@ 125 cdecl ldap_extended_operationW(ptr wstr ptr ptr ptr ptr) 126 cdecl ldap_first_attributeA(ptr ptr ptr) 127 cdecl ldap_first_attributeW(ptr ptr ptr) -128 cdecl ldap_first_reference(ptr ptr) +128 cdecl ldap_first_reference(ptr ptr) WLDAP32_ldap_first_reference 129 cdecl ldap_free_controls(ptr) ldap_free_controlsA 130 cdecl ldap_free_controlsA(ptr) 131 cdecl ldap_free_controlsW(ptr) @@ -155,7 +155,7 @@ 165 cdecl ldap_modrdn_sW(ptr wstr ptr) 166 cdecl ldap_next_attributeA(ptr ptr ptr) 167 cdecl ldap_next_attributeW(ptr ptr ptr) -168 cdecl ldap_next_reference(ptr ptr) +168 cdecl ldap_next_reference(ptr ptr) WLDAP32_ldap_next_reference 169 cdecl ldap_openA(str long) 170 cdecl ldap_openW(wstr long) 171 cdecl ldap_parse_page_control(ptr ptr ptr ptr) ldap_parse_page_controlA @@ -215,18 +215,18 @@ 230 cdecl ldap_check_filterA(ptr str) 231 cdecl ldap_check_filterW(ptr wstr) 232 cdecl ldap_dn2ufnA(str) -300 cdecl ber_init(ptr) -301 cdecl ber_free(ptr long) -302 cdecl ber_bvecfree(ptr) -303 cdecl ber_bvdup(ptr) -304 cdecl ber_alloc_t(long) -305 cdecl ber_skip_tag(ptr ptr) -306 cdecl ber_peek_tag(ptr ptr) -307 cdecl ber_first_element(ptr ptr ptr) -308 cdecl ber_next_element(ptr ptr ptr) -309 cdecl ber_flatten(ptr ptr) -310 varargs ber_printf(ptr str) -311 varargs ber_scanf(ptr str) +300 cdecl ber_init(ptr) WLDAP32_ber_init +301 cdecl ber_free(ptr long) WLDAP32_ber_free +302 cdecl ber_bvecfree(ptr) WLDAP32_ber_bvecfree +303 cdecl ber_bvdup(ptr) WLDAP32_ber_bvdup +304 cdecl ber_alloc_t(long) WLDAP32_ber_alloc_t +305 cdecl ber_skip_tag(ptr ptr) WLDAP32_ber_skip_tag +306 cdecl ber_peek_tag(ptr ptr) WLDAP32_ber_peek_tag +307 cdecl ber_first_element(ptr ptr ptr) WLDAP32_ber_first_element +308 cdecl ber_next_element(ptr ptr ptr) WLDAP32_ber_next_element +309 cdecl ber_flatten(ptr ptr) WLDAP32_ber_flatten +310 varargs ber_printf(ptr str) WLDAP32_ber_printf +311 varargs ber_scanf(ptr str) WLDAP32_ber_scanf 312 cdecl ldap_conn_from_msg(ptr ptr) 313 cdecl ldap_sasl_bindW(ptr wstr wstr ptr ptr ptr ptr) 314 cdecl ldap_sasl_bind_sW(ptr wstr wstr ptr ptr ptr ptr)
From: Hans Leidekker hans@codeweavers.com
--- dlls/wldap32/add.c | 24 +- dlls/wldap32/ber.c | 6 +- dlls/wldap32/bind.c | 62 ++--- dlls/wldap32/compare.c | 24 +- dlls/wldap32/control.c | 38 +-- dlls/wldap32/delete.c | 24 +- dlls/wldap32/dn.c | 14 +- dlls/wldap32/error.c | 44 ++-- dlls/wldap32/extended.c | 26 +- dlls/wldap32/init.c | 17 +- dlls/wldap32/misc.c | 20 +- dlls/wldap32/modify.c | 20 +- dlls/wldap32/modrdn.c | 24 +- dlls/wldap32/option.c | 464 ++++++++++++++++----------------- dlls/wldap32/page.c | 56 ++-- dlls/wldap32/parse.c | 52 ++-- dlls/wldap32/rename.c | 16 +- dlls/wldap32/search.c | 28 +- dlls/wldap32/value.c | 6 +- dlls/wldap32/winldap_private.h | 152 +++++++++++ 20 files changed, 632 insertions(+), 485 deletions(-)
diff --git a/dlls/wldap32/add.c b/dlls/wldap32/add.c index 2afe4fa2b33..e12ed087e26 100644 --- a/dlls/wldap32/add.c +++ b/dlls/wldap32/add.c @@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ ULONG CDECL ldap_addA( LDAP *ld, char *dn, LDAPModA **attrs ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **attrsW = NULL;
@@ -63,7 +63,7 @@ ULONG CDECL ldap_addW( LDAP *ld, WCHAR *dn, LDAPModW **attrs ) TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), attrs );
ret = ldap_add_extW( ld, dn, attrs, NULL, NULL, &msg ); - if (ret == LDAP_SUCCESS) return msg; + if (ret == WLDAP32_LDAP_SUCCESS) return msg; return ~0u; }
@@ -73,14 +73,14 @@ ULONG CDECL ldap_addW( LDAP *ld, WCHAR *dn, LDAPModW **attrs ) ULONG CDECL ldap_add_extA( LDAP *ld, char *dn, LDAPModA **attrs, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **attrsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_a(dn), attrs, serverctrls, clientctrls, message );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attrs && !(attrsW = modarrayAtoW( attrs ))) goto exit; @@ -103,14 +103,14 @@ exit: ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPModU **attrsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls, message );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (attrs && !(attrsU = modarrayWtoU( attrs ))) goto exit; @@ -136,14 +136,14 @@ exit: ULONG CDECL ldap_add_ext_sA( LDAP *ld, char *dn, LDAPModA **attrs, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **attrsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_a(dn), attrs, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attrs && !(attrsW = modarrayAtoW( attrs ))) goto exit; @@ -166,14 +166,14 @@ exit: ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPModU **attrsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (attrs && !(attrsU = modarrayWtoU( attrs ))) goto exit; @@ -198,13 +198,13 @@ exit: */ ULONG CDECL ldap_add_sA( LDAP *ld, char *dn, LDAPModA **attrs ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **attrsW = NULL;
TRACE( "(%p, %s, %p)\n", ld, debugstr_a(dn), attrs );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attrs && !(attrsW = modarrayAtoW( attrs ))) goto exit; diff --git a/dlls/wldap32/ber.c b/dlls/wldap32/ber.c index 0d8f0dfe010..1dbc0cf6080 100644 --- a/dlls/wldap32/ber.c +++ b/dlls/wldap32/ber.c @@ -92,11 +92,11 @@ int CDECL WLDAP32_ber_flatten( WLDAP32_BerElement *ber, BERVAL **berval ) struct berval *bervalW; struct ber_flatten_params params = { BER(ber), &bervalU };
- if (LDAP_CALL( ber_flatten, ¶ms )) return LBER_ERROR; + if (LDAP_CALL( ber_flatten, ¶ms )) return WLDAP32_LBER_ERROR;
- if (!(bervalW = bervalUtoW( bervalU ))) return LBER_ERROR; + if (!(bervalW = bervalUtoW( bervalU ))) return WLDAP32_LBER_ERROR; LDAP_CALL( ber_bvfree, bervalU ); - if (!bervalW) return LBER_ERROR; + if (!bervalW) return WLDAP32_LBER_ERROR; *berval = bervalW; return 0; } diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index 1fe2bc23fda..83b878a88b3 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -36,7 +36,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ ULONG CDECL ldap_bindA( LDAP *ld, char *dn, char *cred, ULONG method ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *credW = NULL;
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_a(dn), cred, method ); @@ -59,7 +59,7 @@ exit: */ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *credU = NULL; struct bervalU pwd = { 0, NULL }; int msg; @@ -67,7 +67,7 @@ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_w(dn), cred, method );
if (!ld) return ~0u; - if (method != LDAP_AUTH_SIMPLE) return LDAP_PARAM_ERROR; + if (method != WLDAP32_LDAP_AUTH_SIMPLE) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (cred) @@ -81,7 +81,7 @@ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) struct ldap_sasl_bind_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg }; ret = map_error( LDAP_CALL( ldap_sasl_bind, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else ret = ~0u; @@ -97,17 +97,17 @@ exit: */ ULONG CDECL ldap_bind_sA( LDAP *ld, char *dn, char *cred, ULONG method ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *credW = NULL;
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_a(dn), cred, method );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (cred) { - if (method == LDAP_AUTH_SIMPLE) + if (method == WLDAP32_LDAP_AUTH_SIMPLE) { if (!(credW = strAtoW( cred ))) goto exit; } @@ -127,15 +127,15 @@ exit: */ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *credU = NULL; struct bervalU pwd = { 0, NULL };
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_w(dn), cred, method );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
- if (method == LDAP_AUTH_SIMPLE) + if (method == WLDAP32_LDAP_AUTH_SIMPLE) { if (dn && !(dnU = strWtoU( dn ))) goto exit; if (cred) @@ -150,7 +150,7 @@ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) ret = map_error( LDAP_CALL( ldap_sasl_bind_s, ¶ms )); } } - else if (method == LDAP_AUTH_NEGOTIATE) + else if (method == WLDAP32_LDAP_AUTH_NEGOTIATE) { SEC_WINNT_AUTH_IDENTITY_A idU; SEC_WINNT_AUTH_IDENTITY_W idW; @@ -194,7 +194,7 @@ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) else { FIXME( "method %#lx not supported\n", method ); - return LDAP_PARAM_ERROR; + return WLDAP32_LDAP_PARAM_ERROR; }
exit: @@ -209,14 +209,14 @@ exit: ULONG CDECL ldap_sasl_bindA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, LDAPControlA **serverctrls, LDAPControlA **clientctrls, int *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW, *mechanismW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(mechanism), cred, serverctrls, clientctrls, message );
- if (!ld || !dn || !mechanism || !cred || !message) return LDAP_PARAM_ERROR; + if (!ld || !dn || !mechanism || !cred || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (!(dnW = strAtoW( dn ))) goto exit; if (!(mechanismW = strAtoW( mechanism ))) goto exit; @@ -239,7 +239,7 @@ exit: ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, int *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU, *mechanismU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU credU; @@ -247,7 +247,7 @@ ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(mechanism), cred, serverctrls, clientctrls, message );
- if (!ld || !dn || !mechanism || !cred || !message) return LDAP_PARAM_ERROR; + if (!ld || !dn || !mechanism || !cred || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (!(dnU = strWtoU( dn ))) goto exit; if (!(mechanismU = strWtoU( mechanism ))) goto exit; @@ -275,14 +275,14 @@ exit: ULONG CDECL ldap_sasl_bind_sA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, LDAPControlA **serverctrls, LDAPControlA **clientctrls, BERVAL **serverdata ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW, *mechanismW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(mechanism), cred, serverctrls, clientctrls, serverdata );
- if (!ld || !dn || !mechanism || !cred || !serverdata) return LDAP_PARAM_ERROR; + if (!ld || !dn || !mechanism || !cred || !serverdata) return WLDAP32_LDAP_PARAM_ERROR;
if (!(dnW = strAtoW( dn ))) goto exit; if (!(mechanismW = strAtoW( mechanism ))) goto exit; @@ -305,7 +305,7 @@ exit: ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, BERVAL **serverdata ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU, *mechanismU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU *dataU, credU; @@ -313,7 +313,7 @@ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(mechanism), cred, serverctrls, clientctrls, serverdata );
- if (!ld || !dn || !mechanism || !cred || !serverdata) return LDAP_PARAM_ERROR; + if (!ld || !dn || !mechanism || !cred || !serverdata) return WLDAP32_LDAP_PARAM_ERROR;
if (!(dnU = strWtoU( dn ))) goto exit; if (!(mechanismU = strWtoU( mechanism ))) goto exit; @@ -327,10 +327,10 @@ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism struct ldap_sasl_bind_s_params params = { CTX(ld), dnU, mechanismU, &credU, serverctrlsU, clientctrlsU, &dataU }; ret = map_error( LDAP_CALL( ldap_sasl_bind_s, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { BERVAL *ptr; - if (!(ptr = bervalUtoW( dataU ))) ret = LDAP_NO_MEMORY; + if (!(ptr = bervalUtoW( dataU ))) ret = WLDAP32_LDAP_NO_MEMORY; else *serverdata = ptr; LDAP_CALL( ber_bvfree, dataU ); } @@ -348,7 +348,7 @@ exit: */ ULONG CDECL ldap_simple_bindA( LDAP *ld, char *dn, char *passwd ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *passwdW = NULL;
TRACE( "(%p, %s, %p)\n", ld, debugstr_a(dn), passwd ); @@ -371,7 +371,7 @@ exit: */ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *passwdU = NULL; struct bervalU pwd = { 0, NULL }; int msg; @@ -392,7 +392,7 @@ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) struct ldap_sasl_bind_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg }; ret = map_error( LDAP_CALL( ldap_sasl_bind, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else ret = ~0u; @@ -408,12 +408,12 @@ exit: */ ULONG CDECL ldap_simple_bind_sA( LDAP *ld, char *dn, char *passwd ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *passwdW = NULL;
TRACE( "(%p, %s, %p)\n", ld, debugstr_a(dn), passwd );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (passwd && !(passwdW = strAtoW( passwd ))) goto exit; @@ -431,13 +431,13 @@ exit: */ ULONG CDECL ldap_simple_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *passwdU = NULL; struct bervalU pwd = { 0, NULL };
TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), passwd );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (passwd) @@ -472,7 +472,7 @@ ULONG CDECL WLDAP32_ldap_unbind( LDAP *ld ) struct ldap_unbind_ext_params params = { CTX(ld), NULL, NULL }; ret = map_error( LDAP_CALL( ldap_unbind_ext, ¶ms )); } - else return LDAP_PARAM_ERROR; + else return WLDAP32_LDAP_PARAM_ERROR;
if (SERVER_CTRLS(ld)) LDAP_CALL( ldap_value_free_len, SERVER_CTRLS(ld) );
@@ -494,7 +494,7 @@ ULONG CDECL WLDAP32_ldap_unbind_s( LDAP *ld ) struct ldap_unbind_ext_s_params params = { CTX(ld), NULL, NULL }; ret = map_error( LDAP_CALL( ldap_unbind_ext_s, ¶ms )); } - else return LDAP_PARAM_ERROR; + else return WLDAP32_LDAP_PARAM_ERROR;
if (SERVER_CTRLS(ld)) LDAP_CALL( ldap_value_free_len, SERVER_CTRLS(ld) );
diff --git a/dlls/wldap32/compare.c b/dlls/wldap32/compare.c index 37b87c11c39..f5bae71e09a 100644 --- a/dlls/wldap32/compare.c +++ b/dlls/wldap32/compare.c @@ -64,7 +64,7 @@ ULONG CDECL ldap_compareW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value ) TRACE( "(%p, %s, %s, %s)\n", ld, debugstr_w(dn), debugstr_w(attr), debugstr_w(value) );
ret = ldap_compare_extW( ld, dn, attr, value, NULL, NULL, NULL, &msg ); - if (ret == LDAP_SUCCESS) return msg; + if (ret == WLDAP32_LDAP_SUCCESS) return msg; return ~0u; }
@@ -75,14 +75,14 @@ ULONG CDECL ldap_compare_extA( LDAP *ld, char *dn, char *attr, char *value, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *attrW = NULL, *valueW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(attr), debugstr_a(value), data, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attr && !(attrW = strAtoW( attr ))) goto exit; @@ -107,7 +107,7 @@ exit: ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *attrU = NULL, *valueU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU *dataU = NULL, val = { 0, NULL }; @@ -115,8 +115,8 @@ ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, s TRACE( "(%p, %s, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(attr), debugstr_w(value), data, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; - if (!attr) return LDAP_NO_MEMORY; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if (!attr) return WLDAP32_LDAP_NO_MEMORY;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (!(attrU = strWtoU( attr ))) goto exit; @@ -155,14 +155,14 @@ exit: ULONG CDECL ldap_compare_ext_sA( LDAP *ld, char *dn, char *attr, char *value, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *attrW = NULL, *valueW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %s, %p, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(attr), debugstr_a(value), data, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attr && !(attrW = strAtoW( attr ))) goto exit; @@ -187,7 +187,7 @@ exit: ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *attrU = NULL, *valueU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU *dataU = NULL, val = { 0, NULL }; @@ -195,7 +195,7 @@ ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, TRACE( "(%p, %s, %s, %s, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(attr), debugstr_w(value), data, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (attr && !(attrU = strWtoU( attr ))) goto exit; @@ -232,12 +232,12 @@ exit: */ ULONG CDECL ldap_compare_sA( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *attrW = NULL, *valueW = NULL;
TRACE( "(%p, %s, %s, %s)\n", ld, debugstr_a(dn), debugstr_a(attr), debugstr_a(value) );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (attr && !(attrW = strAtoW( attr ))) goto exit; diff --git a/dlls/wldap32/control.c b/dlls/wldap32/control.c index a825ada48ce..41aa64cf292 100644 --- a/dlls/wldap32/control.c +++ b/dlls/wldap32/control.c @@ -36,7 +36,7 @@ ULONG CDECL ldap_control_freeA( LDAPControlA *control ) { TRACE( "(%p)\n", control ); controlfreeA( control ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -46,7 +46,7 @@ ULONG CDECL ldap_control_freeW( LDAPControlW *control ) { TRACE( "(%p)\n", control ); controlfreeW( control ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -56,7 +56,7 @@ ULONG CDECL ldap_controls_freeA( LDAPControlA **controls ) { TRACE( "(%p)\n", controls ); controlarrayfreeA( controls ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -66,7 +66,7 @@ ULONG CDECL ldap_controls_freeW( LDAPControlW **controls ) { TRACE( "(%p)\n", controls ); controlarrayfreeW( controls ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -80,16 +80,16 @@ ULONG CDECL ldap_create_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkey, UCHAR c
TRACE( "(%p, %p, 0x%02x, %p)\n", ld, sortkey, critical, control );
- if (!ld || !sortkey || !control) return LDAP_PARAM_ERROR; + if (!ld || !sortkey || !control) return WLDAP32_LDAP_PARAM_ERROR;
- if (!(sortkeyW = sortkeyarrayAtoW( sortkey ))) return LDAP_NO_MEMORY; + if (!(sortkeyW = sortkeyarrayAtoW( sortkey ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_create_sort_controlW( ld, sortkeyW, critical, &controlW ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlA *controlA = controlWtoA( controlW ); if (controlA) *control = controlA; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; ldap_control_freeW( controlW ); }
@@ -108,20 +108,20 @@ ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR c
TRACE( "(%p, %p, 0x%02x, %p)\n", ld, sortkey, critical, control );
- if (!ld || !sortkey || !control) return LDAP_PARAM_ERROR; + if (!ld || !sortkey || !control) return WLDAP32_LDAP_PARAM_ERROR;
if ((sortkeyU = sortkeyarrayWtoU( sortkey ))) { struct ldap_create_sort_control_params params = { CTX(ld), sortkeyU, critical, &controlU }; ret = map_error( LDAP_CALL( ldap_create_sort_control, ¶ms )); } - else return LDAP_NO_MEMORY; + else return WLDAP32_LDAP_NO_MEMORY;
- if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlW *controlW = controlUtoW( controlU ); if (controlW) *control = controlW; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_control_free, controlU ); }
@@ -142,11 +142,11 @@ INT CDECL ldap_create_vlv_controlA( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, if (!ld || !control) return ~0u;
ret = ldap_create_vlv_controlW( ld, info, critical, &controlW ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlA *controlA = controlWtoA( controlW ); if (controlA) *control = controlA; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; ldap_control_freeW( controlW ); }
@@ -166,17 +166,17 @@ INT CDECL ldap_create_vlv_controlW( LDAP *ld, LDAPVLVInfo *info, UCHAR critical,
if (!ld || !control) return ~0u;
- if (info && !(infoU = vlvinfoWtoU( info ))) return LDAP_NO_MEMORY; + if (info && !(infoU = vlvinfoWtoU( info ))) return WLDAP32_LDAP_NO_MEMORY; else { struct ldap_create_vlv_control_params params = { CTX(ld), infoU, &controlU }; ret = map_error( LDAP_CALL( ldap_create_vlv_control, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlW *controlW = controlUtoW( controlU ); if (controlW) *control = controlW; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_control_free, controlU ); }
@@ -203,7 +203,7 @@ ULONG CDECL ldap_encode_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkeys, LDAPCo LDAPControlA *control; ULONG result;
- if ((result = ldap_create_sort_controlA( ld, sortkeys, critical, &control )) == LDAP_SUCCESS) + if ((result = ldap_create_sort_controlA( ld, sortkeys, critical, &control )) == WLDAP32_LDAP_SUCCESS) { ret->ldctl_oid = strdupU(control->ldctl_oid); bv_val_dup( &control->ldctl_value, &ret->ldctl_value ); @@ -221,7 +221,7 @@ ULONG CDECL ldap_encode_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkeys, LDAPCo LDAPControlW *control; ULONG result;
- if ((result = ldap_create_sort_controlW( ld, sortkeys, critical, &control )) == LDAP_SUCCESS) + if ((result = ldap_create_sort_controlW( ld, sortkeys, critical, &control )) == WLDAP32_LDAP_SUCCESS) { ret->ldctl_oid = strdupW(control->ldctl_oid); bv_val_dup( &control->ldctl_value, &ret->ldctl_value ); diff --git a/dlls/wldap32/delete.c b/dlls/wldap32/delete.c index 325aac4a580..be5bb36a851 100644 --- a/dlls/wldap32/delete.c +++ b/dlls/wldap32/delete.c @@ -40,7 +40,7 @@ ULONG CDECL ldap_deleteA( LDAP *ld, char *dn ) TRACE( "(%p, %s)\n", ld, debugstr_a(dn) );
if (!ld) return ~0u; - if (dn && !(dnW = strAtoW( dn ))) return LDAP_NO_MEMORY; + if (dn && !(dnW = strAtoW( dn ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_deleteW( ld, dnW ); free( dnW ); @@ -57,7 +57,7 @@ ULONG CDECL ldap_deleteW( LDAP *ld, WCHAR *dn ) TRACE( "(%p, %s)\n", ld, debugstr_w(dn) );
ret = ldap_delete_extW( ld, dn, NULL, NULL, &msg ); - if (ret == LDAP_SUCCESS) return msg; + if (ret == WLDAP32_LDAP_SUCCESS) return msg; return ~0u; }
@@ -67,13 +67,13 @@ ULONG CDECL ldap_deleteW( LDAP *ld, WCHAR *dn ) ULONG CDECL ldap_delete_extA( LDAP *ld, char *dn, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_a(dn), serverctrls, clientctrls, message );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (serverctrls && !(serverctrlsW = controlarrayAtoW( serverctrls ))) goto exit; @@ -94,13 +94,13 @@ exit: ULONG CDECL ldap_delete_extW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls, message );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -123,13 +123,13 @@ exit: */ ULONG CDECL ldap_delete_ext_sA( LDAP *ld, char *dn, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p)\n", ld, debugstr_a(dn), serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (serverctrls && !(serverctrlsW = controlarrayAtoW( serverctrls ))) goto exit; @@ -149,13 +149,13 @@ exit: */ ULONG CDECL ldap_delete_ext_sW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -183,8 +183,8 @@ ULONG CDECL ldap_delete_sA( LDAP *ld, char *dn )
TRACE( "(%p, %s)\n", ld, debugstr_a(dn) );
- if (!ld) return LDAP_PARAM_ERROR; - if (dn && !(dnW = strAtoW( dn ))) return LDAP_NO_MEMORY; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (dn && !(dnW = strAtoW( dn ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_delete_sW( ld, dnW ); free( dnW ); diff --git a/dlls/wldap32/dn.c b/dlls/wldap32/dn.c index 14c4617726a..3003fec71e3 100644 --- a/dlls/wldap32/dn.c +++ b/dlls/wldap32/dn.c @@ -164,16 +164,16 @@ ULONG CDECL ldap_ufn2dnA( char *ufn, char **dn )
TRACE( "(%s, %p)\n", debugstr_a(ufn), dn );
- if (!dn) return LDAP_PARAM_ERROR; + if (!dn) return WLDAP32_LDAP_PARAM_ERROR;
*dn = NULL; - if (ufn && !(ufnW = strAtoW( ufn ))) return LDAP_NO_MEMORY; + if (ufn && !(ufnW = strAtoW( ufn ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_ufn2dnW( ufnW, &dnW ); if (dnW) { char *str; - if (!(str = strWtoA( dnW ))) ret = LDAP_NO_MEMORY; + if (!(str = strWtoA( dnW ))) ret = WLDAP32_LDAP_NO_MEMORY; else *dn = str; }
@@ -187,21 +187,21 @@ ULONG CDECL ldap_ufn2dnA( char *ufn, char **dn ) */ ULONG CDECL ldap_ufn2dnW( WCHAR *ufn, WCHAR **dn ) { - ULONG ret = LDAP_SUCCESS; + ULONG ret = WLDAP32_LDAP_SUCCESS; char *ufnU = NULL;
TRACE( "(%s, %p)\n", debugstr_w(ufn), dn );
- if (!dn) return LDAP_PARAM_ERROR; + if (!dn) return WLDAP32_LDAP_PARAM_ERROR;
*dn = NULL; if (ufn) { WCHAR *str; - if (!(ufnU = strWtoU( ufn ))) return LDAP_NO_MEMORY; + if (!(ufnU = strWtoU( ufn ))) return WLDAP32_LDAP_NO_MEMORY;
/* FIXME: do more than just a copy */ - if (!(str = strUtoW( ufnU ))) ret = LDAP_NO_MEMORY; + if (!(str = strUtoW( ufnU ))) ret = WLDAP32_LDAP_NO_MEMORY; else *dn = str; }
diff --git a/dlls/wldap32/error.c b/dlls/wldap32/error.c index 2b3d0166eb5..80c7bd48bf8 100644 --- a/dlls/wldap32/error.c +++ b/dlls/wldap32/error.c @@ -36,24 +36,24 @@ ULONG map_error( int error ) { switch (error) { - case 0: return LDAP_SUCCESS; - case -1: return LDAP_SERVER_DOWN; - case -2: return LDAP_LOCAL_ERROR; - case -3: return LDAP_ENCODING_ERROR; - case -4: return LDAP_DECODING_ERROR; - case -5: return LDAP_TIMEOUT; - case -6: return LDAP_AUTH_UNKNOWN; - case -7: return LDAP_FILTER_ERROR; - case -8: return LDAP_USER_CANCELLED; - case -9: return LDAP_PARAM_ERROR; - case -10: return LDAP_NO_MEMORY; - case -11: return LDAP_CONNECT_ERROR; - case -12: return LDAP_NOT_SUPPORTED; - case -13: return LDAP_CONTROL_NOT_FOUND; - case -14: return LDAP_NO_RESULTS_RETURNED; - case -15: return LDAP_MORE_RESULTS_TO_RETURN; - case -16: return LDAP_CLIENT_LOOP; - case -17: return LDAP_REFERRAL_LIMIT_EXCEEDED; + case 0: return WLDAP32_LDAP_SUCCESS; + case -1: return WLDAP32_LDAP_SERVER_DOWN; + case -2: return WLDAP32_LDAP_LOCAL_ERROR; + case -3: return WLDAP32_LDAP_ENCODING_ERROR; + case -4: return WLDAP32_LDAP_DECODING_ERROR; + case -5: return WLDAP32_LDAP_TIMEOUT; + case -6: return WLDAP32_LDAP_AUTH_UNKNOWN; + case -7: return WLDAP32_LDAP_FILTER_ERROR; + case -8: return WLDAP32_LDAP_USER_CANCELLED; + case -9: return WLDAP32_LDAP_PARAM_ERROR; + case -10: return WLDAP32_LDAP_NO_MEMORY; + case -11: return WLDAP32_LDAP_CONNECT_ERROR; + case -12: return WLDAP32_LDAP_NOT_SUPPORTED; + case -13: return WLDAP32_LDAP_CONTROL_NOT_FOUND; + case -14: return WLDAP32_LDAP_NO_RESULTS_RETURNED; + case -15: return WLDAP32_LDAP_MORE_RESULTS_TO_RETURN; + case -16: return WLDAP32_LDAP_CLIENT_LOOP; + case -17: return WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED; default: return error; } } @@ -67,10 +67,10 @@ char * CDECL ldap_err2stringA( ULONG err )
TRACE( "(%#lx)\n", err );
- if (err <= LDAP_REFERRAL_LIMIT_EXCEEDED) + if (err <= WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED) LoadStringA( hwldap32, err, buf, 256 ); else - LoadStringA( hwldap32, LDAP_LOCAL_ERROR, buf, 256 ); + LoadStringA( hwldap32, WLDAP32_LDAP_LOCAL_ERROR, buf, 256 );
return buf; } @@ -84,10 +84,10 @@ WCHAR * CDECL ldap_err2stringW( ULONG err )
TRACE( "(%#lx)\n", err );
- if (err <= LDAP_REFERRAL_LIMIT_EXCEEDED) + if (err <= WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED) LoadStringW( hwldap32, err, buf, 256 ); else - LoadStringW( hwldap32, LDAP_LOCAL_ERROR, buf, 256 ); + LoadStringW( hwldap32, WLDAP32_LDAP_LOCAL_ERROR, buf, 256 );
return buf; } diff --git a/dlls/wldap32/extended.c b/dlls/wldap32/extended.c index 8c49c1d6b20..fead8e1b075 100644 --- a/dlls/wldap32/extended.c +++ b/dlls/wldap32/extended.c @@ -36,8 +36,8 @@ ULONG CDECL ldap_close_extended_op( LDAP *ld, ULONG msgid ) { TRACE( "(%p, %#lx)\n", ld, msgid );
- if (!ld) return LDAP_PARAM_ERROR; - return LDAP_SUCCESS; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -46,13 +46,13 @@ ULONG CDECL ldap_close_extended_op( LDAP *ld, ULONG msgid ) ULONG CDECL ldap_extended_operationA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *oidW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_a(oid), data, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (oid && !(oidW = strAtoW( oid ))) goto exit; if (serverctrls && !(serverctrlsW = controlarrayAtoW( serverctrls ))) goto exit; @@ -73,14 +73,14 @@ exit: ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *oidU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU *dataU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (oid && !(oidU = strWtoU( oid ))) goto exit; if (data && !(dataU = bervalWtoU( data ))) goto exit; @@ -106,13 +106,13 @@ exit: ULONG CDECL ldap_extended_operation_sA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, char **retoid, struct berval **retdata ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *oidW = NULL, *retoidW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p, %p)\n", ld, debugstr_a(oid), data, serverctrls, clientctrls, retoid, retdata );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (oid && !(oidW = strAtoW( oid ))) goto exit; if (serverctrls && !(serverctrlsW = controlarrayAtoW( serverctrls ))) goto exit; @@ -123,7 +123,7 @@ ULONG CDECL ldap_extended_operation_sA( LDAP *ld, char *oid, struct berval *data { char *str = strWtoA( retoidW ); if (str) *retoid = str; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; ldap_memfreeW( retoidW ); }
@@ -140,14 +140,14 @@ exit: ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, WCHAR **retoid, struct berval **retdata ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *oidU = NULL, *retoidU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct bervalU *retdataU, *dataU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, retoid, retdata );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (oid && !(oidU = strWtoU( oid ))) goto exit; if (data && !(dataU = bervalWtoU( data ))) goto exit; @@ -163,14 +163,14 @@ ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *dat { WCHAR *str = strUtoW( retoidU ); if (str) *retoid = str; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_memfree, retoidU ); } if (retdata && retdataU) { struct berval *bv = bervalUtoW( retdataU ); if (bv) *retdata = bv; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ber_bvfree, retdataU ); }
diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index 88fa55b77f7..a17b14a635c 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -190,19 +190,18 @@ static char *urlify_hostnames( const char *scheme, char *hostnames, ULONG port ) return url; }
- static LDAP *create_context( const char *url ) { LDAP *ld; - int version = LDAP_VERSION3; + int version = WLDAP32_LDAP_VERSION3; struct ldap_initialize_params params;
if (!(ld = calloc( 1, sizeof( *ld )))) return NULL; params.ld = &CTX(ld); params.url = url; - if (map_error( LDAP_CALL( ldap_initialize, ¶ms )) == LDAP_SUCCESS) + if (map_error( LDAP_CALL( ldap_initialize, ¶ms )) == WLDAP32_LDAP_SUCCESS) { - struct ldap_set_option_params opt_params = { CTX(ld), LDAP_OPT_PROTOCOL_VERSION, &version }; + struct ldap_set_option_params opt_params = { CTX(ld), WLDAP32_LDAP_OPT_PROTOCOL_VERSION, &version }; LDAP_CALL( ldap_set_option, &opt_params ); return ld; } @@ -256,8 +255,8 @@ ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout ) { TRACE( "(%p, %p)\n", ld, timeout );
- if (!ld) return LDAP_PARAM_ERROR; - return LDAP_SUCCESS; /* FIXME: do something, e.g. ping the host */ + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + return WLDAP32_LDAP_SUCCESS; /* FIXME: do something, e.g. ping the host */ }
/*********************************************************************** @@ -388,7 +387,7 @@ exit: ULONG CDECL ldap_start_tls_sA( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls ); @@ -412,7 +411,7 @@ exit: ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls ); @@ -444,7 +443,7 @@ exit: ULONG CDECL ldap_startup( LDAP_VERSION_INFO *version, HANDLE *instance ) { TRACE( "(%p, %p)\n", version, instance ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** diff --git a/dlls/wldap32/misc.c b/dlls/wldap32/misc.c index c8dcf614683..7f4fd70d7ae 100644 --- a/dlls/wldap32/misc.c +++ b/dlls/wldap32/misc.c @@ -55,8 +55,8 @@ ULONG CDECL ldap_check_filterA( LDAP *ld, char *filter )
TRACE( "(%p, %s)\n", ld, debugstr_a(filter) );
- if (!ld) return LDAP_PARAM_ERROR; - if (filter && !(filterW = strAtoW( filter ))) return LDAP_NO_MEMORY; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (filter && !(filterW = strAtoW( filter ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_check_filterW( ld, filterW );
@@ -71,8 +71,8 @@ ULONG CDECL ldap_check_filterW( LDAP *ld, WCHAR *filter ) { TRACE( "(%p, %s)\n", ld, debugstr_w(filter) );
- if (!ld) return LDAP_PARAM_ERROR; - return LDAP_SUCCESS; /* FIXME: do some checks */ + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + return WLDAP32_LDAP_SUCCESS; /* FIXME: do some checks */ }
/*********************************************************************** @@ -81,7 +81,7 @@ ULONG CDECL ldap_check_filterW( LDAP *ld, WCHAR *filter ) ULONG CDECL ldap_cleanup( HANDLE instance ) { TRACE( "(%p)\n", instance ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -172,10 +172,10 @@ ULONG CDECL ldap_escape_filter_elementA( char *src, ULONG srclen, char *dst, ULO TRACE( "(%p, %#lx, %p, %#lx)\n", src, srclen, dst, dstlen );
if (!dst) return len; - if (!src || dstlen < len) return LDAP_PARAM_ERROR; + if (!src || dstlen < len) return WLDAP32_LDAP_PARAM_ERROR;
escape_filter_element( src, srclen, dst ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -190,7 +190,7 @@ ULONG CDECL ldap_escape_filter_elementW( char *src, ULONG srclen, WCHAR *dst, UL if (!dst) return len;
/* no matter what you throw at it, this is what native returns */ - return LDAP_PARAM_ERROR; + return WLDAP32_LDAP_PARAM_ERROR; }
/*********************************************************************** @@ -314,7 +314,7 @@ ULONG CDECL WLDAP32_ldap_msgfree( LDAPMessage *res )
TRACE( "(%p)\n", res );
- if (!res) return LDAP_SUCCESS; + if (!res) return WLDAP32_LDAP_SUCCESS;
LDAP_CALL( ldap_msgfree, MSG(res) ); while (list) @@ -324,7 +324,7 @@ ULONG CDECL WLDAP32_ldap_msgfree( LDAPMessage *res ) free( entry ); }
- return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** diff --git a/dlls/wldap32/modify.c b/dlls/wldap32/modify.c index 553437a0b22..72b9cce2e0b 100644 --- a/dlls/wldap32/modify.c +++ b/dlls/wldap32/modify.c @@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ ULONG CDECL ldap_modifyA( LDAP *ld, char *dn, LDAPModA **mods ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **modsW = NULL;
@@ -63,7 +63,7 @@ ULONG CDECL ldap_modifyW( LDAP *ld, WCHAR *dn, LDAPModW **mods ) TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), mods );
ret = ldap_modify_extW( ld, dn, mods, NULL, NULL, &msg ); - if (ret == LDAP_SUCCESS) return msg; + if (ret == WLDAP32_LDAP_SUCCESS) return msg; return ~0u; }
@@ -73,7 +73,7 @@ ULONG CDECL ldap_modifyW( LDAP *ld, WCHAR *dn, LDAPModW **mods ) ULONG CDECL ldap_modify_extA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **modsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL; @@ -103,7 +103,7 @@ exit: ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPModU **modsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; @@ -136,14 +136,14 @@ exit: ULONG CDECL ldap_modify_ext_sA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **modsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_a(dn), mods, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (mods && !(modsW = modarrayAtoW( mods ))) goto exit; @@ -166,14 +166,14 @@ exit: ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; LDAPModU **modsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), mods, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (mods && !(modsU = modarrayWtoU( mods ))) goto exit; @@ -198,13 +198,13 @@ exit: */ ULONG CDECL ldap_modify_sA( LDAP *ld, char *dn, LDAPModA **mods ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; LDAPModW **modsW = NULL;
TRACE( "(%p, %s, %p)\n", ld, debugstr_a(dn), mods );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (mods && !(modsW = modarrayAtoW( mods ))) goto exit; diff --git a/dlls/wldap32/modrdn.c b/dlls/wldap32/modrdn.c index 999e5b5df62..7df09b941af 100644 --- a/dlls/wldap32/modrdn.c +++ b/dlls/wldap32/modrdn.c @@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ ULONG CDECL ldap_modrdnA( LDAP *ld, char *dn, char *newdn ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newdnW = NULL;
TRACE( "(%p, %s, %s)\n", ld, debugstr_a(dn), debugstr_a(newdn) ); @@ -66,7 +66,7 @@ ULONG CDECL ldap_modrdnW( LDAP *ld, WCHAR *dn, WCHAR *newdn ) */ ULONG CDECL ldap_modrdn2A( LDAP *ld, char *dn, char *newdn, int delete ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newdnW = NULL;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_a(dn), newdn, delete ); @@ -89,7 +89,7 @@ exit: */ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *newdnU = NULL; ULONG msg;
@@ -97,13 +97,13 @@ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete )
if (!ld || !newdn) return ~0u;
- if (dn && !(dnU = strWtoU( dn ))) return LDAP_NO_MEMORY; + if (dn && !(dnU = strWtoU( dn ))) return WLDAP32_LDAP_NO_MEMORY;
if ((newdnU = strWtoU( newdn ))) { struct ldap_rename_params params = { CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL, &msg }; ret = LDAP_CALL( ldap_rename, ¶ms ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else ret = ~0u; @@ -118,12 +118,12 @@ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) */ ULONG CDECL ldap_modrdn2_sA( LDAP *ld, char *dn, char *newdn, int delete ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newdnW = NULL;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_a(dn), newdn, delete );
- if (!ld || !newdn) return LDAP_PARAM_ERROR; + if (!ld || !newdn) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (!(newdnW = strAtoW( newdn ))) goto exit; @@ -141,14 +141,14 @@ exit: */ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *newdnU = NULL;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_w(dn), newdn, delete );
- if (!ld || !newdn) return LDAP_PARAM_ERROR; + if (!ld || !newdn) return WLDAP32_LDAP_PARAM_ERROR;
- if (dn && !(dnU = strWtoU( dn ))) return LDAP_NO_MEMORY; + if (dn && !(dnU = strWtoU( dn ))) return WLDAP32_LDAP_NO_MEMORY;
if ((newdnU = strWtoU( newdn ))) { @@ -165,12 +165,12 @@ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) */ ULONG CDECL ldap_modrdn_sA( LDAP *ld, char *dn, char *newdn ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newdnW = NULL;
TRACE( "(%p, %s, %p)\n", ld, debugstr_a(dn), newdn );
- if (!ld || !newdn) return LDAP_PARAM_ERROR; + if (!ld || !newdn) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (!(newdnW = strAtoW( newdn ))) goto exit; diff --git a/dlls/wldap32/option.c b/dlls/wldap32/option.c index d848522fa56..354fdee08e1 100644 --- a/dlls/wldap32/option.c +++ b/dlls/wldap32/option.c @@ -29,10 +29,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
-#ifndef LDAP_OPT_SERVER_CONTROLS -#define LDAP_OPT_SERVER_CONTROLS 0x0012 -#endif - /*********************************************************************** * ldap_get_optionA (WLDAP32.@) */ @@ -42,28 +38,28 @@ ULONG CDECL ldap_get_optionA( LDAP *ld, int option, void *value )
TRACE( "(%p, 0x%08x, %p)\n", ld, option, value );
- if (!ld || !value) return LDAP_PARAM_ERROR; + if (!ld || !value) return WLDAP32_LDAP_PARAM_ERROR;
switch (option) { - case LDAP_OPT_API_FEATURE_INFO: + case WLDAP32_LDAP_OPT_API_FEATURE_INFO: { LDAPAPIFeatureInfoW featureW; LDAPAPIFeatureInfoA *featureA = value;
- if (!featureA->ldapaif_name) return LDAP_PARAM_ERROR; + if (!featureA->ldapaif_name) return WLDAP32_LDAP_PARAM_ERROR;
featureW.ldapaif_info_version = featureA->ldapaif_info_version; - if (!(featureW.ldapaif_name = strAtoW( featureA->ldapaif_name ))) return LDAP_NO_MEMORY; + if (!(featureW.ldapaif_name = strAtoW( featureA->ldapaif_name ))) return WLDAP32_LDAP_NO_MEMORY; featureW.ldapaif_version = 0;
ret = ldap_get_optionW( ld, option, &featureW );
- if (ret == LDAP_SUCCESS) featureA->ldapaif_version = featureW.ldapaif_version; + if (ret == WLDAP32_LDAP_SUCCESS) featureA->ldapaif_version = featureW.ldapaif_version; free( featureW.ldapaif_name ); return ret; } - case LDAP_OPT_API_INFO: + case WLDAP32_LDAP_OPT_API_INFO: { LDAPAPIInfoW infoW; LDAPAPIInfoA *infoA = value; @@ -72,17 +68,17 @@ ULONG CDECL ldap_get_optionA( LDAP *ld, int option, void *value ) infoW.ldapai_info_version = infoA->ldapai_info_version;
ret = ldap_get_optionW( ld, option, &infoW ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { infoA->ldapai_api_version = infoW.ldapai_api_version; infoA->ldapai_protocol_version = infoW.ldapai_protocol_version;
if (infoW.ldapai_extensions && !(infoA->ldapai_extensions = strarrayWtoA( infoW.ldapai_extensions ))) - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; if (infoW.ldapai_vendor_name && !(infoA->ldapai_vendor_name = strWtoA( infoW.ldapai_vendor_name ))) { ldap_value_freeW( infoW.ldapai_extensions ); - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; } infoA->ldapai_vendor_version = infoW.ldapai_vendor_version;
@@ -92,61 +88,61 @@ ULONG CDECL ldap_get_optionA( LDAP *ld, int option, void *value ) return ret; }
- case LDAP_OPT_DEREF: - case LDAP_OPT_DESC: - case LDAP_OPT_ERROR_NUMBER: - case LDAP_OPT_PROTOCOL_VERSION: - case LDAP_OPT_REFERRALS: - case LDAP_OPT_SIZELIMIT: - case LDAP_OPT_TIMELIMIT: + case WLDAP32_LDAP_OPT_DEREF: + case WLDAP32_LDAP_OPT_DESC: + case WLDAP32_LDAP_OPT_ERROR_NUMBER: + case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: + case WLDAP32_LDAP_OPT_REFERRALS: + case WLDAP32_LDAP_OPT_SIZELIMIT: + case WLDAP32_LDAP_OPT_TIMELIMIT: return ldap_get_optionW( ld, option, value );
- case LDAP_OPT_CACHE_ENABLE: - case LDAP_OPT_CACHE_FN_PTRS: - case LDAP_OPT_CACHE_STRATEGY: - case LDAP_OPT_IO_FN_PTRS: - case LDAP_OPT_REBIND_ARG: - case LDAP_OPT_REBIND_FN: - case LDAP_OPT_RESTART: - case LDAP_OPT_THREAD_FN_PTRS: - return LDAP_LOCAL_ERROR; - - case LDAP_OPT_AREC_EXCLUSIVE: - case LDAP_OPT_AUTO_RECONNECT: - case LDAP_OPT_CLIENT_CERTIFICATE: - case LDAP_OPT_DNSDOMAIN_NAME: - case LDAP_OPT_ENCRYPT: - case LDAP_OPT_ERROR_STRING: - case LDAP_OPT_FAST_CONCURRENT_BIND: - case LDAP_OPT_GETDSNAME_FLAGS: - case LDAP_OPT_HOST_NAME: - case LDAP_OPT_HOST_REACHABLE: - case LDAP_OPT_PING_KEEP_ALIVE: - case LDAP_OPT_PING_LIMIT: - case LDAP_OPT_PING_WAIT_TIME: - case LDAP_OPT_PROMPT_CREDENTIALS: - case LDAP_OPT_REF_DEREF_CONN_PER_MSG: - case LDAP_OPT_REFERRAL_CALLBACK: - case LDAP_OPT_REFERRAL_HOP_LIMIT: - case LDAP_OPT_ROOTDSE_CACHE: - case LDAP_OPT_SASL_METHOD: - case LDAP_OPT_SECURITY_CONTEXT: - case LDAP_OPT_SEND_TIMEOUT: - case LDAP_OPT_SERVER_CERTIFICATE: - case LDAP_OPT_SERVER_CONTROLS: - case LDAP_OPT_SERVER_ERROR: - case LDAP_OPT_SERVER_EXT_ERROR: - case LDAP_OPT_SIGN: - case LDAP_OPT_SSL: - case LDAP_OPT_SSL_INFO: - case LDAP_OPT_SSPI_FLAGS: - case LDAP_OPT_TCP_KEEPALIVE: + case WLDAP32_LDAP_OPT_CACHE_ENABLE: + case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: + case WLDAP32_LDAP_OPT_CACHE_STRATEGY: + case WLDAP32_LDAP_OPT_IO_FN_PTRS: + case WLDAP32_LDAP_OPT_REBIND_ARG: + case WLDAP32_LDAP_OPT_REBIND_FN: + case WLDAP32_LDAP_OPT_RESTART: + case WLDAP32_LDAP_OPT_THREAD_FN_PTRS: + return WLDAP32_LDAP_LOCAL_ERROR; + + case WLDAP32_LDAP_OPT_AREC_EXCLUSIVE: + case WLDAP32_LDAP_OPT_AUTO_RECONNECT: + case WLDAP32_LDAP_OPT_CLIENT_CERTIFICATE: + case WLDAP32_LDAP_OPT_DNSDOMAIN_NAME: + case WLDAP32_LDAP_OPT_ENCRYPT: + case WLDAP32_LDAP_OPT_ERROR_STRING: + case WLDAP32_LDAP_OPT_FAST_CONCURRENT_BIND: + case WLDAP32_LDAP_OPT_GETDSNAME_FLAGS: + case WLDAP32_LDAP_OPT_HOST_NAME: + case WLDAP32_LDAP_OPT_HOST_REACHABLE: + case WLDAP32_LDAP_OPT_PING_KEEP_ALIVE: + case WLDAP32_LDAP_OPT_PING_LIMIT: + case WLDAP32_LDAP_OPT_PING_WAIT_TIME: + case WLDAP32_LDAP_OPT_PROMPT_CREDENTIALS: + case WLDAP32_LDAP_OPT_REF_DEREF_CONN_PER_MSG: + case WLDAP32_LDAP_OPT_REFERRAL_CALLBACK: + case WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT: + case WLDAP32_LDAP_OPT_ROOTDSE_CACHE: + case WLDAP32_LDAP_OPT_SASL_METHOD: + case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: + case WLDAP32_LDAP_OPT_SEND_TIMEOUT: + case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: + case WLDAP32_LDAP_OPT_SERVER_CONTROLS: + case WLDAP32_LDAP_OPT_SERVER_ERROR: + case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: + case WLDAP32_LDAP_OPT_SIGN: + case WLDAP32_LDAP_OPT_SSL: + case WLDAP32_LDAP_OPT_SSL_INFO: + case WLDAP32_LDAP_OPT_SSPI_FLAGS: + case WLDAP32_LDAP_OPT_TCP_KEEPALIVE: FIXME( "Unsupported option: 0x%02x\n", option ); - return LDAP_NOT_SUPPORTED; + return WLDAP32_LDAP_NOT_SUPPORTED;
default: FIXME( "Unknown option: 0x%02x\n", option ); - return LDAP_LOCAL_ERROR; + return WLDAP32_LDAP_LOCAL_ERROR; } }
@@ -159,16 +155,16 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value )
TRACE( "(%p, 0x%08x, %p)\n", ld, option, value );
- if (!ld || !value) return LDAP_PARAM_ERROR; + if (!ld || !value) return WLDAP32_LDAP_PARAM_ERROR;
switch (option) { - case LDAP_OPT_API_FEATURE_INFO: + case WLDAP32_LDAP_OPT_API_FEATURE_INFO: { LDAPAPIFeatureInfoU featureU; LDAPAPIFeatureInfoW *featureW = value;
- if (!featureW->ldapaif_name) return LDAP_PARAM_ERROR; + if (!featureW->ldapaif_name) return WLDAP32_LDAP_PARAM_ERROR;
featureU.ldapaif_info_version = featureW->ldapaif_info_version; if ((featureU.ldapaif_name = strWtoU( featureW->ldapaif_name ))) @@ -177,13 +173,13 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) featureU.ldapaif_version = 0; ret = map_error( LDAP_CALL( ldap_get_option, ¶ms )); } - else return LDAP_NO_MEMORY; + else return WLDAP32_LDAP_NO_MEMORY;
- if (ret == LDAP_SUCCESS) featureW->ldapaif_version = featureU.ldapaif_version; + if (ret == WLDAP32_LDAP_SUCCESS) featureW->ldapaif_version = featureU.ldapaif_version; free( featureU.ldapaif_name ); return ret; } - case LDAP_OPT_API_INFO: + case WLDAP32_LDAP_OPT_API_INFO: { LDAPAPIInfoU infoU; LDAPAPIInfoW *infoW = value; @@ -193,17 +189,17 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) infoU.ldapai_info_version = infoW->ldapai_info_version;
ret = map_error( LDAP_CALL( ldap_get_option, ¶ms )); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { infoW->ldapai_api_version = infoU.ldapai_api_version; infoW->ldapai_protocol_version = infoU.ldapai_protocol_version;
if (infoU.ldapai_extensions && !(infoW->ldapai_extensions = strarrayUtoW( infoU.ldapai_extensions ))) - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; if (infoU.ldapai_vendor_name && !(infoW->ldapai_vendor_name = strUtoW( infoU.ldapai_vendor_name ))) { LDAP_CALL( ldap_memvfree, infoU.ldapai_extensions ); - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; } infoW->ldapai_vendor_version = infoU.ldapai_vendor_version;
@@ -213,64 +209,64 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) return ret; }
- case LDAP_OPT_DEREF: - case LDAP_OPT_DESC: - case LDAP_OPT_ERROR_NUMBER: - case LDAP_OPT_PROTOCOL_VERSION: - case LDAP_OPT_REFERRALS: - case LDAP_OPT_SIZELIMIT: - case LDAP_OPT_TIMELIMIT: + case WLDAP32_LDAP_OPT_DEREF: + case WLDAP32_LDAP_OPT_DESC: + case WLDAP32_LDAP_OPT_ERROR_NUMBER: + case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: + case WLDAP32_LDAP_OPT_REFERRALS: + case WLDAP32_LDAP_OPT_SIZELIMIT: + case WLDAP32_LDAP_OPT_TIMELIMIT: { struct ldap_get_option_params params = { CTX(ld), option, value }; return map_error( LDAP_CALL( ldap_get_option, ¶ms )); }
- case LDAP_OPT_CACHE_ENABLE: - case LDAP_OPT_CACHE_FN_PTRS: - case LDAP_OPT_CACHE_STRATEGY: - case LDAP_OPT_IO_FN_PTRS: - case LDAP_OPT_REBIND_ARG: - case LDAP_OPT_REBIND_FN: - case LDAP_OPT_RESTART: - case LDAP_OPT_THREAD_FN_PTRS: - return LDAP_LOCAL_ERROR; - - case LDAP_OPT_AREC_EXCLUSIVE: - case LDAP_OPT_AUTO_RECONNECT: - case LDAP_OPT_CLIENT_CERTIFICATE: - case LDAP_OPT_DNSDOMAIN_NAME: - case LDAP_OPT_ENCRYPT: - case LDAP_OPT_ERROR_STRING: - case LDAP_OPT_FAST_CONCURRENT_BIND: - case LDAP_OPT_GETDSNAME_FLAGS: - case LDAP_OPT_HOST_NAME: - case LDAP_OPT_HOST_REACHABLE: - case LDAP_OPT_PING_KEEP_ALIVE: - case LDAP_OPT_PING_LIMIT: - case LDAP_OPT_PING_WAIT_TIME: - case LDAP_OPT_PROMPT_CREDENTIALS: - case LDAP_OPT_REF_DEREF_CONN_PER_MSG: - case LDAP_OPT_REFERRAL_CALLBACK: - case LDAP_OPT_REFERRAL_HOP_LIMIT: - case LDAP_OPT_ROOTDSE_CACHE: - case LDAP_OPT_SASL_METHOD: - case LDAP_OPT_SECURITY_CONTEXT: - case LDAP_OPT_SEND_TIMEOUT: - case LDAP_OPT_SERVER_CERTIFICATE: - case LDAP_OPT_SERVER_CONTROLS: - case LDAP_OPT_SERVER_ERROR: - case LDAP_OPT_SERVER_EXT_ERROR: - case LDAP_OPT_SIGN: - case LDAP_OPT_SSL: - case LDAP_OPT_SSL_INFO: - case LDAP_OPT_SSPI_FLAGS: - case LDAP_OPT_TCP_KEEPALIVE: + case WLDAP32_LDAP_OPT_CACHE_ENABLE: + case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: + case WLDAP32_LDAP_OPT_CACHE_STRATEGY: + case WLDAP32_LDAP_OPT_IO_FN_PTRS: + case WLDAP32_LDAP_OPT_REBIND_ARG: + case WLDAP32_LDAP_OPT_REBIND_FN: + case WLDAP32_LDAP_OPT_RESTART: + case WLDAP32_LDAP_OPT_THREAD_FN_PTRS: + return WLDAP32_LDAP_LOCAL_ERROR; + + case WLDAP32_LDAP_OPT_AREC_EXCLUSIVE: + case WLDAP32_LDAP_OPT_AUTO_RECONNECT: + case WLDAP32_LDAP_OPT_CLIENT_CERTIFICATE: + case WLDAP32_LDAP_OPT_DNSDOMAIN_NAME: + case WLDAP32_LDAP_OPT_ENCRYPT: + case WLDAP32_LDAP_OPT_ERROR_STRING: + case WLDAP32_LDAP_OPT_FAST_CONCURRENT_BIND: + case WLDAP32_LDAP_OPT_GETDSNAME_FLAGS: + case WLDAP32_LDAP_OPT_HOST_NAME: + case WLDAP32_LDAP_OPT_HOST_REACHABLE: + case WLDAP32_LDAP_OPT_PING_KEEP_ALIVE: + case WLDAP32_LDAP_OPT_PING_LIMIT: + case WLDAP32_LDAP_OPT_PING_WAIT_TIME: + case WLDAP32_LDAP_OPT_PROMPT_CREDENTIALS: + case WLDAP32_LDAP_OPT_REF_DEREF_CONN_PER_MSG: + case WLDAP32_LDAP_OPT_REFERRAL_CALLBACK: + case WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT: + case WLDAP32_LDAP_OPT_ROOTDSE_CACHE: + case WLDAP32_LDAP_OPT_SASL_METHOD: + case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: + case WLDAP32_LDAP_OPT_SEND_TIMEOUT: + case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: + case WLDAP32_LDAP_OPT_SERVER_CONTROLS: + case WLDAP32_LDAP_OPT_SERVER_ERROR: + case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: + case WLDAP32_LDAP_OPT_SIGN: + case WLDAP32_LDAP_OPT_SSL: + case WLDAP32_LDAP_OPT_SSL_INFO: + case WLDAP32_LDAP_OPT_SSPI_FLAGS: + case WLDAP32_LDAP_OPT_TCP_KEEPALIVE: FIXME( "Unsupported option: 0x%02x\n", option ); - return LDAP_NOT_SUPPORTED; + return WLDAP32_LDAP_NOT_SUPPORTED;
default: FIXME( "Unknown option: 0x%02x\n", option ); - return LDAP_LOCAL_ERROR; + return WLDAP32_LDAP_LOCAL_ERROR; } }
@@ -283,76 +279,76 @@ ULONG CDECL ldap_set_optionA( LDAP *ld, int option, void *value )
TRACE( "(%p, 0x%08x, %p)\n", ld, option, value );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
switch (option) { - case LDAP_OPT_SERVER_CONTROLS: + case WLDAP32_LDAP_OPT_SERVER_CONTROLS: { LDAPControlW **ctrlsW; - if (!(ctrlsW = controlarrayAtoW( value ))) return LDAP_NO_MEMORY; + if (!(ctrlsW = controlarrayAtoW( value ))) return WLDAP32_LDAP_NO_MEMORY; ret = ldap_set_optionW( ld, option, ctrlsW ); controlarrayfreeW( ctrlsW ); return ret; } - case LDAP_OPT_DEREF: - case LDAP_OPT_DESC: - case LDAP_OPT_ERROR_NUMBER: - case LDAP_OPT_PROTOCOL_VERSION: - case LDAP_OPT_REFERRALS: - case LDAP_OPT_SIZELIMIT: - case LDAP_OPT_TIMELIMIT: + case WLDAP32_LDAP_OPT_DEREF: + case WLDAP32_LDAP_OPT_DESC: + case WLDAP32_LDAP_OPT_ERROR_NUMBER: + case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: + case WLDAP32_LDAP_OPT_REFERRALS: + case WLDAP32_LDAP_OPT_SIZELIMIT: + case WLDAP32_LDAP_OPT_TIMELIMIT: return ldap_set_optionW( ld, option, value );
- case LDAP_OPT_CACHE_ENABLE: - case LDAP_OPT_CACHE_FN_PTRS: - case LDAP_OPT_CACHE_STRATEGY: - case LDAP_OPT_IO_FN_PTRS: - case LDAP_OPT_REBIND_ARG: - case LDAP_OPT_REBIND_FN: - case LDAP_OPT_RESTART: - case LDAP_OPT_THREAD_FN_PTRS: - return LDAP_LOCAL_ERROR; - - case LDAP_OPT_API_FEATURE_INFO: - case LDAP_OPT_API_INFO: - return LDAP_UNWILLING_TO_PERFORM; - - case LDAP_OPT_AREC_EXCLUSIVE: - case LDAP_OPT_AUTO_RECONNECT: - case LDAP_OPT_CLIENT_CERTIFICATE: - case LDAP_OPT_DNSDOMAIN_NAME: - case LDAP_OPT_ENCRYPT: - case LDAP_OPT_ERROR_STRING: - case LDAP_OPT_FAST_CONCURRENT_BIND: - case LDAP_OPT_GETDSNAME_FLAGS: - case LDAP_OPT_HOST_NAME: - case LDAP_OPT_HOST_REACHABLE: - case LDAP_OPT_PING_KEEP_ALIVE: - case LDAP_OPT_PING_LIMIT: - case LDAP_OPT_PING_WAIT_TIME: - case LDAP_OPT_PROMPT_CREDENTIALS: - case LDAP_OPT_REF_DEREF_CONN_PER_MSG: - case LDAP_OPT_REFERRAL_CALLBACK: - case LDAP_OPT_REFERRAL_HOP_LIMIT: - case LDAP_OPT_ROOTDSE_CACHE: - case LDAP_OPT_SASL_METHOD: - case LDAP_OPT_SECURITY_CONTEXT: - case LDAP_OPT_SEND_TIMEOUT: - case LDAP_OPT_SERVER_CERTIFICATE: - case LDAP_OPT_SERVER_ERROR: - case LDAP_OPT_SERVER_EXT_ERROR: - case LDAP_OPT_SIGN: - case LDAP_OPT_SSL: - case LDAP_OPT_SSL_INFO: - case LDAP_OPT_SSPI_FLAGS: - case LDAP_OPT_TCP_KEEPALIVE: + case WLDAP32_LDAP_OPT_CACHE_ENABLE: + case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: + case WLDAP32_LDAP_OPT_CACHE_STRATEGY: + case WLDAP32_LDAP_OPT_IO_FN_PTRS: + case WLDAP32_LDAP_OPT_REBIND_ARG: + case WLDAP32_LDAP_OPT_REBIND_FN: + case WLDAP32_LDAP_OPT_RESTART: + case WLDAP32_LDAP_OPT_THREAD_FN_PTRS: + return WLDAP32_LDAP_LOCAL_ERROR; + + case WLDAP32_LDAP_OPT_API_FEATURE_INFO: + case WLDAP32_LDAP_OPT_API_INFO: + return WLDAP32_LDAP_UNWILLING_TO_PERFORM; + + case WLDAP32_LDAP_OPT_AREC_EXCLUSIVE: + case WLDAP32_LDAP_OPT_AUTO_RECONNECT: + case WLDAP32_LDAP_OPT_CLIENT_CERTIFICATE: + case WLDAP32_LDAP_OPT_DNSDOMAIN_NAME: + case WLDAP32_LDAP_OPT_ENCRYPT: + case WLDAP32_LDAP_OPT_ERROR_STRING: + case WLDAP32_LDAP_OPT_FAST_CONCURRENT_BIND: + case WLDAP32_LDAP_OPT_GETDSNAME_FLAGS: + case WLDAP32_LDAP_OPT_HOST_NAME: + case WLDAP32_LDAP_OPT_HOST_REACHABLE: + case WLDAP32_LDAP_OPT_PING_KEEP_ALIVE: + case WLDAP32_LDAP_OPT_PING_LIMIT: + case WLDAP32_LDAP_OPT_PING_WAIT_TIME: + case WLDAP32_LDAP_OPT_PROMPT_CREDENTIALS: + case WLDAP32_LDAP_OPT_REF_DEREF_CONN_PER_MSG: + case WLDAP32_LDAP_OPT_REFERRAL_CALLBACK: + case WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT: + case WLDAP32_LDAP_OPT_ROOTDSE_CACHE: + case WLDAP32_LDAP_OPT_SASL_METHOD: + case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: + case WLDAP32_LDAP_OPT_SEND_TIMEOUT: + case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: + case WLDAP32_LDAP_OPT_SERVER_ERROR: + case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: + case WLDAP32_LDAP_OPT_SIGN: + case WLDAP32_LDAP_OPT_SSL: + case WLDAP32_LDAP_OPT_SSL_INFO: + case WLDAP32_LDAP_OPT_SSPI_FLAGS: + case WLDAP32_LDAP_OPT_TCP_KEEPALIVE: FIXME( "Unsupported option: 0x%02x\n", option ); - return LDAP_NOT_SUPPORTED; + return WLDAP32_LDAP_NOT_SUPPORTED;
default: FIXME( "Unknown option: 0x%02x\n", option ); - return LDAP_LOCAL_ERROR; + return WLDAP32_LDAP_LOCAL_ERROR; } }
@@ -371,7 +367,7 @@ static BOOL query_supported_server_ctrls( LDAP *ld ) } else return TRUE;
- if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { struct ldap_first_entry_params params = { CTX(ld), res, &entry }; if (!LDAP_CALL( ldap_first_entry, ¶ms )) @@ -427,18 +423,18 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value )
TRACE( "(%p, 0x%08x, %p)\n", ld, option, value );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
switch (option) { - case LDAP_OPT_SERVER_CONTROLS: + case WLDAP32_LDAP_OPT_SERVER_CONTROLS: { LDAPControlU **ctrlsU;
- if (!(ctrlsU = controlarrayWtoU( value ))) return LDAP_NO_MEMORY; + if (!(ctrlsU = controlarrayWtoU( value ))) return WLDAP32_LDAP_NO_MEMORY;
if (!is_supported_server_ctrls( ld, ctrlsU )) - ret = LDAP_PARAM_ERROR; + ret = WLDAP32_LDAP_PARAM_ERROR; else { struct ldap_set_option_params params = { CTX(ld), option, ctrlsU }; @@ -447,74 +443,74 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) controlarrayfreeU( ctrlsU ); return ret; } - case LDAP_OPT_REFERRALS: + case WLDAP32_LDAP_OPT_REFERRALS: { struct ldap_set_option_params params = { CTX(ld), option, LDAP_OPT_ON }; - if (value == LDAP_OPT_OFF) + if (value == WLDAP32_LDAP_OPT_OFF) params.value = LDAP_OPT_OFF; else - FIXME("upgrading referral value %p to LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value); + FIXME("upgrading referral value %p to WLDAP32_LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value); return map_error( LDAP_CALL( ldap_set_option, ¶ms )); } - case LDAP_OPT_DEREF: - case LDAP_OPT_DESC: - case LDAP_OPT_ERROR_NUMBER: - case LDAP_OPT_PROTOCOL_VERSION: - case LDAP_OPT_SIZELIMIT: - case LDAP_OPT_TIMELIMIT: + case WLDAP32_LDAP_OPT_DEREF: + case WLDAP32_LDAP_OPT_DESC: + case WLDAP32_LDAP_OPT_ERROR_NUMBER: + case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: + case WLDAP32_LDAP_OPT_SIZELIMIT: + case WLDAP32_LDAP_OPT_TIMELIMIT: { struct ldap_set_option_params params = { CTX(ld), option, value }; return map_error( LDAP_CALL( ldap_set_option, ¶ms )); }
- case LDAP_OPT_CACHE_ENABLE: - case LDAP_OPT_CACHE_FN_PTRS: - case LDAP_OPT_CACHE_STRATEGY: - case LDAP_OPT_IO_FN_PTRS: - case LDAP_OPT_REBIND_ARG: - case LDAP_OPT_REBIND_FN: - case LDAP_OPT_RESTART: - case LDAP_OPT_THREAD_FN_PTRS: - return LDAP_LOCAL_ERROR; - - case LDAP_OPT_API_FEATURE_INFO: - case LDAP_OPT_API_INFO: - return LDAP_UNWILLING_TO_PERFORM; - - case LDAP_OPT_AREC_EXCLUSIVE: - case LDAP_OPT_AUTO_RECONNECT: - case LDAP_OPT_CLIENT_CERTIFICATE: - case LDAP_OPT_DNSDOMAIN_NAME: - case LDAP_OPT_ENCRYPT: - case LDAP_OPT_ERROR_STRING: - case LDAP_OPT_FAST_CONCURRENT_BIND: - case LDAP_OPT_GETDSNAME_FLAGS: - case LDAP_OPT_HOST_NAME: - case LDAP_OPT_HOST_REACHABLE: - case LDAP_OPT_PING_KEEP_ALIVE: - case LDAP_OPT_PING_LIMIT: - case LDAP_OPT_PING_WAIT_TIME: - case LDAP_OPT_PROMPT_CREDENTIALS: - case LDAP_OPT_REF_DEREF_CONN_PER_MSG: - case LDAP_OPT_REFERRAL_CALLBACK: - case LDAP_OPT_REFERRAL_HOP_LIMIT: - case LDAP_OPT_ROOTDSE_CACHE: - case LDAP_OPT_SASL_METHOD: - case LDAP_OPT_SECURITY_CONTEXT: - case LDAP_OPT_SEND_TIMEOUT: - case LDAP_OPT_SERVER_CERTIFICATE: - case LDAP_OPT_SERVER_ERROR: - case LDAP_OPT_SERVER_EXT_ERROR: - case LDAP_OPT_SIGN: - case LDAP_OPT_SSL: - case LDAP_OPT_SSL_INFO: - case LDAP_OPT_SSPI_FLAGS: - case LDAP_OPT_TCP_KEEPALIVE: + case WLDAP32_LDAP_OPT_CACHE_ENABLE: + case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: + case WLDAP32_LDAP_OPT_CACHE_STRATEGY: + case WLDAP32_LDAP_OPT_IO_FN_PTRS: + case WLDAP32_LDAP_OPT_REBIND_ARG: + case WLDAP32_LDAP_OPT_REBIND_FN: + case WLDAP32_LDAP_OPT_RESTART: + case WLDAP32_LDAP_OPT_THREAD_FN_PTRS: + return WLDAP32_LDAP_LOCAL_ERROR; + + case WLDAP32_LDAP_OPT_API_FEATURE_INFO: + case WLDAP32_LDAP_OPT_API_INFO: + return WLDAP32_LDAP_UNWILLING_TO_PERFORM; + + case WLDAP32_LDAP_OPT_AREC_EXCLUSIVE: + case WLDAP32_LDAP_OPT_AUTO_RECONNECT: + case WLDAP32_LDAP_OPT_CLIENT_CERTIFICATE: + case WLDAP32_LDAP_OPT_DNSDOMAIN_NAME: + case WLDAP32_LDAP_OPT_ENCRYPT: + case WLDAP32_LDAP_OPT_ERROR_STRING: + case WLDAP32_LDAP_OPT_FAST_CONCURRENT_BIND: + case WLDAP32_LDAP_OPT_GETDSNAME_FLAGS: + case WLDAP32_LDAP_OPT_HOST_NAME: + case WLDAP32_LDAP_OPT_HOST_REACHABLE: + case WLDAP32_LDAP_OPT_PING_KEEP_ALIVE: + case WLDAP32_LDAP_OPT_PING_LIMIT: + case WLDAP32_LDAP_OPT_PING_WAIT_TIME: + case WLDAP32_LDAP_OPT_PROMPT_CREDENTIALS: + case WLDAP32_LDAP_OPT_REF_DEREF_CONN_PER_MSG: + case WLDAP32_LDAP_OPT_REFERRAL_CALLBACK: + case WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT: + case WLDAP32_LDAP_OPT_ROOTDSE_CACHE: + case WLDAP32_LDAP_OPT_SASL_METHOD: + case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: + case WLDAP32_LDAP_OPT_SEND_TIMEOUT: + case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: + case WLDAP32_LDAP_OPT_SERVER_ERROR: + case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: + case WLDAP32_LDAP_OPT_SIGN: + case WLDAP32_LDAP_OPT_SSL: + case WLDAP32_LDAP_OPT_SSL_INFO: + case WLDAP32_LDAP_OPT_SSPI_FLAGS: + case WLDAP32_LDAP_OPT_TCP_KEEPALIVE: FIXME( "Unsupported option: 0x%02x\n", option ); - return LDAP_NOT_SUPPORTED; + return WLDAP32_LDAP_NOT_SUPPORTED;
default: FIXME( "Unknown option: 0x%02x\n", option ); - return LDAP_LOCAL_ERROR; + return WLDAP32_LDAP_LOCAL_ERROR; } } diff --git a/dlls/wldap32/page.c b/dlls/wldap32/page.c index fd574eca2e7..101ddc46483 100644 --- a/dlls/wldap32/page.c +++ b/dlls/wldap32/page.c @@ -45,10 +45,10 @@ ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct berval *
TRACE( "(%p, %#lx, %p, 0x%02x, %p)\n", ld, pagesize, cookie, critical, control );
- if (!ld || !control || pagesize > INT_MAX) return LDAP_PARAM_ERROR; + if (!ld || !control || pagesize > INT_MAX) return WLDAP32_LDAP_PARAM_ERROR;
ret = ldap_create_page_controlW( ld, pagesize, cookie, critical, &controlW ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { *control = controlWtoA( controlW ); ldap_control_freeW( controlW ); @@ -65,7 +65,7 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c int ret, len; char *val;
- if (!(ber = WLDAP32_ber_alloc_t( LBER_USE_DER ))) return LDAP_NO_MEMORY; + if (!(ber = WLDAP32_ber_alloc_t( LBER_USE_DER ))) return WLDAP32_LDAP_NO_MEMORY;
vec[1] = NULL; if (cookie) @@ -77,11 +77,11 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c ret = WLDAP32_ber_flatten( ber, &berval ); WLDAP32_ber_free( ber, 1 );
- if (len == LBER_ERROR) return LDAP_ENCODING_ERROR; - if (ret == -1) return LDAP_NO_MEMORY; + if (len == WLDAP32_LBER_ERROR) return WLDAP32_LDAP_ENCODING_ERROR; + if (ret == -1) return WLDAP32_LDAP_NO_MEMORY;
/* copy the berval so it can be properly freed by the caller */ - if (!(val = malloc( berval->bv_len ))) return LDAP_NO_MEMORY; + if (!(val = malloc( berval->bv_len ))) return WLDAP32_LDAP_NO_MEMORY;
len = berval->bv_len; memcpy( val, berval->bv_val, len ); @@ -90,20 +90,20 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c if (!(ctrl = malloc( sizeof(*ctrl) ))) { free( val ); - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; } if (!(ctrl->ldctl_oid = strAtoW( LDAP_PAGED_RESULT_OID_STRING ))) { free( val ); free( ctrl ); - return LDAP_NO_MEMORY; + return WLDAP32_LDAP_NO_MEMORY; } ctrl->ldctl_value.bv_len = len; ctrl->ldctl_value.bv_val = val; ctrl->ldctl_iscritical = critical;
*control = ctrl; - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -114,7 +114,7 @@ ULONG CDECL ldap_create_page_controlW( LDAP *ld, ULONG pagesize, struct berval * { TRACE( "(%p, %#lx, %p, 0x%02x, %p)\n", ld, pagesize, cookie, critical, control );
- if (!ld || !control || pagesize > INT_MAX) return LDAP_PARAM_ERROR; + if (!ld || !control || pagesize > INT_MAX) return WLDAP32_LDAP_PARAM_ERROR; return create_page_control( pagesize, cookie, critical, control ); }
@@ -123,7 +123,7 @@ ULONG CDECL ldap_get_next_page( LDAP *ld, LDAPSearch *search, ULONG pagesize, UL FIXME( "(%p, %p, %#lx, %p)\n", ld, search, pagesize, message );
if (!ld) return ~0u; - return LDAP_NOT_SUPPORTED; + return WLDAP32_LDAP_NOT_SUPPORTED; }
ULONG CDECL ldap_get_next_page_s( LDAP *ld, LDAPSearch *search, struct l_timeval *timeout, ULONG pagesize, @@ -140,7 +140,7 @@ ULONG CDECL ldap_get_next_page_s( LDAP *ld, LDAPSearch *search, struct l_timeval /* end of paged results */ *count = 0; *results = NULL; - return LDAP_NO_RESULTS_RETURNED; + return WLDAP32_LDAP_NO_RESULTS_RETURNED; }
if (search->serverctrls[0]) @@ -151,12 +151,12 @@ ULONG CDECL ldap_get_next_page_s( LDAP *ld, LDAPSearch *search, struct l_timeval
TRACE("search->cookie: %s\n", search->cookie ? debugstr_an(search->cookie->bv_val, search->cookie->bv_len) : "NULL"); ret = ldap_create_page_controlW( ld, pagesize, search->cookie, 1, &search->serverctrls[0] ); - if (ret != LDAP_SUCCESS) return ret; + if (ret != WLDAP32_LDAP_SUCCESS) return ret;
ret = ldap_search_ext_sW( ld, search->dn, search->scope, search->filter, search->attrs, search->attrsonly, search->serverctrls, search->clientctrls, search->timeout.tv_sec ? &search->timeout : NULL, search->sizelimit, results ); - if (ret != LDAP_SUCCESS) return ret; + if (ret != WLDAP32_LDAP_SUCCESS) return ret;
return ldap_get_paged_count( ld, search, count, *results ); } @@ -168,24 +168,24 @@ ULONG CDECL ldap_get_paged_count( LDAP *ld, LDAPSearch *search, ULONG *count, LD
TRACE( "(%p, %p, %p, %p)\n", ld, search, count, results );
- if (!ld || !count || !results) return LDAP_PARAM_ERROR; + if (!ld || !count || !results) return WLDAP32_LDAP_PARAM_ERROR;
*count = 0;
ret = ldap_parse_resultW( ld, results, NULL, NULL, NULL, NULL, &server_ctrls, 0 ); - if (ret != LDAP_SUCCESS) return ret; + if (ret != WLDAP32_LDAP_SUCCESS) return ret;
if (!server_ctrls) /* assume end of paged results */ { search->cookie = &null_cookieW; - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
free( search->cookie ); search->cookie = NULL;
ret = ldap_parse_page_controlW( ld, server_ctrls, count, &search->cookie ); - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) TRACE( "new search->cookie: %s, count %lu\n", debugstr_an(search->cookie->bv_val, search->cookie->bv_len), *count );
@@ -203,9 +203,9 @@ ULONG CDECL ldap_parse_page_controlA( LDAP *ld, LDAPControlA **ctrls, ULONG *cou
TRACE( "(%p, %p, %p, %p)\n", ld, ctrls, count, cookie );
- if (!ld || !ctrls || !count || !cookie) return LDAP_PARAM_ERROR; + if (!ld || !ctrls || !count || !cookie) return WLDAP32_LDAP_PARAM_ERROR;
- if (!(ctrlsW = controlarrayAtoW( ctrls ))) return LDAP_NO_MEMORY; + if (!(ctrlsW = controlarrayAtoW( ctrls ))) return WLDAP32_LDAP_NO_MEMORY; ret = ldap_parse_page_controlW( ld, ctrlsW, count, cookie ); controlarrayfreeW( ctrlsW ); return ret; @@ -225,24 +225,24 @@ ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret
TRACE( "(%p, %p, %p, %p)\n", ld, ctrls, ret_count, ret_cookie );
- if (!ld || !ctrls || !ret_count || !ret_cookie) return LDAP_PARAM_ERROR; + if (!ld || !ctrls || !ret_count || !ret_cookie) return WLDAP32_LDAP_PARAM_ERROR;
for (i = 0; ctrls[i]; i++) { if (!wcscmp( LDAP_PAGED_RESULT_OID_STRING_W, ctrls[i]->ldctl_oid )) control = ctrls[i]; } - if (!control) return LDAP_CONTROL_NOT_FOUND; + if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND;
- if (!(ber = WLDAP32_ber_init( &control->ldctl_value ))) return LDAP_NO_MEMORY; + if (!(ber = WLDAP32_ber_init( &control->ldctl_value ))) return WLDAP32_LDAP_NO_MEMORY;
tag = WLDAP32_ber_scanf( ber, (char *)"{iO}", &count, &cookie ); - if (tag == LBER_ERROR) ret = LDAP_DECODING_ERROR; + if (tag == WLDAP32_LBER_ERROR) ret = WLDAP32_LDAP_DECODING_ERROR; else { *ret_count = count; *ret_cookie = cookie; - ret = LDAP_SUCCESS; + ret = WLDAP32_LDAP_SUCCESS; }
WLDAP32_ber_free( ber, 1 ); @@ -269,7 +269,7 @@ ULONG CDECL ldap_search_abandon_page( LDAP *ld, LDAPSearch *search ) if (search->cookie && search->cookie != &null_cookieW) free( search->cookie ); free( search );
- return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
LDAPSearch * CDECL ldap_search_init_pageA( LDAP *ld, char *dn, ULONG scope, char *filter, char **attrs, @@ -293,7 +293,7 @@ LDAPSearch * CDECL ldap_search_init_pageW( LDAP *ld, WCHAR *dn, ULONG scope, WCH
if (!(search = calloc( 1, sizeof(*search) ))) { - ld->ld_errno = LDAP_NO_MEMORY; + ld->ld_errno = WLDAP32_LDAP_NO_MEMORY; return NULL; }
@@ -330,6 +330,6 @@ LDAPSearch * CDECL ldap_search_init_pageW( LDAP *ld, WCHAR *dn, ULONG scope, WCH
fail: ldap_search_abandon_page( ld, search ); - ld->ld_errno = LDAP_NO_MEMORY; + ld->ld_errno = WLDAP32_LDAP_NO_MEMORY; return NULL; } diff --git a/dlls/wldap32/parse.c b/dlls/wldap32/parse.c index bcd0e61607a..432278618fe 100644 --- a/dlls/wldap32/parse.c +++ b/dlls/wldap32/parse.c @@ -40,15 +40,15 @@ ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, LDAPMessage *result, char **o
TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
- if (!ld) return LDAP_PARAM_ERROR; - if (!result) return LDAP_NO_RESULTS_RETURNED; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED;
ret = ldap_parse_extended_resultW( ld, result, &oidW, data, free ); if (oid && oidW) { char *str; if ((str = strWtoA( oidW ))) *oid = str; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; ldap_memfreeW( oidW ); } return ret; @@ -66,8 +66,8 @@ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR **
TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
- if (!ld) return LDAP_PARAM_ERROR; - if (!result) return LDAP_NO_RESULTS_RETURNED; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; else { struct ldap_parse_extended_result_params params = { CTX(ld), result, &oidU, &dataU, free }; @@ -77,14 +77,14 @@ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR ** { WCHAR *str; if ((str = strUtoW( oidU ))) *oid = str; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_memfree, oidU ); } if (data && dataU) { struct berval *bv; if ((bv = bervalUtoW( dataU ))) *data = bv; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ber_bvfree, dataU ); }
@@ -108,7 +108,7 @@ ULONG CDECL ldap_parse_referenceA( LDAP *ld, LDAPMessage *message, char ***refer { char **ref; if ((ref = strarrayWtoA( referralsW ))) *referrals = ref; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; ldap_value_freeW( referralsW ); } return ret; @@ -133,7 +133,7 @@ ULONG CDECL ldap_parse_referenceW( LDAP *ld, LDAPMessage *message, WCHAR ***refe { WCHAR **ref; if ((ref = strarrayUtoW( referralsU ))) *referrals = ref; - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_memfree, referralsU ); } return ret; @@ -152,7 +152,7 @@ ULONG CDECL ldap_parse_resultA( LDAP *ld, LDAPMessage *result, ULONG *retcode, c TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, matched, error, referrals, serverctrls, free );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
ret = ldap_parse_resultW( ld, result, retcode, &matchedW, &errorW, &referralsW, &serverctrlsW, free );
@@ -187,7 +187,7 @@ ULONG CDECL ldap_parse_resultW( LDAP *ld, LDAPMessage *result, ULONG *retcode, W &errorU, &referralsU, &serverctrlsU, free }; ret = map_error( LDAP_CALL( ldap_parse_result, ¶ms )); } - else return LDAP_PARAM_ERROR; + else return WLDAP32_LDAP_PARAM_ERROR;
if (matched) *matched = strUtoW( matchedU ); if (error) *error = strUtoW( errorU ); @@ -212,9 +212,9 @@ ULONG CDECL ldap_parse_sort_controlA( LDAP *ld, LDAPControlA **control, ULONG *r
TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
- if (!ld) return LDAP_PARAM_ERROR; - if (!control) return LDAP_CONTROL_NOT_FOUND; - if (!(controlW = controlarrayAtoW( control ))) return LDAP_NO_MEMORY; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; + if (!(controlW = controlarrayAtoW( control ))) return WLDAP32_LDAP_NO_MEMORY;
ret = ldap_parse_sort_controlW( ld, controlW, result, &attrW );
@@ -236,9 +236,9 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r
TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
- if (!ld) return LDAP_PARAM_ERROR; - if (!control) return LDAP_CONTROL_NOT_FOUND; - if (!(controlU = controlarrayWtoU( control ))) return LDAP_NO_MEMORY; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; + if (!(controlU = controlarrayWtoU( control ))) return WLDAP32_LDAP_NO_MEMORY;
for (i = 0; controlU[i]; i++) { @@ -248,14 +248,14 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r if (!sortcontrol) { controlarrayfreeU( controlU ); - return LDAP_CONTROL_NOT_FOUND; + return WLDAP32_LDAP_CONTROL_NOT_FOUND; } else { struct ldap_parse_sortresponse_control_params params = { CTX(ld), sortcontrol, &res, &attrU }; ret = map_error( LDAP_CALL( ldap_parse_sortresponse_control, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { WCHAR *str; if ((str = strUtoW( attrU ))) @@ -263,7 +263,7 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r *attr = str; *result = res; } - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ldap_memfree, attrU ); }
@@ -275,7 +275,7 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r * ldap_parse_vlv_controlA (WLDAP32.@) */ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targetpos, ULONG *listcount, - struct berval **context, int *errcode ) + struct berval **context, int *errcode ) { int ret; LDAPControlW **controlW = NULL; @@ -284,7 +284,7 @@ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targ
if (!ld) return ~0u;
- if (control && !(controlW = controlarrayAtoW( control ))) return LDAP_NO_MEMORY; + if (control && !(controlW = controlarrayAtoW( control ))) return WLDAP32_LDAP_NO_MEMORY; ret = ldap_parse_vlv_controlW( ld, controlW, targetpos, listcount, context, errcode ); controlarrayfreeW( controlW ); return ret; @@ -305,7 +305,7 @@ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targ
if (!ld || !control) return ~0u;
- if (!(controlU = controlarrayWtoU( control ))) return LDAP_NO_MEMORY; + if (!(controlU = controlarrayWtoU( control ))) return WLDAP32_LDAP_NO_MEMORY;
for (i = 0; controlU[i]; i++) { @@ -315,14 +315,14 @@ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targ if (!vlvcontrolU) { controlarrayfreeU( controlU ); - return LDAP_CONTROL_NOT_FOUND; + return WLDAP32_LDAP_CONTROL_NOT_FOUND; } else { struct ldap_parse_vlvresponse_control_params params = { CTX(ld), vlvcontrolU, &pos, &count, &ctxU, errcode }; ret = map_error( LDAP_CALL( ldap_parse_vlvresponse_control, ¶ms )); } - if (ret == LDAP_SUCCESS) + if (ret == WLDAP32_LDAP_SUCCESS) { struct berval *bv; if ((bv = bervalUtoW( ctxU ))) @@ -331,7 +331,7 @@ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targ *targetpos = pos; *listcount = count; } - else ret = LDAP_NO_MEMORY; + else ret = WLDAP32_LDAP_NO_MEMORY; LDAP_CALL( ber_bvfree, ctxU ); }
diff --git a/dlls/wldap32/rename.c b/dlls/wldap32/rename.c index 58a2f2101b3..411fbf4b817 100644 --- a/dlls/wldap32/rename.c +++ b/dlls/wldap32/rename.c @@ -35,14 +35,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); ULONG CDECL ldap_rename_extA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newrdnW = NULL, *newparentW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(newrdn), debugstr_a(newparent), delete, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (newrdn && !(newrdnW = strAtoW( newrdn ))) goto exit; @@ -67,14 +67,14 @@ exit: ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(newrdn), debugstr_w(newparent), delete, serverctrls, clientctrls, message );
- if (!ld || !message) return LDAP_PARAM_ERROR; + if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (newrdn && !(newrdnU = strWtoU( newrdn ))) goto exit; @@ -101,14 +101,14 @@ exit: ULONG CDECL ldap_rename_ext_sA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newrdnW = NULL, *newparentW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p)\n", ld, debugstr_a(dn), debugstr_a(newrdn), debugstr_a(newparent), delete, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnW = strAtoW( dn ))) goto exit; if (newrdn && !(newrdnW = strAtoW( newrdn ))) goto exit; @@ -133,14 +133,14 @@ exit: ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = LDAP_PARAM_ERROR; + ULONG ret = WLDAP32_LDAP_PARAM_ERROR; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(newrdn), debugstr_w(newparent), delete, serverctrls, clientctrls );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (newrdn && !(newrdnU = strWtoU( newrdn ))) goto exit; diff --git a/dlls/wldap32/search.c b/dlls/wldap32/search.c index 738344de685..924bb4321a2 100644 --- a/dlls/wldap32/search.c +++ b/dlls/wldap32/search.c @@ -35,7 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ ULONG CDECL ldap_searchA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx)\n", ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly ); @@ -64,7 +64,7 @@ ULONG CDECL ldap_searchW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCH TRACE( "(%p, %s, %#lx, %s, %p, %#lx)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly );
ret = ldap_search_extW( ld, base, scope, filter, attrs, attrsonly, NULL, NULL, 0, 0, &msg ); - if (ret == LDAP_SUCCESS) return msg; + if (ret == WLDAP32_LDAP_SUCCESS) return msg; return ~0u; }
@@ -74,14 +74,14 @@ ULONG CDECL ldap_searchW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCH ULONG CDECL ldap_search_extA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly, serverctrls, clientctrls, timelimit, sizelimit, message );
- if (!ld) return LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
if (base && !(baseW = strAtoW( base ))) goto exit; if (filter && !(filterW = strAtoW( filter ))) goto exit; @@ -108,7 +108,7 @@ ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct timevalU timevalU; @@ -148,14 +148,14 @@ ULONG CDECL ldap_search_ext_sA( LDAP *ld, char *base, ULONG scope, char *filter, ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, struct l_timeval *timeout, ULONG sizelimit, LDAPMessage **res ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %p, %#lx, %p)\n", ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly, serverctrls, clientctrls, timeout, sizelimit, res );
- if (!ld || !res) return LDAP_PARAM_ERROR; + if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
if (base && !(baseW = strAtoW( base ))) goto exit; if (filter && !(filterW = strAtoW( filter ))) goto exit; @@ -182,7 +182,7 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, struct l_timeval *timeout, ULONG sizelimit, LDAPMessage **res ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; struct timevalU timevalU; @@ -191,7 +191,7 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %p, %#lx, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, serverctrls, clientctrls, timeout, sizelimit, res );
- if (!ld || !res) return LDAP_PARAM_ERROR; + if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
if (base && !(baseU = strWtoU( base ))) goto exit; if (filter && !(filterU = strWtoU( filter ))) goto exit; @@ -222,7 +222,7 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte else { LDAP_CALL( ldap_msgfree, msgU ); - ret = LDAP_NO_MEMORY; + ret = WLDAP32_LDAP_NO_MEMORY; } }
@@ -241,13 +241,13 @@ exit: ULONG CDECL ldap_search_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, LDAPMessage **res ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p)\n", ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly, res );
- if (!ld || !res) return LDAP_PARAM_ERROR; + if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
if (base && !(baseW = strAtoW( base ))) goto exit; if (filter && !(filterW = strAtoW( filter ))) goto exit; @@ -279,13 +279,13 @@ ULONG CDECL ldap_search_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, W ULONG CDECL ldap_search_stA( LDAP *ld, const PCHAR base, ULONG scope, const PCHAR filter, char **attrs, ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ) { - ULONG ret = LDAP_NO_MEMORY; + ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p)\n", ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly, timeout, res );
- if (!ld || !res) return LDAP_PARAM_ERROR; + if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
if (base && !(baseW = strAtoW( base ))) goto exit; if (filter && !(filterW = strAtoW( filter ))) goto exit; diff --git a/dlls/wldap32/value.c b/dlls/wldap32/value.c index 3d2149a41d3..4c58227e299 100644 --- a/dlls/wldap32/value.c +++ b/dlls/wldap32/value.c @@ -218,7 +218,7 @@ ULONG CDECL WLDAP32_ldap_value_free_len( struct berval **values ) TRACE( "(%p)\n", values );
bvarrayfreeW( values ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -229,7 +229,7 @@ ULONG CDECL ldap_value_freeA( char **values ) TRACE( "(%p)\n", values );
strarrayfreeA( values ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -240,5 +240,5 @@ ULONG CDECL ldap_value_freeW( WCHAR **values ) TRACE( "(%p)\n", values );
strarrayfreeW( values ); - return LDAP_SUCCESS; + return WLDAP32_LDAP_SUCCESS; } diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h index c2b47dcda50..5df5683a84a 100644 --- a/dlls/wldap32/winldap_private.h +++ b/dlls/wldap32/winldap_private.h @@ -24,6 +24,158 @@ #include "winnls.h" #include "libldap.h"
+#define WLDAP32_LBER_ERROR (~0l) + +typedef enum { + WLDAP32_LDAP_SUCCESS = 0x00, + WLDAP32_LDAP_OPERATIONS_ERROR = 0x01, + WLDAP32_LDAP_PROTOCOL_ERROR = 0x02, + WLDAP32_LDAP_TIMELIMIT_EXCEEDED = 0x03, + WLDAP32_LDAP_SIZELIMIT_EXCEEDED = 0x04, + WLDAP32_LDAP_COMPARE_FALSE = 0x05, + WLDAP32_LDAP_COMPARE_TRUE = 0x06, + WLDAP32_LDAP_AUTH_METHOD_NOT_SUPPORTED = 0x07, + WLDAP32_LDAP_STRONG_AUTH_REQUIRED = 0x08, + WLDAP32_LDAP_REFERRAL_V2 = 0x09, + WLDAP32_LDAP_PARTIAL_RESULTS = 0x09, + WLDAP32_LDAP_REFERRAL = 0x0a, + WLDAP32_LDAP_ADMIN_LIMIT_EXCEEDED = 0x0b, + WLDAP32_LDAP_UNAVAILABLE_CRIT_EXTENSION = 0x0c, + WLDAP32_LDAP_CONFIDENTIALITY_REQUIRED = 0x0d, + WLDAP32_LDAP_SASL_BIND_IN_PROGRESS = 0x0e, + + WLDAP32_LDAP_NO_SUCH_ATTRIBUTE = 0x10, + WLDAP32_LDAP_UNDEFINED_TYPE = 0x11, + WLDAP32_LDAP_INAPPROPRIATE_MATCHING = 0x12, + WLDAP32_LDAP_CONSTRAINT_VIOLATION = 0x13, + WLDAP32_LDAP_ATTRIBUTE_OR_VALUE_EXISTS = 0x14, + WLDAP32_LDAP_INVALID_SYNTAX = 0x15, + + WLDAP32_LDAP_NO_SUCH_OBJECT = 0x20, + WLDAP32_LDAP_ALIAS_PROBLEM = 0x21, + WLDAP32_LDAP_INVALID_DN_SYNTAX = 0x22, + WLDAP32_LDAP_IS_LEAF = 0x23, + WLDAP32_LDAP_ALIAS_DEREF_PROBLEM = 0x24, + + WLDAP32_LDAP_INAPPROPRIATE_AUTH = 0x30, + WLDAP32_LDAP_INVALID_CREDENTIALS = 0x31, + WLDAP32_LDAP_INSUFFICIENT_RIGHTS = 0x32, + WLDAP32_LDAP_BUSY = 0x33, + WLDAP32_LDAP_UNAVAILABLE = 0x34, + WLDAP32_LDAP_UNWILLING_TO_PERFORM = 0x35, + WLDAP32_LDAP_LOOP_DETECT = 0x36, + WLDAP32_LDAP_SORT_CONTROL_MISSING = 0x3C, + WLDAP32_LDAP_OFFSET_RANGE_ERROR = 0x3D, + + WLDAP32_LDAP_NAMING_VIOLATION = 0x40, + WLDAP32_LDAP_OBJECT_CLASS_VIOLATION = 0x41, + WLDAP32_LDAP_NOT_ALLOWED_ON_NONLEAF = 0x42, + WLDAP32_LDAP_NOT_ALLOWED_ON_RDN = 0x43, + WLDAP32_LDAP_ALREADY_EXISTS = 0x44, + WLDAP32_LDAP_NO_OBJECT_CLASS_MODS = 0x45, + WLDAP32_LDAP_RESULTS_TOO_LARGE = 0x46, + WLDAP32_LDAP_AFFECTS_MULTIPLE_DSAS = 0x47, + + WLDAP32_LDAP_VIRTUAL_LIST_VIEW_ERROR = 0x4c, + + WLDAP32_LDAP_OTHER = 0x50, + WLDAP32_LDAP_SERVER_DOWN = 0x51, + WLDAP32_LDAP_LOCAL_ERROR = 0x52, + WLDAP32_LDAP_ENCODING_ERROR = 0x53, + WLDAP32_LDAP_DECODING_ERROR = 0x54, + WLDAP32_LDAP_TIMEOUT = 0x55, + WLDAP32_LDAP_AUTH_UNKNOWN = 0x56, + WLDAP32_LDAP_FILTER_ERROR = 0x57, + WLDAP32_LDAP_USER_CANCELLED = 0x58, + WLDAP32_LDAP_PARAM_ERROR = 0x59, + WLDAP32_LDAP_NO_MEMORY = 0x5a, + WLDAP32_LDAP_CONNECT_ERROR = 0x5b, + WLDAP32_LDAP_NOT_SUPPORTED = 0x5c, + WLDAP32_LDAP_CONTROL_NOT_FOUND = 0x5d, + WLDAP32_LDAP_NO_RESULTS_RETURNED = 0x5e, + WLDAP32_LDAP_MORE_RESULTS_TO_RETURN = 0x5f, + + WLDAP32_LDAP_CLIENT_LOOP = 0x60, + WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED = 0x61 +} WLDAP32_LDAP_RETCODE; + +#define WLDAP32_LDAP_SCOPE_BASE 0x00 +#define WLDAP32_LDAP_SCOPE_ONELEVEL 0x01 +#define WLDAP32_LDAP_SCOPE_SUBTREE 0x02 + +#define WLDAP32_LBER_USE_DER 0x01 + +#define WLDAP32_LDAP_OPT_API_INFO 0x00 +#define WLDAP32_LDAP_OPT_DESC 0x01 +#define WLDAP32_LDAP_OPT_DEREF 0x02 +#define WLDAP32_LDAP_OPT_SIZELIMIT 0x03 +#define WLDAP32_LDAP_OPT_TIMELIMIT 0x04 +#define WLDAP32_LDAP_OPT_THREAD_FN_PTRS 0x05 +#define WLDAP32_LDAP_OPT_REBIND_FN 0x06 +#define WLDAP32_LDAP_OPT_REBIND_ARG 0x07 +#define WLDAP32_LDAP_OPT_REFERRALS 0x08 +#define WLDAP32_LDAP_OPT_RESTART 0x09 +#define WLDAP32_LDAP_OPT_SSL 0x0a +#define WLDAP32_LDAP_OPT_IO_FN_PTRS 0x0b +#define WLDAP32_LDAP_OPT_CACHE_FN_PTRS 0x0d +#define WLDAP32_LDAP_OPT_CACHE_STRATEGY 0x0e +#define WLDAP32_LDAP_OPT_CACHE_ENABLE 0x0f +#define WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT 0x10 +#define WLDAP32_LDAP_OPT_PROTOCOL_VERSION 0x11 +#define WLDAP32_LDAP_OPT_VERSION 0x11 +#define WLDAP32_LDAP_OPT_SERVER_CONTROLS 0x12 +#define WLDAP32_LDAP_OPT_API_FEATURE_INFO 0x15 +#define WLDAP32_LDAP_OPT_HOST_NAME 0x30 +#define WLDAP32_LDAP_OPT_ERROR_NUMBER 0x31 +#define WLDAP32_LDAP_OPT_ERROR_STRING 0x32 +#define WLDAP32_LDAP_OPT_SERVER_ERROR 0x33 +#define WLDAP32_LDAP_OPT_SERVER_EXT_ERROR 0x34 +#define WLDAP32_LDAP_OPT_PING_KEEP_ALIVE 0x36 +#define WLDAP32_LDAP_OPT_PING_WAIT_TIME 0x37 +#define WLDAP32_LDAP_OPT_PING_LIMIT 0x38 +#define WLDAP32_LDAP_OPT_DNSDOMAIN_NAME 0x3b +#define WLDAP32_LDAP_OPT_GETDSNAME_FLAGS 0x3d +#define WLDAP32_LDAP_OPT_HOST_REACHABLE 0x3e +#define WLDAP32_LDAP_OPT_PROMPT_CREDENTIALS 0x3f +#define WLDAP32_LDAP_OPT_TCP_KEEPALIVE 0x40 +#define WLDAP32_LDAP_OPT_FAST_CONCURRENT_BIND 0x41 +#define WLDAP32_LDAP_OPT_SEND_TIMEOUT 0x42 +#define WLDAP32_LDAP_OPT_REFERRAL_CALLBACK 0x70 +#define WLDAP32_LDAP_OPT_CLIENT_CERTIFICATE 0x80 +#define WLDAP32_LDAP_OPT_SERVER_CERTIFICATE 0x81 +#define WLDAP32_LDAP_OPT_AUTO_RECONNECT 0x91 +#define WLDAP32_LDAP_OPT_SSPI_FLAGS 0x92 +#define WLDAP32_LDAP_OPT_SSL_INFO 0x93 +#define WLDAP32_LDAP_OPT_REF_DEREF_CONN_PER_MSG 0x94 +#define WLDAP32_LDAP_OPT_TLS LDAP_OPT_SSL +#define WLDAP32_LDAP_OPT_TLS_INFO LDAP_OPT_SSL_INFO +#define WLDAP32_LDAP_OPT_SIGN 0x95 +#define WLDAP32_LDAP_OPT_ENCRYPT 0x96 +#define WLDAP32_LDAP_OPT_SASL_METHOD 0x97 +#define WLDAP32_LDAP_OPT_AREC_EXCLUSIVE 0x98 +#define WLDAP32_LDAP_OPT_SECURITY_CONTEXT 0x99 +#define WLDAP32_LDAP_OPT_ROOTDSE_CACHE 0x9a + +#define WLDAP32_LDAP_OPT_ON ((void *)1) +#define WLDAP32_LDAP_OPT_OFF ((void *)0) + +#define WLDAP32_LDAP_VERSION1 1 +#define WLDAP32_LDAP_VERSION2 2 +#define WLDAP32_LDAP_VERSION3 3 +#define WLDAP32_LDAP_VERSION WLDAP32_LDAP_VERSION2 + +#define WLDAP32_LDAP_AUTH_SIMPLE 0x80 +#define WLDAP32_LDAP_AUTH_SASL 0x83 +#define WLDAP32_LDAP_AUTH_OTHERKIND 0x86 + +#define WLDAP32_LDAP_AUTH_EXTERNAL (WLDAP32_LDAP_AUTH_OTHERKIND | 0x0020) +#define WLDAP32_LDAP_AUTH_SICILY (WLDAP32_LDAP_AUTH_OTHERKIND | 0x0200) +#define WLDAP32_LDAP_AUTH_NEGOTIATE (WLDAP32_LDAP_AUTH_OTHERKIND | 0x0400) +#define WLDAP32_LDAP_AUTH_MSN (WLDAP32_LDAP_AUTH_OTHERKIND | 0x0800) +#define WLDAP32_LDAP_AUTH_NTLM (WLDAP32_LDAP_AUTH_OTHERKIND | 0x1000) +#define WLDAP32_LDAP_AUTH_DPA (WLDAP32_LDAP_AUTH_OTHERKIND | 0x2000) +#define WLDAP32_LDAP_AUTH_DIGEST (WLDAP32_LDAP_AUTH_OTHERKIND | 0x4000) + typedef struct WLDAP32_berelement { char *opaque;
From: Hans Leidekker hans@codeweavers.com
--- configure.ac | 28 +- dlls/wldap32/Makefile.in | 7 +- dlls/wldap32/add.c | 15 +- dlls/wldap32/ber.c | 166 +++---- dlls/wldap32/bind.c | 161 +++---- dlls/wldap32/compare.c | 33 +- dlls/wldap32/control.c | 34 +- dlls/wldap32/delete.c | 15 +- dlls/wldap32/dn.c | 55 +-- dlls/wldap32/error.c | 91 ++-- dlls/wldap32/extended.c | 38 +- dlls/wldap32/init.c | 18 +- dlls/wldap32/libldap.c | 683 ----------------------------- dlls/wldap32/libldap.h | 624 -------------------------- dlls/wldap32/main.c | 6 - dlls/wldap32/misc.c | 131 ++---- dlls/wldap32/modify.c | 23 +- dlls/wldap32/modrdn.c | 9 +- dlls/wldap32/option.c | 80 ++-- dlls/wldap32/page.c | 38 +- dlls/wldap32/parse.c | 88 ++-- dlls/wldap32/rename.c | 20 +- dlls/wldap32/search.c | 57 ++- dlls/wldap32/tests/ber.c | 2 +- dlls/wldap32/value.c | 40 +- dlls/wldap32/winldap_private.h | 776 +++++++++++++++++++++++---------- 26 files changed, 1061 insertions(+), 2177 deletions(-) delete mode 100644 dlls/wldap32/libldap.c delete mode 100644 dlls/wldap32/libldap.h
diff --git a/configure.ac b/configure.ac index 96a1712b0b7..035a01e2ef4 100644 --- a/configure.ac +++ b/configure.ac @@ -42,8 +42,6 @@ AC_ARG_WITH(gssapi, AS_HELP_STRING([--without-gssapi],[do not use GSSAPI (Ker AC_ARG_WITH(gstreamer, AS_HELP_STRING([--without-gstreamer],[do not use GStreamer (codecs support)])) AC_ARG_WITH(inotify, AS_HELP_STRING([--without-inotify],[do not use inotify (filesystem change notifications)])) AC_ARG_WITH(krb5, AS_HELP_STRING([--without-krb5],[do not use krb5 (Kerberos)])) -AC_ARG_WITH(ldap, AS_HELP_STRING([--without-ldap],[do not use LDAP]), - [if test "x$withval" = "xno"; then ac_cv_header_ldap_h=no; ac_cv_header_lber_h=no; fi]) AC_ARG_WITH(mingw, AS_HELP_STRING([--without-mingw],[do not use the MinGW cross-compiler])) AC_ARG_WITH(netapi, AS_HELP_STRING([--without-netapi],[do not use the Samba NetAPI library])) AC_ARG_WITH(opencl, AS_HELP_STRING([--without-opencl],[do not use OpenCL]), @@ -1183,6 +1181,7 @@ WINE_EXTLIB_FLAGS(GSM, gsm, gsm, "-I$(top_srcdir)/libs/gsm/inc") WINE_EXTLIB_FLAGS(JPEG, jpeg, jpeg, "-I$(top_srcdir)/libs/jpeg") WINE_EXTLIB_FLAGS(JXR, jxr, jxr, "-I$(top_srcdir)/libs/jxr/jxrgluelib -I$(top_srcdir)/libs/jxr/image/sys") WINE_EXTLIB_FLAGS(LCMS2, lcms2, lcms2, "-I$(top_srcdir)/libs/lcms2/include") +WINE_EXTLIB_FLAGS(LDAP, ldap, ldap, "-I$(top_srcdir)/libs/ldap/include") WINE_EXTLIB_FLAGS(MPG123, mpg123, mpg123, "-I$(top_srcdir)/libs/mpg123/src/libmpg123") WINE_EXTLIB_FLAGS(PNG, png, "png $(ZLIB_PE_LIBS)", "-I$(top_srcdir)/libs/png") WINE_EXTLIB_FLAGS(TIFF, tiff, "tiff $(ZLIB_PE_LIBS)", "-I$(top_srcdir)/libs/tiff/libtiff") @@ -2078,31 +2077,6 @@ case $host_os in ;; esac
-dnl **** Check for OpenLDAP *** -if test "x$with_ldap" != "xno" -then - dnl Actually there's no pkg-config support for ldap, but this way we can still override the flags - WINE_PACKAGE_FLAGS(LDAP,[openldap],[-lldap -llber],,, - [AC_CHECK_HEADERS([ldap.h lber.h]) - if test "$ac_cv_header_ldap_h" = "yes" -a "$ac_cv_header_lber_h" = "yes" - then - AC_CHECK_TYPE(LDAPSortKey, - [AC_CHECK_LIB(ldap, ldap_initialize, - [AC_CHECK_LIB(lber, ber_init, - [AC_DEFINE(HAVE_LDAP, 1, [Define if you have the OpenLDAP development environment])], - [LDAP_LIBS=""], - [$PTHREAD_LIBS $LDAP_LIBS])], - [LDAP_LIBS=""], - [$PTHREAD_LIBS $LDAP_LIBS])], - [LDAP_LIBS=""], - [#include <ldap.h>]) - else - LDAP_LIBS="" - fi]) -fi -WINE_NOTICE_WITH(ldap,[test "x$LDAP_LIBS" = "x"], - [libldap (OpenLDAP) ${notice_platform}development files not found, LDAP won't be supported.]) - AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, AC_LINK_IFELSE([AC_LANG_PROGRAM( [[#include <sched.h>]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) diff --git a/dlls/wldap32/Makefile.in b/dlls/wldap32/Makefile.in index 71e9d0ea2cb..ed8630e47af 100644 --- a/dlls/wldap32/Makefile.in +++ b/dlls/wldap32/Makefile.in @@ -1,9 +1,7 @@ MODULE = wldap32.dll -UNIXLIB = wldap32.so IMPORTLIB = wldap32 -IMPORTS = user32 -UNIX_CFLAGS = $(LDAP_CFLAGS) -UNIX_LIBS = $(LDAP_LIBS) +IMPORTS = $(LDAP_PE_LIBS) secur32 ws2_32 user32 +EXTRAINCL = $(LDAP_PE_CFLAGS)
C_SRCS = \ add.c \ @@ -16,7 +14,6 @@ C_SRCS = \ error.c \ extended.c \ init.c \ - libldap.c \ main.c \ misc.c \ modify.c \ diff --git a/dlls/wldap32/add.c b/dlls/wldap32/add.c index e12ed087e26..6fd0f82cf33 100644 --- a/dlls/wldap32/add.c +++ b/dlls/wldap32/add.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -105,8 +104,8 @@ ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW * { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPModU **attrsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPMod **attrsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls, message );
@@ -118,8 +117,7 @@ ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW * if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_add_ext_params params = { CTX(ld), dnU, attrsU, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_add_ext, ¶ms )); + ret = map_error( ldap_add_ext( CTX(ld), dnU, attrsU, serverctrlsU, clientctrlsU, (int *)message ) ); }
exit: @@ -168,8 +166,8 @@ ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPModU **attrsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPMod **attrsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls );
@@ -181,8 +179,7 @@ ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_add_ext_s_params params = { CTX(ld), dnU, attrsU, serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_add_ext_s, ¶ms )); + ret = map_error( ldap_add_ext_s( CTX(ld), dnU, attrsU, serverctrlsU, clientctrlsU ) ); }
exit: diff --git a/dlls/wldap32/ber.c b/dlls/wldap32/ber.c index 1dbc0cf6080..07013ad35ae 100644 --- a/dlls/wldap32/ber.c +++ b/dlls/wldap32/ber.c @@ -23,8 +23,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h" -#include "winber.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -37,17 +35,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); WLDAP32_BerElement * CDECL WLDAP32_ber_alloc_t( int options ) { WLDAP32_BerElement *ret; - struct ber_alloc_t_params params;
- if (!(ret = malloc( sizeof(*ret) ))) return NULL; - params.options = options; - params.ret = (void **)&BER(ret); - if (LDAP_CALL( ber_alloc_t, ¶ms )) - { - free( ret ); - return NULL; - } - return ret; + TRACE( "%d\n", options ); + + if (options != WLDAP32_LBER_USE_DER || !(ret = malloc( sizeof(*ret) ))) return NULL; + if ((ret->opaque = (char *)ber_alloc_t( options ))) return ret; + free( ret ); + return NULL; }
/*********************************************************************** @@ -55,6 +49,7 @@ WLDAP32_BerElement * CDECL WLDAP32_ber_alloc_t( int options ) */ BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL *berval ) { + TRACE( "%p\n", berval ); return bervalWtoW( berval ); }
@@ -63,6 +58,7 @@ BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL *berval ) */ void CDECL WLDAP32_ber_bvecfree( BERVAL **berval ) { + TRACE( "%p\n", berval ); bvarrayfreeW( berval ); }
@@ -71,6 +67,7 @@ void CDECL WLDAP32_ber_bvecfree( BERVAL **berval ) */ void CDECL WLDAP32_ber_bvfree( BERVAL *berval ) { + TRACE( "berval\n" ); free( berval ); }
@@ -79,8 +76,8 @@ void CDECL WLDAP32_ber_bvfree( BERVAL *berval ) */ ULONG CDECL WLDAP32_ber_first_element( WLDAP32_BerElement *ber, ULONG *len, char **opaque ) { - struct ber_first_element_params params = { BER(ber), (unsigned int *)len, opaque }; - return LDAP_CALL( ber_first_element, ¶ms ); + TRACE( "%p, %p, %p\n", ber, len, opaque ); + return ber_first_element( BER(ber), len, opaque ); }
/*********************************************************************** @@ -88,15 +85,14 @@ ULONG CDECL WLDAP32_ber_first_element( WLDAP32_BerElement *ber, ULONG *len, char */ int CDECL WLDAP32_ber_flatten( WLDAP32_BerElement *ber, BERVAL **berval ) { - struct bervalU *bervalU; - struct berval *bervalW; - struct ber_flatten_params params = { BER(ber), &bervalU }; + struct berval *bervalU; + struct WLDAP32_berval *bervalW;
- if (LDAP_CALL( ber_flatten, ¶ms )) return WLDAP32_LBER_ERROR; + TRACE( "%p, %p\n", ber, berval );
+ if (ber_flatten( BER(ber), &bervalU )) return WLDAP32_LBER_ERROR; if (!(bervalW = bervalUtoW( bervalU ))) return WLDAP32_LBER_ERROR; - LDAP_CALL( ber_bvfree, bervalU ); - if (!bervalW) return WLDAP32_LBER_ERROR; + ber_bvfree( bervalU ); *berval = bervalW; return 0; } @@ -106,8 +102,8 @@ int CDECL WLDAP32_ber_flatten( WLDAP32_BerElement *ber, BERVAL **berval ) */ void CDECL WLDAP32_ber_free( WLDAP32_BerElement *ber, int freebuf ) { - struct ber_free_params params = { BER(ber), freebuf }; - LDAP_CALL( ber_free, ¶ms ); + TRACE( "%p, %d\n", ber, freebuf ); + ber_free( BER(ber), freebuf ); free( ber ); }
@@ -116,9 +112,11 @@ void CDECL WLDAP32_ber_free( WLDAP32_BerElement *ber, int freebuf ) */ WLDAP32_BerElement * CDECL WLDAP32_ber_init( BERVAL *berval ) { - struct bervalU *bervalU; + struct berval *bervalU; WLDAP32_BerElement *ret; - struct ber_init_params params; + BerElement *ber; + + TRACE( "%p\n", berval );
if (!(ret = malloc( sizeof(*ret) ))) return NULL; if (!(bervalU = bervalWtoU( berval ))) @@ -126,15 +124,12 @@ WLDAP32_BerElement * CDECL WLDAP32_ber_init( BERVAL *berval ) free( ret ); return NULL; } - params.berval = bervalU; - params.ret = (void **)&BER(ret); - if (LDAP_CALL( ber_init, ¶ms )) - { - free( ret ); - ret = NULL; - } + + ber = ber_init( bervalU ); free( bervalU ); - return ret; + if ((ret->opaque = (char *)ber)) return ret; + free( ret ); + return NULL; }
/*********************************************************************** @@ -142,8 +137,8 @@ WLDAP32_BerElement * CDECL WLDAP32_ber_init( BERVAL *berval ) */ ULONG CDECL WLDAP32_ber_next_element( WLDAP32_BerElement *ber, ULONG *len, char *opaque ) { - struct ber_next_element_params params = { BER(ber), (unsigned int *)len, opaque }; - return LDAP_CALL( ber_next_element, ¶ms ); + TRACE( "%p, %p, %p\n", ber, len, opaque ); + return ber_next_element( BER(ber), len, opaque ); }
/*********************************************************************** @@ -151,8 +146,8 @@ ULONG CDECL WLDAP32_ber_next_element( WLDAP32_BerElement *ber, ULONG *len, char */ ULONG CDECL WLDAP32_ber_peek_tag( WLDAP32_BerElement *ber, ULONG *len ) { - struct ber_peek_tag_params params = { BER(ber), (unsigned int *)len }; - return LDAP_CALL( ber_peek_tag, ¶ms ); + TRACE( "%p, %p\n", ber, len ); + return ber_peek_tag( BER(ber), len ); }
/*********************************************************************** @@ -160,8 +155,8 @@ ULONG CDECL WLDAP32_ber_peek_tag( WLDAP32_BerElement *ber, ULONG *len ) */ ULONG CDECL WLDAP32_ber_skip_tag( WLDAP32_BerElement *ber, ULONG *len ) { - struct ber_skip_tag_params params = { BER(ber), (unsigned int *)len }; - return LDAP_CALL( ber_skip_tag, ¶ms ); + TRACE( "%p, %p\n", ber, len ); + return ber_skip_tag( BER(ber), len ); }
/*********************************************************************** @@ -173,53 +168,61 @@ int WINAPIV WLDAP32_ber_printf( WLDAP32_BerElement *ber, char *fmt, ... ) int ret = 0; char new_fmt[2];
+ TRACE( "%p(%p), %s\n", ber, ber->opaque, fmt ); + new_fmt[1] = 0; va_start( list, fmt ); while (*fmt) { - struct ber_printf_params params = { BER(ber), new_fmt }; new_fmt[0] = *fmt++; switch (new_fmt[0]) { case 'b': case 'e': case 'i': - params.arg1 = va_arg( list, int ); - ret = LDAP_CALL( ber_printf, ¶ms ); + { + int arg = va_arg( list, int ); + ret = ber_printf( BER(ber), new_fmt, arg ); break; + } case 'o': case 's': - params.arg1 = (ULONG_PTR)va_arg( list, char * ); - ret = LDAP_CALL( ber_printf, ¶ms ); + { + char *arg = va_arg( list, char * ); + ret = ber_printf( BER(ber), new_fmt, arg ); break; + } case 't': - params.arg1 = va_arg( list, unsigned int ); - ret = LDAP_CALL( ber_printf, ¶ms ); + { + unsigned int arg = va_arg( list, unsigned int ); + ret = ber_printf( BER(ber), new_fmt, arg ); break; + } case 'v': - params.arg1 = (ULONG_PTR)va_arg( list, char ** ); - ret = LDAP_CALL( ber_printf, ¶ms ); + { + char **arg = va_arg( list, char ** ); + ret = ber_printf( BER(ber), new_fmt, arg ); break; + } case 'V': { - struct berval **array = va_arg( list, struct berval ** ); - struct bervalU **arrayU; + struct WLDAP32_berval **array = va_arg( list, struct WLDAP32_berval ** ); + struct berval **arrayU; if (!(arrayU = bvarrayWtoU( array ))) { ret = -1; break; } - params.arg1 = (ULONG_PTR)arrayU; - ret = LDAP_CALL( ber_printf, ¶ms ); + ret = ber_printf( BER(ber), new_fmt, arrayU ); bvarrayfreeU( arrayU ); break; } case 'X': { - params.arg1 = (ULONG_PTR)va_arg( list, char * ); - params.arg2 = va_arg( list, int ); + char *arg = va_arg( list, char * ); + int arg2 = va_arg( list, int ); new_fmt[0] = 'B'; /* 'X' is deprecated */ - ret = LDAP_CALL( ber_printf, ¶ms ); + ret = ber_printf( BER(ber), new_fmt, arg, arg2 ); break; } case 'n': @@ -227,7 +230,7 @@ int WINAPIV WLDAP32_ber_printf( WLDAP32_BerElement *ber, char *fmt, ... ) case '}': case '[': case ']': - ret = LDAP_CALL( ber_printf, ¶ms ); + ret = ber_printf( BER(ber), new_fmt ); break;
default: @@ -250,78 +253,77 @@ ULONG WINAPIV WLDAP32_ber_scanf( WLDAP32_BerElement *ber, char *fmt, ... ) int ret = 0; char new_fmt[2];
+ TRACE( "%p, %s\n", ber, fmt ); + new_fmt[1] = 0; va_start( list, fmt ); while (*fmt) { - struct ber_scanf_params params = { BER(ber), new_fmt }; new_fmt[0] = *fmt++; switch (new_fmt[0]) { case 'a': { char *str, **ptr = va_arg( list, char ** ); - params.arg1 = &str; - if ((ret = LDAP_CALL( ber_scanf, ¶ms )) == -1) break; + if ((ret = ber_scanf( BER(ber), new_fmt, &str )) == -1) break; *ptr = strdupU( str ); - LDAP_CALL( ldap_memfree, str ); + ldap_memfree( str ); break; } case 'b': case 'e': case 'i': - params.arg1 = va_arg( list, int * ); - ret = LDAP_CALL( ber_scanf, ¶ms ); + { + int *arg = va_arg( list, int * ); + ret = ber_scanf( BER(ber), new_fmt, arg ); break; + } case 't': - params.arg1 = va_arg( list, unsigned int * ); - ret = LDAP_CALL( ber_scanf, ¶ms ); + { + unsigned int *arg = va_arg( list, unsigned int * ); + ret = ber_scanf( BER(ber), new_fmt, arg ); break; + } case 'v': { char *str, **arrayU, **ptr, ***array = va_arg( list, char *** ); - params.arg1 = &arrayU; - if ((ret = LDAP_CALL( ber_scanf, ¶ms )) == -1) break; + if ((ret = ber_scanf( BER(ber), new_fmt, &arrayU )) == -1) break; *array = strarrayUtoU( arrayU ); ptr = arrayU; while ((str = *ptr)) { - LDAP_CALL( ldap_memfree, str ); + ldap_memfree( str ); ptr++; } - LDAP_CALL( ldap_memfree, arrayU ); + ldap_memfree( arrayU ); break; } case 'B': { char *strU, **str = va_arg( list, char ** ); int *len = va_arg( list, int * ); - params.arg1 = &strU; - params.arg2 = len; - if ((ret = LDAP_CALL( ber_scanf, ¶ms )) == -1) break; + if ((ret = ber_scanf( BER(ber), new_fmt, &strU, len )) == -1) break; *str = malloc( *len ); memcpy( *str, strU, *len ); - LDAP_CALL( ldap_memfree, strU ); + ldap_memfree( strU ); break; } case 'O': { - struct berval **berval = va_arg( list, struct berval ** ); - struct bervalU *bervalU; - params.arg1 = &bervalU; - if ((ret = LDAP_CALL( ber_scanf, ¶ms )) == -1) break; + struct WLDAP32_berval **berval = va_arg( list, struct WLDAP32_berval ** ); + struct berval *bervalU; + if ((ret = ber_scanf( BER(ber), new_fmt, &bervalU )) == -1) break; *berval = bervalUtoW( bervalU ); - LDAP_CALL( ber_bvfree, bervalU ); + ber_bvfree( bervalU ); break; } case 'V': { - struct berval ***array = va_arg( list, struct berval *** ); - struct bervalU **arrayU; - params.arg1 = &arrayU; - if ((ret = LDAP_CALL( ber_scanf, ¶ms )) == -1) break; + struct WLDAP32_berval ***array = va_arg( list, struct WLDAP32_berval *** ); + struct berval **arrayU; + if ((ret = ber_scanf( BER(ber), new_fmt, &arrayU )) == -1) break; *array = bvarrayUtoW( arrayU ); - LDAP_CALL( ber_bvecfree, arrayU ); + ber_bvecfree( arrayU ); break; } case 'n': @@ -330,7 +332,7 @@ ULONG WINAPIV WLDAP32_ber_scanf( WLDAP32_BerElement *ber, char *fmt, ... ) case '}': case '[': case ']': - ret = LDAP_CALL( ber_scanf, ¶ms ); + ret = ber_scanf( BER(ber), new_fmt ); break;
default: diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index 83b878a88b3..5441aeba6c7 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -24,7 +24,6 @@ #include "winbase.h" #include "winnls.h" #include "rpc.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -61,7 +60,7 @@ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *credU = NULL; - struct bervalU pwd = { 0, NULL }; + struct berval pwd = { 0, NULL }; int msg;
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_w(dn), cred, method ); @@ -77,10 +76,7 @@ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) pwd.bv_val = credU; }
- { - struct ldap_sasl_bind_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg }; - ret = map_error( LDAP_CALL( ldap_sasl_bind, ¶ms )); - } + ret = map_error( ldap_sasl_bind( CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg ) ); if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else @@ -122,6 +118,54 @@ exit: return ret; }
+#define SASL_CB_LIST_END 0 +#define SASL_CB_AUTHNAME 0x4002 +#define SASL_CB_PASS 0x4004 +#define SASL_CB_GETREALM 0x4008 + +struct sasl_interact +{ + unsigned long id; + const char *challenge; + const char *prompt; + const char *defresult; + const void *result; + unsigned int len; +}; + +static int interact_callback( LDAP *ld, unsigned flags, void *defaults, void *sasl_interact ) +{ + SEC_WINNT_AUTH_IDENTITY_W *id = defaults; + struct sasl_interact *ptr = sasl_interact; + + TRACE( "%p, %08xlx, %p, %p\n", ld, flags, defaults, sasl_interact ); + + while (ptr && ptr->id != SASL_CB_LIST_END) + { + switch (ptr->id) + { + case SASL_CB_AUTHNAME: + ptr->result = id->User; + ptr->len = id->UserLength; + break; + case SASL_CB_GETREALM: + ptr->result = id->Domain; + ptr->len = id->DomainLength; + break; + case SASL_CB_PASS: + ptr->result = id->Password; + ptr->len = id->PasswordLength; + break; + default: + ERR( "unexpected callback %#lx\n", ptr->id ); + return -1; + } + ptr++; + } + + return 0; +} + /*********************************************************************** * ldap_bind_sW (WLDAP32.@) */ @@ -129,7 +173,7 @@ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *credU = NULL; - struct bervalU pwd = { 0, NULL }; + struct berval pwd = { 0, NULL };
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_w(dn), cred, method );
@@ -145,51 +189,28 @@ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) pwd.bv_val = credU; }
- { - struct ldap_sasl_bind_s_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, NULL }; - ret = map_error( LDAP_CALL( ldap_sasl_bind_s, ¶ms )); - } + ret = map_error( ldap_sasl_bind_s( CTX(ld), dnU, 0, &pwd, NULL, NULL, NULL ) ); } else if (method == WLDAP32_LDAP_AUTH_NEGOTIATE) { - SEC_WINNT_AUTH_IDENTITY_A idU; - SEC_WINNT_AUTH_IDENTITY_W idW; - SEC_WINNT_AUTH_IDENTITY_W *id = (SEC_WINNT_AUTH_IDENTITY_W *)cred; - - memset( &idU, 0, sizeof(idU) ); - if (id) - { - if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI) - { - idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - idW.Domain = (unsigned short *)strnAtoW( (char *)id->Domain, id->DomainLength, &idW.DomainLength ); - idW.User = (unsigned short *)strnAtoW( (char *)id->User, id->UserLength, &idW.UserLength ); - idW.Password = (unsigned short *)strnAtoW( (char *)id->Password, id->PasswordLength, &idW.PasswordLength ); - id = &idW; - } - idU.Domain = (unsigned char *)strnWtoU( id->Domain, id->DomainLength, &idU.DomainLength ); - idU.User = (unsigned char *)strnWtoU( id->User, id->UserLength, &idU.UserLength ); - idU.Password = (unsigned char *)strnWtoU( id->Password, id->PasswordLength, &idU.PasswordLength ); - } + SEC_WINNT_AUTH_IDENTITY_W *id = (SEC_WINNT_AUTH_IDENTITY_W *)cred, idW;
+ if (id && (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)) { - struct ldap_sasl_interactive_bind_s_params params = { CTX(ld), - NULL /* server will ignore DN anyway */, - NULL /* query supportedSASLMechanisms */, - NULL, NULL, 2 /* LDAP_SASL_QUIET */, &idU }; - ret = map_error( LDAP_CALL( ldap_sasl_interactive_bind_s, ¶ms )); + idW.User = (unsigned short *)strnAtoW( (char *)id->User, id->UserLength, &idW.UserLength ); + idW.Domain = (unsigned short *)strnAtoW( (char *)id->Domain, id->DomainLength, &idW.DomainLength ); + idW.Password = (unsigned short *)strnAtoW( (char *)id->Password, id->PasswordLength, &idW.PasswordLength ); + id = &idW; }
+ ret = map_error( ldap_sasl_interactive_bind_s( CTX(ld), NULL, NULL, NULL, NULL, LDAP_SASL_QUIET, + interact_callback, id ) ); if (id && (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)) { - free( (WCHAR *)idW.Domain ); - free( (WCHAR *)idW.User ); - free( (WCHAR *)idW.Password ); + free( idW.User ); + free( idW.Domain ); + free( idW.Password ); } - - free( (char *)idU.Domain ); - free( (char *)idU.User ); - free( (char *)idU.Password ); } else { @@ -207,7 +228,7 @@ exit: * ldap_sasl_bindA (WLDAP32.@) */ ULONG CDECL ldap_sasl_bindA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, - LDAPControlA **serverctrls, LDAPControlA **clientctrls, int *message ) + LDAPControlA **serverctrls, LDAPControlA **clientctrls, int *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW, *mechanismW = NULL; @@ -237,12 +258,12 @@ exit: * ldap_sasl_bindW (WLDAP32.@) */ ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, - LDAPControlW **serverctrls, LDAPControlW **clientctrls, int *message ) + LDAPControlW **serverctrls, LDAPControlW **clientctrls, int *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU, *mechanismU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU credU; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval credU;
TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(mechanism), cred, serverctrls, clientctrls, message ); @@ -255,10 +276,9 @@ ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_sasl_bind_params params = { CTX(ld), dnU, mechanismU, &credU, serverctrlsU, clientctrlsU, message }; credU.bv_len = cred->bv_len; credU.bv_val = cred->bv_val; - ret = map_error( LDAP_CALL( ldap_sasl_bind, ¶ms )); + ret = map_error( ldap_sasl_bind( CTX(ld), dnU, mechanismU, &credU, serverctrlsU, clientctrlsU, message) ); }
exit: @@ -273,7 +293,7 @@ exit: * ldap_sasl_bind_sA (WLDAP32.@) */ ULONG CDECL ldap_sasl_bind_sA( LDAP *ld, const PCHAR dn, const PCHAR mechanism, const BERVAL *cred, - LDAPControlA **serverctrls, LDAPControlA **clientctrls, BERVAL **serverdata ) + LDAPControlA **serverctrls, LDAPControlA **clientctrls, BERVAL **serverdata ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW, *mechanismW = NULL; @@ -303,12 +323,12 @@ exit: * ldap_sasl_bind_sW (WLDAP32.@) */ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, - LDAPControlW **serverctrls, LDAPControlW **clientctrls, BERVAL **serverdata ) + LDAPControlW **serverctrls, LDAPControlW **clientctrls, BERVAL **serverdata ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU, *mechanismU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU *dataU, credU; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval *dataU, credU;
TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(mechanism), cred, serverctrls, clientctrls, serverdata ); @@ -322,17 +342,14 @@ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism
credU.bv_len = cred->bv_len; credU.bv_val = cred->bv_val; + ret = map_error( ldap_sasl_bind_s( CTX(ld), dnU, mechanismU, &credU, serverctrlsU, clientctrlsU, &dataU ) );
- { - struct ldap_sasl_bind_s_params params = { CTX(ld), dnU, mechanismU, &credU, serverctrlsU, clientctrlsU, &dataU }; - ret = map_error( LDAP_CALL( ldap_sasl_bind_s, ¶ms )); - } if (ret == WLDAP32_LDAP_SUCCESS) { BERVAL *ptr; if (!(ptr = bervalUtoW( dataU ))) ret = WLDAP32_LDAP_NO_MEMORY; else *serverdata = ptr; - LDAP_CALL( ber_bvfree, dataU ); + ber_bvfree( dataU ); }
exit: @@ -373,7 +390,7 @@ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *passwdU = NULL; - struct bervalU pwd = { 0, NULL }; + struct berval pwd = { 0, NULL }; int msg;
TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), passwd ); @@ -388,10 +405,7 @@ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) pwd.bv_val = passwdU; }
- { - struct ldap_sasl_bind_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg }; - ret = map_error( LDAP_CALL( ldap_sasl_bind, ¶ms )); - } + ret = map_error( ldap_sasl_bind( CTX(ld), dnU, 0, &pwd, NULL, NULL, &msg ) ); if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else @@ -433,7 +447,7 @@ ULONG CDECL ldap_simple_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *passwdU = NULL; - struct bervalU pwd = { 0, NULL }; + struct berval pwd = { 0, NULL };
TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), passwd );
@@ -447,10 +461,7 @@ ULONG CDECL ldap_simple_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) pwd.bv_val = passwdU; }
- { - struct ldap_sasl_bind_s_params params = { CTX(ld), dnU, 0, &pwd, NULL, NULL, NULL }; - ret = map_error( LDAP_CALL( ldap_sasl_bind_s, ¶ms )); - } + ret = map_error( ldap_sasl_bind_s( CTX(ld), dnU, 0, &pwd, NULL, NULL, NULL ) );
exit: free( dnU ); @@ -467,14 +478,10 @@ ULONG CDECL WLDAP32_ldap_unbind( LDAP *ld )
TRACE( "(%p)\n", ld );
- if (ld) - { - struct ldap_unbind_ext_params params = { CTX(ld), NULL, NULL }; - ret = map_error( LDAP_CALL( ldap_unbind_ext, ¶ms )); - } + if (ld) ret = map_error( ldap_unbind_ext( CTX(ld), NULL, NULL ) ); else return WLDAP32_LDAP_PARAM_ERROR;
- if (SERVER_CTRLS(ld)) LDAP_CALL( ldap_value_free_len, SERVER_CTRLS(ld) ); + if (SERVER_CTRLS(ld)) ldap_value_free_len( SERVER_CTRLS(ld) );
free( ld ); return ret; @@ -489,14 +496,10 @@ ULONG CDECL WLDAP32_ldap_unbind_s( LDAP *ld )
TRACE( "(%p)\n", ld );
- if (ld) - { - struct ldap_unbind_ext_s_params params = { CTX(ld), NULL, NULL }; - ret = map_error( LDAP_CALL( ldap_unbind_ext_s, ¶ms )); - } + if (ld) ret = map_error( ldap_unbind_ext_s( CTX(ld), NULL, NULL ) ); else return WLDAP32_LDAP_PARAM_ERROR;
- if (SERVER_CTRLS(ld)) LDAP_CALL( ldap_value_free_len, SERVER_CTRLS(ld) ); + if (SERVER_CTRLS(ld)) ldap_value_free_len( SERVER_CTRLS(ld) );
free( ld ); return ret; diff --git a/dlls/wldap32/compare.c b/dlls/wldap32/compare.c index f5bae71e09a..c7fb83a3723 100644 --- a/dlls/wldap32/compare.c +++ b/dlls/wldap32/compare.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -71,9 +70,8 @@ ULONG CDECL ldap_compareW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value ) /*********************************************************************** * ldap_compare_extA (WLDAP32.@) */ -ULONG CDECL ldap_compare_extA( LDAP *ld, char *dn, char *attr, char *value, - struct berval *data, LDAPControlA **serverctrls, LDAPControlA **clientctrls, - ULONG *message ) +ULONG CDECL ldap_compare_extA( LDAP *ld, char *dn, char *attr, char *value, struct WLDAP32_berval *data, + LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *attrW = NULL, *valueW = NULL; @@ -104,13 +102,13 @@ exit: /*********************************************************************** * ldap_compare_extW (WLDAP32.@) */ -ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, - LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) +ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct WLDAP32_berval *data, + LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *attrU = NULL, *valueU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU *dataU = NULL, val = { 0, NULL }; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval *dataU = NULL, val = { 0, NULL };
TRACE( "(%p, %s, %s, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(attr), debugstr_w(value), data, serverctrls, clientctrls, message ); @@ -135,8 +133,8 @@ ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, s if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_compare_ext_params params = { CTX(ld), dnU, attrU, dataU ? dataU : &val, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_compare_ext, ¶ms )); + ret = map_error( ldap_compare_ext( CTX(ld), dnU, attrU, dataU ? dataU : &val, serverctrlsU, clientctrlsU, + (int *)message ) ); }
exit: @@ -152,8 +150,8 @@ exit: /*********************************************************************** * ldap_compare_ext_sA (WLDAP32.@) */ -ULONG CDECL ldap_compare_ext_sA( LDAP *ld, char *dn, char *attr, char *value, struct berval *data, - LDAPControlA **serverctrls, LDAPControlA **clientctrls ) +ULONG CDECL ldap_compare_ext_sA( LDAP *ld, char *dn, char *attr, char *value, struct WLDAP32_berval *data, + LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *attrW = NULL, *valueW = NULL; @@ -184,13 +182,13 @@ exit: /*********************************************************************** * ldap_compare_ext_sW (WLDAP32.@) */ -ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct berval *data, - LDAPControlW **serverctrls, LDAPControlW **clientctrls ) +ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct WLDAP32_berval *data, + LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *attrU = NULL, *valueU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU *dataU = NULL, val = { 0, NULL }; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval *dataU = NULL, val = { 0, NULL };
TRACE( "(%p, %s, %s, %s, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(attr), debugstr_w(value), data, serverctrls, clientctrls ); @@ -214,8 +212,7 @@ ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_compare_ext_s_params params = { CTX(ld), dnU, attrU, dataU ? dataU : &val, serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_compare_ext_s, ¶ms )); + ret = map_error( ldap_compare_ext_s( CTX(ld), dnU, attrU, dataU ? dataU : &val, serverctrlsU, clientctrlsU ) ); } exit: free( dnU ); diff --git a/dlls/wldap32/control.c b/dlls/wldap32/control.c index 41aa64cf292..746ef6049ce 100644 --- a/dlls/wldap32/control.c +++ b/dlls/wldap32/control.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -103,26 +102,22 @@ ULONG CDECL ldap_create_sort_controlA( LDAP *ld, LDAPSortKeyA **sortkey, UCHAR c ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR critical, LDAPControlW **control ) { ULONG ret; - LDAPSortKeyU **sortkeyU; - LDAPControlU *controlU; + LDAPSortKey **sortkeyU; + LDAPControl *controlU;
TRACE( "(%p, %p, 0x%02x, %p)\n", ld, sortkey, critical, control );
if (!ld || !sortkey || !control) return WLDAP32_LDAP_PARAM_ERROR;
- if ((sortkeyU = sortkeyarrayWtoU( sortkey ))) - { - struct ldap_create_sort_control_params params = { CTX(ld), sortkeyU, critical, &controlU }; - ret = map_error( LDAP_CALL( ldap_create_sort_control, ¶ms )); - } - else return WLDAP32_LDAP_NO_MEMORY; + if (!(sortkeyU = sortkeyarrayWtoU( sortkey ))) return WLDAP32_LDAP_NO_MEMORY;
+ ret = map_error( ldap_create_sort_control( CTX(ld), sortkeyU, critical, &controlU ) ); if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlW *controlW = controlUtoW( controlU ); if (controlW) *control = controlW; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_control_free, controlU ); + ldap_control_free( controlU ); }
sortkeyarrayfreeU( sortkeyU ); @@ -132,7 +127,7 @@ ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR c /*********************************************************************** * ldap_create_vlv_controlA (WLDAP32.@) */ -INT CDECL ldap_create_vlv_controlA( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, LDAPControlA **control ) +INT CDECL ldap_create_vlv_controlA( LDAP *ld, WLDAP32_LDAPVLVInfo *info, UCHAR critical, LDAPControlA **control ) { INT ret; LDAPControlW *controlW; @@ -156,35 +151,32 @@ INT CDECL ldap_create_vlv_controlA( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, /*********************************************************************** * ldap_create_vlv_controlW (WLDAP32.@) */ -INT CDECL ldap_create_vlv_controlW( LDAP *ld, LDAPVLVInfo *info, UCHAR critical, LDAPControlW **control ) +INT CDECL ldap_create_vlv_controlW( LDAP *ld, WLDAP32_LDAPVLVInfo *info, UCHAR critical, LDAPControlW **control ) { ULONG ret; - LDAPVLVInfoU *infoU = NULL; - LDAPControlU *controlU; + LDAPVLVInfo *infoU = NULL; + LDAPControl *controlU;
TRACE( "(%p, %p, 0x%02x, %p)\n", ld, info, critical, control );
if (!ld || !control) return ~0u;
if (info && !(infoU = vlvinfoWtoU( info ))) return WLDAP32_LDAP_NO_MEMORY; - else - { - struct ldap_create_vlv_control_params params = { CTX(ld), infoU, &controlU }; - ret = map_error( LDAP_CALL( ldap_create_vlv_control, ¶ms )); - } + + ret = map_error( ldap_create_vlv_control( CTX(ld), infoU, &controlU ) ); if (ret == WLDAP32_LDAP_SUCCESS) { LDAPControlW *controlW = controlUtoW( controlU ); if (controlW) *control = controlW; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_control_free, controlU ); + ldap_control_free( controlU ); }
vlvinfofreeU( infoU ); return ret; }
-static inline void bv_val_dup( const struct berval *src, struct berval *dst ) +static inline void bv_val_dup( const struct WLDAP32_berval *src, struct WLDAP32_berval *dst ) { if ((dst->bv_val = RtlAllocateHeap( GetProcessHeap(), 0 , src->bv_len ))) { diff --git a/dlls/wldap32/delete.c b/dlls/wldap32/delete.c index be5bb36a851..b085142d83d 100644 --- a/dlls/wldap32/delete.c +++ b/dlls/wldap32/delete.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -65,7 +64,7 @@ ULONG CDECL ldap_deleteW( LDAP *ld, WCHAR *dn ) * ldap_delete_extA (WLDAP32.@) */ ULONG CDECL ldap_delete_extA( LDAP *ld, char *dn, LDAPControlA **serverctrls, LDAPControlA **clientctrls, - ULONG *message ) + ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; @@ -92,11 +91,11 @@ exit: * ldap_delete_extW (WLDAP32.@) */ ULONG CDECL ldap_delete_extW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls, - ULONG *message ) + ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls, message );
@@ -107,8 +106,7 @@ ULONG CDECL ldap_delete_extW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, L if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_delete_ext_params params = { CTX(ld), dnU, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_delete_ext, ¶ms )); + ret = map_error( ldap_delete_ext( CTX(ld), dnU, serverctrlsU, clientctrlsU, (int *)message ) ); }
exit: @@ -151,7 +149,7 @@ ULONG CDECL ldap_delete_ext_sW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls );
@@ -162,8 +160,7 @@ ULONG CDECL ldap_delete_ext_sW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_delete_ext_s_params params = { CTX(ld), dnU, serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_delete_ext_s, ¶ms )); + ret = map_error( ldap_delete_ext_s( CTX(ld), dnU, serverctrlsU, clientctrlsU ) ); }
exit: diff --git a/dlls/wldap32/dn.c b/dlls/wldap32/dn.c index 3003fec71e3..c2e523d68d6 100644 --- a/dlls/wldap32/dn.c +++ b/dlls/wldap32/dn.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -34,16 +33,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); */ char * CDECL ldap_dn2ufnA( char *dn ) { - char *ret; + char *ret = NULL; WCHAR *dnW, *retW;
TRACE( "(%s)\n", debugstr_a(dn) );
if (!(dnW = strAtoW( dn ))) return NULL; - - retW = ldap_dn2ufnW( dnW ); - ret = strWtoA( retW ); - + if ((retW = ldap_dn2ufnW( dnW ))) ret = strWtoA( retW ); free( dnW ); ldap_memfreeW( retW ); return ret; @@ -59,16 +55,10 @@ WCHAR * CDECL ldap_dn2ufnW( WCHAR *dn )
TRACE( "(%s)\n", debugstr_w(dn) );
- if ((dnU = strWtoU( dn ))) - { - struct ldap_dn2ufn_params params = { dnU, &retU }; - LDAP_CALL( ldap_dn2ufn, ¶ms ); - - ret = strUtoW( retU ); - - free( dnU ); - LDAP_CALL( ldap_memfree, retU ); - } + if (!(dnU = strWtoU( dn ))) return NULL; + if ((retU = ldap_dn2ufn( dnU ))) ret = strUtoW( retU ); + free( dnU ); + ldap_memfree( retU ); return ret; }
@@ -77,16 +67,13 @@ WCHAR * CDECL ldap_dn2ufnW( WCHAR *dn ) */ char ** CDECL ldap_explode_dnA( char *dn, ULONG notypes ) { - char **ret; + char **ret = NULL; WCHAR *dnW, **retW;
TRACE( "(%s, %#lx)\n", debugstr_a(dn), notypes );
if (!(dnW = strAtoW( dn ))) return NULL; - - retW = ldap_explode_dnW( dnW, notypes ); - ret = strarrayWtoA( retW ); - + if ((retW = ldap_explode_dnW( dnW, notypes ))) ret = strarrayWtoA( retW ); free( dnW ); ldap_value_freeW( retW ); return ret; @@ -102,15 +89,10 @@ WCHAR ** CDECL ldap_explode_dnW( WCHAR *dn, ULONG notypes )
TRACE( "(%s, %#lx)\n", debugstr_w(dn), notypes );
- if ((dnU = strWtoU( dn ))) - { - struct ldap_explode_dn_params params = { dnU, notypes, &retU }; - LDAP_CALL( ldap_explode_dn, ¶ms ); - ret = strarrayUtoW( retU ); - - free( dnU ); - LDAP_CALL( ldap_memvfree, retU ); - } + if (!(dnU = strWtoU( dn ))) return NULL; + if ((retU = ldap_explode_dn( dnU, notypes ))) ret = strarrayUtoW( retU ); + free( dnU ); + ldap_memvfree( (void **)retU ); return ret; }
@@ -119,16 +101,14 @@ WCHAR ** CDECL ldap_explode_dnW( WCHAR *dn, ULONG notypes ) */ char * CDECL ldap_get_dnA( LDAP *ld, LDAPMessage *entry ) { - char *ret; + char *ret = NULL; WCHAR *retW;
TRACE( "(%p, %p)\n", ld, entry );
if (!ld || !entry) return NULL;
- retW = ldap_get_dnW( ld, entry ); - - ret = strWtoA( retW ); + if ((retW = ldap_get_dnW( ld, entry ))) ret = strWtoA( retW ); ldap_memfreeW( retW ); return ret; } @@ -145,11 +125,8 @@ WCHAR * CDECL ldap_get_dnW( LDAP *ld, LDAPMessage *entry )
if (ld && entry) { - struct ldap_get_dn_params params = { CTX(ld), MSG(entry), &retU }; - LDAP_CALL( ldap_get_dn, ¶ms ); - - ret = strUtoW( retU ); - LDAP_CALL( ldap_memfree, retU ); + if ((retU = ldap_get_dn( CTX(ld), MSG(entry) ))) ret = strUtoW( retU ); + ldap_memfree( retU ); } return ret; } diff --git a/dlls/wldap32/error.c b/dlls/wldap32/error.c index 80c7bd48bf8..c8897165d1d 100644 --- a/dlls/wldap32/error.c +++ b/dlls/wldap32/error.c @@ -23,7 +23,6 @@ #include "winbase.h" #include "winuser.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -36,25 +35,69 @@ ULONG map_error( int error ) { switch (error) { - case 0: return WLDAP32_LDAP_SUCCESS; - case -1: return WLDAP32_LDAP_SERVER_DOWN; - case -2: return WLDAP32_LDAP_LOCAL_ERROR; - case -3: return WLDAP32_LDAP_ENCODING_ERROR; - case -4: return WLDAP32_LDAP_DECODING_ERROR; - case -5: return WLDAP32_LDAP_TIMEOUT; - case -6: return WLDAP32_LDAP_AUTH_UNKNOWN; - case -7: return WLDAP32_LDAP_FILTER_ERROR; - case -8: return WLDAP32_LDAP_USER_CANCELLED; - case -9: return WLDAP32_LDAP_PARAM_ERROR; - case -10: return WLDAP32_LDAP_NO_MEMORY; - case -11: return WLDAP32_LDAP_CONNECT_ERROR; - case -12: return WLDAP32_LDAP_NOT_SUPPORTED; - case -13: return WLDAP32_LDAP_CONTROL_NOT_FOUND; - case -14: return WLDAP32_LDAP_NO_RESULTS_RETURNED; - case -15: return WLDAP32_LDAP_MORE_RESULTS_TO_RETURN; - case -16: return WLDAP32_LDAP_CLIENT_LOOP; - case -17: return WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED; - default: return error; + case LDAP_SUCCESS: return WLDAP32_LDAP_SUCCESS; + case LDAP_OPERATIONS_ERROR: return WLDAP32_LDAP_OPERATIONS_ERROR; + case LDAP_PROTOCOL_ERROR: return WLDAP32_LDAP_PROTOCOL_ERROR; + case LDAP_TIMELIMIT_EXCEEDED: return WLDAP32_LDAP_TIMELIMIT_EXCEEDED; + case LDAP_SIZELIMIT_EXCEEDED: return WLDAP32_LDAP_SIZELIMIT_EXCEEDED; + case LDAP_COMPARE_FALSE: return WLDAP32_LDAP_COMPARE_FALSE; + case LDAP_COMPARE_TRUE: return WLDAP32_LDAP_COMPARE_TRUE; + case LDAP_AUTH_METHOD_NOT_SUPPORTED: return WLDAP32_LDAP_AUTH_METHOD_NOT_SUPPORTED; + case LDAP_STRONG_AUTH_REQUIRED: return WLDAP32_LDAP_STRONG_AUTH_REQUIRED; + case LDAP_PARTIAL_RESULTS: return WLDAP32_LDAP_PARTIAL_RESULTS; + case LDAP_REFERRAL: return WLDAP32_LDAP_REFERRAL; + case LDAP_ADMINLIMIT_EXCEEDED: return WLDAP32_LDAP_ADMIN_LIMIT_EXCEEDED; + case LDAP_UNAVAILABLE_CRITICAL_EXTENSION: return WLDAP32_LDAP_UNAVAILABLE_CRIT_EXTENSION; + case LDAP_CONFIDENTIALITY_REQUIRED: return WLDAP32_LDAP_CONFIDENTIALITY_REQUIRED; + case LDAP_SASL_BIND_IN_PROGRESS: return WLDAP32_LDAP_SASL_BIND_IN_PROGRESS; + case LDAP_NO_SUCH_ATTRIBUTE: return WLDAP32_LDAP_NO_SUCH_ATTRIBUTE; + case LDAP_UNDEFINED_TYPE: return WLDAP32_LDAP_UNDEFINED_TYPE; + case LDAP_INAPPROPRIATE_MATCHING: return WLDAP32_LDAP_INAPPROPRIATE_MATCHING; + case LDAP_CONSTRAINT_VIOLATION: return WLDAP32_LDAP_CONSTRAINT_VIOLATION; + case LDAP_TYPE_OR_VALUE_EXISTS: return WLDAP32_LDAP_ATTRIBUTE_OR_VALUE_EXISTS; + case LDAP_INVALID_SYNTAX: return WLDAP32_LDAP_INVALID_SYNTAX; + case LDAP_NO_SUCH_OBJECT: return WLDAP32_LDAP_NO_SUCH_OBJECT; + case LDAP_ALIAS_PROBLEM: return WLDAP32_LDAP_ALIAS_PROBLEM; + case LDAP_INVALID_DN_SYNTAX: return WLDAP32_LDAP_INVALID_DN_SYNTAX; + case LDAP_IS_LEAF: return WLDAP32_LDAP_IS_LEAF; + case LDAP_ALIAS_DEREF_PROBLEM: return WLDAP32_LDAP_ALIAS_DEREF_PROBLEM; + case LDAP_INAPPROPRIATE_AUTH: return WLDAP32_LDAP_INAPPROPRIATE_AUTH; + case LDAP_INVALID_CREDENTIALS: return WLDAP32_LDAP_INVALID_CREDENTIALS; + case LDAP_INSUFFICIENT_ACCESS: return WLDAP32_LDAP_INSUFFICIENT_RIGHTS; + case LDAP_BUSY: return WLDAP32_LDAP_BUSY; + case LDAP_UNAVAILABLE: return WLDAP32_LDAP_UNAVAILABLE; + case LDAP_UNWILLING_TO_PERFORM: return WLDAP32_LDAP_UNWILLING_TO_PERFORM; + case LDAP_LOOP_DETECT: return WLDAP32_LDAP_LOOP_DETECT; + case LDAP_NAMING_VIOLATION: return WLDAP32_LDAP_NAMING_VIOLATION; + case LDAP_OBJECT_CLASS_VIOLATION: return WLDAP32_LDAP_OBJECT_CLASS_VIOLATION; + case LDAP_NOT_ALLOWED_ON_NONLEAF: return WLDAP32_LDAP_NOT_ALLOWED_ON_NONLEAF; + case LDAP_NOT_ALLOWED_ON_RDN: return WLDAP32_LDAP_NOT_ALLOWED_ON_RDN; + case LDAP_ALREADY_EXISTS: return WLDAP32_LDAP_ALREADY_EXISTS; + case LDAP_NO_OBJECT_CLASS_MODS: return WLDAP32_LDAP_NO_OBJECT_CLASS_MODS; + case LDAP_RESULTS_TOO_LARGE: return WLDAP32_LDAP_RESULTS_TOO_LARGE; + case LDAP_AFFECTS_MULTIPLE_DSAS: return WLDAP32_LDAP_AFFECTS_MULTIPLE_DSAS; + case LDAP_VLV_ERROR: return WLDAP32_LDAP_VIRTUAL_LIST_VIEW_ERROR; + case LDAP_OTHER: return WLDAP32_LDAP_OTHER; + case LDAP_SERVER_DOWN: return WLDAP32_LDAP_SERVER_DOWN; + case LDAP_LOCAL_ERROR: return WLDAP32_LDAP_LOCAL_ERROR; + case LDAP_ENCODING_ERROR: return WLDAP32_LDAP_ENCODING_ERROR; + case LDAP_DECODING_ERROR: return WLDAP32_LDAP_DECODING_ERROR; + case LDAP_TIMEOUT: return WLDAP32_LDAP_TIMEOUT; + case LDAP_AUTH_UNKNOWN: return WLDAP32_LDAP_AUTH_UNKNOWN; + case LDAP_FILTER_ERROR: return WLDAP32_LDAP_FILTER_ERROR; + case LDAP_USER_CANCELLED: return WLDAP32_LDAP_USER_CANCELLED; + case LDAP_PARAM_ERROR: return WLDAP32_LDAP_PARAM_ERROR; + case LDAP_NO_MEMORY: return WLDAP32_LDAP_NO_MEMORY; + case LDAP_CONNECT_ERROR: return WLDAP32_LDAP_CONNECT_ERROR; + case LDAP_NOT_SUPPORTED: return WLDAP32_LDAP_NOT_SUPPORTED; + case LDAP_CONTROL_NOT_FOUND: return WLDAP32_LDAP_CONTROL_NOT_FOUND; + case LDAP_NO_RESULTS_RETURNED: return WLDAP32_LDAP_NO_RESULTS_RETURNED; + case LDAP_MORE_RESULTS_TO_RETURN: return WLDAP32_LDAP_MORE_RESULTS_TO_RETURN; + case LDAP_CLIENT_LOOP: return WLDAP32_LDAP_CLIENT_LOOP; + case LDAP_REFERRAL_LIMIT_EXCEEDED: return WLDAP32_LDAP_REFERRAL_LIMIT_EXCEEDED; + default: + FIXME( "no mapping for %d\n", error ); + return error; } }
@@ -109,11 +152,9 @@ ULONG CDECL WLDAP32_ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG free )
TRACE( "(%p, %p, %#lx)\n", ld, res, free );
- if (ld && res) - { - struct ldap_parse_result_params params = { CTX(ld), MSG(res), &error, NULL, NULL, NULL, NULL, free }; - if (!LDAP_CALL( ldap_parse_result, ¶ms )) return error; - } + if (ld && res && !ldap_parse_result( CTX(ld), MSG(res), &error, NULL, NULL, NULL, NULL, free )) + return error; + return ~0u; }
diff --git a/dlls/wldap32/extended.c b/dlls/wldap32/extended.c index fead8e1b075..fad2a3d42d4 100644 --- a/dlls/wldap32/extended.c +++ b/dlls/wldap32/extended.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -43,8 +42,8 @@ ULONG CDECL ldap_close_extended_op( LDAP *ld, ULONG msgid ) /*********************************************************************** * ldap_extended_operationA (WLDAP32.@) */ -ULONG CDECL ldap_extended_operationA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, - LDAPControlA **clientctrls, ULONG *message ) +ULONG CDECL ldap_extended_operationA( LDAP *ld, char *oid, struct WLDAP32_berval *data, LDAPControlA **serverctrls, + LDAPControlA **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *oidW = NULL; @@ -70,13 +69,13 @@ exit: /*********************************************************************** * ldap_extended_operationW (WLDAP32.@) */ -ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, - LDAPControlW **clientctrls, ULONG *message ) +ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct WLDAP32_berval *data, LDAPControlW **serverctrls, + LDAPControlW **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *oidU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU *dataU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval *dataU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, message );
@@ -88,8 +87,7 @@ ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct berval *data, if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_extended_operation_params params = { CTX(ld), oidU, dataU, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_extended_operation, ¶ms )); + ret = map_error( ldap_extended_operation( CTX(ld), oidU, dataU, serverctrlsU, clientctrlsU, (int *)message ) ); }
exit: @@ -103,8 +101,8 @@ exit: /*********************************************************************** * ldap_extended_operation_sA (WLDAP32.@) */ -ULONG CDECL ldap_extended_operation_sA( LDAP *ld, char *oid, struct berval *data, LDAPControlA **serverctrls, - LDAPControlA **clientctrls, char **retoid, struct berval **retdata ) +ULONG CDECL ldap_extended_operation_sA( LDAP *ld, char *oid, struct WLDAP32_berval *data, LDAPControlA **serverctrls, + LDAPControlA **clientctrls, char **retoid, struct WLDAP32_berval **retdata ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *oidW = NULL, *retoidW = NULL; @@ -137,13 +135,13 @@ exit: /*********************************************************************** * ldap_extended_operation_sW (WLDAP32.@) */ -ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *data, LDAPControlW **serverctrls, - LDAPControlW **clientctrls, WCHAR **retoid, struct berval **retdata ) +ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct WLDAP32_berval *data, LDAPControlW **serverctrls, + LDAPControlW **clientctrls, WCHAR **retoid, struct WLDAP32_berval **retdata ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *oidU = NULL, *retoidU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct bervalU *retdataU, *dataU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct berval *retdataU, *dataU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, retoid, retdata );
@@ -155,8 +153,8 @@ ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *dat if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_extended_operation_s_params params = { CTX(ld), oidU, dataU, serverctrlsU, clientctrlsU, &retoidU, &retdataU }; - ret = map_error( LDAP_CALL( ldap_extended_operation_s, ¶ms )); + ret = map_error( ldap_extended_operation_s( CTX(ld), oidU, dataU, serverctrlsU, clientctrlsU, &retoidU, + &retdataU ) ); }
if (retoid && retoidU) @@ -164,14 +162,14 @@ ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct berval *dat WCHAR *str = strUtoW( retoidU ); if (str) *retoid = str; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_memfree, retoidU ); + ldap_memfree( retoidU ); } if (retdata && retdataU) { - struct berval *bv = bervalUtoW( retdataU ); + struct WLDAP32_berval *bv = bervalUtoW( retdataU ); if (bv) *retdata = bv; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ber_bvfree, retdataU ); + ber_bvfree( retdataU ); }
exit: diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index a17b14a635c..512c558936d 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -24,7 +24,6 @@ #include "winbase.h" #include "winnls.h" #include "winternl.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -194,15 +193,11 @@ static LDAP *create_context( const char *url ) { LDAP *ld; int version = WLDAP32_LDAP_VERSION3; - struct ldap_initialize_params params;
if (!(ld = calloc( 1, sizeof( *ld )))) return NULL; - params.ld = &CTX(ld); - params.url = url; - if (map_error( LDAP_CALL( ldap_initialize, ¶ms )) == WLDAP32_LDAP_SUCCESS) + if (map_error( ldap_initialize( &CTX(ld), url ) ) == WLDAP32_LDAP_SUCCESS) { - struct ldap_set_option_params opt_params = { CTX(ld), WLDAP32_LDAP_OPT_PROTOCOL_VERSION, &version }; - LDAP_CALL( ldap_set_option, &opt_params ); + ldap_set_option( CTX(ld), WLDAP32_LDAP_OPT_PROTOCOL_VERSION, &version ); return ld; } free( ld ); @@ -385,7 +380,7 @@ exit: * ldap_start_tls_sA (WLDAP32.@) */ ULONG CDECL ldap_start_tls_sA( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlA **serverctrls, - LDAPControlA **clientctrls ) + LDAPControlA **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL; @@ -409,10 +404,10 @@ exit: * ldap_start_tls_s (WLDAP32.@) */ ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlW **serverctrls, - LDAPControlW **clientctrls ) + LDAPControlW **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls ); if (result) @@ -427,8 +422,7 @@ ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LD if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_start_tls_s_params params = { CTX(ld), serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_start_tls_s, ¶ms )); + ret = map_error( ldap_start_tls_s( CTX(ld), serverctrlsU, clientctrlsU ) ); }
exit: diff --git a/dlls/wldap32/libldap.c b/dlls/wldap32/libldap.c deleted file mode 100644 index 592e526ecdc..00000000000 --- a/dlls/wldap32/libldap.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Unix interface for libldap - * - * Copyright 2021 Hans Leidekker for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#if 0 -#pragma makedep unix -#endif - -#include "config.h" - -#ifdef HAVE_LDAP -#include <assert.h> -#include <stdarg.h> -#include <sys/time.h> -#ifdef HAVE_LDAP_H -# include <ldap.h> -#endif -#ifdef HAVE_SASL_SASL_H -# include <sasl/sasl.h> -#endif - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winternl.h" -#include "winbase.h" - -#include "wine/debug.h" -#include "libldap.h" - -WINE_DEFAULT_DEBUG_CHANNEL(wldap32); - -C_ASSERT( sizeof(BerValueU) == sizeof(BerValue) ); -C_ASSERT( sizeof(LDAPModU) == sizeof(LDAPMod) ); -C_ASSERT( sizeof(LDAPControlU) == sizeof(LDAPControl) ); -C_ASSERT( sizeof(LDAPSortKeyU) == sizeof(LDAPSortKey) ); -C_ASSERT( sizeof(LDAPVLVInfoU) == sizeof(LDAPVLVInfo) ); -C_ASSERT( sizeof(LDAPAPIInfoU) == sizeof(LDAPAPIInfo) ); -C_ASSERT( sizeof(LDAPAPIFeatureInfoU) == sizeof(LDAPAPIFeatureInfo) ); - -static struct timeval *convert_timeval(const struct timevalU *tvu, struct timeval *tv) -{ - if (!tvu) return NULL; - tv->tv_sec = tvu->tv_sec; - tv->tv_usec = tvu->tv_usec; - return tv; -} - -#define WLDAP32_LBER_ERROR (~0l) - -static LDAPMod *nullmods[] = { NULL }; - -static NTSTATUS wrap_ber_alloc_t( void *args ) -{ - struct ber_alloc_t_params *params = args; - *params->ret = ber_alloc_t( params->options ); - return *params->ret ? LDAP_SUCCESS : WLDAP32_LBER_ERROR; -} - -static NTSTATUS wrap_ber_bvecfree( void *args ) -{ - ber_bvecfree( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ber_bvfree( void *args ) -{ - ber_bvfree( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ber_first_element( void *args ) -{ - struct ber_first_element_params *params = args; - ber_len_t len; - ber_tag_t ret; - - if ((ret = ber_first_element( params->ber, &len, params->last )) == LBER_ERROR) - return WLDAP32_LBER_ERROR; - if (ret > ~0u) - { - ERR( "ret too large\n" ); - return WLDAP32_LBER_ERROR; - } - if (len > ~0u) - { - ERR( "len too large\n" ); - return WLDAP32_LBER_ERROR; - } - - *params->ret_len = len; - return ret; -} - -static NTSTATUS wrap_ber_flatten( void *args ) -{ - struct ber_flatten_params *params = args; - return ber_flatten( params->ber, (struct berval **)params->berval ); -} - -static NTSTATUS wrap_ber_free( void *args ) -{ - struct ber_free_params *params = args; - - ber_free( params->ber, params->freebuf ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ber_init( void *args ) -{ - struct ber_init_params *params = args; - *params->ret = ber_init( (struct berval *)params->berval ); - return *params->ret ? LDAP_SUCCESS : WLDAP32_LBER_ERROR; -} - -static NTSTATUS wrap_ber_next_element( void *args ) -{ - struct ber_next_element_params *params = args; - ber_len_t len; - ber_tag_t ret; - - if ((ret = ber_next_element( params->ber, &len, params->last )) == LBER_ERROR) - return WLDAP32_LBER_ERROR; - if (ret > ~0u) - { - ERR( "ret too large\n" ); - return WLDAP32_LBER_ERROR; - } - if (len > ~0u) - { - ERR( "len too large\n" ); - return WLDAP32_LBER_ERROR; - } - - *params->ret_len = len; - return ret; -} - -static NTSTATUS wrap_ber_peek_tag( void *args ) -{ - struct ber_peek_tag_params *params = args; - ber_len_t len; - ber_tag_t ret; - - if ((ret = ber_peek_tag( params->ber, &len )) == LBER_ERROR) return WLDAP32_LBER_ERROR; - if (len > ~0u) - { - ERR( "len too large\n" ); - return WLDAP32_LBER_ERROR; - } - - *params->ret_len = len; - return ret; -} - -static NTSTATUS wrap_ber_skip_tag( void *args ) -{ - struct ber_skip_tag_params *params = args; - ber_len_t len; - ber_tag_t ret; - - if ((ret = ber_skip_tag( params->ber, &len )) == LBER_ERROR) return WLDAP32_LBER_ERROR; - if (len > ~0u) - { - ERR( "len too large\n" ); - return WLDAP32_LBER_ERROR; - } - - *params->ret_len = len; - return ret; -} - -static NTSTATUS wrap_ber_printf( void *args ) -{ - struct ber_printf_params *params = args; - - assert( strlen(params->fmt) == 1 ); - - return ber_printf( params->ber, params->fmt, params->arg1, params->arg2 ); -} - -static NTSTATUS wrap_ber_scanf( void *args ) -{ - struct ber_scanf_params *params = args; - - assert( strlen(params->fmt) == 1 ); - - return ber_scanf( params->ber, params->fmt, params->arg1, params->arg2 ); -} - -static NTSTATUS wrap_ldap_abandon_ext( void *args ) -{ - struct ldap_abandon_ext_params *params = args; - return ldap_abandon_ext( params->ld, params->msgid, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_add_ext( void *args ) -{ - struct ldap_add_ext_params *params = args; - int dummy; - return ldap_add_ext( params->ld, params->dn ? params->dn : "", - params->attrs ? (LDAPMod **)params->attrs : nullmods, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls, - params->msg ? (int *)params->msg : &dummy ); -} - -static NTSTATUS wrap_ldap_add_ext_s( void *args ) -{ - struct ldap_add_ext_s_params *params = args; - return ldap_add_ext_s( params->ld, params->dn ? params->dn : "", - params->attrs ? (LDAPMod **)params->attrs : nullmods, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_compare_ext( void *args ) -{ - struct ldap_compare_ext_params *params = args; - int dummy; - return ldap_compare_ext( params->ld, params->dn ? params->dn : "", params->attrs ? params->attrs : "", - (struct berval *)params->value, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, params->msg ? (int *)params->msg : &dummy ); -} - -static NTSTATUS wrap_ldap_compare_ext_s( void *args ) -{ - struct ldap_compare_ext_s_params *params = args; - return ldap_compare_ext_s( params->ld, params->dn ? params->dn : "", params->attrs ? params->attrs : "", - (struct berval *)params->value, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_control_free( void *args ) -{ - ldap_control_free( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ldap_controls_free( void *args ) -{ - ldap_controls_free( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ldap_count_entries( void *args ) -{ - struct ldap_count_entries_params *params = args; - return ldap_count_entries( params->ld, params->chain ); -} - -static NTSTATUS wrap_ldap_count_references( void *args ) -{ - struct ldap_count_references_params *params = args; - return ldap_count_references( params->ld, params->chain ); -} - -static NTSTATUS wrap_ldap_count_values_len( void *args ) -{ - return ldap_count_values_len( args ); -} - -static NTSTATUS wrap_ldap_create_sort_control( void *args ) -{ - struct ldap_create_sort_control_params *params = args; - return ldap_create_sort_control( params->ld, (LDAPSortKey **)params->keylist, params->critical, - (LDAPControl **)params->control ); -} - -static NTSTATUS wrap_ldap_create_vlv_control( void *args ) -{ - struct ldap_create_vlv_control_params *params = args; - return ldap_create_vlv_control( params->ld, (LDAPVLVInfo *)params->info, - (LDAPControl **)params->control ); -} - -static NTSTATUS wrap_ldap_delete_ext( void *args ) -{ - struct ldap_delete_ext_params *params = args; - int dummy; - return ldap_delete_ext( params->ld, params->dn ? params->dn : "", (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, params->msg ? (int *)params->msg : &dummy ); -} - -static NTSTATUS wrap_ldap_delete_ext_s( void *args ) -{ - struct ldap_delete_ext_s_params *params = args; - return ldap_delete_ext_s( params->ld, params->dn ? params->dn : "", (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_dn2ufn( void *args ) -{ - struct ldap_dn2ufn_params *params = args; - *params->ret = ldap_dn2ufn( params->dn ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_explode_dn( void *args ) -{ - struct ldap_explode_dn_params *params = args; - *params->ret = ldap_explode_dn( params->dn, params->notypes ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_extended_operation( void *args ) -{ - struct ldap_extended_operation_params *params = args; - int dummy; - return ldap_extended_operation( params->ld, params->oid ? params->oid : "", - (struct berval *)params->data, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, - params->msg ? (int *)params->msg : &dummy ); -} - -static NTSTATUS wrap_ldap_extended_operation_s( void *args ) -{ - struct ldap_extended_operation_s_params *params = args; - return ldap_extended_operation_s( params->ld, params->oid ? params->oid : "", - (struct berval *)params->data, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, params->retoid, - (struct berval **)params->retdata ); -} - -static NTSTATUS wrap_ldap_get_dn( void *args ) -{ - struct ldap_get_dn_params *params = args; - *params->ret = ldap_get_dn( params->ld, params->entry ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_first_attribute( void *args ) -{ - struct ldap_first_attribute_params *params = args; - *params->ret = ldap_first_attribute( params->ld, params->entry, (BerElement **)params->ber ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_first_entry( void *args ) -{ - struct ldap_first_entry_params *params = args; - *params->ret = ldap_first_entry( params->ld, params->chain ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_first_reference( void *args ) -{ - struct ldap_first_reference_params *params = args; - *params->ret = ldap_first_reference( params->ld, params->chain ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_get_option( void *args ) -{ - struct ldap_get_option_params *params = args; - return ldap_get_option( params->ld, params->option, params->value ); -} - -static NTSTATUS wrap_ldap_get_values_len( void *args ) -{ - struct ldap_get_values_len_params *params = args; - *params->ret = (struct bervalU **)ldap_get_values_len( params->ld, params->entry, params->attr ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_initialize( void *args ) -{ - struct ldap_initialize_params *params = args; - return ldap_initialize( (LDAP **)params->ld, params->url ); -} - -static NTSTATUS wrap_ldap_memfree( void *args ) -{ - ldap_memfree( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ldap_memvfree( void *args ) -{ - ldap_memvfree( args ); - return STATUS_SUCCESS; -} - -static NTSTATUS wrap_ldap_modify_ext( void *args ) -{ - struct ldap_modify_ext_params *params = args; - int dummy; - return ldap_modify_ext( params->ld, params->dn ? params->dn : "", - params->mods ? (LDAPMod **)params->mods : nullmods, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls, - params->msg ? (int *)params->msg : &dummy ); -} - -static NTSTATUS wrap_ldap_modify_ext_s( void *args ) -{ - struct ldap_modify_ext_s_params *params = args; - return ldap_modify_ext_s( params->ld, params->dn ? params->dn : "", - params->mods ? (LDAPMod **)params->mods : nullmods, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_msgfree( void *args ) -{ - return ldap_msgfree( args ); -} - -static NTSTATUS wrap_ldap_next_attribute( void *args ) -{ - struct ldap_next_attribute_params *params = args; - *params->ret = ldap_next_attribute( params->ld, params->entry, params->ber ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_next_entry( void *args ) -{ - struct ldap_next_entry_params *params = args; - *params->ret = ldap_next_entry( params->ld, params->entry ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_next_reference( void *args ) -{ - struct ldap_next_reference_params *params = args; - *params->ret = ldap_next_reference( params->ld, params->entry ); - return *params->ret ? 0 : -1; -} - -static NTSTATUS wrap_ldap_parse_extended_result( void *args ) -{ - struct ldap_parse_extended_result_params *params = args; - return ldap_parse_extended_result( params->ld, params->result, params->retoid, - (struct berval **)params->retdata, params->free ); -} - -static NTSTATUS wrap_ldap_parse_reference( void *args ) -{ - struct ldap_parse_reference_params *params = args; - return ldap_parse_reference( params->ld, params->ref, params->referrals, - (LDAPControl ***)params->serverctrls, params->free ); -} - -static NTSTATUS wrap_ldap_parse_result( void *args ) -{ - struct ldap_parse_result_params *params = args; - return ldap_parse_result( params->ld, params->res, params->errcode, params->matcheddn, params->errmsg, - params->referrals, (LDAPControl ***)params->serverctrls, params->free ); -} - -static NTSTATUS wrap_ldap_parse_sortresponse_control( void *args ) -{ - struct ldap_parse_sortresponse_control_params *params = args; - return ldap_parse_sortresponse_control( params->ld, (LDAPControl *)params->ctrl, - params->result, params->attr ); -} - -static NTSTATUS wrap_ldap_parse_vlvresponse_control( void *args ) -{ - struct ldap_parse_vlvresponse_control_params *params = args; - return ldap_parse_vlvresponse_control( params->ld, (LDAPControl *)params->ctrls, params->target_pos, - params->list_count, (struct berval **)params->ctx, - params->errcode ); -} - -static NTSTATUS wrap_ldap_rename( void *args ) -{ - struct ldap_rename_params *params = args; - return ldap_rename( params->ld, params->dn ? params->dn : "", params->newrdn, params->newparent, - params->delete, (LDAPControl **)params->clientctrls, - (LDAPControl **)params->serverctrls, (int *)params->msg ); -} - -static NTSTATUS wrap_ldap_rename_s( void *args ) -{ - struct ldap_rename_s_params *params = args; - return ldap_rename_s( params->ld, params->dn ? params->dn : "", params->newrdn, params->newparent, - params->delete, (LDAPControl **)params->clientctrls, - (LDAPControl **)params->serverctrls ); -} - -static NTSTATUS wrap_ldap_result( void *args ) -{ - struct ldap_result_params *params = args; - struct timeval tv; - return ldap_result( params->ld, params->msgid, params->all, - convert_timeval(params->timeout, &tv), (LDAPMessage **)params->result ); -} - -static NTSTATUS wrap_ldap_sasl_bind( void *args ) -{ - struct ldap_sasl_bind_params *params = args; - return ldap_sasl_bind( params->ld, params->dn, params->mech, (struct berval *)params->cred, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls, - params->msgid ); -} - -static NTSTATUS wrap_ldap_sasl_bind_s( void *args ) -{ - struct ldap_sasl_bind_s_params *params = args; - return ldap_sasl_bind_s( params->ld, params->dn, params->mech, (struct berval *)params->cred, - (LDAPControl **)params->serverctrls, (LDAPControl **)params->clientctrls, - (struct berval **)params->servercred ); -} - -static int wrap_sasl_interact( LDAP *ld, unsigned int flags, void *defaults, void *interact ) -{ -#ifdef HAVE_SASL_SASL_H - struct sasl_interactive_bind_id *id = defaults; - struct sasl_interact *sasl = interact; - - TRACE( "(%p, 0x%08x, %p, %p)\n", ld, flags, defaults, interact ); - - while (sasl->id != SASL_CB_LIST_END) - { - TRACE( "sasl->id = %04lx\n", sasl->id ); - - if (sasl->id == SASL_CB_GETREALM) - { - sasl->result = id->domain; - sasl->len = id->domain_len; - } - else if (sasl->id == SASL_CB_USER) - { - sasl->result = id->user; - sasl->len = id->user_len; - } - else if (sasl->id == SASL_CB_PASS) - { - sasl->result = id->password; - sasl->len = id->password_len; - } - sasl++; - } - - return LDAP_SUCCESS; -#endif - return -1; -} - -static NTSTATUS wrap_ldap_sasl_interactive_bind_s( void *args ) -{ - struct ldap_sasl_interactive_bind_s_params *params = args; - return ldap_sasl_interactive_bind_s( params->ld, params->dn, params->mech, - (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, params->flags, - wrap_sasl_interact, params->defaults ); -} - -static NTSTATUS wrap_ldap_search_ext( void *args ) -{ - struct ldap_search_ext_params *params = args; - struct timeval tv; - return ldap_search_ext( params->ld, params->base, params->scope, params->filter, params->attrs, - params->attrsonly, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, convert_timeval(params->timeout, &tv), - params->sizelimit, (int *)params->msg ); -} - -static NTSTATUS wrap_ldap_search_ext_s( void *args ) -{ - struct ldap_search_ext_s_params *params = args; - struct timeval tv; - return ldap_search_ext_s( params->ld, params->base, params->scope, params->filter, params->attrs, - params->attrsonly, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls, convert_timeval(params->timeout, &tv), - params->sizelimit, (LDAPMessage **)params->result ); -} - -static NTSTATUS wrap_ldap_set_option( void *args ) -{ - struct ldap_set_option_params *params = args; - return ldap_set_option( params->ld, params->option, params->value ); -} - -static NTSTATUS wrap_ldap_start_tls_s( void *args ) -{ - struct ldap_start_tls_s_params *params = args; - return ldap_start_tls_s( params->ld, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_unbind_ext( void *args ) -{ - struct ldap_unbind_ext_params *params = args; - return ldap_unbind_ext( params->ld, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_unbind_ext_s( void *args ) -{ - struct ldap_unbind_ext_s_params *params = args; - return ldap_unbind_ext_s( params->ld, (LDAPControl **)params->serverctrls, - (LDAPControl **)params->clientctrls ); -} - -static NTSTATUS wrap_ldap_value_free_len( void *args ) -{ - ldap_value_free_len( args ); - return STATUS_SUCCESS; -} - -unixlib_entry_t __wine_unix_call_funcs[] = -{ - wrap_ber_alloc_t, - wrap_ber_bvecfree, - wrap_ber_bvfree, - wrap_ber_first_element, - wrap_ber_flatten, - wrap_ber_free, - wrap_ber_init, - wrap_ber_next_element, - wrap_ber_peek_tag, - wrap_ber_printf, - wrap_ber_scanf, - wrap_ber_skip_tag, - wrap_ldap_abandon_ext, - wrap_ldap_add_ext, - wrap_ldap_add_ext_s, - wrap_ldap_compare_ext, - wrap_ldap_compare_ext_s, - wrap_ldap_control_free, - wrap_ldap_controls_free, - wrap_ldap_count_entries, - wrap_ldap_count_references, - wrap_ldap_count_values_len, - wrap_ldap_create_sort_control, - wrap_ldap_create_vlv_control, - wrap_ldap_delete_ext, - wrap_ldap_delete_ext_s, - wrap_ldap_dn2ufn, - wrap_ldap_explode_dn, - wrap_ldap_extended_operation, - wrap_ldap_extended_operation_s, - wrap_ldap_first_attribute, - wrap_ldap_first_entry, - wrap_ldap_first_reference, - wrap_ldap_get_dn, - wrap_ldap_get_option, - wrap_ldap_get_values_len, - wrap_ldap_initialize, - wrap_ldap_memfree, - wrap_ldap_memvfree, - wrap_ldap_modify_ext, - wrap_ldap_modify_ext_s, - wrap_ldap_msgfree, - wrap_ldap_next_attribute, - wrap_ldap_next_entry, - wrap_ldap_next_reference, - wrap_ldap_parse_extended_result, - wrap_ldap_parse_reference, - wrap_ldap_parse_result, - wrap_ldap_parse_sortresponse_control, - wrap_ldap_parse_vlvresponse_control, - wrap_ldap_rename, - wrap_ldap_rename_s, - wrap_ldap_result, - wrap_ldap_sasl_bind, - wrap_ldap_sasl_bind_s, - wrap_ldap_sasl_interactive_bind_s, - wrap_ldap_search_ext, - wrap_ldap_search_ext_s, - wrap_ldap_set_option, - wrap_ldap_start_tls_s, - wrap_ldap_unbind_ext, - wrap_ldap_unbind_ext_s, - wrap_ldap_value_free_len, -}; - -#endif /* HAVE_LDAP */ diff --git a/dlls/wldap32/libldap.h b/dlls/wldap32/libldap.h deleted file mode 100644 index 65487f16fe6..00000000000 --- a/dlls/wldap32/libldap.h +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright 2021 Hans Leidekker for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "wine/unixlib.h" - -/* compatible with structures defined in ldap.h */ -typedef struct bervalU -{ - ULONG_PTR bv_len; - char *bv_val; -} BerValueU; - -typedef struct -{ - int mod_op; - char *mod_type; - union - { - char **modv_strvals; - struct bervalU **modv_bvals; - } mod_vals; -} LDAPModU; - -typedef struct -{ - char *ldctl_oid; - struct bervalU ldctl_value; - char ldctl_iscritical; -} LDAPControlU; - -typedef struct -{ - char *attributeType; - char *orderingRule; - int reverseOrder; -} LDAPSortKeyU; - -typedef struct -{ - int ldvlv_version; - int ldvlv_before_count; - int ldvlv_after_count; - int ldvlv_offset; - int ldvlv_count; - struct bervalU *ldvlv_attrvalue; - struct bervalU *ldvlv_context; - void *ldvlv_extradata; -} LDAPVLVInfoU; - -typedef struct -{ - int ldapai_info_version; - int ldapai_api_version; - int ldapai_protocol_version; - char **ldapai_extensions; - char *ldapai_vendor_name; - int ldapai_vendor_version; -} LDAPAPIInfoU; - -typedef struct -{ - int ldapaif_info_version; - char *ldapaif_name; - int ldapaif_version; -} LDAPAPIFeatureInfoU; - -typedef struct timevalU -{ - LONG_PTR tv_sec; - LONG_PTR tv_usec; -} LDAP_TIMEVALU; - -struct sasl_interactive_bind_id -{ - unsigned char* user; - ULONG user_len; - unsigned char* domain; - ULONG domain_len; - unsigned char* password; - ULONG password_len; -}; - -/* FIXME: we should not be directly returning pointers allocated by the Unix libldap */ - -struct ber_alloc_t_params -{ - int options; - void **ret; -}; - -struct ber_first_element_params -{ - void *ber; - unsigned int *ret_len; - char **last; -}; - -struct ber_flatten_params -{ - void *ber; - struct bervalU **berval; -}; - -struct ber_free_params -{ - void *ber; - int freebuf; -}; - -struct ber_init_params -{ - struct bervalU *berval; - void **ret; -}; - -struct ber_next_element_params -{ - void *ber; - unsigned int *ret_len; - char *last; -}; - -struct ber_peek_tag_params -{ - void *ber; - unsigned int *ret_len; -}; - -struct ber_printf_params -{ - void *ber; - char *fmt; - ULONG_PTR arg1; - ULONG_PTR arg2; -}; - -struct ber_scanf_params -{ - void *ber; - char *fmt; - void *arg1; - void *arg2; -}; - -struct ber_skip_tag_params -{ - void *ber; - unsigned int *ret_len; -}; - -struct ldap_abandon_ext_params -{ - void *ld; - int msgid; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_add_ext_params -{ - void *ld; - const char *dn; - LDAPModU **attrs; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - ULONG *msg; -}; - -struct ldap_add_ext_s_params -{ - void *ld; - const char *dn; - LDAPModU **attrs; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_compare_ext_params -{ - void *ld; - const char *dn; - const char *attrs; - struct bervalU *value; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - ULONG *msg; -}; - - -struct ldap_compare_ext_s_params -{ - void *ld; - const char *dn; - const char *attrs; - struct bervalU *value; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_count_entries_params -{ - void *ld; - void *chain; -}; - -struct ldap_count_references_params -{ - void *ld; - void *chain; -}; - -struct ldap_create_sort_control_params -{ - void *ld; - LDAPSortKeyU **keylist; - int critical; - LDAPControlU **control; -}; - -struct ldap_create_vlv_control_params -{ - void *ld; - LDAPVLVInfoU *info; - LDAPControlU **control; -}; - -struct ldap_delete_ext_params -{ - void *ld; - const char *dn; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - ULONG *msg; -}; - -struct ldap_delete_ext_s_params -{ - void *ld; - const char *dn; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_dn2ufn_params -{ - const char *dn; - char **ret; -}; - -struct ldap_explode_dn_params -{ - const char *dn; - int notypes; - char ***ret; -}; - -struct ldap_extended_operation_params -{ - void *ld; - const char *oid; - struct bervalU *data; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - ULONG *msg; -}; - -struct ldap_extended_operation_s_params -{ - void *ld; - const char *oid; - struct bervalU *data; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - char **retoid; - struct bervalU **retdata; -}; - -struct ldap_first_attribute_params -{ - void *ld; - void *entry; - void **ber; - char **ret; -}; - -struct ldap_first_entry_params -{ - void *ld; - void *chain; - void **ret; -}; - -struct ldap_first_reference_params -{ - void *ld; - void *chain; - void **ret; -}; - -struct ldap_get_dn_params -{ - void *ld; - void *entry; - char **ret; -}; - -struct ldap_get_option_params -{ - void *ld; - int option; - void *value; -}; - -struct ldap_get_values_len_params -{ - void *ld; - void *entry; - const char *attr; - struct bervalU ***ret; -}; - -struct ldap_initialize_params -{ - void **ld; - const char *url; -}; - -struct ldap_modify_ext_params -{ - void *ld; - const char *dn; - LDAPModU **mods; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - ULONG *msg; -}; - -struct ldap_modify_ext_s_params -{ - void *ld; - const char *dn; - LDAPModU **mods; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_next_attribute_params -{ - void *ld; - void *entry; - void *ber; - char **ret; -}; - -struct ldap_next_entry_params -{ - void *ld; - void *entry; - void **ret; -}; - -struct ldap_next_reference_params -{ - void *ld; - void *entry; - void **ret; -}; - -struct ldap_parse_extended_result_params -{ - void *ld; - void *result; - char **retoid; - struct bervalU **retdata; - int free; -}; - -struct ldap_parse_reference_params -{ - void *ld; - void *ref; - char ***referrals; - LDAPControlU ***serverctrls; - int free; -}; - -struct ldap_parse_result_params -{ - void *ld; - void *res; - int *errcode; - char **matcheddn; - char **errmsg; - char ***referrals; - LDAPControlU ***serverctrls; - int free; -}; - -struct ldap_parse_sortresponse_control_params -{ - void *ld; - LDAPControlU *ctrl; - int *result; - char **attr; -}; - -struct ldap_parse_vlvresponse_control_params -{ - void *ld; - LDAPControlU *ctrls; - int *target_pos; - int *list_count; - struct bervalU **ctx; - int *errcode; -}; - -struct ldap_rename_params -{ - void *ld; - const char *dn; - const char *newrdn; - const char *newparent; - int delete; - LDAPControlU **clientctrls; - LDAPControlU **serverctrls; - ULONG *msg; -}; - -struct ldap_rename_s_params -{ - void *ld; - const char *dn; - const char *newrdn; - const char *newparent; - int delete; - LDAPControlU **clientctrls; - LDAPControlU **serverctrls; -}; - -struct ldap_result_params -{ - void *ld; - int msgid; - int all; - struct timevalU *timeout; - void **result; -}; - -struct ldap_sasl_bind_params -{ - void *ld; - const char *dn; - const char *mech; - struct bervalU *cred; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - int *msgid; -}; - -struct ldap_sasl_bind_s_params -{ - void *ld; - const char *dn; - const char *mech; - struct bervalU *cred; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - struct bervalU **servercred; -}; - -struct ldap_sasl_interactive_bind_s_params -{ - void *ld; - const char *dn; - const char *mech; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - unsigned int flags; - void *defaults; -}; - -struct ldap_search_ext_params -{ - void *ld; - const char *base; - int scope; - const char *filter; - char **attrs; - int attrsonly; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - struct timevalU *timeout; - int sizelimit; - ULONG *msg; -}; - -struct ldap_search_ext_s_params -{ - void *ld; - const char *base; - int scope; - const char *filter; - char **attrs; - int attrsonly; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; - struct timevalU *timeout; - int sizelimit; - void **result; -}; - -struct ldap_set_option_params -{ - void *ld; - int option; - const void *value; -}; - -struct ldap_start_tls_s_params -{ - void *ld; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_unbind_ext_params -{ - void *ld; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -struct ldap_unbind_ext_s_params -{ - void *ld; - LDAPControlU **serverctrls; - LDAPControlU **clientctrls; -}; - -enum unix_ldap_funcs -{ - unix_ber_alloc_t, - unix_ber_bvecfree, - unix_ber_bvfree, - unix_ber_first_element, - unix_ber_flatten, - unix_ber_free, - unix_ber_init, - unix_ber_next_element, - unix_ber_peek_tag, - unix_ber_printf, - unix_ber_scanf, - unix_ber_skip_tag, - unix_ldap_abandon_ext, - unix_ldap_add_ext, - unix_ldap_add_ext_s, - unix_ldap_compare_ext, - unix_ldap_compare_ext_s, - unix_ldap_control_free, - unix_ldap_controls_free, - unix_ldap_count_entries, - unix_ldap_count_references, - unix_ldap_count_values_len, - unix_ldap_create_sort_control, - unix_ldap_create_vlv_control, - unix_ldap_delete_ext, - unix_ldap_delete_ext_s, - unix_ldap_dn2ufn, - unix_ldap_explode_dn, - unix_ldap_extended_operation, - unix_ldap_extended_operation_s, - unix_ldap_first_attribute, - unix_ldap_first_entry, - unix_ldap_first_reference, - unix_ldap_get_dn, - unix_ldap_get_option, - unix_ldap_get_values_len, - unix_ldap_initialize, - unix_ldap_memfree, - unix_ldap_memvfree, - unix_ldap_modify_ext, - unix_ldap_modify_ext_s, - unix_ldap_msgfree, - unix_ldap_next_attribute, - unix_ldap_next_entry, - unix_ldap_next_reference, - unix_ldap_parse_extended_result, - unix_ldap_parse_reference, - unix_ldap_parse_result, - unix_ldap_parse_sortresponse_control, - unix_ldap_parse_vlvresponse_control, - unix_ldap_rename, - unix_ldap_rename_s, - unix_ldap_result, - unix_ldap_sasl_bind, - unix_ldap_sasl_bind_s, - unix_ldap_sasl_interactive_bind_s, - unix_ldap_search_ext, - unix_ldap_search_ext_s, - unix_ldap_set_option, - unix_ldap_start_tls_s, - unix_ldap_unbind_ext, - unix_ldap_unbind_ext_s, - unix_ldap_value_free_len, -}; - -extern unixlib_handle_t ldap_handle DECLSPEC_HIDDEN; - -#define LDAP_CALL( func, params ) __wine_unix_call( ldap_handle, unix_ ## func, params ) diff --git a/dlls/wldap32/main.c b/dlls/wldap32/main.c index 2fffb11f064..ac983372da7 100644 --- a/dlls/wldap32/main.c +++ b/dlls/wldap32/main.c @@ -24,14 +24,11 @@ #include "winbase.h"
#include "wine/debug.h" -#include "libldap.h"
HINSTANCE hwldap32;
WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
-unixlib_handle_t ldap_handle = 0; - BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { TRACE( "(%p, %#lx, %p)\n", hinst, reason, reserved ); @@ -41,9 +38,6 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) case DLL_PROCESS_ATTACH: hwldap32 = hinst; DisableThreadLibraryCalls( hinst ); - if (NtQueryVirtualMemory( GetCurrentProcess(), hinst, MemoryWineUnixFuncs, - &ldap_handle, sizeof(ldap_handle), NULL )) - ERR( "No libldap support, expect problems\n" ); break; } return TRUE; diff --git a/dlls/wldap32/misc.c b/dlls/wldap32/misc.c index 7f4fd70d7ae..edf1f196353 100644 --- a/dlls/wldap32/misc.c +++ b/dlls/wldap32/misc.c @@ -23,7 +23,7 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h" +#include "winsock2.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -38,11 +38,7 @@ ULONG CDECL WLDAP32_ldap_abandon( LDAP *ld, ULONG msgid ) TRACE( "(%p, %#lx)\n", ld, msgid );
if (!ld) return ~0u; - else - { - struct ldap_abandon_ext_params params = { CTX(ld), msgid }; - return map_error( LDAP_CALL( ldap_abandon_ext, ¶ms )); - } + return map_error( ldap_abandon_ext( CTX(ld), msgid, NULL, NULL ) ); }
/*********************************************************************** @@ -87,7 +83,7 @@ ULONG CDECL ldap_cleanup( HANDLE instance ) /*********************************************************************** * ldap_conn_from_msg (WLDAP32.@) */ -LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res ) +LDAP * CDECL ldap_conn_from_msg( LDAP *ld, WLDAP32_LDAPMessage *res ) { TRACE( "(%p, %p)\n", ld, res );
@@ -98,31 +94,23 @@ LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res ) /*********************************************************************** * ldap_count_entries (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_count_entries( LDAP *ld, LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_count_entries( LDAP *ld, WLDAP32_LDAPMessage *res ) { TRACE( "(%p, %p)\n", ld, res );
if (!ld) return ~0u; - else - { - struct ldap_count_entries_params params = { CTX(ld), MSG(res) }; - return LDAP_CALL( ldap_count_entries, ¶ms ); - } + return ldap_count_entries( CTX(ld), MSG(res) ); }
/*********************************************************************** * ldap_count_references (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_count_references( LDAP *ld, LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_count_references( LDAP *ld, WLDAP32_LDAPMessage *res ) { TRACE( "(%p, %p)\n", ld, res );
if (!ld) return 0; - else - { - struct ldap_count_references_params params = { CTX(ld), MSG(res) }; - return LDAP_CALL( ldap_count_references, ¶ms ); - } + return ldap_count_references( CTX(ld), MSG(res) ); }
static ULONG get_escape_size( PCHAR src, ULONG srclen ) @@ -196,7 +184,7 @@ ULONG CDECL ldap_escape_filter_elementW( char *src, ULONG srclen, WCHAR *dst, UL /*********************************************************************** * ldap_first_attributeA (WLDAP32.@) */ -char * CDECL ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **ber ) +char * CDECL ldap_first_attributeA( LDAP *ld, WLDAP32_LDAPMessage *entry, WLDAP32_BerElement **ber ) { char *ret = NULL; WCHAR *retW; @@ -218,50 +206,42 @@ char * CDECL ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **b /*********************************************************************** * ldap_first_attributeW (WLDAP32.@) */ -WCHAR * CDECL ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement **ptr ) +WCHAR * CDECL ldap_first_attributeW( LDAP *ld, WLDAP32_LDAPMessage *entry, WLDAP32_BerElement **ptr ) { WCHAR *ret = NULL; - BerElement *ber; + WLDAP32_BerElement *ber; char *retU; - void *berU; + BerElement *berU;
TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
- if (ld && entry) - { - struct ldap_first_attribute_params params = { CTX(ld), MSG(entry), &berU, &retU }; - LDAP_CALL( ldap_first_attribute, ¶ms ); - } + if (ld && entry) retU = ldap_first_attribute( CTX(ld), MSG(entry), &berU ); else return NULL;
if (retU && (ber = malloc( sizeof(*ber) ))) { - BER(ber) = (char *)berU; + ber->opaque = (char *)berU; *ptr = ber; ret = strUtoW( retU ); }
- LDAP_CALL( ldap_memfree, retU ); + ldap_memfree( retU ); return ret; }
/*********************************************************************** * ldap_first_entry (WLDAP32.@) - */ -LDAPMessage * CDECL WLDAP32_ldap_first_entry( LDAP *ld, LDAPMessage *res ) +*/ +WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_entry( LDAP *ld, WLDAP32_LDAPMessage *res ) { - void *msgU; + LDAPMessage *msgU;
TRACE( "(%p, %p)\n", ld, res );
- if (ld && res) + if (ld && res && (msgU = ldap_first_entry( CTX(ld), MSG(res) ))) { - struct ldap_first_entry_params params = { CTX(ld), MSG(res), &msgU }; - if (!LDAP_CALL( ldap_first_entry, ¶ms )) - { - assert( msgU == MSG(res) ); - return res; - } + assert( msgU == MSG(res) ); + return res; } return NULL; } @@ -269,20 +249,16 @@ LDAPMessage * CDECL WLDAP32_ldap_first_entry( LDAP *ld, LDAPMessage *res ) /*********************************************************************** * ldap_first_reference (WLDAP32.@) */ -LDAPMessage * CDECL WLDAP32_ldap_first_reference( LDAP *ld, LDAPMessage *res ) +WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_reference( LDAP *ld, WLDAP32_LDAPMessage *res ) { - void *msgU; + LDAPMessage *msgU;
TRACE( "(%p, %p)\n", ld, res );
- if (ld) + if (ld && (msgU = ldap_first_reference( CTX(ld), MSG(res) ))) { - struct ldap_first_reference_params params = { CTX(ld), MSG(res), &msgU }; - if (!LDAP_CALL( ldap_first_reference, ¶ms )) - { - assert( msgU == MSG(res) ); - return res; - } + assert( msgU == MSG(res) ); + return res; } return NULL; } @@ -308,15 +284,15 @@ void CDECL ldap_memfreeW( WCHAR *block ) /*********************************************************************** * ldap_msgfree (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_msgfree( LDAPMessage *res ) +ULONG CDECL WLDAP32_ldap_msgfree( WLDAP32_LDAPMessage *res ) { - LDAPMessage *entry, *list = res; + WLDAP32_LDAPMessage *entry, *list = res;
TRACE( "(%p)\n", res );
if (!res) return WLDAP32_LDAP_SUCCESS;
- LDAP_CALL( ldap_msgfree, MSG(res) ); + ldap_msgfree( MSG(res) ); while (list) { entry = list; @@ -330,7 +306,7 @@ ULONG CDECL WLDAP32_ldap_msgfree( LDAPMessage *res ) /*********************************************************************** * ldap_next_attributeA (WLDAP32.@) */ -char * CDECL ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr ) +char * CDECL ldap_next_attributeA( LDAP *ld, WLDAP32_LDAPMessage *entry, WLDAP32_BerElement *ptr ) { char *ret = NULL; WCHAR *retW; @@ -352,21 +328,17 @@ char * CDECL ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr /*********************************************************************** * ldap_next_attributeW (WLDAP32.@) */ -WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *ptr ) +WCHAR * CDECL ldap_next_attributeW( LDAP *ld, WLDAP32_LDAPMessage *entry, WLDAP32_BerElement *ptr ) { WCHAR *ret = NULL; char *retU;
TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
- if (ld && entry && ptr) + if (ld && entry && ptr && (retU = ldap_next_attribute( CTX(ld), MSG(entry), BER(ptr) ))) { - struct ldap_next_attribute_params params = { CTX(ld), MSG(entry), BER(ptr), &retU }; - if (!LDAP_CALL( ldap_next_attribute, ¶ms )) - { - ret = strUtoW( retU ); - LDAP_CALL( ldap_memfree, retU ); - } + ret = strUtoW( retU ); + ldap_memfree( retU ); } return ret; } @@ -374,22 +346,18 @@ WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *pt /*********************************************************************** * ldap_next_entry (WLDAP32.@) */ -LDAPMessage * CDECL WLDAP32_ldap_next_entry( LDAP *ld, LDAPMessage *entry ) +WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_entry( LDAP *ld, WLDAP32_LDAPMessage *entry ) { - LDAPMessage *msg = NULL; - void *msgU; + WLDAP32_LDAPMessage *msg = NULL; + LDAPMessage *msgU;
TRACE( "(%p, %p)\n", ld, entry );
if (!ld || !entry) return NULL;
if (entry->lm_next) return entry->lm_next; - else - { - struct ldap_next_entry_params params = { CTX(ld), MSG(entry), &msgU }; - LDAP_CALL( ldap_next_entry, ¶ms ); - }
+ msgU = ldap_next_entry( CTX(ld), MSG(entry) ); if (msgU && (msg = calloc( 1, sizeof(*msg) ))) { MSG(msg) = msgU; @@ -402,21 +370,18 @@ LDAPMessage * CDECL WLDAP32_ldap_next_entry( LDAP *ld, LDAPMessage *entry ) /*********************************************************************** * ldap_next_reference (WLDAP32.@) */ -LDAPMessage * CDECL WLDAP32_ldap_next_reference( LDAP *ld, LDAPMessage *entry ) +WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_reference( LDAP *ld, WLDAP32_LDAPMessage *entry ) { - LDAPMessage *msg = NULL; - void *msgU; + WLDAP32_LDAPMessage *msg = NULL; + LDAPMessage *msgU;
TRACE( "(%p, %p)\n", ld, entry );
if (!ld || !entry) return NULL;
if (entry->lm_next) return entry->lm_next; - else - { - struct ldap_next_reference_params params = { CTX(ld), MSG(entry), &msgU }; - LDAP_CALL( ldap_next_reference, ¶ms ); - } + + msgU = ldap_next_reference( CTX(ld), MSG(entry) ); if (msgU && (msg = calloc( 1, sizeof(*msg) ))) { MSG(msg) = msgU; @@ -429,26 +394,24 @@ LDAPMessage * CDECL WLDAP32_ldap_next_reference( LDAP *ld, LDAPMessage *entry ) /*********************************************************************** * ldap_result (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res ) +ULONG CDECL WLDAP32_ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, WLDAP32_LDAPMessage **res ) { - LDAPMessage *msg; - struct timevalU timeval; - void *msgU = NULL; + WLDAP32_LDAPMessage *msg; + struct timeval timeval; + LDAPMessage *msgU = NULL; ULONG ret = ~0u;
TRACE( "(%p, %#lx, %#lx, %p, %p)\n", ld, msgid, all, timeout, res );
if (ld && res && msgid != ~0u) { - struct ldap_result_params params = { CTX(ld), msgid, all, timeout ? &timeval : NULL, &msgU }; - if (timeout) { timeval.tv_sec = timeout->tv_sec; timeval.tv_usec = timeout->tv_usec; }
- ret = LDAP_CALL( ldap_result, ¶ms ); + ret = ldap_result( CTX(ld), msgid, all, timeout ? &timeval : NULL, &msgU ); } if (msgU && (msg = calloc( 1, sizeof(*msg) ))) { diff --git a/dlls/wldap32/modify.c b/dlls/wldap32/modify.c index 72b9cce2e0b..a062bf4bb15 100644 --- a/dlls/wldap32/modify.c +++ b/dlls/wldap32/modify.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -71,7 +70,7 @@ ULONG CDECL ldap_modifyW( LDAP *ld, WCHAR *dn, LDAPModW **mods ) * ldap_modify_extA (WLDAP32.@) */ ULONG CDECL ldap_modify_extA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, - LDAPControlA **clientctrls, ULONG *message ) + LDAPControlA **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; @@ -101,12 +100,12 @@ exit: * ldap_modify_extW (WLDAP32.@) */ ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, - LDAPControlW **clientctrls, ULONG *message ) + LDAPControlW **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPModU **modsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPMod **modsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), mods, serverctrls, clientctrls, message );
@@ -118,8 +117,7 @@ ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_modify_ext_params params = { CTX(ld), dnU, modsU, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_modify_ext, ¶ms )); + ret = map_error( ldap_modify_ext( CTX(ld), dnU, modsU, serverctrlsU, clientctrlsU, (int *)message ) ); }
exit: @@ -134,7 +132,7 @@ exit: * ldap_modify_ext_sA (WLDAP32.@) */ ULONG CDECL ldap_modify_ext_sA( LDAP *ld, char *dn, LDAPModA **mods, LDAPControlA **serverctrls, - LDAPControlA **clientctrls ) + LDAPControlA **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL; @@ -164,12 +162,12 @@ exit: * ldap_modify_ext_sW (WLDAP32.@) */ ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, - LDAPControlW **clientctrls ) + LDAPControlW **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL; - LDAPModU **modsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPMod **modsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), mods, serverctrls, clientctrls );
@@ -181,8 +179,7 @@ ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPContro if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_modify_ext_s_params params = { CTX(ld), dnU, modsU, serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_modify_ext_s, ¶ms )); + ret = map_error( ldap_modify_ext_s( CTX(ld), dnU, modsU, serverctrlsU, clientctrlsU ) ); }
exit: diff --git a/dlls/wldap32/modrdn.c b/dlls/wldap32/modrdn.c index 7df09b941af..4acf16eb5e4 100644 --- a/dlls/wldap32/modrdn.c +++ b/dlls/wldap32/modrdn.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -91,7 +90,7 @@ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *newdnU = NULL; - ULONG msg; + int msg;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_w(dn), newdn, delete );
@@ -101,8 +100,7 @@ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete )
if ((newdnU = strWtoU( newdn ))) { - struct ldap_rename_params params = { CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL, &msg }; - ret = LDAP_CALL( ldap_rename, ¶ms ); + ret = ldap_rename( CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL, &msg ); if (ret == WLDAP32_LDAP_SUCCESS) ret = msg; else @@ -152,8 +150,7 @@ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete )
if ((newdnU = strWtoU( newdn ))) { - struct ldap_rename_s_params params = { CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL }; - ret = map_error( LDAP_CALL( ldap_rename_s, ¶ms )); + ret = map_error( ldap_rename_s( CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL ) ); free( newdnU ); } free( dnU ); diff --git a/dlls/wldap32/option.c b/dlls/wldap32/option.c index 354fdee08e1..cc85ed1340b 100644 --- a/dlls/wldap32/option.c +++ b/dlls/wldap32/option.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -161,7 +160,7 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) { case WLDAP32_LDAP_OPT_API_FEATURE_INFO: { - LDAPAPIFeatureInfoU featureU; + LDAPAPIFeatureInfo featureU; LDAPAPIFeatureInfoW *featureW = value;
if (!featureW->ldapaif_name) return WLDAP32_LDAP_PARAM_ERROR; @@ -169,9 +168,8 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) featureU.ldapaif_info_version = featureW->ldapaif_info_version; if ((featureU.ldapaif_name = strWtoU( featureW->ldapaif_name ))) { - struct ldap_get_option_params params = { CTX(ld), option, &featureU }; featureU.ldapaif_version = 0; - ret = map_error( LDAP_CALL( ldap_get_option, ¶ms )); + ret = map_error( ldap_get_option( CTX(ld), option, &featureU ) ); } else return WLDAP32_LDAP_NO_MEMORY;
@@ -181,14 +179,13 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) } case WLDAP32_LDAP_OPT_API_INFO: { - LDAPAPIInfoU infoU; + LDAPAPIInfo infoU; LDAPAPIInfoW *infoW = value; - struct ldap_get_option_params params = { CTX(ld), option, &infoU };
memset( &infoU, 0, sizeof(infoU) ); infoU.ldapai_info_version = infoW->ldapai_info_version;
- ret = map_error( LDAP_CALL( ldap_get_option, ¶ms )); + ret = map_error( ldap_get_option( CTX(ld), option, &infoU ) ); if (ret == WLDAP32_LDAP_SUCCESS) { infoW->ldapai_api_version = infoU.ldapai_api_version; @@ -198,13 +195,13 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) return WLDAP32_LDAP_NO_MEMORY; if (infoU.ldapai_vendor_name && !(infoW->ldapai_vendor_name = strUtoW( infoU.ldapai_vendor_name ))) { - LDAP_CALL( ldap_memvfree, infoU.ldapai_extensions ); + ldap_memvfree( (void **)infoU.ldapai_extensions ); return WLDAP32_LDAP_NO_MEMORY; } infoW->ldapai_vendor_version = infoU.ldapai_vendor_version;
- LDAP_CALL( ldap_memvfree, infoU.ldapai_extensions ); - LDAP_CALL( ldap_memfree, infoU.ldapai_vendor_name ); + ldap_memvfree( (void **)infoU.ldapai_extensions ); + ldap_memfree( infoU.ldapai_vendor_name ); } return ret; } @@ -216,10 +213,7 @@ ULONG CDECL ldap_get_optionW( LDAP *ld, int option, void *value ) case WLDAP32_LDAP_OPT_REFERRALS: case WLDAP32_LDAP_OPT_SIZELIMIT: case WLDAP32_LDAP_OPT_TIMELIMIT: - { - struct ldap_get_option_params params = { CTX(ld), option, value }; - return map_error( LDAP_CALL( ldap_get_option, ¶ms )); - } + return map_error( ldap_get_option( CTX(ld), option, value ) );
case WLDAP32_LDAP_OPT_CACHE_ENABLE: case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: @@ -355,38 +349,32 @@ ULONG CDECL ldap_set_optionA( LDAP *ld, int option, void *value ) static BOOL query_supported_server_ctrls( LDAP *ld ) { char *attrs[] = { (char *)"supportedControl", NULL }; - void *res, *entry; - struct bervalU **ctrls = SERVER_CTRLS(ld); + LDAPMessage *res, *entry; + struct berval **ctrls = SERVER_CTRLS(ld); ULONG ret;
- if (!ctrls) - { - struct ldap_search_ext_s_params params = { CTX(ld), (char *)"", LDAP_SCOPE_BASE, - (char *)"(objectClass=*)", attrs, FALSE, NULL, NULL, NULL, 0, &res }; - ret = map_error( LDAP_CALL( ldap_search_ext_s, ¶ms )); - } - else return TRUE; + if (ctrls) return TRUE;
+ ret = map_error( ldap_search_ext_s( CTX(ld), (char *)"", WLDAP32_LDAP_SCOPE_BASE, (char *)"(objectClass=*)", + attrs, FALSE, NULL, NULL, NULL, 0, &res ) ); if (ret == WLDAP32_LDAP_SUCCESS) { - struct ldap_first_entry_params params = { CTX(ld), res, &entry }; - if (!LDAP_CALL( ldap_first_entry, ¶ms )) + if ((entry = ldap_first_entry( CTX(ld), res ))) { ULONG count, i; - struct ldap_get_values_len_params get_params = { CTX(ld), entry, attrs[0], &ctrls }; - LDAP_CALL( ldap_get_values_len, &get_params ); - count = LDAP_CALL( ldap_count_values_len, ctrls ); + ctrls = ldap_get_values_len( CTX(ld), entry, attrs[0] ); + count = ldap_count_values_len( ctrls ); for (i = 0; i < count; i++) TRACE( "%lu: %s\n", i, debugstr_an( ctrls[i]->bv_val, ctrls[i]->bv_len ) ); - *(struct bervalU ***)&SERVER_CTRLS(ld) = ctrls; + *(struct berval ***)&SERVER_CTRLS(ld) = ctrls; } } else return FALSE;
- LDAP_CALL( ldap_msgfree, res ); + ldap_msgfree( res ); return ctrls != NULL; }
-static BOOL is_supported_server_ctrls( LDAP *ld, LDAPControlU **ctrls ) +static BOOL is_supported_server_ctrls( LDAP *ld, LDAPControl **ctrls ) { ULONG user_count, server_count, i, n, supported = 0;
@@ -394,7 +382,7 @@ static BOOL is_supported_server_ctrls( LDAP *ld, LDAPControlU **ctrls ) return TRUE; /* can't verify, let the server handle it on next query */
user_count = controlarraylenU( ctrls ); - server_count = LDAP_CALL( ldap_count_values_len, SERVER_CTRLS(ld) ); + server_count = ldap_count_values_len( SERVER_CTRLS(ld) );
for (n = 0; n < user_count; n++) { @@ -402,7 +390,7 @@ static BOOL is_supported_server_ctrls( LDAP *ld, LDAPControlU **ctrls )
for (i = 0; i < server_count; i++) { - struct bervalU **server_ctrls = SERVER_CTRLS(ld); + struct berval **server_ctrls = SERVER_CTRLS(ld); if (!strncmp( ctrls[n]->ldctl_oid, server_ctrls[i]->bv_val, server_ctrls[i]->bv_len)) { supported++; @@ -429,28 +417,27 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) { case WLDAP32_LDAP_OPT_SERVER_CONTROLS: { - LDAPControlU **ctrlsU; + LDAPControl **ctrlsU;
if (!(ctrlsU = controlarrayWtoU( value ))) return WLDAP32_LDAP_NO_MEMORY;
if (!is_supported_server_ctrls( ld, ctrlsU )) ret = WLDAP32_LDAP_PARAM_ERROR; else - { - struct ldap_set_option_params params = { CTX(ld), option, ctrlsU }; - ret = map_error( LDAP_CALL( ldap_set_option, ¶ms )); - } + ret = map_error( ldap_set_option( CTX(ld), option, ctrlsU ) ); + controlarrayfreeU( ctrlsU ); return ret; } case WLDAP32_LDAP_OPT_REFERRALS: { - struct ldap_set_option_params params = { CTX(ld), option, LDAP_OPT_ON }; - if (value == WLDAP32_LDAP_OPT_OFF) - params.value = LDAP_OPT_OFF; - else - FIXME("upgrading referral value %p to WLDAP32_LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value); - return map_error( LDAP_CALL( ldap_set_option, ¶ms )); + if (value == WLDAP32_LDAP_OPT_OFF) value = LDAP_OPT_OFF; + else if (value != WLDAP32_LDAP_OPT_ON) + { + FIXME( "upgrading referral value %p to LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value ); + value = LDAP_OPT_ON; + } + return map_error( ldap_set_option( CTX(ld), option, value ) ); } case WLDAP32_LDAP_OPT_DEREF: case WLDAP32_LDAP_OPT_DESC: @@ -458,10 +445,7 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: case WLDAP32_LDAP_OPT_SIZELIMIT: case WLDAP32_LDAP_OPT_TIMELIMIT: - { - struct ldap_set_option_params params = { CTX(ld), option, value }; - return map_error( LDAP_CALL( ldap_set_option, ¶ms )); - } + return map_error( ldap_set_option( CTX(ld), option, value ) );
case WLDAP32_LDAP_OPT_CACHE_ENABLE: case WLDAP32_LDAP_OPT_CACHE_FN_PTRS: diff --git a/dlls/wldap32/page.c b/dlls/wldap32/page.c index 101ddc46483..7e066015d7e 100644 --- a/dlls/wldap32/page.c +++ b/dlls/wldap32/page.c @@ -24,21 +24,19 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h" -#include "winber.h"
#include "wine/debug.h" #include "winldap_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
-static struct berval null_cookieW = { 0, NULL }; +static struct WLDAP32_berval null_cookieW = { 0, NULL };
/*********************************************************************** * ldap_create_page_controlA (WLDAP32.@) */ -ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct berval *cookie, UCHAR critical, - LDAPControlA **control ) +ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct WLDAP32_berval *cookie, UCHAR critical, + LDAPControlA **control ) { ULONG ret; LDAPControlW *controlW = NULL; @@ -57,15 +55,16 @@ ULONG CDECL ldap_create_page_controlA( LDAP *ld, ULONG pagesize, struct berval * }
/* create a page control by hand */ -static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR critical, LDAPControlW **control ) +static ULONG create_page_control( ULONG pagesize, struct WLDAP32_berval *cookie, UCHAR critical, + LDAPControlW **control ) { LDAPControlW *ctrl; WLDAP32_BerElement *ber; - struct berval *berval, *vec[2]; + struct WLDAP32_berval *berval, *vec[2]; int ret, len; char *val;
- if (!(ber = WLDAP32_ber_alloc_t( LBER_USE_DER ))) return WLDAP32_LDAP_NO_MEMORY; + if (!(ber = WLDAP32_ber_alloc_t( WLDAP32_LBER_USE_DER ))) return WLDAP32_LDAP_NO_MEMORY;
vec[1] = NULL; if (cookie) @@ -109,8 +108,8 @@ static ULONG create_page_control( ULONG pagesize, struct berval *cookie, UCHAR c /*********************************************************************** * ldap_create_page_controlW (WLDAP32.@) */ -ULONG CDECL ldap_create_page_controlW( LDAP *ld, ULONG pagesize, struct berval *cookie, UCHAR critical, - LDAPControlW **control ) +ULONG CDECL ldap_create_page_controlW( LDAP *ld, ULONG pagesize, struct WLDAP32_berval *cookie, UCHAR critical, + LDAPControlW **control ) { TRACE( "(%p, %#lx, %p, 0x%02x, %p)\n", ld, pagesize, cookie, critical, control );
@@ -127,7 +126,7 @@ ULONG CDECL ldap_get_next_page( LDAP *ld, LDAPSearch *search, ULONG pagesize, UL }
ULONG CDECL ldap_get_next_page_s( LDAP *ld, LDAPSearch *search, struct l_timeval *timeout, ULONG pagesize, - ULONG *count, LDAPMessage **results ) + ULONG *count, WLDAP32_LDAPMessage **results ) { ULONG ret;
@@ -161,7 +160,7 @@ ULONG CDECL ldap_get_next_page_s( LDAP *ld, LDAPSearch *search, struct l_timeval return ldap_get_paged_count( ld, search, count, *results ); }
-ULONG CDECL ldap_get_paged_count( LDAP *ld, LDAPSearch *search, ULONG *count, LDAPMessage *results ) +ULONG CDECL ldap_get_paged_count( LDAP *ld, LDAPSearch *search, ULONG *count, WLDAP32_LDAPMessage *results ) { ULONG ret; LDAPControlW **server_ctrls = NULL; @@ -196,7 +195,7 @@ ULONG CDECL ldap_get_paged_count( LDAP *ld, LDAPSearch *search, ULONG *count, LD /*********************************************************************** * ldap_parse_page_controlA (WLDAP32.@) */ -ULONG CDECL ldap_parse_page_controlA( LDAP *ld, LDAPControlA **ctrls, ULONG *count, struct berval **cookie ) +ULONG CDECL ldap_parse_page_controlA( LDAP *ld, LDAPControlA **ctrls, ULONG *count, struct WLDAP32_berval **cookie ) { ULONG ret; LDAPControlW **ctrlsW = NULL; @@ -214,12 +213,13 @@ ULONG CDECL ldap_parse_page_controlA( LDAP *ld, LDAPControlA **ctrls, ULONG *cou /*********************************************************************** * ldap_parse_page_controlW (WLDAP32.@) */ -ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret_count, struct berval **ret_cookie ) +ULONG CDECL ldap_parse_page_controlW( LDAP *ld, LDAPControlW **ctrls, ULONG *ret_count, + struct WLDAP32_berval **ret_cookie ) { ULONG ret, count; LDAPControlW *control = NULL; WLDAP32_BerElement *ber; - struct berval *cookie = NULL; + struct WLDAP32_berval *cookie = NULL; int tag; ULONG i;
@@ -273,8 +273,8 @@ ULONG CDECL ldap_search_abandon_page( LDAP *ld, LDAPSearch *search ) }
LDAPSearch * CDECL ldap_search_init_pageA( LDAP *ld, char *dn, ULONG scope, char *filter, char **attrs, - ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG timelimit, ULONG sizelimit, - LDAPSortKeyA **sortkeys ) + ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, + ULONG timelimit, ULONG sizelimit, LDAPSortKeyA **sortkeys ) { FIXME( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld, debugstr_a(dn), scope, debugstr_a(filter), attrs, attrsonly, serverctrls, clientctrls, timelimit, sizelimit, sortkeys ); @@ -282,8 +282,8 @@ LDAPSearch * CDECL ldap_search_init_pageA( LDAP *ld, char *dn, ULONG scope, char }
LDAPSearch * CDECL ldap_search_init_pageW( LDAP *ld, WCHAR *dn, ULONG scope, WCHAR *filter, WCHAR **attrs, - ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, ULONG sizelimit, - LDAPSortKeyW **sortkeys ) + ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, + ULONG timelimit, ULONG sizelimit, LDAPSortKeyW **sortkeys ) { LDAPSearch *search; DWORD i, len; diff --git a/dlls/wldap32/parse.c b/dlls/wldap32/parse.c index 432278618fe..436d38d5c42 100644 --- a/dlls/wldap32/parse.c +++ b/dlls/wldap32/parse.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -32,8 +31,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); /*********************************************************************** * ldap_parse_extended_resultA (WLDAP32.@) */ -ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, LDAPMessage *result, char **oid, struct berval **data, - BOOLEAN free ) +ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, WLDAP32_LDAPMessage *result, char **oid, + struct WLDAP32_berval **data, BOOLEAN free ) { ULONG ret; WCHAR *oidW = NULL; @@ -57,12 +56,12 @@ ULONG CDECL ldap_parse_extended_resultA( LDAP *ld, LDAPMessage *result, char **o /*********************************************************************** * ldap_parse_extended_resultW (WLDAP32.@) */ -ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR **oid, struct berval **data, - BOOLEAN free ) +ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, WLDAP32_LDAPMessage *result, WCHAR **oid, + struct WLDAP32_berval **data, BOOLEAN free ) { ULONG ret; char *oidU = NULL; - struct bervalU *dataU = NULL; + struct berval *dataU = NULL;
TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
@@ -70,22 +69,21 @@ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR ** if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; else { - struct ldap_parse_extended_result_params params = { CTX(ld), result, &oidU, &dataU, free }; - ret = map_error( LDAP_CALL( ldap_parse_extended_result, ¶ms )); + ret = map_error( ldap_parse_extended_result( CTX(ld), result, &oidU, &dataU, free ) ); } if (oid && oidU) { WCHAR *str; if ((str = strUtoW( oidU ))) *oid = str; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_memfree, oidU ); + ldap_memfree( oidU ); } if (data && dataU) { - struct berval *bv; + struct WLDAP32_berval *bv; if ((bv = bervalUtoW( dataU ))) *data = bv; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ber_bvfree, dataU ); + ber_bvfree( dataU ); }
return ret; @@ -94,7 +92,7 @@ ULONG CDECL ldap_parse_extended_resultW( LDAP *ld, LDAPMessage *result, WCHAR ** /*********************************************************************** * ldap_parse_referenceA (WLDAP32.@) */ -ULONG CDECL ldap_parse_referenceA( LDAP *ld, LDAPMessage *message, char ***referrals ) +ULONG CDECL ldap_parse_referenceA( LDAP *ld, WLDAP32_LDAPMessage *message, char ***referrals ) { ULONG ret; WCHAR **referralsW = NULL; @@ -117,24 +115,21 @@ ULONG CDECL ldap_parse_referenceA( LDAP *ld, LDAPMessage *message, char ***refer /*********************************************************************** * ldap_parse_referenceW (WLDAP32.@) */ -ULONG CDECL ldap_parse_referenceW( LDAP *ld, LDAPMessage *message, WCHAR ***referrals ) +ULONG CDECL ldap_parse_referenceW( LDAP *ld, WLDAP32_LDAPMessage *message, WCHAR ***referrals ) { ULONG ret = ~0u; char **referralsU = NULL;
TRACE( "(%p, %p, %p)\n", ld, message, referrals );
- if (ld) - { - struct ldap_parse_reference_params params = { CTX(ld), message, &referralsU, NULL, 0 }; - ret = map_error( LDAP_CALL( ldap_parse_reference, ¶ms )); - } + if (ld) ret = map_error( ldap_parse_reference( CTX(ld), message, &referralsU, NULL, 0 ) ); + if (referralsU) { WCHAR **ref; if ((ref = strarrayUtoW( referralsU ))) *referrals = ref; else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_memfree, referralsU ); + ldap_memfree( referralsU ); } return ret; } @@ -142,7 +137,7 @@ ULONG CDECL ldap_parse_referenceW( LDAP *ld, LDAPMessage *message, WCHAR ***refe /*********************************************************************** * ldap_parse_resultA (WLDAP32.@) */ -ULONG CDECL ldap_parse_resultA( LDAP *ld, LDAPMessage *result, ULONG *retcode, char **matched, char **error, +ULONG CDECL ldap_parse_resultA( LDAP *ld, WLDAP32_LDAPMessage *result, ULONG *retcode, char **matched, char **error, char ***referrals, LDAPControlA ***serverctrls, BOOLEAN free ) { ULONG ret; @@ -171,33 +166,30 @@ ULONG CDECL ldap_parse_resultA( LDAP *ld, LDAPMessage *result, ULONG *retcode, c /*********************************************************************** * ldap_parse_resultW (WLDAP32.@) */ -ULONG CDECL ldap_parse_resultW( LDAP *ld, LDAPMessage *result, ULONG *retcode, WCHAR **matched, WCHAR **error, +ULONG CDECL ldap_parse_resultW( LDAP *ld, WLDAP32_LDAPMessage *result, ULONG *retcode, WCHAR **matched, WCHAR **error, WCHAR ***referrals, LDAPControlW ***serverctrls, BOOLEAN free ) { ULONG ret; char *matchedU = NULL, *errorU = NULL, **referralsU = NULL; - LDAPControlU **serverctrlsU = NULL; + LDAPControl **serverctrlsU = NULL;
TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, matched, error, referrals, serverctrls, free );
- if (ld) - { - struct ldap_parse_result_params params = { CTX(ld), MSG(result), (int *)retcode, &matchedU, - &errorU, &referralsU, &serverctrlsU, free }; - ret = map_error( LDAP_CALL( ldap_parse_result, ¶ms )); - } - else return WLDAP32_LDAP_PARAM_ERROR; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + + ret = map_error( ldap_parse_result( CTX(ld), MSG(result), (int *)retcode, &matchedU, &errorU, &referralsU, + &serverctrlsU, free ) );
if (matched) *matched = strUtoW( matchedU ); if (error) *error = strUtoW( errorU ); if (referrals) *referrals = strarrayUtoW( referralsU ); if (serverctrls) *serverctrls = controlarrayUtoW( serverctrlsU );
- LDAP_CALL( ldap_memfree, matchedU ); - LDAP_CALL( ldap_memfree, errorU ); - LDAP_CALL( ldap_memvfree, referralsU ); - LDAP_CALL( ldap_controls_free, serverctrlsU ); + ldap_memfree( matchedU ); + ldap_memfree( errorU ); + ldap_memfree( referralsU ); + ldap_controls_free( serverctrlsU ); return ret; }
@@ -230,7 +222,7 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r { ULONG ret; char *attrU = NULL; - LDAPControlU **controlU, *sortcontrol = NULL; + LDAPControl **controlU, *sortcontrol = NULL; int res; unsigned int i;
@@ -250,11 +242,8 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r controlarrayfreeU( controlU ); return WLDAP32_LDAP_CONTROL_NOT_FOUND; } - else - { - struct ldap_parse_sortresponse_control_params params = { CTX(ld), sortcontrol, &res, &attrU }; - ret = map_error( LDAP_CALL( ldap_parse_sortresponse_control, ¶ms )); - } + + ret = map_error( ldap_parse_sortresponse_control( CTX(ld), sortcontrol, &res, &attrU ) ); if (ret == WLDAP32_LDAP_SUCCESS) { WCHAR *str; @@ -264,7 +253,7 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r *result = res; } else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ldap_memfree, attrU ); + ldap_memfree( attrU ); }
controlarrayfreeU( controlU ); @@ -275,7 +264,7 @@ ULONG CDECL ldap_parse_sort_controlW( LDAP *ld, LDAPControlW **control, ULONG *r * ldap_parse_vlv_controlA (WLDAP32.@) */ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targetpos, ULONG *listcount, - struct berval **context, int *errcode ) + struct WLDAP32_berval **context, int *errcode ) { int ret; LDAPControlW **controlW = NULL; @@ -294,11 +283,11 @@ int CDECL ldap_parse_vlv_controlA( LDAP *ld, LDAPControlA **control, ULONG *targ * ldap_parse_vlv_controlW (WLDAP32.@) */ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targetpos, ULONG *listcount, - struct berval **context, int *errcode ) + struct WLDAP32_berval **context, int *errcode ) { int ret, pos, count; - LDAPControlU **controlU, *vlvcontrolU = NULL; - struct bervalU *ctxU; + LDAPControl **controlU, *vlvcontrolU = NULL; + struct berval *ctxU; unsigned int i;
TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos, listcount, context, errcode ); @@ -317,14 +306,11 @@ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targ controlarrayfreeU( controlU ); return WLDAP32_LDAP_CONTROL_NOT_FOUND; } - else - { - struct ldap_parse_vlvresponse_control_params params = { CTX(ld), vlvcontrolU, &pos, &count, &ctxU, errcode }; - ret = map_error( LDAP_CALL( ldap_parse_vlvresponse_control, ¶ms )); - } + + ret = map_error( ldap_parse_vlvresponse_control( CTX(ld), vlvcontrolU, &pos, &count, &ctxU, errcode ) ); if (ret == WLDAP32_LDAP_SUCCESS) { - struct berval *bv; + struct WLDAP32_berval *bv; if ((bv = bervalUtoW( ctxU ))) { *context = bv; @@ -332,7 +318,7 @@ int CDECL ldap_parse_vlv_controlW( LDAP *ld, LDAPControlW **control, ULONG *targ *listcount = count; } else ret = WLDAP32_LDAP_NO_MEMORY; - LDAP_CALL( ber_bvfree, ctxU ); + ber_bvfree( ctxU ); }
controlarrayfreeU( controlU ); diff --git a/dlls/wldap32/rename.c b/dlls/wldap32/rename.c index 411fbf4b817..f2b224b3d0f 100644 --- a/dlls/wldap32/rename.c +++ b/dlls/wldap32/rename.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -33,7 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); * ldap_rename_extA (WLDAP32.@) */ ULONG CDECL ldap_rename_extA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, - LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) + LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newrdnW = NULL, *newparentW = NULL; @@ -65,11 +64,11 @@ exit: * ldap_rename_extW (WLDAP32.@) */ ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, - LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) + LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(newrdn), debugstr_w(newparent), delete, serverctrls, clientctrls, message ); @@ -83,8 +82,8 @@ ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newpare if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_rename_params params = { CTX(ld), dnU, newrdnU, newparentU, delete, serverctrlsU, clientctrlsU, message }; - ret = map_error( LDAP_CALL( ldap_rename, ¶ms )); + ret = map_error( ldap_rename( CTX(ld), dnU, newrdnU, newparentU, delete, serverctrlsU, clientctrlsU, + (int *)message ) ); } exit: free( dnU ); @@ -99,7 +98,7 @@ exit: * ldap_rename_ext_sA (WLDAP32.@) */ ULONG CDECL ldap_rename_ext_sA( LDAP *ld, char *dn, char *newrdn, char *newparent, int delete, - LDAPControlA **serverctrls, LDAPControlA **clientctrls ) + LDAPControlA **serverctrls, LDAPControlA **clientctrls ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *dnW = NULL, *newrdnW = NULL, *newparentW = NULL; @@ -131,11 +130,11 @@ exit: * ldap_rename_ext_sW (WLDAP32.@) */ ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, - LDAPControlW **serverctrls, LDAPControlW **clientctrls ) + LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { ULONG ret = WLDAP32_LDAP_PARAM_ERROR; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %s, %s, 0x%02x, %p, %p)\n", ld, debugstr_w(dn), debugstr_w(newrdn), debugstr_w(newparent), delete, serverctrls, clientctrls ); @@ -149,8 +148,7 @@ ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newpa if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; else { - struct ldap_rename_s_params params = { CTX(ld), dnU, newrdnU, newparentU, delete, serverctrlsU, clientctrlsU }; - ret = map_error( LDAP_CALL( ldap_rename_s, ¶ms )); + ret = map_error( ldap_rename_s( CTX(ld), dnU, newrdnU, newparentU, delete, serverctrlsU, clientctrlsU ) ); } exit: free( dnU ); diff --git a/dlls/wldap32/search.c b/dlls/wldap32/search.c index 924bb4321a2..18a079dd5bc 100644 --- a/dlls/wldap32/search.c +++ b/dlls/wldap32/search.c @@ -23,7 +23,7 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h" +#include "winsock2.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -72,7 +72,8 @@ ULONG CDECL ldap_searchW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCH * ldap_search_extA (WLDAP32.@) */ ULONG CDECL ldap_search_extA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, - LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message ) + LDAPControlA **serverctrls, LDAPControlA **clientctrls, ULONG timelimit, + ULONG sizelimit, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; @@ -104,14 +105,14 @@ exit: /*********************************************************************** * ldap_search_extW (WLDAP32.@) */ -ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, - ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, ULONG sizelimit, - ULONG *message ) +ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, + LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, + ULONG sizelimit, ULONG *message ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct timevalU timevalU; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct timeval timevalU;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, serverctrls, clientctrls, timelimit, sizelimit, message ); @@ -127,11 +128,8 @@ ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, timevalU.tv_sec = timelimit; timevalU.tv_usec = 0;
- { - struct ldap_search_ext_params params = { CTX(ld), baseU, scope, filterU, attrsU, attrsonly, - serverctrlsU, clientctrlsU, timelimit ? &timevalU : NULL, sizelimit, message }; - ret = map_error( LDAP_CALL( ldap_search_ext, ¶ms )); - } + ret = map_error( ldap_search_ext( CTX(ld), baseU, scope, filterU, attrsU, attrsonly, serverctrlsU, + clientctrlsU, timelimit ? &timevalU : NULL, sizelimit, (int *)message ) ); exit: free( baseU ); free( filterU ); @@ -144,9 +142,9 @@ exit: /*********************************************************************** * ldap_search_ext_sA (WLDAP32.@) */ -ULONG CDECL ldap_search_ext_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, - ULONG attrsonly, LDAPControlA **serverctrls, LDAPControlA **clientctrls, struct l_timeval *timeout, - ULONG sizelimit, LDAPMessage **res ) +ULONG CDECL ldap_search_ext_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, + LDAPControlA **serverctrls, LDAPControlA **clientctrls, struct l_timeval *timeout, + ULONG sizelimit, WLDAP32_LDAPMessage **res ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; @@ -178,15 +176,15 @@ exit: /*********************************************************************** * ldap_search_ext_sW (WLDAP32.@) */ -ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, - ULONG attrsonly, LDAPControlW **serverctrls, LDAPControlW **clientctrls, struct l_timeval *timeout, - ULONG sizelimit, LDAPMessage **res ) +ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, + LDAPControlW **serverctrls, LDAPControlW **clientctrls, struct l_timeval *timeout, + ULONG sizelimit, LDAPMessage **res ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; - LDAPControlU **serverctrlsU = NULL, **clientctrlsU = NULL; - struct timevalU timevalU; - void *msgU = NULL; + LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; + struct timeval timevalU; + LDAPMessage *msgU = NULL;
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %p, %#lx, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, serverctrls, clientctrls, timeout, sizelimit, res ); @@ -205,11 +203,8 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte timevalU.tv_usec = timeout->tv_usec; }
- { - struct ldap_search_ext_s_params params = { CTX(ld), baseU, scope, filterU, attrsU, attrsonly, - serverctrlsU, clientctrlsU, timeout ? &timevalU : NULL, sizelimit, &msgU }; - ret = map_error( LDAP_CALL( ldap_search_ext_s, ¶ms )); - } + ret = map_error( ldap_search_ext_s( CTX(ld), baseU, scope, filterU, attrsU, attrsonly, serverctrlsU, + clientctrlsU, timeout ? &timevalU : NULL, sizelimit, &msgU ) );
if (msgU) { @@ -221,7 +216,7 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte } else { - LDAP_CALL( ldap_msgfree, msgU ); + ldap_msgfree( msgU ); ret = WLDAP32_LDAP_NO_MEMORY; } } @@ -239,7 +234,7 @@ exit: * ldap_search_sA (WLDAP32.@) */ ULONG CDECL ldap_search_sA( LDAP *ld, char *base, ULONG scope, char *filter, char **attrs, ULONG attrsonly, - LDAPMessage **res ) + WLDAP32_LDAPMessage **res ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; @@ -266,7 +261,7 @@ exit: * ldap_search_sW (WLDAP32.@) */ ULONG CDECL ldap_search_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, WCHAR **attrs, ULONG attrsonly, - LDAPMessage **res ) + WLDAP32_LDAPMessage **res ) { TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, res ); @@ -277,7 +272,7 @@ ULONG CDECL ldap_search_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, W * ldap_search_stA (WLDAP32.@) */ ULONG CDECL ldap_search_stA( LDAP *ld, const PCHAR base, ULONG scope, const PCHAR filter, char **attrs, - ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ) + ULONG attrsonly, struct l_timeval *timeout, WLDAP32_LDAPMessage **res ) { ULONG ret = WLDAP32_LDAP_NO_MEMORY; WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL; @@ -304,7 +299,7 @@ exit: * ldap_search_stW (WLDAP32.@) */ ULONG CDECL ldap_search_stW( LDAP *ld, const PWCHAR base, ULONG scope, const PWCHAR filter, WCHAR **attrs, - ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ) + ULONG attrsonly, struct l_timeval *timeout, WLDAP32_LDAPMessage **res ) { TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, timeout, res ); diff --git a/dlls/wldap32/tests/ber.c b/dlls/wldap32/tests/ber.c index 64565efbcbe..4d2f825e59a 100644 --- a/dlls/wldap32/tests/ber.c +++ b/dlls/wldap32/tests/ber.c @@ -31,7 +31,7 @@ static void test_ber_printf(void) struct berval *bv;
ber = ber_alloc_t( 0 ); - todo_wine ok( ber == NULL, "ber_alloc_t succeeded\n" ); + ok( ber == NULL, "ber_alloc_t succeeded\n" );
ber = ber_alloc_t( LBER_USE_DER ); ok( ber != NULL, "ber_alloc_t failed\n" ); diff --git a/dlls/wldap32/value.c b/dlls/wldap32/value.c index 4c58227e299..54addd7ad70 100644 --- a/dlls/wldap32/value.c +++ b/dlls/wldap32/value.c @@ -23,7 +23,6 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" -#include "winldap.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -33,10 +32,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(wldap32); /*********************************************************************** * ldap_count_values_len (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_count_values_len( struct berval **values ) +ULONG CDECL WLDAP32_ldap_count_values_len( struct WLDAP32_berval **values ) { ULONG ret = 0; - struct berval **ptr = values; + struct WLDAP32_berval **ptr = values;
TRACE( "(%p)\n", values );
@@ -78,7 +77,7 @@ ULONG CDECL ldap_count_valuesW( WCHAR **values ) /*********************************************************************** * ldap_get_valuesA (WLDAP32.@) */ -char ** CDECL ldap_get_valuesA( LDAP *ld, LDAPMessage *entry, char *attr ) +char ** CDECL ldap_get_valuesA( LDAP *ld, WLDAP32_LDAPMessage *entry, char *attr ) { char **ret; WCHAR *attrW = NULL, **retW; @@ -95,7 +94,7 @@ char ** CDECL ldap_get_valuesA( LDAP *ld, LDAPMessage *entry, char *attr ) return ret; }
-static char *bv2str( struct bervalU *bv ) +static char *bv2str( struct berval *bv ) { char *str = NULL; unsigned int len = bv->bv_len; @@ -108,10 +107,10 @@ static char *bv2str( struct bervalU *bv ) return str; }
-static char **bv2str_array( struct bervalU **bv ) +static char **bv2str_array( struct berval **bv ) { unsigned int len = 0, i = 0; - struct bervalU **p = bv; + struct berval **p = bv; char **str;
while (*p) @@ -141,24 +140,22 @@ static char **bv2str_array( struct bervalU **bv ) /*********************************************************************** * ldap_get_valuesW (WLDAP32.@) */ -WCHAR ** CDECL ldap_get_valuesW( LDAP *ld, LDAPMessage *entry, WCHAR *attr ) +WCHAR ** CDECL ldap_get_valuesW( LDAP *ld, WLDAP32_LDAPMessage *entry, WCHAR *attr ) { WCHAR **ret = NULL; char *attrU, **retU; - struct bervalU **bv; + struct berval **bv;
TRACE( "(%p, %p, %s)\n", ld, entry, debugstr_w(attr) );
if (ld && entry && attr && (attrU = strWtoU( attr ))) { - struct ldap_get_values_len_params params = { CTX(ld), MSG(entry), attrU, &bv }; - - if (!LDAP_CALL( ldap_get_values_len, ¶ms )) + if ((bv = ldap_get_values_len( CTX(ld), MSG(entry), attrU ))) { retU = bv2str_array( bv ); ret = strarrayUtoW( retU );
- LDAP_CALL( ldap_value_free_len, bv ); + ldap_value_free_len( bv ); strarrayfreeU( retU ); } free( attrU ); @@ -169,10 +166,10 @@ WCHAR ** CDECL ldap_get_valuesW( LDAP *ld, LDAPMessage *entry, WCHAR *attr ) /*********************************************************************** * ldap_get_values_lenA (WLDAP32.@) */ -struct berval ** CDECL ldap_get_values_lenA( LDAP *ld, LDAPMessage *message, char *attr ) +struct WLDAP32_berval ** CDECL ldap_get_values_lenA( LDAP *ld, LDAPMessage *message, char *attr ) { WCHAR *attrW; - struct berval **ret; + struct WLDAP32_berval **ret;
TRACE( "(%p, %p, %s)\n", ld, message, debugstr_a(attr) );
@@ -187,24 +184,21 @@ struct berval ** CDECL ldap_get_values_lenA( LDAP *ld, LDAPMessage *message, cha /*********************************************************************** * ldap_get_values_lenW (WLDAP32.@) */ -struct berval ** CDECL ldap_get_values_lenW( LDAP *ld, LDAPMessage *message, WCHAR *attr ) +struct WLDAP32_berval ** CDECL ldap_get_values_lenW( LDAP *ld, WLDAP32_LDAPMessage *message, WCHAR *attr ) { char *attrU = NULL; - struct bervalU **retU; - struct berval **ret = NULL; + struct berval **retU; + struct WLDAP32_berval **ret = NULL;
TRACE( "(%p, %p, %s)\n", ld, message, debugstr_w(attr) );
if (ld && message && attr && (attrU = strWtoU( attr ))) { - struct ldap_get_values_len_params params = { CTX(ld), MSG(message), attrU, &retU }; - - if (!LDAP_CALL( ldap_get_values_len, ¶ms )) + if ((retU = ldap_get_values_len( CTX(ld), MSG(message), attrU ))) { ret = bvarrayUtoW( retU ); bvarrayfreeU( retU ); } - free( attrU ); } return ret; @@ -213,7 +207,7 @@ struct berval ** CDECL ldap_get_values_lenW( LDAP *ld, LDAPMessage *message, WCH /*********************************************************************** * ldap_value_free_len (WLDAP32.@) */ -ULONG CDECL WLDAP32_ldap_value_free_len( struct berval **values ) +ULONG CDECL WLDAP32_ldap_value_free_len( struct WLDAP32_berval **values ) { TRACE( "(%p)\n", values );
diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h index 5df5683a84a..49114dcf4ba 100644 --- a/dlls/wldap32/winldap_private.h +++ b/dlls/wldap32/winldap_private.h @@ -22,7 +22,9 @@ #include <stdlib.h> #include "winternl.h" #include "winnls.h" -#include "libldap.h" + +#include <lber.h> +#include <ldap.h>
#define WLDAP32_LBER_ERROR (~0l)
@@ -176,11 +178,175 @@ typedef enum { #define WLDAP32_LDAP_AUTH_DPA (WLDAP32_LDAP_AUTH_OTHERKIND | 0x2000) #define WLDAP32_LDAP_AUTH_DIGEST (WLDAP32_LDAP_AUTH_OTHERKIND | 0x4000)
+typedef struct WLDAP32_berval +{ + ULONG bv_len; + char *bv_val; +} LDAP_BERVAL, *PLDAP_BERVAL, BERVAL, *PBERVAL; + typedef struct WLDAP32_berelement { char *opaque; } WLDAP32_BerElement;
+typedef struct ldap +{ + struct + { + UINT_PTR sb_sd; + UCHAR Reserved1[41]; + ULONG_PTR sb_naddr; + UCHAR Reserved2[24]; + } ld_sb; + + char *ld_host; + ULONG ld_version; + UCHAR ld_lberoptions; + ULONG ld_deref; + ULONG ld_timelimit; + ULONG ld_sizelimit; + ULONG ld_errno; + char *ld_matched; + char *ld_error; + ULONG ld_msgid; + UCHAR Reserved3[25]; + ULONG ld_cldaptries; + ULONG ld_cldaptimeout; + ULONG ld_refhoplimit; + ULONG ld_options; +} LDAP, *PLDAP; + +typedef struct l_timeval +{ + LONG tv_sec; + LONG tv_usec; +} LDAP_TIMEVAL, *PLDAP_TIMEVAL; + +#define LDAP_PAGED_RESULT_OID_STRING "1.2.840.113556.1.4.319" +#define LDAP_SERVER_RESP_SORT_OID "1.2.840.113556.1.4.474" +#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" + +#define LDAP_PAGED_RESULT_OID_STRING_W L"1.2.840.113556.1.4.319" +#define LDAP_SERVER_RESP_SORT_OID_W L"1.2.840.113556.1.4.474" +#define LDAP_CONTROL_VLVRESPONSE_W L"2.16.840.1.113730.3.4.10" + +typedef struct ldapcontrolA +{ + char *ldctl_oid; + struct WLDAP32_berval ldctl_value; + BOOLEAN ldctl_iscritical; +} LDAPControlA, *PLDAPControlA; + +typedef struct ldapcontrolW +{ + WCHAR *ldctl_oid; + struct WLDAP32_berval ldctl_value; + BOOLEAN ldctl_iscritical; +} LDAPControlW, *PLDAPControlW; + +typedef struct ldapmodA { + ULONG mod_op; + char *mod_type; + union { + char **modv_strvals; + struct WLDAP32_berval **modv_bvals; + } mod_vals; +} LDAPModA, *PLDAPModA; + +typedef struct ldapmodW { + ULONG mod_op; + WCHAR *mod_type; + union { + WCHAR **modv_strvals; + struct WLDAP32_berval **modv_bvals; + } mod_vals; +} LDAPModW, *PLDAPModW; + +typedef struct ldapsortkeyA +{ + char *sk_attrtype; + char *sk_matchruleoid; + BOOLEAN sk_reverseorder; +} LDAPSortKeyA, *PLDAPSortKeyA; + +typedef struct ldapsortkeyW +{ + WCHAR *sk_attrtype; + WCHAR *sk_matchruleoid; + BOOLEAN sk_reverseorder; +} LDAPSortKeyW, *PLDAPSortKeyW; + +typedef struct WLDAP32_ldapvlvinfo +{ + int ldvlv_version; + ULONG ldvlv_before_count; + ULONG ldvlv_after_count; + ULONG ldvlv_offset; + ULONG ldvlv_count; + BERVAL *ldvlv_attrvalue; + BERVAL *ldvlv_context; + void *ldvlv_extradata; +} WLDAP32_LDAPVLVInfo, *WLDAP32_PLDAPVLVInfo; + +typedef struct ldapmsg +{ + ULONG lm_msgid; + ULONG lm_msgtype; + void *lm_ber; + struct ldapmsg *lm_chain; + struct ldapmsg *lm_next; + ULONG lm_time; + + LDAP *Connection; + void *Request; + ULONG lm_returncode; + USHORT lm_referral; + BOOLEAN lm_chased; + BOOLEAN lm_eom; + BOOLEAN ConnectionReferenced; +} WLDAP32_LDAPMessage, *WLDAP32_PLDAPMessage; + +typedef struct ldap_version_info +{ + ULONG lv_size; + ULONG lv_major; + ULONG lv_minor; +} LDAP_VERSION_INFO, *PLDAP_VERSION_INFO; + +typedef struct ldap_apifeature_infoA +{ + int ldapaif_info_version; + char *ldapaif_name; + int ldapaif_version; +} LDAPAPIFeatureInfoA; + +typedef struct ldap_apifeature_infoW +{ + int ldapaif_info_version; + WCHAR *ldapaif_name; + int ldapaif_version; +} LDAPAPIFeatureInfoW; + +typedef struct ldapapiinfoA +{ + int ldapai_info_version; + int ldapai_api_version; + int ldapai_protocol_version; + char **ldapai_extensions; + char *ldapai_vendor_name; + int ldapai_vendor_version; +} LDAPAPIInfoA; + +typedef struct ldapapiinfoW +{ + int ldapai_info_version; + int ldapai_api_version; + int ldapai_protocol_version; + WCHAR **ldapai_extensions; + WCHAR *ldapai_vendor_name; + int ldapai_vendor_version; +} LDAPAPIInfoW; + typedef struct ldapsearch { WCHAR *dn; @@ -192,13 +358,13 @@ typedef struct ldapsearch LDAPControlW **clientctrls; struct l_timeval timeout; ULONG sizelimit; - struct berval *cookie; + struct WLDAP32_berval *cookie; } LDAPSearch;
-#define CTX(ld) (*(void **)ld->Reserved3) -#define SERVER_CTRLS(ld) (*(void **)(ld->Reserved3 + sizeof(void *))) +#define CTX(ld) (*(LDAP **)ld->Reserved3) +#define SERVER_CTRLS(ld) (*(struct berval ***)(ld->Reserved3 + sizeof(LDAP *))) #define MSG(entry) (entry->Request) -#define BER(ber) (ber->opaque) +#define BER(ber) ((BerElement *)((ber)->opaque))
WLDAP32_BerElement * CDECL WLDAP32_ber_alloc_t( int ); BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL * ); @@ -214,6 +380,158 @@ ULONG CDECL WLDAP32_ber_skip_tag( WLDAP32_BerElement *, ULONG * ); int WINAPIV WLDAP32_ber_printf( WLDAP32_BerElement *, char *, ... ); ULONG WINAPIV WLDAP32_ber_scanf( WLDAP32_BerElement *, char *, ... );
+ULONG CDECL ldap_addA( LDAP *, char *, LDAPModA ** ); +ULONG CDECL ldap_addW( LDAP *, WCHAR *, LDAPModW ** ); +ULONG CDECL ldap_add_extA( LDAP *, char *, LDAPModA **, LDAPControlA **, LDAPControlA **, ULONG * ); +ULONG CDECL ldap_add_extW( LDAP *, WCHAR *, LDAPModW **, LDAPControlW **, LDAPControlW **, ULONG * ); +ULONG CDECL ldap_add_ext_sA( LDAP *, char *, LDAPModA **, LDAPControlA **, LDAPControlA ** ); +ULONG CDECL ldap_add_ext_sW( LDAP *, WCHAR *, LDAPModW **, LDAPControlW **, LDAPControlW ** ); +ULONG CDECL ldap_add_sA( LDAP *, char *, LDAPModA ** ); +ULONG CDECL ldap_add_sW( LDAP *, WCHAR *, LDAPModW ** ); +ULONG CDECL ldap_bindA( LDAP *, char *, char *, ULONG ); +ULONG CDECL ldap_bindW( LDAP *, WCHAR *, WCHAR *, ULONG ); +ULONG CDECL ldap_bind_sA( LDAP *, char *, char *, ULONG ); +ULONG CDECL ldap_bind_sW( LDAP *, WCHAR *, WCHAR *, ULONG ); +ULONG CDECL ldap_sasl_bindA( LDAP *, const PCHAR, const PCHAR, const BERVAL *, LDAPControlA **, + LDAPControlA **, int * ); +ULONG CDECL ldap_sasl_bindW( LDAP *, const PWCHAR, const PWCHAR, const BERVAL *, LDAPControlW **, + LDAPControlW **, int * ); +ULONG CDECL ldap_sasl_bind_sA( LDAP *,const PCHAR, const PCHAR, const BERVAL *, LDAPControlA **, + LDAPControlA **, BERVAL ** ); +ULONG CDECL ldap_sasl_bind_sW( LDAP *,const PWCHAR, const PWCHAR ,const BERVAL *, LDAPControlW **, + LDAPControlW **, BERVAL ** ); +ULONG CDECL ldap_simple_bindA( LDAP *, char *, char * ); +ULONG CDECL ldap_simple_bindW( LDAP *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_simple_bind_sA( LDAP *, char *, char * ); +ULONG CDECL ldap_simple_bind_sW( LDAP *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_compareA( LDAP *, char *, char *, char * ); +ULONG CDECL ldap_compareW( LDAP *, WCHAR *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_compare_extA( LDAP *, char *, char *, char *, struct WLDAP32_berval *, LDAPControlA **, + LDAPControlA **, ULONG* ); +ULONG CDECL ldap_compare_extW( LDAP *, WCHAR *, WCHAR *, WCHAR *, struct WLDAP32_berval *, LDAPControlW **, + LDAPControlW **, ULONG * ); +ULONG CDECL ldap_compare_ext_sA( LDAP *, char *, char *, char *, struct WLDAP32_berval *, LDAPControlA **, + LDAPControlA ** ); +ULONG CDECL ldap_compare_ext_sW( LDAP *, WCHAR *, WCHAR *, WCHAR *, struct WLDAP32_berval *, LDAPControlW **, + LDAPControlW ** ); +ULONG CDECL ldap_compare_sA( LDAP *, char *, char *, char * ); +ULONG CDECL ldap_compare_sW( LDAP *, WCHAR *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_create_sort_controlA( LDAP *, LDAPSortKeyA **, UCHAR, LDAPControlA ** ); +ULONG CDECL ldap_create_sort_controlW( LDAP *, LDAPSortKeyW **, UCHAR, LDAPControlW ** ); +int CDECL ldap_create_vlv_controlA( LDAP *, WLDAP32_LDAPVLVInfo *, UCHAR, LDAPControlA ** ); +int CDECL ldap_create_vlv_controlW( LDAP *, WLDAP32_LDAPVLVInfo *, UCHAR, LDAPControlW ** ); +ULONG CDECL ldap_deleteA( LDAP *, char * ); +ULONG CDECL ldap_deleteW( LDAP *, WCHAR * ); +ULONG CDECL ldap_delete_extA( LDAP *, char *, LDAPControlA **, LDAPControlA **, ULONG * ); +ULONG CDECL ldap_delete_extW( LDAP *, WCHAR *, LDAPControlW **, LDAPControlW **, ULONG * ); +ULONG CDECL ldap_delete_ext_sA( LDAP *, char *, LDAPControlA **, LDAPControlA ** ); +ULONG CDECL ldap_delete_ext_sW( LDAP *, WCHAR *, LDAPControlW **, LDAPControlW ** ); +ULONG CDECL ldap_delete_sA( LDAP *, char * ); +ULONG CDECL ldap_delete_sW( LDAP *, WCHAR * ); +char * CDECL ldap_dn2ufnA( char * ); +WCHAR * CDECL ldap_dn2ufnW( WCHAR * ); +void CDECL ldap_memfreeA( char * ); +void CDECL ldap_memfreeW( WCHAR * ); +char ** CDECL ldap_explode_dnA( char *, ULONG ); +WCHAR ** CDECL ldap_explode_dnW( WCHAR *, ULONG ); +ULONG CDECL ldap_value_freeA( char ** ); +ULONG CDECL ldap_value_freeW( WCHAR ** ); +char * CDECL ldap_get_dnA( LDAP *, WLDAP32_LDAPMessage * ); +WCHAR * CDECL ldap_get_dnW( LDAP *, WLDAP32_LDAPMessage * ); +ULONG CDECL ldap_ufn2dnA( char *, char ** ); +ULONG CDECL ldap_ufn2dnW( WCHAR *, WCHAR ** ); +ULONG CDECL ldap_extended_operationA( LDAP *, char *, struct WLDAP32_berval *, LDAPControlA **, LDAPControlA **, + ULONG * ); +ULONG CDECL ldap_extended_operationW( LDAP *, WCHAR *, struct WLDAP32_berval *, LDAPControlW **, LDAPControlW **, + ULONG * ); +ULONG CDECL ldap_extended_operation_sA( LDAP *, char *, struct WLDAP32_berval *, LDAPControlA **, LDAPControlA **, + char **, struct WLDAP32_berval ** ); +ULONG CDECL ldap_extended_operation_sW( LDAP *, WCHAR *, struct WLDAP32_berval *, LDAPControlW **, LDAPControlW **, + WCHAR **, struct WLDAP32_berval ** ); +LDAP * CDECL cldap_openA( char *, ULONG ); +LDAP * CDECL cldap_openW( WCHAR *, ULONG ); +LDAP * CDECL ldap_initA( const PCHAR, ULONG ); +LDAP * CDECL ldap_initW( const PWCHAR, ULONG ); +LDAP * CDECL ldap_openA( char *, ULONG ); +LDAP * CDECL ldap_openW( WCHAR *, ULONG ); +LDAP * CDECL ldap_sslinitA( char *, ULONG, int ); +LDAP * CDECL ldap_sslinitW( WCHAR *, ULONG, int ); +ULONG CDECL ldap_start_tls_sA( LDAP *, ULONG *, WLDAP32_LDAPMessage **, LDAPControlA **, LDAPControlA ** ); +ULONG CDECL ldap_start_tls_sW( LDAP *, ULONG *, WLDAP32_LDAPMessage **, LDAPControlW **, LDAPControlW ** ); +ULONG CDECL ldap_check_filterA( LDAP *, char * ); +ULONG CDECL ldap_check_filterW( LDAP *, WCHAR * ); +char * CDECL ldap_first_attributeA( LDAP *, WLDAP32_LDAPMessage *, WLDAP32_BerElement ** ); +WCHAR * CDECL ldap_first_attributeW( LDAP *, WLDAP32_LDAPMessage *, WLDAP32_BerElement ** ); +ULONG CDECL WLDAP32_ldap_msgfree( WLDAP32_LDAPMessage * ); +char * CDECL ldap_next_attributeA( LDAP *, WLDAP32_LDAPMessage *, WLDAP32_BerElement * ); +WCHAR * CDECL ldap_next_attributeW( LDAP *, WLDAP32_LDAPMessage *, WLDAP32_BerElement * ); +ULONG CDECL WLDAP32_ldap_result( LDAP *, ULONG, ULONG, struct l_timeval *, WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_modifyA( LDAP *, char *, LDAPModA ** ); +ULONG CDECL ldap_modifyW( LDAP *, WCHAR *, LDAPModW ** ); +ULONG CDECL ldap_modify_extA( LDAP *, char *, LDAPModA **, LDAPControlA **, LDAPControlA **, ULONG * ); +ULONG CDECL ldap_modify_extW( LDAP *, WCHAR *, LDAPModW **, LDAPControlW **, LDAPControlW **, ULONG * ); +ULONG CDECL ldap_modify_ext_sA( LDAP *, char *, LDAPModA **, LDAPControlA **, LDAPControlA ** ); +ULONG CDECL ldap_modify_ext_sW( LDAP *, WCHAR *, LDAPModW **, LDAPControlW **, LDAPControlW ** ); +ULONG CDECL ldap_modify_sA( LDAP *, char *, LDAPModA ** ); +ULONG CDECL ldap_modify_sW( LDAP *, WCHAR *, LDAPModW ** ); +ULONG CDECL ldap_modrdnA( LDAP *, char *, char * ); +ULONG CDECL ldap_modrdnW( LDAP *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_modrdn2A( LDAP *, char *, char *, int ); +ULONG CDECL ldap_modrdn2W( LDAP *, WCHAR *, WCHAR *, int ); +ULONG CDECL ldap_modrdn2_sA( LDAP *, char *, char *, int ); +ULONG CDECL ldap_modrdn2_sW( LDAP *, WCHAR *, WCHAR *, int ); +ULONG CDECL ldap_modrdn_sA( LDAP *, char *, char * ); +ULONG CDECL ldap_modrdn_sW( LDAP *, WCHAR *, WCHAR * ); +ULONG CDECL ldap_get_optionA( LDAP *, int, void * ); +ULONG CDECL ldap_get_optionW( LDAP *, int, void * ); +ULONG CDECL ldap_set_optionA( LDAP *, int, void * ); +ULONG CDECL ldap_set_optionW( LDAP *, int, void * ); +ULONG CDECL ldap_create_page_controlA( LDAP *, ULONG, struct WLDAP32_berval *, UCHAR, LDAPControlA ** ); +ULONG CDECL ldap_create_page_controlW( LDAP *, ULONG, struct WLDAP32_berval *, UCHAR, LDAPControlW ** ); +ULONG CDECL ldap_control_freeA( LDAPControlA * ); +ULONG CDECL ldap_control_freeW( LDAPControlW * ); +ULONG CDECL ldap_search_ext_sA( LDAP *, char *, ULONG, char *, char **, ULONG, LDAPControlA **, LDAPControlA **, + struct l_timeval *, ULONG, WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_search_ext_sW( LDAP *, WCHAR *, ULONG, WCHAR *, WCHAR **, ULONG, LDAPControlW **, LDAPControlW **, + struct l_timeval *, ULONG, WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_get_paged_count( LDAP *, LDAPSearch *, ULONG *, WLDAP32_LDAPMessage * ); +ULONG CDECL ldap_parse_resultA( LDAP *, WLDAP32_LDAPMessage *, ULONG *, char **, char **, char ***, + LDAPControlA ***, BOOLEAN ); +ULONG CDECL ldap_parse_resultW( LDAP *, WLDAP32_LDAPMessage *, ULONG *, WCHAR **, WCHAR **, WCHAR ***, + LDAPControlW ***, BOOLEAN ); +ULONG CDECL ldap_parse_page_controlA( LDAP *, LDAPControlA **, ULONG *, struct WLDAP32_berval ** ); +ULONG CDECL ldap_parse_page_controlW( LDAP *, LDAPControlW **, ULONG *, struct WLDAP32_berval ** ); +ULONG CDECL ldap_controls_freeA( LDAPControlA ** ); +ULONG CDECL ldap_controls_freeW( LDAPControlW ** ); +ULONG CDECL ldap_parse_extended_resultA( LDAP *, WLDAP32_LDAPMessage *, char **, struct WLDAP32_berval **, BOOLEAN ); +ULONG CDECL ldap_parse_extended_resultW( LDAP *, WLDAP32_LDAPMessage *, WCHAR **, struct WLDAP32_berval **, BOOLEAN ); +ULONG CDECL ldap_parse_referenceA( LDAP *, WLDAP32_LDAPMessage *, char *** ); +ULONG CDECL ldap_parse_referenceW( LDAP *, WLDAP32_LDAPMessage *, WCHAR *** ); +ULONG CDECL ldap_parse_sort_controlA( LDAP *, LDAPControlA **, ULONG *, char ** ); +ULONG CDECL ldap_parse_sort_controlW( LDAP *, LDAPControlW **, ULONG *, WCHAR ** ); +int CDECL ldap_parse_vlv_controlA( LDAP *, LDAPControlA **, ULONG *, ULONG *, struct WLDAP32_berval **, int * ); +int CDECL ldap_parse_vlv_controlW( LDAP *, LDAPControlW **, ULONG *, ULONG *, struct WLDAP32_berval **, int * ); +ULONG CDECL ldap_rename_extA( LDAP *, char *, char *, char *, int, LDAPControlA **, LDAPControlA **, ULONG * ); +ULONG CDECL ldap_rename_extW( LDAP *, WCHAR *, WCHAR *, WCHAR *, int, LDAPControlW **, LDAPControlW **, ULONG * ); +ULONG CDECL ldap_rename_ext_sA( LDAP *, char *, char *, char *, int, LDAPControlA **, LDAPControlA ** ); +ULONG CDECL ldap_rename_ext_sW( LDAP *, WCHAR *, WCHAR *, WCHAR *, int, LDAPControlW **, LDAPControlW ** ); +ULONG CDECL ldap_searchA( LDAP *, char *, ULONG, char *, char **, ULONG ); +ULONG CDECL ldap_searchW( LDAP *, WCHAR *, ULONG, WCHAR *, WCHAR **, ULONG ); +ULONG CDECL ldap_search_extA( LDAP *, char *, ULONG, char *, char **, ULONG, LDAPControlA **, LDAPControlA **, + ULONG, ULONG, ULONG * ); +ULONG CDECL ldap_search_extW( LDAP *, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG, LDAPControlW **, LDAPControlW **, + ULONG, ULONG, ULONG * ); +ULONG CDECL ldap_search_sA( LDAP *, char *, ULONG, char *, char **, ULONG, WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_search_sW( LDAP *, WCHAR *, ULONG, WCHAR *, WCHAR **, ULONG, WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_search_stA( LDAP *, const PCHAR, ULONG, const PCHAR, char **, ULONG, struct l_timeval *, + WLDAP32_LDAPMessage ** ); +ULONG CDECL ldap_search_stW( LDAP *, const PWCHAR, ULONG, const PWCHAR, WCHAR **, ULONG, struct l_timeval *, + WLDAP32_LDAPMessage ** ); +char ** CDECL ldap_get_valuesA( LDAP *, WLDAP32_LDAPMessage *, char * ); +WCHAR ** CDECL ldap_get_valuesW( LDAP *, WLDAP32_LDAPMessage *, WCHAR * ); +struct WLDAP32_berval ** CDECL ldap_get_values_lenA( LDAP *, LDAPMessage *, char * ); +struct WLDAP32_berval ** CDECL ldap_get_values_lenW( LDAP *, LDAPMessage *, WCHAR * ); + ULONG map_error( int ) DECLSPEC_HIDDEN;
static inline char *strdupU( const char *src ) @@ -288,9 +606,9 @@ static inline WCHAR *strnAtoW( const char *str, DWORD in_len, DWORD *out_len ) return ret; }
-static inline DWORD bvarraylenW( struct berval **bv ) +static inline DWORD bvarraylenW( struct WLDAP32_berval **bv ) { - struct berval **p = bv; + struct WLDAP32_berval **p = bv; while (*p) p++; return p - bv; } @@ -304,42 +622,41 @@ static inline DWORD strarraylenW( WCHAR **strarray )
static inline char **strarrayWtoU( WCHAR **strarray ) { - char **strarrayU = NULL; + char **ret = NULL; DWORD size;
if (strarray) { size = sizeof(char *) * (strarraylenW( strarray ) + 1); - if ((strarrayU = malloc( size ))) + if ((ret = malloc( size ))) { WCHAR **p = strarray; - char **q = strarrayU; + char **q = ret;
while (*p) *q++ = strWtoU( *p++ ); *q = NULL; } } - return strarrayU; + return ret; }
static inline WCHAR **strarraydupW( WCHAR **strarray ) { - WCHAR **strarrayW = NULL; + WCHAR **ret = NULL; DWORD size;
if (strarray) { size = sizeof(WCHAR *) * (strarraylenW( strarray ) + 1); - if ((strarrayW = malloc( size ))) + if ((ret = malloc( size ))) { - WCHAR **p = strarray; - WCHAR **q = strarrayW; + WCHAR **p = strarray, **q = ret;
while (*p) *q++ = strdupW( *p++ ); *q = NULL; } } - return strarrayW; + return ret; }
static inline char *strWtoA( const WCHAR *str ) @@ -355,22 +672,22 @@ static inline char *strWtoA( const WCHAR *str )
static inline char **strarrayWtoA( WCHAR **strarray ) { - char **strarrayA = NULL; + char **ret = NULL; DWORD size;
if (strarray) { size = sizeof(char *) * (strarraylenW( strarray ) + 1); - if ((strarrayA = malloc( size ))) + if ((ret = malloc( size ))) { WCHAR **p = strarray; - char **q = strarrayA; + char **q = ret;
while (*p) *q++ = strWtoA( *p++ ); *q = NULL; } } - return strarrayA; + return ret; }
static inline DWORD modarraylenW( LDAPModW **modarray ) @@ -380,132 +697,132 @@ static inline DWORD modarraylenW( LDAPModW **modarray ) return p - modarray; }
-static inline struct bervalU *bervalWtoU( const struct berval *bv ) +static inline struct berval *bervalWtoU( const struct WLDAP32_berval *bv ) { - struct bervalU *berval; - DWORD size = sizeof(*berval) + bv->bv_len; + struct berval *ret; + DWORD size = sizeof(*ret) + bv->bv_len;
- if ((berval = malloc( size ))) + if ((ret = malloc( size ))) { - char *val = (char *)(berval + 1); + char *val = (char *)(ret + 1);
- berval->bv_len = bv->bv_len; - berval->bv_val = val; + ret->bv_len = bv->bv_len; + ret->bv_val = val; memcpy( val, bv->bv_val, bv->bv_len ); } - return berval; + return ret; }
-static inline DWORD bvarraylenU( struct bervalU **bv ) +static inline DWORD bvarraylenU( struct berval **bv ) { - struct bervalU **p = bv; + struct berval **p = bv; while (*p) p++; return p - bv; }
-static inline struct berval *bervalUtoW( const struct bervalU *bv ) +static inline struct WLDAP32_berval *bervalUtoW( const struct berval *bv ) { - struct berval *berval; - DWORD size = sizeof(*berval) + bv->bv_len; + struct WLDAP32_berval *ret; + DWORD size = sizeof(*ret) + bv->bv_len;
assert( bv->bv_len <= ~0u );
- if ((berval = malloc( size ))) + if ((ret = malloc( size ))) { - char *val = (char *)(berval + 1); + char *val = (char *)(ret + 1);
- berval->bv_len = bv->bv_len; - berval->bv_val = val; + ret->bv_len = bv->bv_len; + ret->bv_val = val; memcpy( val, bv->bv_val, bv->bv_len ); } - return berval; + return ret; }
-static inline struct berval **bvarrayUtoW( struct bervalU **bv ) +static inline struct WLDAP32_berval **bvarrayUtoW( struct berval **bv ) { - struct berval **berval = NULL; + struct WLDAP32_berval **ret = NULL; DWORD size;
if (bv) { - size = sizeof(*berval) * (bvarraylenU( bv ) + 1); - if ((berval = malloc( size ))) + size = sizeof(*ret) * (bvarraylenU( bv ) + 1); + if ((ret = malloc( size ))) { - struct bervalU **p = bv; - struct berval **q = berval; + struct berval **p = bv; + struct WLDAP32_berval **q = ret;
while (*p) *q++ = bervalUtoW( *p++ ); *q = NULL; } } - return berval; + return ret; }
-static inline void bvfreeU( struct bervalU *berval ) +static inline void bvfreeU( struct berval *berval ) { free( berval ); }
-static inline struct bervalU **bvarrayWtoU( struct berval **bv ) +static inline struct berval **bvarrayWtoU( struct WLDAP32_berval **bv ) { - struct bervalU **berval = NULL; + struct berval **ret = NULL; DWORD size;
if (bv) { - size = sizeof(*berval) * (bvarraylenW( bv ) + 1); - if ((berval = malloc( size ))) + size = sizeof(*ret) * (bvarraylenW( bv ) + 1); + if ((ret = malloc( size ))) { - struct berval **p = bv; - struct bervalU **q = berval; + struct WLDAP32_berval **p = bv; + struct berval **q = ret;
while (*p) *q++ = bervalWtoU( *p++ ); *q = NULL; } } - return berval; + return ret; }
-static inline LDAPModU *modWtoU( const LDAPModW *mod ) +static inline LDAPMod *modWtoU( const LDAPModW *mod ) { - LDAPModU *modU; + LDAPMod *ret;
- if ((modU = malloc( sizeof(*modU) ))) + if ((ret = malloc( sizeof(*ret) ))) { - modU->mod_op = mod->mod_op; - modU->mod_type = strWtoU( mod->mod_type ); + ret->mod_op = mod->mod_op; + ret->mod_type = strWtoU( mod->mod_type );
if (mod->mod_op & LDAP_MOD_BVALUES) - modU->mod_vals.modv_bvals = bvarrayWtoU( mod->mod_vals.modv_bvals ); + ret->mod_vals.modv_bvals = bvarrayWtoU( mod->mod_vals.modv_bvals ); else - modU->mod_vals.modv_strvals = strarrayWtoU( mod->mod_vals.modv_strvals ); + ret->mod_vals.modv_strvals = strarrayWtoU( mod->mod_vals.modv_strvals ); } - return modU; + return ret; }
-static inline LDAPModU **modarrayWtoU( LDAPModW **modarray ) +static inline LDAPMod **modarrayWtoU( LDAPModW **modarray ) { - LDAPModU **modarrayU = NULL; + LDAPMod **ret = NULL; DWORD size;
if (modarray) { - size = sizeof(LDAPModU *) * (modarraylenW( modarray ) + 1); - if ((modarrayU = malloc( size ))) + size = sizeof(*ret) * (modarraylenW( modarray ) + 1); + if ((ret = malloc( size ))) { LDAPModW **p = modarray; - LDAPModU **q = modarrayU; + LDAPMod **q = ret;
while (*p) *q++ = modWtoU( *p++ ); *q = NULL; } } - return modarrayU; + return ret; }
-static inline void bvarrayfreeU( struct bervalU **bv ) +static inline void bvarrayfreeU( struct berval **bv ) { - struct bervalU **p = bv; + struct berval **p = bv; while (*p) free( *p++ ); free( bv ); } @@ -520,7 +837,7 @@ static inline void strarrayfreeU( char **strarray ) } }
-static inline void modfreeU( LDAPModU *mod ) +static inline void modfreeU( LDAPMod *mod ) { if (mod->mod_op & LDAP_MOD_BVALUES) bvarrayfreeU( mod->mod_vals.modv_bvals ); @@ -529,11 +846,11 @@ static inline void modfreeU( LDAPModU *mod ) free( mod ); }
-static inline void modarrayfreeU( LDAPModU **modarray ) +static inline void modarrayfreeU( LDAPMod **modarray ) { if (modarray) { - LDAPModU **p = modarray; + LDAPMod **p = modarray; while (*p) modfreeU( *p++ ); free( modarray ); } @@ -546,40 +863,39 @@ static inline DWORD modarraylenA( LDAPModA **modarray ) return p - modarray; }
-static inline struct berval *bervalWtoW( const struct berval *bv ) +static inline struct WLDAP32_berval *bervalWtoW( const struct WLDAP32_berval *bv ) { - struct berval *berval; - DWORD size = sizeof(*berval) + bv->bv_len; + struct WLDAP32_berval *ret; + DWORD size = sizeof(*ret) + bv->bv_len;
- if ((berval = malloc( size ))) + if ((ret = malloc( size ))) { - char *val = (char *)(berval + 1); + char *val = (char *)(ret + 1);
- berval->bv_len = bv->bv_len; - berval->bv_val = val; + ret->bv_len = bv->bv_len; + ret->bv_val = val; memcpy( val, bv->bv_val, bv->bv_len ); } - return berval; + return ret; }
-static inline struct berval **bvarrayWtoW( struct berval **bv ) +static inline struct WLDAP32_berval **bvarrayWtoW( struct WLDAP32_berval **bv ) { - struct berval **berval = NULL; + struct WLDAP32_berval **ret = NULL; DWORD size;
if (bv) { - size = sizeof(*berval) * (bvarraylenW( bv ) + 1); - if ((berval = malloc( size ))) + size = sizeof(*ret) * (bvarraylenW( bv ) + 1); + if ((ret = malloc( size ))) { - struct berval **p = bv; - struct berval **q = berval; + struct WLDAP32_berval **p = bv, **q = ret;
while (*p) *q++ = bervalWtoW( *p++ ); *q = NULL; } } - return berval; + return ret; }
static inline DWORD strarraylenA( char **strarray ) @@ -591,64 +907,64 @@ static inline DWORD strarraylenA( char **strarray )
static inline WCHAR **strarrayAtoW( char **strarray ) { - WCHAR **strarrayW = NULL; + WCHAR **ret = NULL; DWORD size;
if (strarray) { - size = sizeof(WCHAR *) * (strarraylenA( strarray ) + 1); - if ((strarrayW = malloc( size ))) + size = sizeof(*ret) * (strarraylenA( strarray ) + 1); + if ((ret = malloc( size ))) { char **p = strarray; - WCHAR **q = strarrayW; + WCHAR **q = ret;
while (*p) *q++ = strAtoW( *p++ ); *q = NULL; } } - return strarrayW; + return ret; }
static inline LDAPModW *modAtoW( const LDAPModA *mod ) { - LDAPModW *modW; + LDAPModW *ret;
- if ((modW = malloc( sizeof(*modW) ))) + if ((ret = malloc( sizeof(*ret) ))) { - modW->mod_op = mod->mod_op; - modW->mod_type = strAtoW( mod->mod_type ); + ret->mod_op = mod->mod_op; + ret->mod_type = strAtoW( mod->mod_type );
if (mod->mod_op & LDAP_MOD_BVALUES) - modW->mod_vals.modv_bvals = bvarrayWtoW( mod->mod_vals.modv_bvals ); + ret->mod_vals.modv_bvals = bvarrayWtoW( mod->mod_vals.modv_bvals ); else - modW->mod_vals.modv_strvals = strarrayAtoW( mod->mod_vals.modv_strvals ); + ret->mod_vals.modv_strvals = strarrayAtoW( mod->mod_vals.modv_strvals ); } - return modW; + return ret; }
static inline LDAPModW **modarrayAtoW( LDAPModA **modarray ) { - LDAPModW **modarrayW = NULL; + LDAPModW **ret = NULL; DWORD size;
if (modarray) { - size = sizeof(LDAPModW *) * (modarraylenA( modarray ) + 1); - if ((modarrayW = malloc( size ))) + size = sizeof(*ret) * (modarraylenA( modarray ) + 1); + if ((ret = malloc( size ))) { LDAPModA **p = modarray; - LDAPModW **q = modarrayW; + LDAPModW **q = ret;
while (*p) *q++ = modAtoW( *p++ ); *q = NULL; } } - return modarrayW; + return ret; }
-static inline void bvarrayfreeW( struct berval **bv ) +static inline void bvarrayfreeW( struct WLDAP32_berval **bv ) { - struct berval **p = bv; + struct WLDAP32_berval **p = bv; while (*p) free( *p++ ); free( bv ); } @@ -691,7 +1007,7 @@ static inline DWORD controlarraylenA( LDAPControlA **controlarray )
static inline LDAPControlW *controlAtoW( const LDAPControlA *control ) { - LDAPControlW *controlW; + LDAPControlW *ret; DWORD len = control->ldctl_value.bv_len; char *val = NULL;
@@ -701,38 +1017,38 @@ static inline LDAPControlW *controlAtoW( const LDAPControlA *control ) memcpy( val, control->ldctl_value.bv_val, len ); }
- if (!(controlW = malloc( sizeof(*controlW) ))) + if (!(ret = malloc( sizeof(*ret) ))) { free( val ); return NULL; }
- controlW->ldctl_oid = strAtoW( control->ldctl_oid ); - controlW->ldctl_value.bv_len = len; - controlW->ldctl_value.bv_val = val; - controlW->ldctl_iscritical = control->ldctl_iscritical; + ret->ldctl_oid = strAtoW( control->ldctl_oid ); + ret->ldctl_value.bv_len = len; + ret->ldctl_value.bv_val = val; + ret->ldctl_iscritical = control->ldctl_iscritical;
- return controlW; + return ret; }
static inline LDAPControlW **controlarrayAtoW( LDAPControlA **controlarray ) { - LDAPControlW **controlarrayW = NULL; + LDAPControlW **ret = NULL; DWORD size;
if (controlarray) { - size = sizeof(LDAPControlW *) * (controlarraylenA( controlarray ) + 1); - if ((controlarrayW = malloc( size ))) + size = sizeof(*ret) * (controlarraylenA( controlarray ) + 1); + if ((ret = malloc( size ))) { LDAPControlA **p = controlarray; - LDAPControlW **q = controlarrayW; + LDAPControlW **q = ret;
while (*p) *q++ = controlAtoW( *p++ ); *q = NULL; } } - return controlarrayW; + return ret; }
static inline void controlfreeW( LDAPControlW *control ) @@ -764,7 +1080,7 @@ static inline DWORD controlarraylenW( LDAPControlW **controlarray )
static inline LDAPControlA *controlWtoA( const LDAPControlW *control ) { - LDAPControlA *controlA; + LDAPControlA *ret; DWORD len = control->ldctl_value.bv_len; char *val = NULL;
@@ -774,18 +1090,18 @@ static inline LDAPControlA *controlWtoA( const LDAPControlW *control ) memcpy( val, control->ldctl_value.bv_val, len ); }
- if (!(controlA = malloc( sizeof(*controlA) ))) + if (!(ret = malloc( sizeof(*ret) ))) { free( val ); return NULL; }
- controlA->ldctl_oid = strWtoA( control->ldctl_oid ); - controlA->ldctl_value.bv_len = len; - controlA->ldctl_value.bv_val = val; - controlA->ldctl_iscritical = control->ldctl_iscritical; + ret->ldctl_oid = strWtoA( control->ldctl_oid ); + ret->ldctl_value.bv_len = len; + ret->ldctl_value.bv_val = val; + ret->ldctl_iscritical = control->ldctl_iscritical;
- return controlA; + return ret; }
static inline void strarrayfreeA( char **strarray ) @@ -818,9 +1134,9 @@ static inline void controlarrayfreeA( LDAPControlA **controlarray ) } }
-static inline LDAPControlU *controlWtoU( const LDAPControlW *control ) +static inline LDAPControl *controlWtoU( const LDAPControlW *control ) { - LDAPControlU *controlU; + LDAPControl *ret; DWORD len = control->ldctl_value.bv_len; char *val = NULL;
@@ -830,41 +1146,41 @@ static inline LDAPControlU *controlWtoU( const LDAPControlW *control ) memcpy( val, control->ldctl_value.bv_val, len ); }
- if (!(controlU = malloc( sizeof(*controlU) ))) + if (!(ret = malloc( sizeof(*ret) ))) { free( val ); return NULL; }
- controlU->ldctl_oid = strWtoU( control->ldctl_oid ); - controlU->ldctl_value.bv_len = len; - controlU->ldctl_value.bv_val = val; - controlU->ldctl_iscritical = control->ldctl_iscritical; + ret->ldctl_oid = strWtoU( control->ldctl_oid ); + ret->ldctl_value.bv_len = len; + ret->ldctl_value.bv_val = val; + ret->ldctl_iscritical = control->ldctl_iscritical;
- return controlU; + return ret; }
-static inline LDAPControlU **controlarrayWtoU( LDAPControlW **controlarray ) +static inline LDAPControl **controlarrayWtoU( LDAPControlW **controlarray ) { - LDAPControlU **controlarrayU = NULL; + LDAPControl **ret = NULL; DWORD size;
if (controlarray) { - size = sizeof(LDAPControlU *) * (controlarraylenW( controlarray ) + 1); - if ((controlarrayU = malloc( size ))) + size = sizeof(*ret) * (controlarraylenW( controlarray ) + 1); + if ((ret = malloc( size ))) { LDAPControlW **p = controlarray; - LDAPControlU **q = controlarrayU; + LDAPControl **q = ret;
while (*p) *q++ = controlWtoU( *p++ ); *q = NULL; } } - return controlarrayU; + return ret; }
-static inline void controlfreeU( LDAPControlU *control ) +static inline void controlfreeU( LDAPControl *control ) { if (control) { @@ -874,26 +1190,26 @@ static inline void controlfreeU( LDAPControlU *control ) } }
-static inline void controlarrayfreeU( LDAPControlU **controlarray ) +static inline void controlarrayfreeU( LDAPControl **controlarray ) { if (controlarray) { - LDAPControlU **p = controlarray; + LDAPControl **p = controlarray; while (*p) controlfreeU( *p++ ); free( controlarray ); } }
-static inline DWORD controlarraylenU( LDAPControlU **controlarray ) +static inline DWORD controlarraylenU( LDAPControl **controlarray ) { - LDAPControlU **p = controlarray; + LDAPControl **p = controlarray; while (*p) p++; return p - controlarray; }
static inline LDAPControlW *controldupW( LDAPControlW *control ) { - LDAPControlW *controlW; + LDAPControlW *ret; DWORD len = control->ldctl_value.bv_len; char *val = NULL;
@@ -903,58 +1219,57 @@ static inline LDAPControlW *controldupW( LDAPControlW *control ) memcpy( val, control->ldctl_value.bv_val, len ); }
- if (!(controlW = malloc( sizeof(*controlW) ))) + if (!(ret = malloc( sizeof(*ret) ))) { free( val ); return NULL; }
- controlW->ldctl_oid = strdupW( control->ldctl_oid ); - controlW->ldctl_value.bv_len = len; - controlW->ldctl_value.bv_val = val; - controlW->ldctl_iscritical = control->ldctl_iscritical; + ret->ldctl_oid = strdupW( control->ldctl_oid ); + ret->ldctl_value.bv_len = len; + ret->ldctl_value.bv_val = val; + ret->ldctl_iscritical = control->ldctl_iscritical;
- return controlW; + return ret; }
static inline LDAPControlW **controlarraydupW( LDAPControlW **controlarray ) { - LDAPControlW **controlarrayW = NULL; + LDAPControlW **ret = NULL; DWORD size;
if (controlarray) { - size = sizeof(LDAPControlW *) * (controlarraylenW( controlarray ) + 1); - if ((controlarrayW = malloc( size ))) + size = sizeof(*ret) * (controlarraylenW( controlarray ) + 1); + if ((ret = malloc( size ))) { - LDAPControlW **p = controlarray; - LDAPControlW **q = controlarrayW; + LDAPControlW **p = controlarray, **q = ret;
while (*p) *q++ = controldupW( *p++ ); *q = NULL; } } - return controlarrayW; + return ret; }
static inline LDAPControlA **controlarrayWtoA( LDAPControlW **controlarray ) { - LDAPControlA **controlarrayA = NULL; + LDAPControlA **ret = NULL; DWORD size;
if (controlarray) { - size = sizeof(LDAPControlA *) * (controlarraylenW( controlarray ) + 1); - if ((controlarrayA = malloc( size ))) + size = sizeof(*ret) * (controlarraylenW( controlarray ) + 1); + if ((ret = malloc( size ))) { LDAPControlW **p = controlarray; - LDAPControlA **q = controlarrayA; + LDAPControlA **q = ret;
while (*p) *q++ = controlWtoA( *p++ ); *q = NULL; } } - return controlarrayA; + return ret; }
static inline WCHAR *strUtoW( const char *str ) @@ -977,47 +1292,46 @@ static inline DWORD strarraylenU( char **strarray )
static inline WCHAR **strarrayUtoW( char **strarray ) { - WCHAR **strarrayW = NULL; + WCHAR **ret = NULL; DWORD size;
if (strarray) { - size = sizeof(WCHAR *) * (strarraylenU( strarray ) + 1); - if ((strarrayW = malloc( size ))) + size = sizeof(*ret) * (strarraylenU( strarray ) + 1); + if ((ret = malloc( size ))) { char **p = strarray; - WCHAR **q = strarrayW; + WCHAR **q = ret;
while (*p) *q++ = strUtoW( *p++ ); *q = NULL; } } - return strarrayW; + return ret; }
static inline char **strarrayUtoU( char **strarray ) { - char **strarrayU = NULL; + char **ret = NULL; DWORD size;
if (strarray) { - size = sizeof(char *) * (strarraylenU( strarray ) + 1); - if ((strarrayU = malloc( size ))) + size = sizeof(*ret) * (strarraylenU( strarray ) + 1); + if ((ret = malloc( size ))) { - char **p = strarray; - char **q = strarrayU; + char **p = strarray, **q = ret;
while (*p) *q++ = strdupU( *p++ ); *q = NULL; } } - return strarrayU; + return ret; }
-static inline LDAPControlW *controlUtoW( const LDAPControlU *control ) +static inline LDAPControlW *controlUtoW( const LDAPControl *control ) { - LDAPControlW *controlW; + LDAPControlW *ret; DWORD len = control->ldctl_value.bv_len; char *val = NULL;
@@ -1027,38 +1341,38 @@ static inline LDAPControlW *controlUtoW( const LDAPControlU *control ) memcpy( val, control->ldctl_value.bv_val, len ); }
- if (!(controlW = malloc( sizeof(*controlW) ))) + if (!(ret = malloc( sizeof(*ret) ))) { free( val ); return NULL; }
- controlW->ldctl_oid = strUtoW( control->ldctl_oid ); - controlW->ldctl_value.bv_len = len; - controlW->ldctl_value.bv_val = val; - controlW->ldctl_iscritical = control->ldctl_iscritical; + ret->ldctl_oid = strUtoW( control->ldctl_oid ); + ret->ldctl_value.bv_len = len; + ret->ldctl_value.bv_val = val; + ret->ldctl_iscritical = control->ldctl_iscritical;
- return controlW; + return ret; }
-static inline LDAPControlW **controlarrayUtoW( LDAPControlU **controlarray ) +static inline LDAPControlW **controlarrayUtoW( LDAPControl **controlarray ) { - LDAPControlW **controlarrayW = NULL; + LDAPControlW **ret = NULL; DWORD size;
if (controlarray) { - size = sizeof(LDAPControlW *) * (controlarraylenU( controlarray ) + 1); - if ((controlarrayW = malloc( size ))) + size = sizeof(*ret) * (controlarraylenU( controlarray ) + 1); + if ((ret = malloc( size ))) { - LDAPControlU **p = controlarray; - LDAPControlW **q = controlarrayW; + LDAPControl **p = controlarray; + LDAPControlW **q = ret;
while (*p) *q++ = controlUtoW( *p++ ); *q = NULL; } } - return controlarrayW; + return ret; }
static inline DWORD sortkeyarraylenA( LDAPSortKeyA **sortkeyarray ) @@ -1070,35 +1384,35 @@ static inline DWORD sortkeyarraylenA( LDAPSortKeyA **sortkeyarray )
static inline LDAPSortKeyW *sortkeyAtoW( const LDAPSortKeyA *sortkey ) { - LDAPSortKeyW *sortkeyW; + LDAPSortKeyW *ret;
- if ((sortkeyW = malloc( sizeof(*sortkeyW) ))) + if ((ret = malloc( sizeof(*ret) ))) { - sortkeyW->sk_attrtype = strAtoW( sortkey->sk_attrtype ); - sortkeyW->sk_matchruleoid = strAtoW( sortkey->sk_matchruleoid ); - sortkeyW->sk_reverseorder = sortkey->sk_reverseorder; + ret->sk_attrtype = strAtoW( sortkey->sk_attrtype ); + ret->sk_matchruleoid = strAtoW( sortkey->sk_matchruleoid ); + ret->sk_reverseorder = sortkey->sk_reverseorder; } - return sortkeyW; + return ret; }
static inline LDAPSortKeyW **sortkeyarrayAtoW( LDAPSortKeyA **sortkeyarray ) { - LDAPSortKeyW **sortkeyarrayW = NULL; + LDAPSortKeyW **ret = NULL; DWORD size;
if (sortkeyarray) { - size = sizeof(LDAPSortKeyW *) * (sortkeyarraylenA( sortkeyarray ) + 1); - if ((sortkeyarrayW = malloc( size ))) + size = sizeof(*ret) * (sortkeyarraylenA( sortkeyarray ) + 1); + if ((ret = malloc( size ))) { LDAPSortKeyA **p = sortkeyarray; - LDAPSortKeyW **q = sortkeyarrayW; + LDAPSortKeyW **q = ret;
while (*p) *q++ = sortkeyAtoW( *p++ ); *q = NULL; } } - return sortkeyarrayW; + return ret; }
static inline void sortkeyfreeW( LDAPSortKeyW *sortkey ) @@ -1128,40 +1442,40 @@ static inline DWORD sortkeyarraylenW( LDAPSortKeyW **sortkeyarray ) return p - sortkeyarray; }
-static inline LDAPSortKeyU *sortkeyWtoU( const LDAPSortKeyW *sortkey ) +static inline LDAPSortKey *sortkeyWtoU( const LDAPSortKeyW *sortkey ) { - LDAPSortKeyU *sortkeyU; + LDAPSortKey *ret;
- if ((sortkeyU = malloc( sizeof(*sortkeyU) ))) + if ((ret = malloc( sizeof(*ret) ))) { - sortkeyU->attributeType = strWtoU( sortkey->sk_attrtype ); - sortkeyU->orderingRule = strWtoU( sortkey->sk_matchruleoid ); - sortkeyU->reverseOrder = sortkey->sk_reverseorder; + ret->attributeType = strWtoU( sortkey->sk_attrtype ); + ret->orderingRule = strWtoU( sortkey->sk_matchruleoid ); + ret->reverseOrder = sortkey->sk_reverseorder; } - return sortkeyU; + return ret; }
-static inline LDAPSortKeyU **sortkeyarrayWtoU( LDAPSortKeyW **sortkeyarray ) +static inline LDAPSortKey **sortkeyarrayWtoU( LDAPSortKeyW **sortkeyarray ) { - LDAPSortKeyU **sortkeyarrayU = NULL; + LDAPSortKey **ret = NULL; DWORD size;
if (sortkeyarray) { - size = sizeof(LDAPSortKeyU *) * (sortkeyarraylenW( sortkeyarray ) + 1); - if ((sortkeyarrayU = malloc( size ))) + size = sizeof(*ret) * (sortkeyarraylenW( sortkeyarray ) + 1); + if ((ret = malloc( size ))) { LDAPSortKeyW **p = sortkeyarray; - LDAPSortKeyU **q = sortkeyarrayU; + LDAPSortKey **q = ret;
while (*p) *q++ = sortkeyWtoU( *p++ ); *q = NULL; } } - return sortkeyarrayU; + return ret; }
-static inline void sortkeyfreeU( LDAPSortKeyU *sortkey ) +static inline void sortkeyfreeU( LDAPSortKey *sortkey ) { if (sortkey) { @@ -1171,44 +1485,44 @@ static inline void sortkeyfreeU( LDAPSortKeyU *sortkey ) } }
-static inline void sortkeyarrayfreeU( LDAPSortKeyU **sortkeyarray ) +static inline void sortkeyarrayfreeU( LDAPSortKey **sortkeyarray ) { if (sortkeyarray) { - LDAPSortKeyU **p = sortkeyarray; + LDAPSortKey **p = sortkeyarray; while (*p) sortkeyfreeU( *p++ ); free( sortkeyarray ); } }
-static inline LDAPVLVInfoU *vlvinfoWtoU( const LDAPVLVInfo *info ) +static inline LDAPVLVInfo *vlvinfoWtoU( const WLDAP32_LDAPVLVInfo *info ) { - LDAPVLVInfoU *infoU; + LDAPVLVInfo *ret;
- if ((infoU = malloc( sizeof(*infoU) ))) + if ((ret = malloc( sizeof(*ret) ))) { - infoU->ldvlv_version = info->ldvlv_version; - infoU->ldvlv_before_count = info->ldvlv_before_count; - infoU->ldvlv_after_count = info->ldvlv_after_count; - infoU->ldvlv_offset = info->ldvlv_offset; - infoU->ldvlv_count = info->ldvlv_count; - if (!(infoU->ldvlv_attrvalue = bervalWtoU( info->ldvlv_attrvalue ))) + ret->ldvlv_version = info->ldvlv_version; + ret->ldvlv_before_count = info->ldvlv_before_count; + ret->ldvlv_after_count = info->ldvlv_after_count; + ret->ldvlv_offset = info->ldvlv_offset; + ret->ldvlv_count = info->ldvlv_count; + if (!(ret->ldvlv_attrvalue = bervalWtoU( info->ldvlv_attrvalue ))) { - free( infoU ); + free( ret ); return NULL; } - if (!(infoU->ldvlv_context = bervalWtoU( info->ldvlv_context ))) + if (!(ret->ldvlv_context = bervalWtoU( info->ldvlv_context ))) { - free( infoU->ldvlv_attrvalue ); - free( infoU ); + free( ret->ldvlv_attrvalue ); + free( ret ); return NULL; } - infoU->ldvlv_extradata = info->ldvlv_extradata; + ret->ldvlv_extradata = info->ldvlv_extradata; } - return infoU; + return ret; }
-static inline void vlvinfofreeU( LDAPVLVInfoU *info ) +static inline void vlvinfofreeU( LDAPVLVInfo *info ) { free( info->ldvlv_attrvalue ); free( info->ldvlv_context );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126185
Your paranoid android.
=== debian11 (32 bit report) ===
d3drm: d3drm.c:5561: Test failed: Cannot create IM device, skipping tests.
=== debian11 (build log) ===
0538:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this. 0538:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this. 0538:err:winediag:d3d_device_create The application wants to create a Direct3D device, but the current DirectDrawRenderer does not support this.