From 1b70e1644888c477890722e45307fea60eaa3d77 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 7 Dec 2002 17:19:29 +0000 Subject: [PATCH] SLAPI - Netscape plugin API for slapd - based on patch contributed by Steve Omrani as ITS#2073 --- configure.in | 36 + include/slapi-plugin.h | 370 +++++++ servers/slapd/Makefile.in | 25 +- servers/slapd/add.c | 56 +- servers/slapd/backend.c | 48 +- servers/slapd/bind.c | 45 + servers/slapd/compare.c | 47 + servers/slapd/config.c | 45 + servers/slapd/connection.c | 18 +- servers/slapd/controls.c | 6 + servers/slapd/delete.c | 45 + servers/slapd/extended.c | 90 +- servers/slapd/main.c | 17 + servers/slapd/modify.c | 45 + servers/slapd/modrdn.c | 49 + servers/slapd/operation.c | 12 + servers/slapd/proto-slap.h | 20 +- servers/slapd/result.c | 10 +- servers/slapd/root_dse.c | 13 + servers/slapd/search.c | 52 + servers/slapd/slap.h | 93 ++ servers/slapd/slapi/Makefile.in | 45 + servers/slapd/slapi/README | 55 + servers/slapd/slapi/ibm_pblock_params.h | 68 ++ servers/slapd/slapi/plugin.c | 679 ++++++++++++ servers/slapd/slapi/plugin.h | 28 + servers/slapd/slapi/printmsg.c | 118 ++ servers/slapd/slapi/slapi-plugin.h | 379 +++++++ servers/slapd/slapi/slapi.h | 296 +++++ servers/slapd/slapi/slapi_cl.h | 55 + servers/slapd/slapi/slapi_common.h | 40 + servers/slapd/slapi/slapi_ops.c | 1269 ++++++++++++++++++++++ servers/slapd/slapi/slapi_ops.c.all | 1303 +++++++++++++++++++++++ servers/slapd/slapi/slapi_ops.c.save | 1271 ++++++++++++++++++++++ servers/slapd/slapi/slapi_ops.h | 34 + servers/slapd/slapi/slapi_pblock.c | 436 ++++++++ servers/slapd/slapi/slapi_pblock.h | 40 + servers/slapd/slapi/slapi_utils.c | 1132 ++++++++++++++++++++ servers/slapd/slapi/slapi_utils.h | 115 ++ servers/slapd/tools/Makefile.in | 3 +- servers/slapd/tools/mimic.c | 22 +- 41 files changed, 8473 insertions(+), 57 deletions(-) create mode 100644 include/slapi-plugin.h create mode 100644 servers/slapd/slapi/Makefile.in create mode 100644 servers/slapd/slapi/README create mode 100644 servers/slapd/slapi/ibm_pblock_params.h create mode 100644 servers/slapd/slapi/plugin.c create mode 100644 servers/slapd/slapi/plugin.h create mode 100644 servers/slapd/slapi/printmsg.c create mode 100644 servers/slapd/slapi/slapi-plugin.h create mode 100644 servers/slapd/slapi/slapi.h create mode 100644 servers/slapd/slapi/slapi_cl.h create mode 100644 servers/slapd/slapi/slapi_common.h create mode 100644 servers/slapd/slapi/slapi_ops.c create mode 100644 servers/slapd/slapi/slapi_ops.c.all create mode 100644 servers/slapd/slapi/slapi_ops.c.save create mode 100644 servers/slapd/slapi/slapi_ops.h create mode 100644 servers/slapd/slapi/slapi_pblock.c create mode 100644 servers/slapd/slapi/slapi_pblock.h create mode 100644 servers/slapd/slapi/slapi_utils.c create mode 100644 servers/slapd/slapi/slapi_utils.h diff --git a/configure.in b/configure.in index e0594ebed2..464d36f6d6 100644 --- a/configure.in +++ b/configure.in @@ -186,6 +186,8 @@ OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups of client OL_ARG_ENABLE(slp, [ --enable-slp enable SLPv2 support], no)dnl OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl +OL_ARG_ENABLE(slapi,[ --enable-slapi enable installation of slapi library], yes)dnl + dnl SLAPD Backend options OL_ARG_ENABLE(bdb,[ --enable-bdb enable Berkeley DB backend], yes)dnl OL_ARG_WITH(bdb_module,[ --with-bdb-module module type static|dynamic], static, @@ -247,6 +249,9 @@ dnl General "enable" options # validate options if test $ol_enable_slapd = no ; then dnl SLAPD was specificallly disabled + if test $ol_enable_slapi = yes ; then + AC_MSG_WARN([slapd disabled, ignoring --enable-slapi argument]) + fi if test $ol_enable_bdb = yes ; then AC_MSG_WARN([slapd disabled, ignoring --enable-bdb argument]) fi @@ -351,6 +356,7 @@ if test $ol_enable_slapd = no ; then fi # force settings to no + ol_enable_slapi=no ol_enable_bdb=no ol_enable_dnssrv=no ol_enable_ldap=no @@ -521,6 +527,9 @@ BUILD_SLURPD=no BUILD_THREAD=no +BUILD_SLAPI=no +SLAPD_SLAPI_DEPEND= + BUILD_BDB=no BUILD_DNSSRV=no BUILD_LDAP=no @@ -569,6 +578,7 @@ SASL_LIBS= TERMCAP_LIBS= TLS_LIBS= MODULES_LIBS= +SLAPI_LIBS= AUTH_LIBS= SLAPD_SLP_LIBS= @@ -2504,6 +2514,22 @@ OL_SYS_ERRLIST dnl ---------------------------------------------------------------- dnl Sort out defines +if test "$ol_enable_slapi" != no ; then + dnl This check is donel also if --enable-modules is used; + dnl it is duplicated here, 'cause it'd be cached anyway + AC_CHECK_HEADERS(ltdl.h) + + if test $ac_cv_header_ltdl_h != yes ; then + AC_MSG_ERROR([could not locate ]) + fi + AC_CHECK_LIB(ltdl, lt_dlinit, [ + SLAPI_LIBS=-lltdl + AC_DEFINE(HAVE_LIBLTDL,1,[define if you have libtool -ltdl]) + ],[AC_MSG_ERROR([could not locate libtool -lltdl])]) + + AC_DEFINE(LDAP_SLAPI,1, [define this to add SLAPI code]) +fi + if test "$ol_enable_debug" != no ; then AC_DEFINE(LDAP_DEBUG,1, [define this to add debugging code]) @@ -2764,6 +2790,12 @@ if test "$ol_enable_rewrite" != no ; then BUILD_REWRITE=yes fi +if test "$ol_enable_slapi" != no ; then + AC_DEFINE(ENABLE_SLAPI,1,[define to enable slapi library]) + BUILD_SLAPI=yes + SLAPD_SLAPI_DEPEND=libslapi.a +fi + dnl ---------------------------------------------------------------- dnl @@ -2789,6 +2821,8 @@ AC_SUBST(PLAT) AC_SUBST(BUILD_LIBS_DYNAMIC) AC_SUBST(BUILD_SLAPD) + AC_SUBST(BUILD_SLAPI) + AC_SUBST(SLAPD_SLAPI_DEPEND) AC_SUBST(BUILD_BDB) AC_SUBST(BUILD_DNSSRV) AC_SUBST(BUILD_LDAP) @@ -2843,6 +2877,7 @@ AC_SUBST(SASL_LIBS) AC_SUBST(TERMCAP_LIBS) AC_SUBST(TLS_LIBS) AC_SUBST(MODULES_LIBS) +AC_SUBST(SLAPI_LIBS) AC_SUBST(AUTH_LIBS) AC_SUBST(SLAPD_SLP_LIBS) @@ -2896,6 +2931,7 @@ servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk \ servers/slapd/back-tcl/Makefile:build/top.mk:servers/slapd/back-tcl/Makefile.in:build/mod.mk \ servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk \ +servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk \ servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \ servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \ tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk \ diff --git a/include/slapi-plugin.h b/include/slapi-plugin.h new file mode 100644 index 0000000000..cbded3a4bd --- /dev/null +++ b/include/slapi-plugin.h @@ -0,0 +1,370 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _SLAPI_PLUGIN_H +#define _SLAPI_PLUGIN_H + +#include "lber.h" +#include "ldap.h" + +typedef struct slapi_pblock Slapi_PBlock; +typedef struct slapi_entry Slapi_Entry; +typedef struct slapi_attr Slapi_Attr; +typedef struct slapi_filter Slapi_Filter; + + +/* pblock routines */ +int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ); +int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ); +Slapi_PBlock *slapi_pblock_new(); +void slapi_pblock_destroy( Slapi_PBlock* ); + +/*entry/attr/dn routines */ +Slapi_Entry *slapi_str2entry( char *s, int flags ); +char *slapi_entry2str( Slapi_Entry *e, int *len ); +char *slapi_entry_get_dn( Slapi_Entry *e ); +void slapi_entry_set_dn(Slapi_Entry *e, char *dn); +Slapi_Entry *slapi_entry_dup(Slapi_Entry *e); +int slapi_entry_attr_delete( Slapi_Entry *e, char *type ); +Slapi_Entry *slapi_entry_alloc(); +void slapi_entry_free( Slapi_Entry *e ); +int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals ); +int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr ); +int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals ); +char *slapi_dn_normalize( char *dn ); +char *slapi_dn_normalize_case( char *dn ); +int slapi_dn_issuffix( char *dn, char *suffix ); +char *slapi_dn_ignore_case( char *dn ); + +/* char routines */ +char * slapi_ch_malloc( unsigned long size ); +void slapi_ch_free( void *ptr ); +char *slapi_ch_calloc( unsigned long nelem, unsigned long size ); +char *slapi_ch_realloc(char *block, unsigned long size ); +char *slapi_ch_strdup(char *s ); + + +/* LDAP V3 routines */ +int slapi_control_present( LDAPControl **controls, char *oid, struct berval **val, int *iscritical); +void slapi_register_supported_control(char *controloid, unsigned long controlops); +#define SLAPI_OPERATION_BIND 0x00000001L +#define SLAPI_OPERATION_UNBIND 0x00000002L +#define SLAPI_OPERATION_SEARCH 0x00000004L +#define SLAPI_OPERATION_MODIFY 0x00000008L +#define SLAPI_OPERATION_ADD 0x00000010L +#define SLAPI_OPERATION_DELETE 0x00000020L +#define SLAPI_OPERATION_MODDN 0x00000040L +#define SLAPI_OPERATION_MODRDN SLAPI_OPERATION_MODDN +#define SLAPI_OPERATION_COMPARE 0x00000080L +#define SLAPI_OPERATION_ABANDON 0x00000100L +#define SLAPI_OPERATION_EXTENDED 0x00000200L +#define SLAPI_OPERATION_ANY 0xFFFFFFFFL +#define SLAPI_OPERATION_NONE 0x00000000L +int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp); +void slapi_register_supported_saslmechanism(char *mechanism); +char **slapi_get_supported_saslmechanisms(); +char **slapi_get_supported_extended_ops(void); + + +/* send ldap result back */ +void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched, char *text, + int nentries, struct berval **urls ); +int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls, + char **attrs, int attrsonly ); + +/* filter routines */ +Slapi_Filter *slapi_str2filter( char *str ); +void slapi_filter_free( Slapi_Filter *f, int recurse ); +int slapi_filter_get_choice( Slapi_Filter *f); +int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval ); +Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f ); +Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev ); + +/* internal add/delete/search/modify routines */ +Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, + LDAPControl **controls, char **attrs, int attrsonly ); +Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods, + LDAPControl **controls, int log_change); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, LDAPControl **controls, int log_changes ); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_delete_internal( char * dn, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, char *newParent, int deloldrdn, LDAPControl **controls, int log_change); +void slapi_free_search_results_internal(Slapi_PBlock *pb); + +/* connection related routines */ +int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL); +int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort); + +/* parameters currently supported */ + + +/* plugin types supported */ + +#define SLAPI_PLUGIN_DATABASE 1 +#define SLAPI_PLUGIN_EXTENDEDOP 2 +#define SLAPI_PLUGIN_PREOPERATION 3 +#define SLAPI_PLUGIN_POSTOPERATION 4 +#define SLAPI_PLUGIN_AUDIT 7 + +/* misc params */ + +#define SLAPI_BACKEND 130 +#define SLAPI_CONNECTION 131 +#define SLAPI_OPERATION 132 +#define SLAPI_REQUESTOR_ISROOT 133 +#define SLAPI_BE_MONITORDN 134 +#define SLAPI_BE_TYPE 135 +#define SLAPI_BE_READONLY 136 +#define SLAPI_BE_LASTMOD 137 +#define SLAPI_CONN_ID 139 + +/* operation params */ +#define SLAPI_OPINITIATED_TIME 140 +#define SLAPI_REQUESTOR_DN 141 +#define SLAPI_REQUESTOR_ISUPDATEDN 142 + +/* connection structure params*/ +#define SLAPI_CONN_DN 143 +#define SLAPI_CONN_AUTHTYPE 144 + +/* Authentication types */ +#define SLAPD_AUTH_NONE "none" +#define SLAPD_AUTH_SIMPLE "simple" +#define SLAPD_AUTH_SSL "SSL" +#define SLAPD_AUTH_SASL "SASL " + +/* plugin configuration parmams */ +#define SLAPI_PLUGIN 3 +#define SLAPI_PLUGIN_PRIVATE 4 +#define SLAPI_PLUGIN_TYPE 5 +#define SLAPI_PLUGIN_ARGV 6 +#define SLAPI_PLUGIN_ARGC 7 +#define SLAPI_PLUGIN_VERSION 8 +#define SLAPI_PLUGIN_OPRETURN 9 +#define SLAPI_PLUGIN_OBJECT 10 +#define SLAPI_PLUGIN_DESTROY_FN 11 +#define SLAPI_PLUGIN_DESCRIPTION 12 + +/* internal opreations params */ +#define SLAPI_PLUGIN_INTOP_RESULT 15 +#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES 16 +#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS 17 + +/* function pointer params for backends */ +#define SLAPI_PLUGIN_DB_BIND_FN 200 +#define SLAPI_PLUGIN_DB_UNBIND_FN 201 +#define SLAPI_PLUGIN_DB_SEARCH_FN 202 +#define SLAPI_PLUGIN_DB_COMPARE_FN 203 +#define SLAPI_PLUGIN_DB_MODIFY_FN 204 +#define SLAPI_PLUGIN_DB_MODRDN_FN 205 +#define SLAPI_PLUGIN_DB_ADD_FN 206 +#define SLAPI_PLUGIN_DB_DELETE_FN 207 +#define SLAPI_PLUGIN_DB_ABANDON_FN 208 +#define SLAPI_PLUGIN_DB_CONFIG_FN 209 +#define SLAPI_PLUGIN_CLOSE_FN 210 +#define SLAPI_PLUGIN_DB_FLUSH_FN 211 +#define SLAPI_PLUGIN_START_FN 212 +#define SLAPI_PLUGIN_DB_SEQ_FN 213 +#define SLAPI_PLUGIN_DB_ENTRY_FN 214 +#define SLAPI_PLUGIN_DB_REFERRAL_FN 215 +#define SLAPI_PLUGIN_DB_RESULT_FN 216 +#define SLAPI_PLUGIN_DB_LDIF2DB_FN 217 +#define SLAPI_PLUGIN_DB_DB2LDIF_FN 218 +#define SLAPI_PLUGIN_DB_BEGIN_FN 219 +#define SLAPI_PLUGIN_DB_COMMIT_FN 220 +#define SLAPI_PLUGIN_DB_ABORT_FN 221 +#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN 222 +#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN 223 +#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN 224 +#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN 225 +#define SLAPI_PLUGIN_DB_SIZE_FN 226 +#define SLAPI_PLUGIN_DB_TEST_FN 227 + + +/* functions pointers for LDAP V3 extended ops */ +#define SLAPI_PLUGIN_EXT_OP_FN 300 +#define SLAPI_PLUGIN_EXT_OP_OIDLIST 301 + +/* functions for preoperation functions */ +#define SLAPI_PLUGIN_PRE_BIND_FN 401 +#define SLAPI_PLUGIN_PRE_UNBIND_FN 402 +#define SLAPI_PLUGIN_PRE_SEARCH_FN 403 +#define SLAPI_PLUGIN_PRE_COMPARE_FN 404 +#define SLAPI_PLUGIN_PRE_MODIFY_FN 405 +#define SLAPI_PLUGIN_PRE_MODRDN_FN 406 +#define SLAPI_PLUGIN_PRE_ADD_FN 407 +#define SLAPI_PLUGIN_PRE_DELETE_FN 408 +#define SLAPI_PLUGIN_PRE_ABANDON_FN 409 +#define SLAPI_PLUGIN_PRE_ENTRY_FN 410 +#define SLAPI_PLUGIN_PRE_REFERRAL_FN 411 +#define SLAPI_PLUGIN_PRE_RESULT_FN 412 + +/* functions for postoperation functions*/ +#define SLAPI_PLUGIN_POST_BIND_FN 501 +#define SLAPI_PLUGIN_POST_UNBIND_FN 502 +#define SLAPI_PLUGIN_POST_SEARCH_FN 503 +#define SLAPI_PLUGIN_POST_COMPARE_FN 504 +#define SLAPI_PLUGIN_POST_MODIFY_FN 505 +#define SLAPI_PLUGIN_POST_MODRDN_FN 506 +#define SLAPI_PLUGIN_POST_ADD_FN 507 +#define SLAPI_PLUGIN_POST_DELETE_FN 508 +#define SLAPI_PLUGIN_POST_ABANDON_FN 509 +#define SLAPI_PLUGIN_POST_ENTRY_FN 510 +#define SLAPI_PLUGIN_POST_REFERRAL_FN 511 +#define SLAPI_PLUGIN_POST_RESULT_FN 512 + +/* audit plugin defines */ +#define SLAPI_PLUGIN_AUDIT_DATA 1100 +#define SLAPI_PLUGIN_AUDIT_FN 1101 + +/* managedsait control */ +#define SLAPI_MANAGEDSAIT 1000 + +/* config stuff */ +#define SLAPI_CONFIG_FILENAME 40 +#define SLAPI_CONFIG_LINENO 41 +#define SLAPI_CONFIG_ARGC 42 +#define SLAPI_CONFIG_ARGV 43 + +/* operational params */ +#define SLAPI_TARGET_DN 50 +#define SLAPI_REQCONTROLS 51 + +/* server LDAPv3 controls */ +#define SLAPI_RESCONTROLS 55 +#define SLAPI_ADD_RESCONTROL 56 + +/* add params */ +#define SLAPI_ADD_TARGET SLAPI_TARGET_DN +#define SLAPI_ADD_ENTRY 60 + +/* bind params */ +#define SLAPI_BIND_TARGET SLAPI_TARGET_DN +#define SLAPI_BIND_METHOD 70 +#define SLAPI_BIND_CREDENTIALS 71 +#define SLAPI_BIND_SASLMECHANISM 72 +#define SLAPI_BIND_RET_SASLCREDS 73 + +/* compare params */ +#define SLAPI_COMPARE_TARGET SLAPI_TARGET_DN +#define SLAPI_COMPARE_TYPE 80 +#define SLAPI_COMPARE_VALUE 81 + +/* delete params */ +#define SLAPI_DELETE_TARGET SLAPI_TARGET_DN + +/* modify params */ +#define SLAPI_MODIFY_TARGET SLAPI_TARGET_DN +#define SLAPI_MODIFY_MODS 90 + +/* modrdn params */ +#define SLAPI_MODRDN_TARGET SLAPI_TARGET_DN +#define SLAPI_MODRDN_NEWRDN 100 +#define SLAPI_MODRDN_DELOLDRDN 101 +#define SLAPI_MODRDN_NEWSUPERIOR 102 /* v3 only */ + +/* search params */ +#define SLAPI_SEARCH_TARGET SLAPI_TARGET_DN +#define SLAPI_SEARCH_SCOPE 110 +#define SLAPI_SEARCH_DEREF 111 +#define SLAPI_SEARCH_SIZELIMIT 112 +#define SLAPI_SEARCH_TIMELIMIT 113 +#define SLAPI_SEARCH_FILTER 114 +#define SLAPI_SEARCH_STRFILTER 115 +#define SLAPI_SEARCH_ATTRS 116 +#define SLAPI_SEARCH_ATTRSONLY 117 + +/* abandon params */ +#define SLAPI_ABANDON_MSGID 120 + +/* extended operation params */ +#define SLAPI_EXT_OP_REQ_OID 160 +#define SLAPI_EXT_OP_REQ_VALUE 161 + +/* extended operation return codes */ +#define SLAPI_EXT_OP_RET_OID 162 +#define SLAPI_EXT_OP_RET_VALUE 163 + +#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT -1 + +/* Search result params */ +#define SLAPI_SEARCH_RESULT_SET 193 +#define SLAPI_SEARCH_RESULT_ENTRY 194 +#define SLAPI_NENTRIES 195 +#define SLAPI_SEARCH_REFERRALS 196 + + +/* filter types */ +#ifndef LDAP_FILTER_AND +#define LDAP_FILTER_AND 0xa0L +#endif +#ifndef LDAP_FILTER_OR +#define LDAP_FILTER_OR 0xa1L +#endif +#ifndef LDAP_FILTER_NOT +#define LDAP_FILTER_NOT 0xa2L +#endif +#ifndef LDAP_FILTER_EQUALITY +#define LDAP_FILTER_EQUALITY 0xa3L +#endif +#ifndef LDAP_FILTER_SUBSTRINGS +#define LDAP_FILTER_SUBSTRINGS 0xa4L +#endif +#ifndef LDAP_FILTER_GE +#define LDAP_FILTER_GE 0xa5L +#endif +#ifndef LDAP_FILTER_LE +#define LDAP_FILTER_LE 0xa6L +#endif +#ifndef LDAP_FILTER_PRESENT +#define LDAP_FILTER_PRESENT 0x87L +#endif +#ifndef LDAP_FILTER_APPROX +#define LDAP_FILTER_APPROX 0xa8L +#endif +#ifndef LDAP_FILTER_EXT_MATCH +#define LDAP_FILTER_EXT_MATCH 0xa9L +#endif + +int slapi_log_error( int severity, char *subsystem, char *fmt, ... ); +#define SLAPI_LOG_FATAL 0 +#define SLAPI_LOG_TRACE 1 +#define SLAPI_LOG_PACKETS 2 +#define SLAPI_LOG_ARGS 3 +#define SLAPI_LOG_CONNS 4 +#define SLAPI_LOG_BER 5 +#define SLAPI_LOG_FILTER 6 +#define SLAPI_LOG_CONFIG 7 +#define SLAPI_LOG_ACL 8 +#define SLAPI_LOG_SHELL 9 +#define SLAPI_LOG_PARSE 10 +#define SLAPI_LOG_HOUSE 11 +#define SLAPI_LOG_REPL 12 +#define SLAPI_LOG_CACHE 13 +#define SLAPI_LOG_PLUGIN 14 +#define SLAPI_LOG_TIMING 15 + +#define SLAPI_PLUGIN_DESCRIPTION 12 +typedef struct slapi_plugindesc { + char *spd_id; + char *spd_vendor; + char *spd_version; + char *spd_description; +} Slapi_PluginDesc; + +#define SLAPI_PLUGIN_VERSION_01 "01" +#define SLAPI_PLUGIN_VERSION_02 "02" +#define SLAPI_PLUGIN_VERSION_03 "03" +#define SLAPI_PLUGIN_CURRENT_VERSION SLAPI_PLUGIN_VERSION_03 + +#endif diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 717b91dc70..4bc2c73142 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -35,11 +35,11 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o cr.o \ limits.o backglue.o operational.o matchedValues.o \ $(@PLAT@_OBJS) -LDAP_INCDIR= ../../include +LDAP_INCDIR= ../../include -Islapi LDAP_LIBDIR= ../../libraries SLAP_DIR= -SLAPD_STATIC_DEPENDS=@SLAPD_NO_STATIC@ libbackends.a +SLAPD_STATIC_DEPENDS=@SLAPD_SLAPI_DEPEND@ @SLAPD_NO_STATIC@ libbackends.a SLAPD_STATIC_BACKENDS=@SLAPD_STATIC_BACKENDS@ SLAPD_DYNAMIC_BACKENDS=@SLAPD_DYNAMIC_BACKENDS@ @@ -48,7 +48,7 @@ XLDFLAGS = $(MODULES_LDFLAGS) XLIBS = $(SLAPD_STATIC_DEPENDS) $(SLAPD_L) XXLIBS = $(LDBM_LIBS) $(SLAPD_LIBS) $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS) -XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS) +XXXLIBS = $(LTHREAD_LIBS) $(MODULES_LIBS) $(SLAPI_LIBS) BUILD_OPT = "--enable-slapd" BUILD_SRV = @BUILD_SLAPD@ @@ -224,8 +224,17 @@ slapd.exp: libslapd.a dlltool --dllname slapd.exe --input-def slapd.def \ --base-file slapd.base --output-exp $@ +.slapi: FORCE + (cd slapi; $(MAKE) $(MFLAGS) all) + +libslapi.a: .slapi + $(AR) ruv slapi/libtmpslapd.a $(OBJS) + cp slapi/.libs/libslapi.a . + slapd: $(SLAPD_DEPENDS) - $(LTLINK) -o $@ $(SLAPD_OBJECTS) $(LIBS) $(WRAP_LIBS) + $(LTLINK) -o $@ $(SLAPD_OBJECTS) $(LIBS) \ + libslapi.a slapi/libtmpslapd.a \ + $(WRAP_LIBS) sslapd: version.o $(LTLINK) -static -o $@ $(OBJS) version.o $(LIBS) $(WRAP_LIBS) @@ -280,7 +289,7 @@ version.c: $(OBJS) $(SLAPD_LIBDEPEND) $(MKVERSION) -s -n Versionstr slapd > $@ depend-local-srv: FORCE - @for i in back-* shell-backends tools; do \ + @for i in back-* shell-backends slapi tools; do \ if test -d $$i -a -f $$i/Makefile ; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) depend"; \ ( cd $$i; $(MAKE) $(MFLAGS) depend ); \ @@ -293,7 +302,7 @@ clean-local: rm -f *.exp *.def *.base *.a *.objs symdummy.c clean-local-srv: FORCE - @for i in back-* shell-backends tools; do \ + @for i in back-* shell-backends slapi tools; do \ if test -d $$i -a -f $$i/Makefile ; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \ ( cd $$i; $(MAKE) $(MFLAGS) clean ); \ @@ -303,7 +312,7 @@ clean-local-srv: FORCE rm -f *.tmp all-cffiles veryclean-local-srv: FORCE - @for i in back-* shell-backends tools; do \ + @for i in back-* shell-backends slapi tools; do \ if test -d $$i -a -f $$i/Makefile ; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \ ( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \ @@ -317,7 +326,7 @@ install-slapd: FORCE -$(MKDIR) $(DESTDIR)$(localstatedir) $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 \ slapd$(EXEEXT) $(DESTDIR)$(libexecdir) - @for i in back-* shell-backends tools; do \ + @for i in back-* shell-backends slapi tools; do \ if test -d $$i -a -f $$i/Makefile ; then \ echo; echo " cd $$i; $(MAKE) $(MFLAGS) install"; \ ( cd $$i; $(MAKE) $(MFLAGS) install ); \ diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 85e6f7ca50..35a686f093 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -16,6 +16,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include #include @@ -24,13 +25,7 @@ #include "ldap_pvt.h" #include "slap.h" - -static int slap_mods2entry( - Modifications *mods, - Entry **e, - int repl_user, - const char **text, - char *textbuf, size_t textlen ); +#include "slapi.h" int do_add( Connection *conn, Operation *op ) @@ -49,6 +44,8 @@ do_add( Connection *conn, Operation *op ) int rc = LDAP_SUCCESS; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_add: conn %d enter\n", conn->c_connid,0,0 ); #else @@ -228,6 +225,31 @@ do_add( Connection *conn, Operation *op ) goto done; } +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_ADD_ENTRY, (void *)e ); + slapi_pblock_set( pb, SLAPI_ADD_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_ADD_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (add) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_add: add preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " add preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + /* * do the add if 1 && (2 || 3) * 1) there is an add function implemented in this backend; @@ -314,6 +336,23 @@ do_add( Connection *conn, Operation *op ) NULL, "operation not supported within namingContext", NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_ADD_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (Add) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_add: Add postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " Add postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + done: if( modlist != NULL ) { slap_mods_free( modlist ); @@ -325,7 +364,8 @@ done: return rc; } -static int slap_mods2entry( +int +slap_mods2entry( Modifications *mods, Entry **e, int repl_user, diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 124ec7c422..fb1272b4b7 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -7,6 +7,7 @@ #include "portable.h" +#include "slapi_common.h" #include @@ -16,6 +17,7 @@ #include #include "slap.h" +#include "slapi.h" #include "lutil.h" #include "lber_pvt.h" @@ -686,12 +688,56 @@ backend_unbind( Operation *op ) { - int i; + int i; + int rc; + Slapi_PBlock *pb = op->o_pb; + +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); +#endif /* defined( LDAP_SLAPI ) */ for ( i = 0; i < nbackends; i++ ) { +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)&backends[i] ); + rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_PRE_UNBIND_FN, + (Slapi_PBlock *)pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (unbind) plugins + * or a plugin failed. Just log it. + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Unbind preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " Unbind preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + if ( backends[i].be_unbind ) { (*backends[i].be_unbind)( &backends[i], conn, op ); } + +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_POST_UNBIND_FN, + (Slapi_PBlock *)pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (unbind) plugins + * or a plugin failed. Just log it. + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_unbind: Unbind postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " Unbind postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ } return 0; diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index 1b3220c2c3..f5062ba5cf 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -18,6 +18,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -26,6 +27,7 @@ #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" int do_bind( @@ -47,6 +49,8 @@ do_bind( struct berval cred = { 0, NULL }; Backend *be = NULL; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_bind: conn %d\n", conn->c_connid, 0, 0 ); #else @@ -526,6 +530,30 @@ do_bind( goto cleanup; } +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_BIND_METHOD, (void *)method ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_BIND_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (bind) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Bind preOps failed\n")); +#else + Debug(LDAP_DEBUG_TRACE, " Bind preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + if ( be->be_bind ) { int ret; @@ -592,6 +620,23 @@ do_bind( NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_BIND_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no pretOp (bind) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_bind: Bind postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " Bind postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + cleanup: conn->c_sasl_bindop = NULL; diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index 81e3e9f54e..ab0546ffc9 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -16,12 +16,14 @@ */ #include "portable.h" +#include "slapi_common.h" #include #include #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" static int compare_entry( Connection *conn, @@ -48,6 +50,8 @@ do_compare( const char *text = NULL; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + ava.aa_desc = NULL; #ifdef NEW_LOGGING @@ -267,6 +271,32 @@ do_compare( /* deref suffix alias if appropriate */ suffix_alias( be, &ndn ); +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + slapi_pblock_set( pb, SLAPI_COMPARE_TYPE, (void *)desc.bv_val ); + slapi_pblock_set( pb, SLAPI_COMPARE_VALUE, (void *)&value ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_COMPARE_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (compare) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_compare: compare preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " compare preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + if ( be->be_compare ) { (*be->be_compare)( be, conn, op, &pdn, &ndn, &ava ); } else { @@ -275,6 +305,23 @@ do_compare( NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_COMPARE_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (compare) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_compare: compare postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " compare postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + cleanup: free( pdn.bv_val ); free( ndn.bv_val ); diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 45616ae406..d87bf6f432 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -6,6 +6,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -18,6 +19,7 @@ #include "lutil.h" #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" #define ARGS_STEP 512 @@ -2311,6 +2313,49 @@ read_config( const char *fname, int depth ) #endif #endif /* !SLAPD_RLOOKUPS */ + /* Netscape plugins */ + } else if ( strcasecmp( cargv[0], "plugin" ) == 0 ) { +#if defined( LDAP_SLAPI ) + + /* + * a "plugin" line must be inside a database + * definition, since we implement pre-,post- + * and extended operation plugins + */ + if ( be == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, INFO, + "%s: line %d: plugin line must appear " + "inside a database definition.\n", + fname, lineno, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "%s: line %d: plugin " + "line must appear inside a database " + "definition\n", fname, lineno, 0 ); +#endif + return( 1 ); + } + + if ( netscape_plugin( be, fname, lineno, cargc, cargv ) + != LDAP_SUCCESS ) { + return( 1 ); + } + +#else /* !defined( LDAP_SLAPI ) */ +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, INFO, + "%s: line %d: SLAPI not supported.\n", + fname, lineno, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "%s: line %d: SLAPI " + "not supported.\n", fname, lineno, 0 ); +#endif + return( 1 ); + +#endif /* !defined( LDAP_SLAPI ) */ + + + /* pass anything else to the current backend info/db config routine */ } else { if ( bi != NULL ) { diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index aeed4237b8..8dbf0e63d7 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -395,22 +395,28 @@ long connection_init( if( c == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, - "connection_init: skt %d connection table full (%d/%d)\n", - s, i, dtblsize ); + "connection_init: skt %d connection table full " + "(%d/%d)\n", s, i, dtblsize ); #else Debug( LDAP_DEBUG_ANY, - "connection_init(%d): connection table full (%d/%d)\n", - s, i, dtblsize); + "connection_init(%d): connection table full " + "(%d/%d)\n", s, i, dtblsize); #endif ldap_pvt_thread_mutex_unlock( &connections_mutex ); return -1; } - } + } #endif - assert( c != NULL ); + assert( c != NULL ); if( c->c_struct_state == SLAP_C_UNINITIALIZED ) { + c->c_send_ldap_result = slap_send_ldap_result; + c->c_send_search_entry = slap_send_search_entry; + c->c_send_search_result = slap_send_search_result; + c->c_send_search_reference = slap_send_search_reference; + c->c_send_ldap_extended = slap_send_ldap_extended; + c->c_authmech.bv_val = NULL; c->c_authmech.bv_len = 0; c->c_dn.bv_val = NULL; diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index cf8fdd2469..465884c412 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -106,6 +106,12 @@ get_supported_ctrl(int index) return supportedControls[index].sc_oid; } +slap_mask_t +get_supported_ctrl_mask(int index) +{ + return supportedControls[index].sc_mask; +} + static struct slap_control * find_ctrl( const char *oid ) { diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 97f073e1b9..849a494bc7 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -16,6 +16,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -24,6 +25,7 @@ #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" int do_delete( @@ -39,6 +41,8 @@ do_delete( int rc; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_delete: conn %d\n", conn->c_connid, 0, 0 ); @@ -153,6 +157,30 @@ do_delete( /* deref suffix alias if appropriate */ suffix_alias( be, &ndn ); +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_DELETE_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (delete) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: delete preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " delete preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + /* * do the delete if 1 && (2 || 3) * 1) there is a delete function implemented in this backend; @@ -193,6 +221,23 @@ do_delete( NULL, "operation not supported within namingContext", NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_DELETE_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (delete) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: delete postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " delete postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + cleanup: free( pdn.bv_val ); free( ndn.bv_val ); diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index dfff66d4d7..84d8698d5a 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -26,14 +26,18 @@ */ #include "portable.h" +#include "slapi_common.h" #include #include #include #include "slap.h" +#include "slapi.h" #include "lber_pvt.h" +#define UNSUPPORTED_EXTENDEDOP "unsupported extended operation" + static struct extop_list { struct extop_list *next; struct berval oid; @@ -102,6 +106,12 @@ do_extended( struct berval *rspdata; LDAPControl **rspctrls; + Slapi_PBlock *pb = op->o_pb; + SLAPI_FUNC funcAddr = NULL; + int extop_rc; + int msg_sent=FALSE; + char *result_msg=""; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_extended: conn %d\n", conn->c_connid, 0, 0 ); #else @@ -136,7 +146,10 @@ do_extended( goto done; } - if( !(ext = find_extop(supp_ext_list, &reqoid)) ) { + /* Netscape extended operation */ + getPluginFunc( &reqoid, &funcAddr ); + + if( !(ext = find_extop(supp_ext_list, &reqoid)) && !(funcAddr) ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_extended: conn %d unsupported operation \"%s\"\n", @@ -202,29 +215,72 @@ do_extended( text = NULL; refs = NULL; - rc = (ext->ext_main)( conn, op, - reqoid.bv_val, reqdata.bv_val ? &reqdata : NULL, - &rspoid, &rspdata, &rspctrls, &text, &refs ); + if (ext != NULL) { /* OpenLDAP extended operation */ + rc = (ext->ext_main)( conn, op, + reqoid.bv_val, reqdata.bv_val ? &reqdata : NULL, + &rspoid, &rspdata, &rspctrls, &text, &refs ); + + if( rc != SLAPD_ABANDON ) { + if ( rc == LDAP_REFERRAL && refs == NULL ) { + refs = referral_rewrite( default_referral, + NULL, NULL, LDAP_SCOPE_DEFAULT ); + } - if( rc != SLAPD_ABANDON ) { - if ( rc == LDAP_REFERRAL && refs == NULL ) { - refs = referral_rewrite( default_referral, - NULL, NULL, LDAP_SCOPE_DEFAULT ); + send_ldap_extended( conn, op, rc, NULL, text, refs, + rspoid, rspdata, rspctrls ); + + ber_bvarray_free( refs ); } - send_ldap_extended( conn, op, rc, NULL, text, refs, - rspoid, rspdata, rspctrls ); + if ( rspoid != NULL ) { + free( rspoid ); + } - ber_bvarray_free( refs ); + if ( rspdata != NULL ) { + ber_bvfree( rspdata ); + } +#if !defined( LDAP_SLAPI ) } +#else /* defined( LDAP_SLAPI ) */ + goto done; /* end of OpenLDAP extended operation */ + + } else { /* start of Netscape extended operation */ + if ( ( rc = slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_OID,(void *)reqoid.bv_val) ) == 0 && + ( rc = slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_VALUE,(void *)&reqdata) ) == 0 && + ( rc = slapi_pblock_set( pb, SLAPI_CONNECTION,(void *)conn) ) == 0 && + ( rc = slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op) ) == 0) { + extop_rc = (*funcAddr)( pb ); + if ( extop_rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) { + msg_sent = TRUE; + } else if ( extop_rc == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) { + rc = LDAP_PROTOCOL_ERROR; + result_msg = UNSUPPORTED_EXTENDEDOP; + } else { + if ( ( rc = slapi_pblock_get(pb, SLAPI_EXT_OP_RET_OID,&rspoid) ) == 0 && + ( rc = slapi_pblock_get(pb, SLAPI_EXT_OP_RET_VALUE,&rspdata) ) == 0 ) { + send_ldap_extended( conn, op, extop_rc, NULL, text, refs, + rspoid, rspdata, rspctrls ); + msg_sent = TRUE; + } else { + rc = LDAP_OPERATIONS_ERROR; + } + } + } else { + rc = LDAP_OPERATIONS_ERROR; + } - if ( rspoid != NULL ) { - free( rspoid ); - } + if ( rc != LDAP_SUCCESS && msg_sent == FALSE ) { + send_ldap_result( conn, op, rc, NULL, result_msg, NULL, NULL ); + } + if ( rspoid != NULL ) { + free( rspoid ); + } + if ( rspdata != NULL ) { + ber_bvfree( rspdata ); + } - if ( rspdata != NULL ) { - ber_bvfree( rspdata ); - } + } /* end of Netscape extended operation */ +#endif /* defined( LDAP_SLAPI ) */ done: return rc; diff --git a/servers/slapd/main.c b/servers/slapd/main.c index 1dc199c838..40a036ce89 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -4,6 +4,7 @@ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ #include "portable.h" +#include "slapi_common.h" #include @@ -16,7 +17,9 @@ #include "ldap_pvt.h" + #include "slap.h" +#include "slapi.h" #include "lutil.h" #include "ldif.h" @@ -405,6 +408,20 @@ int main( int argc, char **argv ) (void) ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc ); #endif +#ifdef LDAP_SLAPI + if ( slapi_init() != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, CRIT, "main: slapi initialization error\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, + "slapi initialization error\n", + 0, 0, 0 ); +#endif + + goto destroy; + } +#endif /* LDAP_SLAPI */ + if ( read_config( configfile, 0 ) != 0 ) { rc = 1; SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 0f0c716375..e9c7bd72b7 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -16,6 +16,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -27,6 +28,7 @@ #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" int do_modify( @@ -49,6 +51,8 @@ do_modify( const char *text; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_modify: enter\n", 0, 0, 0 ); #else @@ -303,6 +307,30 @@ do_modify( /* deref suffix alias if appropriate */ suffix_alias( be, &ndn ); +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODIFY_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (modify) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modify: modify preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " modify preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + /* * do the modify if 1 && (2 || 3) * 1) there is a modify function implemented in this backend; @@ -380,6 +408,23 @@ do_modify( NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_MODIFY_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (modify) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modify: modify postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " modify postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + cleanup: free( pdn.bv_val ); free( ndn.bv_val ); diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 372f0a33e8..a4dc801038 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -29,6 +29,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -37,6 +38,7 @@ #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" int do_modrdn( @@ -64,6 +66,8 @@ do_modrdn( const char *text; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_modrdn: begin\n", 0, 0, 0 ); #else @@ -324,6 +328,34 @@ do_modrdn( /* deref suffix alias if appropriate */ suffix_alias( be, &ndn ); +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)dn.bv_val ); + slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn.bv_val ); + slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, + (void *)newSuperior.bv_val ); + slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, (void *)deloldrdn ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODRDN_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (modrdn) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modrdn: modrdn preOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " modrdn preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + /* * do the add if 1 && (2 || 3) * 1) there is an add function implemented in this backend; @@ -370,6 +402,23 @@ do_modrdn( NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_MODRDN_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (modrdn) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_modrdn: modrdn postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " modrdn postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + cleanup: free( pdn.bv_val ); free( ndn.bv_val ); diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c index 59fc1b9cd7..4745076706 100644 --- a/servers/slapd/operation.c +++ b/servers/slapd/operation.c @@ -6,6 +6,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -13,6 +14,7 @@ #include #include "slap.h" +#include "slapi.h" void @@ -42,6 +44,12 @@ slap_op_free( Operation *op ) } #endif /* LDAP_CLIENT_UPDATE */ +#if defined( LDAP_SLAPI ) + if ( op->o_pb != NULL ) { + slapi_pblock_destroy( (Slapi_PBlock *)op->o_pb ); + } +#endif /* defined( LDAP_SLAPI ) */ + free( (char *) op ); } @@ -64,5 +72,9 @@ slap_op_alloc( op->o_time = slap_get_time(); op->o_opid = id; +#if defined( LDAP_SLAPI ) + op->o_pb = slapi_pblock_new(); +#endif /* defined( LDAP_SLAPI ) */ + return( op ); } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 0085f5f8d6..f00570c60d 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -84,7 +84,13 @@ LDAP_SLAPD_F (AttributeDescription *) ad_find_lang LDAP_P(( LDAP_SLAPD_F (AttributeName *) str2anlist LDAP_P(( AttributeName *an, char *str, const char *brkstr )); -LDAP_SLAPD_F (int) an_find LDAP_P(( AttributeName *a, struct berval *s )); +LDAP_SLAPD_F (int) an_find LDAP_P(( AttributeName *a, struct berval *s )); + +/* + * add.c + */ +LDAP_SLAPD_F (int) slap_mods2entry LDAP_P(( Modifications *mods, Entry **e, + int repl_user, const char **text, char *textbuf, size_t textlen )); /* * at.c @@ -271,6 +277,8 @@ LDAP_SLAPD_F (int) get_ctrls LDAP_P(( LDAP_SLAPD_F (char *) get_supported_ctrl LDAP_P((int index)); +LDAP_SLAPD_F (slap_mask_t) get_supported_ctrl_mask LDAP_P((int index)); + /* * config.c */ @@ -773,7 +781,7 @@ LDAP_SLAPD_F (void) replog LDAP_P(( Backend *be, Operation *op, /* * result.c */ -LDAP_SLAPD_F (void) send_ldap_result LDAP_P(( +LDAP_SLAPD_F (void) slap_send_ldap_result LDAP_P(( Connection *conn, Operation *op, ber_int_t err, const char *matched, const char *text, BerVarray refs, @@ -791,7 +799,7 @@ LDAP_SLAPD_F (void) send_ldap_disconnect LDAP_P(( Connection *conn, Operation *op, ber_int_t err, const char *text )); -LDAP_SLAPD_F (void) send_ldap_extended LDAP_P(( +LDAP_SLAPD_F (void) slap_send_ldap_extended LDAP_P(( Connection *conn, Operation *op, ber_int_t err, const char *matched, const char *text, BerVarray refs, @@ -803,20 +811,20 @@ LDAP_SLAPD_F (void) send_ldap_partial LDAP_P(( const char *rspoid, struct berval *rspdata, LDAPControl **ctrls )); -LDAP_SLAPD_F (void) send_search_result LDAP_P(( +LDAP_SLAPD_F (void) slap_send_search_result LDAP_P(( Connection *conn, Operation *op, ber_int_t err, const char *matched, const char *text, BerVarray refs, LDAPControl **ctrls, int nentries )); -LDAP_SLAPD_F (int) send_search_reference LDAP_P(( +LDAP_SLAPD_F (int) slap_send_search_reference LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e, BerVarray refs, LDAPControl **ctrls, BerVarray *v2refs )); -LDAP_SLAPD_F (int) send_search_entry LDAP_P(( +LDAP_SLAPD_F (int) slap_send_search_entry LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e, AttributeName *attrs, int attrsonly, LDAPControl **ctrls )); diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 7f87db28d4..d26573bb3b 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -429,7 +429,7 @@ send_ldap_disconnect( } void -send_ldap_result( +slap_send_ldap_result( Connection *conn, Operation *op, ber_int_t err, @@ -545,7 +545,7 @@ send_ldap_sasl( } void -send_ldap_extended( +slap_send_ldap_extended( Connection *conn, Operation *op, ber_int_t err, @@ -583,7 +583,7 @@ send_ldap_extended( void -send_search_result( +slap_send_search_result( Connection *conn, Operation *op, ber_int_t err, @@ -661,7 +661,7 @@ send_search_result( } int -send_search_entry( +slap_send_search_entry( Backend *be, Connection *conn, Operation *op, @@ -1214,7 +1214,7 @@ error_return:; } int -send_search_reference( +slap_send_search_reference( Backend *be, Connection *conn, Operation *op, diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index 312052605b..86777acfae 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -11,13 +11,18 @@ */ #include "portable.h" +#include "slapi_common.h" #include #include #include "slap.h" +#include "slapi.h" #include #include "lber_pvt.h" +#include "slapi/slapi_utils.h" + +struct berval *ns_get_supported_extop (int); static struct berval supportedFeatures[] = { BER_BVC(LDAP_FEATURE_ALL_OPERATIONAL_ATTRS), /* all Operational Attributes ("+") */ @@ -134,6 +139,14 @@ root_dse_info( return LDAP_OTHER; } +#if defined( LDAP_SLAPI ) + /* netscape supportedExtension */ + for ( i = 0; (bv = ns_get_supported_extop(i)) != NULL; i++ ) { + vals[0] = *bv; + attr_merge( e, ad_supportedExtension, vals ); + } +#endif /* defined( LDAP_SLAPI ) */ + /* supportedFeatures */ if( attr_merge( e, ad_supportedFeatures, supportedFeatures ) ) return LDAP_OTHER; diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 4699633403..3260f8ab34 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -16,6 +16,7 @@ */ #include "portable.h" +#include "slapi_common.h" #include @@ -24,6 +25,7 @@ #include "ldap_pvt.h" #include "slap.h" +#include "slapi.h" int do_search( @@ -44,6 +46,8 @@ do_search( const char *text; int manageDSAit; + Slapi_PBlock *pb = op->o_pb; + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_search: conn %d\n", conn->c_connid, 0, 0 ); #else @@ -310,6 +314,37 @@ do_search( /* deref the base if needed */ suffix_alias( be, &nbase ); +#if defined( LDAP_SLAPI ) + slapi_pblock_set( pb, SLAPI_BACKEND, (void *)be ); + slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn ); + slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op ); + slapi_pblock_set( pb, SLAPI_BIND_TARGET, (void *)base.bv_val ); + slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, (void *)scope ); + slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, (void *)deref ); + slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)sizelimit ); + slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)timelimit ); + slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, (void *)filter ); + slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)fstr.bv_val ); + slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)attrsonly ); + slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)op->o_ctrls ); + slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); + + rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_SEARCH_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no preOp (search) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_search: search preOps failed\n")); +#else + Debug(LDAP_DEBUG_TRACE, "search preOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + /* actually do the search and send the result(s) */ if ( be->be_search ) { (*be->be_search)( be, conn, op, &pbase, &nbase, @@ -321,6 +356,23 @@ do_search( NULL, NULL ); } +#if defined( LDAP_SLAPI ) + rc = doPluginFNs( be, SLAPI_PLUGIN_POST_SEARCH_FN, pb ); + if ( rc != 0 && rc != LDAP_OTHER ) { + /* + * either there is no postOp (search) plugins + * or a plugin failed. Just log it + * + * FIXME: is this correct? + */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_search: search postOps failed\n")); +#else + Debug (LDAP_DEBUG_TRACE, " search postOps failed.\n", 0, 0, 0); +#endif + } +#endif /* defined( LDAP_SLAPI ) */ + return_results:; #ifdef LDAP_CLIENT_UPDATE if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) ) diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 1e611159c1..a763f6c4ee 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1327,6 +1327,8 @@ struct slap_backend_db { BerVarray be_update_refs; /* where to refer modifying clients to */ char *be_realm; void *be_private; /* anything the backend database needs */ + + void *be_pb; /* Netscape plugin */ }; struct slap_conn; @@ -1689,6 +1691,9 @@ typedef struct slap_op { LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */ ValuesReturnFilter *vrFilter; /* Structure represents ValuesReturnFilter */ + + void *o_pb; /* Netscape plugin */ + } Operation; #define get_manageDSAit(op) ((int)(op)->o_managedsait) @@ -1697,6 +1702,80 @@ typedef struct slap_op { #define get_pagedresults(op) ((int)(op)->o_pagedresults) + +typedef void (*SEND_LDAP_RESULT)( + struct slap_conn *conn, + struct slap_op *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray ref, + LDAPControl **ctrls + ); + +#define send_ldap_result( conn, op, err, matched, text, ref, ctrls ) \ +(*conn->c_send_ldap_result)( conn, op, err, matched, text, ref, ctrls ) + + +typedef int (*SEND_SEARCH_ENTRY)( + struct slap_backend_db *be, + struct slap_conn *conn, + struct slap_op *op, + struct slap_entry *e, + AttributeName *attrs, + int attrsonly, + LDAPControl **ctrls + ); + +#define send_search_entry( be, conn, op, e, attrs, attrsonly, ctrls) \ +(*conn->c_send_search_entry)( be, conn, op, e, attrs, attrsonly, ctrls) + + +typedef void (*SEND_SEARCH_RESULT)( + struct slap_conn *conn, + struct slap_op *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray refs, + LDAPControl **ctrls, + int nentries + ); + +#define send_search_result( conn, op, err, matched, text, refs, ctrls, nentries ) \ +(*conn->c_send_search_result)( conn, op, err, matched, text, refs, ctrls, nentries ) + + +typedef int (*SEND_SEARCH_REFERENCE)( + struct slap_backend_db *be, + struct slap_conn *conn, + struct slap_op *op, + struct slap_entry *e, + BerVarray refs, + LDAPControl **ctrls, + BerVarray *v2refs + ); + +#define send_search_reference( be, conn, op, e, refs, ctrls, v2refs ) \ +(*conn->c_send_search_reference)( be, conn, op, e, refs, ctrls, v2refs ) + + +typedef void (*SEND_LDAP_EXTENDED)( + struct slap_conn *conn, + struct slap_op *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray refs, + const char *rspoid, + struct berval *rspdata, + LDAPControl **ctrls + ); + +#define send_ldap_extended( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls) \ +(*conn->c_send_ldap_extended)( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls ) + + /* * Caches the result of a backend_group check for ACL evaluation */ @@ -1777,6 +1856,20 @@ typedef struct slap_conn { long c_n_get; /* num of get calls */ long c_n_read; /* num of read calls */ long c_n_write; /* num of write calls */ + + void *c_pb; /* Netscape plugin */ + + /* + * These are the "callbacks" that are available for back-ends to + * supply data back to connected clients that are connected + * through the "front-end". + */ + SEND_LDAP_RESULT c_send_ldap_result; + SEND_SEARCH_ENTRY c_send_search_entry; + SEND_SEARCH_RESULT c_send_search_result; + SEND_SEARCH_REFERENCE c_send_search_reference; + SEND_LDAP_EXTENDED c_send_ldap_extended; + } Connection; #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) diff --git a/servers/slapd/slapi/Makefile.in b/servers/slapd/slapi/Makefile.in new file mode 100644 index 0000000000..f66c2cfa43 --- /dev/null +++ b/servers/slapd/slapi/Makefile.in @@ -0,0 +1,45 @@ +## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. +## COPYING RESTRICTIONS APPLY, see COPYRIGHT file + +## (C) Copyright IBM Corp. 1997,2002 +## Redistribution and use in source and binary forms are permitted +## provided that this notice is preserved and that due credit is +## given to IBM Corporation. This software is provided ``as is'' +## without express or implied warranty. + + +LIBRARY = libslapi.la +XLIBRARY = libtmpslapd.a + +#all-common: $(LIBRARY) $(PROGRAMS) +# @touch plugin.c slapi_pblock.c slapi_utils.c slapi_ops.c + +NT_SRCS = nt_err.c +NT_OBJS = nt_err.lo + +LIB_DEFS = -DSLAPI_LIBRARY + +SRCS= plugin.c slapi_pblock.c slapi_utils.c printmsg.c slapi_ops.c $(@PLAT@_SRCS) +OBJS= plugin.lo slapi_pblock.lo slapi_utils.lo printmsg.lo slapi_ops.lo $(@PLAT@_SRCS) + +XSRCS= version.c + +LDAP_INCDIR= ../../../include -I.. -I. +LDAP_LIBDIR= ../../../libraries + +XLIBS = $(LIBRARY) +XXLIBS = +NT_LINK_LIBS = $(AC_LIBS) + +XDEFS = $(MODULES_CPPFLAGS) + +UNIX_LINK_LIBS = ./libtmpslapd.a ../libbackends.a ../../../libraries/libavl/libavl.a ../../../libraries/liblber/.libs/liblber.a ../../../libraries/libldbm/libldbm.a ../../../libraries/libldif/libldif.a ../../../libraries/liblutil/liblutil.a ../../../libraries/liblunicode/liblunicode.a ../../../libraries/libldap_r/.libs/libldap_r.a ./libtmpslapd.a + +BUILD_MOD = @BUILD_SLAPI@ + +install-local: FORCE + if test "$(BUILD_MOD)" = "yes"; then \ + $(MKDIR) $(DESTDIR)$(libdir); \ + $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir); \ + fi + diff --git a/servers/slapd/slapi/README b/servers/slapd/slapi/README new file mode 100644 index 0000000000..5edb84edd4 --- /dev/null +++ b/servers/slapd/slapi/README @@ -0,0 +1,55 @@ +Files included in this patch: + +I. Modified OpenLDAP files +--------------------------------- + +1. top level configure.in +2. slap.h +3. back-ldbm/Makefile.in +4. back-ldbm/config.c +5. back-bdb/Makefile.in +6. back-bdb/config.c +7. slapd/tools/Makefile.in +8. ldap/include/Makefile.in +9. slapd/Makefile.in +10. operation.c +11. root_dse.c +12. extended.c +13. bind.c +14. backend.c +15. add.c +16. delete.c +17. compare.c +18. moddify.c +19. modrdn.c +20. search.c +21. result.c +22. mimic.c + + +II. New files +------------------------------- + +1. slapd/slapi/Makefile.in +2. slapd/slapi/ldapload.h +3. slapd/slapi/ldapload.c +4. slapd/slapi/plugin.h +5. slapd/slapi/plugin.c +6. slapd/slapi/printmsg.c +7. slapd/slapi/slapi_pblock.h +8. slapd/slapi/slapi_pblock.c +9. slapd/slapi/slapi_ops.h +10.slapd/slapi/slapi_utils.h +11.slapd/slapi/slapi_utils.c +12.slapd/slapi/ibm_pblock_params.h +13.slapd/slapi/slapi_common.h +14.slapd/slapi/slapi.h +15.slapd/slapi/slapi_cl.h +16.ldap/include/slapi-plugin.h + +III. General procedure + +The directory ldap/servers/slapd/slapi should be created and +files 1-15, section II above should be placed in that directory. +The file slapi-plugin.h (16 above) should also be copied into +the ldap/include directory. diff --git a/servers/slapd/slapi/ibm_pblock_params.h b/servers/slapd/slapi/ibm_pblock_params.h new file mode 100644 index 0000000000..13be5fda86 --- /dev/null +++ b/servers/slapd/slapi/ibm_pblock_params.h @@ -0,0 +1,68 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _ibm_pblock_params_H +#define _ibm_pblock_params_H + +#define FIRST_PARAM -1 +#define LAST_IBM_PARAM -48 +#define NETSCAPE_RESERVED(p) (p >= 280) && (p <= 299) +#define IBM_RESERVED(p) (p >= LAST_IBM_PARAM) && (p <= FIRST_PARAM) + +#define SLAPI_IBM_THREAD_CONTROL (FIRST_PARAM - 1) +#define SLAPI_IBM_PBLOCK (FIRST_PARAM - 2) +#define SLAPI_IBM_CONNECTION_PTR (FIRST_PARAM - 3) +#define SLAPI_IBM_BACKENDS (FIRST_PARAM - 4) +#define SLAPI_PRE_BIND_ALL (FIRST_PARAM - 5) +#define SLAPI_POST_BIND_ALL (FIRST_PARAM - 6) +#define SLAPI_IBM_ADMIN_DN (FIRST_PARAM - 7) +#define SLAPI_CONFIG_STATE (FIRST_PARAM - 8) +#define SLAPI_PLUGIN_DB_REGISTER_SERVICE_FN (FIRST_PARAM - 9) +#define SLAPI_PLUGIN_DB_INSERT_REPL_ENTRIES_FN (FIRST_PARAM - 10) +#define SLAPI_PLUGIN_DB_GET_REPL_ENTRIES_FN (FIRST_PARAM - 11) +#define SLAPI_PLUGIN_DB_REPLICA_DONE_FN (FIRST_PARAM - 12) +#define SLAPI_PLUGIN_DB_INIT_REPL_LIST_FN (FIRST_PARAM - 13) +#define SLAPI_PLUGIN_DB_THREAD_INITIALIZE_FN (FIRST_PARAM - 14) +#define SLAPI_PLUGIN_DB_THREAD_TERMINATE_FN (FIRST_PARAM - 15) +#define SLAPI_PLUGIN_DB_SCHEMA_MODIFY_ATTRTYPE_FN (FIRST_PARAM - 16) +#define SLAPI_PLUGIN_DB_SCHEMA_MODIFY_OBJCLASS_FN (FIRST_PARAM - 17) +#define SLAPI_PLUGIN_DB_INIT_FN (FIRST_PARAM - 18) +#define SLAPI_IBM_EXTENDED_OPS (FIRST_PARAM - 19) +#define SLAPI_IBM_CONTROLS (FIRST_PARAM - 20) +#define SLAPI_IBM_SASLMECHANISMS (FIRST_PARAM - 21) +#define SLAPI_IBM_BROADCAST_BE (FIRST_PARAM - 22) +#define SLAPI_IBM_NOTIFY_BIND_FN (FIRST_PARAM - 23) +#define SLAPI_IBM_SECRET (FIRST_PARAM - 24) +#define SLAPI_IBM_CL_START_FN (FIRST_PARAM - 25) +#define SLAPI_IBM_REPLICATE (FIRST_PARAM - 26) +#define SLAPI_IBM_CL_CLASS (FIRST_PARAM - 27) +#define SLAPI_IBM_CL_SUFFIX (FIRST_PARAM - 28) +#define SLAPI_IBM_CL_MAX_ENTRIES (FIRST_PARAM - 29) +#define SLAPI_IBM_CONNINFO (FIRST_PARAM - 30) +#define SLAPI_IBM_CL_FIRST_ENTRY (FIRST_PARAM - 31) +#define SLAPI_IBM_CL_LAST_ENTRY (FIRST_PARAM - 32) +#define SLAPI_IBM_CONN_DN_ALT (FIRST_PARAM - 33) +#define SLAPI_IBM_GSSAPI_CONTEXT (FIRST_PARAM - 34) +#define SLAPI_IBM_ADD_ENTRY (FIRST_PARAM - 35) +#define SLAPI_IBM_DELETE_ENTRY (FIRST_PARAM - 36) +#define SLAPI_IBM_MODIFY_ENTRY (FIRST_PARAM - 37) +#define SLAPI_IBM_MODIFY_MODS (FIRST_PARAM - 38) +#define SLAPI_IBM_MODRDN_ENTRY (FIRST_PARAM - 39) +#define SLAPI_IBM_MODRDN_NEWDN (FIRST_PARAM - 40) +#define SLAPI_IBM_EVENT_ENABLED (FIRST_PARAM - 41) +#define SLAPI_IBM_EVENT_MAXREG (FIRST_PARAM - 42) +#define SLAPI_IBM_EVENT_REGPERCONN (FIRST_PARAM - 43) +#define SLAPI_IBM_EVENT_CURREG (FIRST_PARAM - 44) +#define SLAPI_IBM_EVENT_SENTREG (FIRST_PARAM - 45) +#define SLAPI_IBM_CONN_DN_ORIG (FIRST_PARAM - 46) +#define SLAPI_PLUGIN_DB_DELETE_PROGRESS_FN (FIRST_PARAM - 47) +#endif diff --git a/servers/slapd/slapi/plugin.c b/servers/slapd/slapi/plugin.c new file mode 100644 index 0000000000..858cbeb37e --- /dev/null +++ b/servers/slapd/slapi/plugin.c @@ -0,0 +1,679 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" +#include +#include +#include + +/* + * Note: if ltdl.h is not available, slapi should not be compiled + */ +#include + +static int loadPlugin( Slapi_PBlock *, const char *, const char *, int, + SLAPI_FUNC *, lt_dlhandle * ); + +/* pointer to link list of extended objects */ +static ExtendedOp *pGExtendedOps = NULL; + +/********************************************************************* + * Function Name: newPlugin + * + * Description: This routine creates a new Slapi_PBlock structure, + * loads in the plugin module and executes the init + * function provided by the module. + * + * Input: type - type of the plugin, such as SASL, database, etc. + * path - the loadpath to load the module in + * initfunc - name of the plugin function to execute first + * argc - number of arguements + * argv[] - an array of char pointers point to + * the arguments passed in via + * the configuration file. + * + * Output: + * + * Return Values: a pointer to a newly created Slapi_PBlock structrue or + * NULL - function failed + * + * Messages: None + *********************************************************************/ + +Slapi_PBlock * +newPlugin( + int type, + const char *path, + const char *initfunc, + int argc, + char *argv[] ) +{ + Slapi_PBlock *pPlugin = NULL; + lt_dlhandle hdLoadHandle; + int rc; + + pPlugin = slapi_pblock_new(); + if ( pPlugin == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)type ); + if ( rc != LDAP_SUCCESS ) { + goto done; + } + + rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)argc ); + if ( rc != LDAP_SUCCESS ) { + goto done; + } + + rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv ); + if ( rc != LDAP_SUCCESS ) { + goto done; + } + + rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle ); + +done: + if ( rc != LDAP_SUCCESS && pPlugin != NULL ) { + slapi_pblock_destroy( pPlugin ); + pPlugin = NULL; + } + + return pPlugin; +} + +/********************************************************************* + * Function Name: insertPlugin + * + * Description: insert the slapi_pblock structure to the end of the plugin + * list + * + * Input: a pointer to a plugin slapi_pblock structure to be added to + * the list + * + * Output: none + * + * Return Values: LDAP_SUCCESS - successfully inserted. + * LDAP_LOCAL_ERROR. + * + * Messages: None + *********************************************************************/ +int +insertPlugin( + Backend *be, + Slapi_PBlock *pPB ) +{ + Slapi_PBlock *pTmpPB; + Slapi_PBlock *pSavePB; + int rc = LDAP_SUCCESS; + + pTmpPB = (Slapi_PBlock *)(be->be_pb); + + if ( pTmpPB == NULL ) { + be->be_pb = (void *)pPB; + } else { + while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) { + pSavePB = pTmpPB; + rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, + &pTmpPB ); + if ( rc != LDAP_SUCCESS ) { + rc = LDAP_OTHER; + } + } + + if ( rc == LDAP_SUCCESS ) { + rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK, + (void *)pPB ); + if ( rc != LDAP_SUCCESS ) { + rc = LDAP_OTHER; + } + } + } + + return rc; +} + +/********************************************************************* + * Function Name: getAllPluginFuncs + * + * Description: get the desired type of function pointers defined + * in all the plugins + * + * Input: the type of the functions to get, such as pre-operation,etc. + * + * Output: none + * + * Return Values: this routine returns a pointer to an array of function + * pointers + * + * Messages: None + *********************************************************************/ +int +getAllPluginFuncs( + Backend *be, + int functype, + SLAPI_FUNC **ppFuncPtrs ) +{ + + Slapi_PBlock *pCurrentPB; + SLAPI_FUNC FuncPtr; + SLAPI_FUNC *pTmpFuncPtr; + int numPB = 0; + int rc = LDAP_SUCCESS; + + assert( be ); + assert( ppFuncPtrs ); + + pCurrentPB = (Slapi_PBlock *)(be->be_pb); + + if ( pCurrentPB == NULL ) { + /* + * LDAP_OTHER is returned if no plugins are installed + */ + rc = LDAP_OTHER; + goto done; + } + + while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) { + rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr ); + if ( rc == LDAP_SUCCESS ) { + if ( FuncPtr != NULL ) { + numPB++; + } + rc = slapi_pblock_get( pCurrentPB, + SLAPI_IBM_PBLOCK, &pCurrentPB ); + } + } + + if ( rc != LDAP_SUCCESS ) { + goto done; + } + + if ( numPB == 0 ) { + *ppFuncPtrs = NULL; + rc = LDAP_SUCCESS; + goto done; + } + + *ppFuncPtrs = pTmpFuncPtr = + (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) ); + if ( ppFuncPtrs == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + pCurrentPB = (Slapi_PBlock *)(be->be_pb); + while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) { + rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr ); + if ( rc == LDAP_SUCCESS ) { + if ( FuncPtr != NULL ) { + *pTmpFuncPtr = FuncPtr; + pTmpFuncPtr++; + } + rc = slapi_pblock_get( pCurrentPB, + SLAPI_IBM_PBLOCK, &pCurrentPB ); + } + } + *pTmpFuncPtr = NULL ; + +done: + if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) { + ch_free( *ppFuncPtrs ); + *ppFuncPtrs = NULL; + } + + return rc; +} + +/********************************************************************* + * Function Name: createExtendedOp + * + * Description: Creates an extended operation structure and + * initializes the fields + * + * Return value: A newly allocated structure or NULL + ********************************************************************/ +ExtendedOp * +createExtendedOp() +{ + ExtendedOp *ret; + + ret = (ExtendedOp *)ch_malloc(sizeof(ExtendedOp)); + if ( ret != NULL ) { + ret->ext_oid.bv_val = NULL; + ret->ext_oid.bv_len = 0; + ret->ext_func = NULL; + ret->ext_be = NULL; + ret->ext_next = NULL; + } + + return ret; +} + + +/********************************************************************* + * Function Name: removeExtendedOp + * + * Description: This routine removes the ExtendedOp structures + * asscoiated with a particular extended operation + * plugin. + * + * Input: pBE - pointer to a backend structure + * opList - pointer to a linked list of extended + * operation structures + * pPB - pointer to a slapi parameter block + * + * Output: + * + * Return Value: none + * + * Messages: None + *********************************************************************/ +void +removeExtendedOp( + Backend *pBE, + ExtendedOp **opList, + Slapi_PBlock *pPB ) +{ + ExtendedOp *pTmpExtOp, *backExtOp; + char **pTmpOIDs; + int i; + +#if 0 + assert( pBE != NULL); /* unused */ +#endif /* 0 */ + assert( opList != NULL ); + assert( pPB != NULL ); + + if ( *opList == NULL ) { + return; + } + + slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs ); + if ( pTmpOIDs == NULL ) { + return; + } + + for ( i = 0; pTmpOIDs[i] != NULL; i++ ) { + backExtOp = NULL; + pTmpExtOp = *opList; + for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) { + int rc; + rc = strcasecmp( pTmpExtOp->ext_oid.bv_val, + pTmpOIDs[ i ] ); + if ( rc == 0 ) { + if ( backExtOp == NULL ) { + *opList = pTmpExtOp->ext_next; + } else { + backExtOp->ext_next + = pTmpExtOp->ext_next; + } + + ch_free( pTmpExtOp ); + break; + } + backExtOp = pTmpExtOp; + } + } +} + + +/********************************************************************* + * Function Name: newExtendedOp + * + * Description: This routine creates a new ExtendedOp structure, loads + * in the extended op module and put the extended op function address + * in the structure. The function will not be executed in + * this routine. + * + * Input: pBE - pointer to a backend structure + * opList - pointer to a linked list of extended + * operation structures + * pPB - pointer to a slapi parameter block + * + * Output: + * + * Return Value: an LDAP return code + * + * Messages: None + *********************************************************************/ +int +newExtendedOp( + Backend *pBE, + ExtendedOp **opList, + Slapi_PBlock *pPB ) +{ + ExtendedOp *pTmpExtOp = NULL; + SLAPI_FUNC tmpFunc; + char **pTmpOIDs; + int rc = LDAP_OTHER; + int i; + + if ( (*opList) == NULL ) { + *opList = createExtendedOp(); + if ( (*opList) == NULL ) { + rc = LDAP_NO_MEMORY; + goto error_return; + } + pTmpExtOp = *opList; + + } else { /* Find the end of the list */ + for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL; + pTmpExtOp = pTmpExtOp->ext_next ) + ; /* EMPTY */ + pTmpExtOp->ext_next = createExtendedOp(); + if ( pTmpExtOp->ext_next == NULL ) { + rc = LDAP_NO_MEMORY; + goto error_return; + } + pTmpExtOp = pTmpExtOp->ext_next; + } + + rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs ); + if ( rc != LDAP_SUCCESS ) { + rc = LDAP_OTHER; + goto error_return; + } + + rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc); + if ( rc != 0 ) { + rc = LDAP_OTHER; + goto error_return; + } + + if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) { + rc = LDAP_OTHER; + goto error_return; + } + + for ( i = 0; pTmpOIDs[i] != NULL; i++ ) { + pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i]; + pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] ); + pTmpExtOp->ext_func = tmpFunc; + pTmpExtOp->ext_be = pBE; + if ( pTmpOIDs[i + 1] != NULL ) { + pTmpExtOp->ext_next = createExtendedOp(); + if ( pTmpExtOp->ext_next == NULL ) { + rc = LDAP_NO_MEMORY; + break; + } + pTmpExtOp = pTmpExtOp->ext_next; + } + } + +error_return: + return rc; +} + +/********************************************************************* + * Function Name: getPluginFunc + * + * Description: This routine gets the function address for a given function + * name. + * + * Input: + * funcName - name of the extended op function, ie. an OID. + * + * Output: pFuncAddr - the function address of the requested function name. + * + * Return Values: a pointer to a newly created ExtendOp structrue or + * NULL - function failed + * + * Messages: None + *********************************************************************/ +int +getPluginFunc( + struct berval *reqoid, + SLAPI_FUNC *pFuncAddr ) +{ + ExtendedOp *pTmpExtOp; + + assert( reqoid != NULL ); + assert( pFuncAddr != NULL ); + + *pFuncAddr = NULL; + + if ( pGExtendedOps == NULL ) { + return LDAP_OTHER; + } + + pTmpExtOp = pGExtendedOps; + while ( pTmpExtOp != NULL ) { + int rc; + + rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val ); + if ( rc == 0 ) { + *pFuncAddr = pTmpExtOp->ext_func; + break; + } + pTmpExtOp = pTmpExtOp->ext_next; + } + + return ( *pFuncAddr == NULL ? 1 : 0 ); +} + +/*************************************************************************** + * This function is similar to getPluginFunc above. except it returns one OID + * per call. It is called from root_dse_info (root_dse.c). + * The function is a modified version of get_supported_extop (file extended.c). + ***************************************************************************/ +struct berval * +ns_get_supported_extop( int index ) +{ + ExtendedOp *ext; + + for ( ext = pGExtendedOps ; ext != NULL && --index >= 0; + ext = ext->ext_next) { + ; /* empty */ + } + + if ( ext == NULL ) { + return NULL; + } + + return &ext->ext_oid ; +} + +/********************************************************************* + * Function Name: loadPlugin + * + * Description: This routine loads the specified DLL, gets and executes the init function + * if requested. + * + * Input: + * pPlugin - a pointer to a Slapi_PBlock struct which will be passed to + * the DLL init function. + * path - path name of the DLL to be load. + * initfunc - either the DLL initialization function or an OID of the + * loaded extended operation. + * doInit - if it is TRUE, execute the init function, otherwise, save the + * function address but not execute it. + * + * Output: pInitFunc - the function address of the loaded function. This param + * should be not be null if doInit is FALSE. + * pLdHandle - handle returned by lt_dlopen() + * + * Return Values: LDAP_SUCCESS, LDAP_LOCAL_ERROR + * + * Messages: None + *********************************************************************/ + +static int +loadPlugin( + Slapi_PBlock *pPlugin, + const char *path, + const char *initfunc, + int doInit, + SLAPI_FUNC *pInitFunc, + lt_dlhandle *pLdHandle ) +{ + int rc = LDAP_SUCCESS; + SLAPI_FUNC fpInitFunc = NULL; + + assert( pLdHandle ); + + if ( lt_dlinit() ) { + return LDAP_LOCAL_ERROR; + } + + /* load in the module */ + *pLdHandle = lt_dlopen( path ); + if ( *pLdHandle == NULL ) { + return LDAP_LOCAL_ERROR; + } + + fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc ); + if ( fpInitFunc == NULL ) { + lt_dlclose( *pLdHandle ); + return LDAP_LOCAL_ERROR; + } + + if ( doInit == TRUE ) { + rc = ( *fpInitFunc )( pPlugin ); + if ( rc != LDAP_SUCCESS ) { + lt_dlclose( *pLdHandle ); + } + + } else { + *pInitFunc = fpInitFunc; + } + + return rc; +} + + +int +doPluginFNs( + Backend *be, + int funcType, + Slapi_PBlock *pPB ) +{ + + int rc = LDAP_SUCCESS; + SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL; + + rc = getAllPluginFuncs(be, funcType, &tmpPlugin ); + if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) { + return rc; + } + + for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) { + /* + * FIXME: operation stops at first non-success + * + * FIXME: we should provide here a sort of sandbox, + * to protect from plugin faults; e.g. trap signals + * and longjump here, marking the plugin as unsafe for + * later executions ... + */ + rc = (*pGetPlugin)(pPB); + + if ( rc != LDAP_SUCCESS ) { + break; + } + } + + ch_free( tmpPlugin ); + + return rc; +} + +int +netscape_plugin( + Backend *be, + const char *fname, + int lineno, + int argc, + char **argv ) +{ + int iType = -1; + int numPluginArgc = 0; + char **ppPluginArgv = NULL; + + if ( argc < 4 ) { + fprintf( stderr, + "%s: line %d: missing arguments " + "in \"plugin " + " []\" line\n", + fname, lineno ); + return 1; + } + + if ( strcasecmp( argv[1], "preoperation" ) == 0 ) { + iType = SLAPI_PLUGIN_PREOPERATION; + } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) { + iType = SLAPI_PLUGIN_POSTOPERATION; + } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) { + iType = SLAPI_PLUGIN_EXTENDEDOP; + } else { + fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n", + fname, lineno, argv[1] ); + return 1; + } + + numPluginArgc = argc - 4; + if ( numPluginArgc > 0 ) { + ppPluginArgv = &argv[4]; + } else { + ppPluginArgv = NULL; + } + + if ( iType == SLAPI_PLUGIN_PREOPERATION || + iType == SLAPI_PLUGIN_EXTENDEDOP || + iType == SLAPI_PLUGIN_POSTOPERATION ) { + int rc; + Slapi_PBlock *pPlugin; + + pPlugin = newPlugin( iType, argv[2], argv[3], + numPluginArgc, ppPluginArgv ); + if (pPlugin == NULL) { + return 1; + } + + if (iType == SLAPI_PLUGIN_EXTENDEDOP) { + rc = newExtendedOp(be, &pGExtendedOps, pPlugin); + if ( rc != LDAP_SUCCESS ) { + slapi_pblock_destroy( pPlugin ); + return 1; + } + } + + rc = insertPlugin( be, pPlugin ); + if ( rc != LDAP_SUCCESS ) { + if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) { + removeExtendedOp( be, &pGExtendedOps, pPlugin ); + } + slapi_pblock_destroy( pPlugin ); + return 1; + } + } + + return 0; +} + +int +slapi_init(void) +{ + if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) { + return -1; + } + + if ( ldap_pvt_thread_mutex_init( &slapi_time_mutex ) ) { + return -1; + } + + return 0; +} + diff --git a/servers/slapd/slapi/plugin.h b/servers/slapd/slapi/plugin.h new file mode 100644 index 0000000000..7aaa20ef60 --- /dev/null +++ b/servers/slapd/slapi/plugin.h @@ -0,0 +1,28 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +Slapi_PBlock *newPlugin ( int type, const char *path, const char *initfunc, + int argc, char *argv[] ); +int insertPlugin(Backend *be, Slapi_PBlock *pPB); +int doPluginFNs(Backend *be, int funcType, Slapi_PBlock * pPB); +int getAllPluginFuncs(Backend *be, int functype, SLAPI_FUNC **ppFuncPtrs); +int newExtendedOp(Backend *pBE, ExtendedOp **opList, Slapi_PBlock *pPB); +int getPluginFunc(struct berval *reqoid, SLAPI_FUNC *pFuncAddr ); +int netscape_plugin(Backend *be, const char *fname, int lineno, + int argc, char **argv ); +int slapi_init(void); + +#endif /* _PLUGIN_H_ */ + diff --git a/servers/slapd/slapi/printmsg.c b/servers/slapd/slapi/printmsg.c new file mode 100644 index 0000000000..6ecdadc3a8 --- /dev/null +++ b/servers/slapd/slapi/printmsg.c @@ -0,0 +1,118 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* Single threads access to routine */ +static ldap_pvt_thread_mutex_t PrintMessage_mutex; +static int PrintMessage_mutex_inited = 0; + +static void +InitMutex () +{ + if (PrintMessage_mutex_inited == 0) { + PrintMessage_mutex_inited = 1; + ldap_pvt_thread_mutex_init(&PrintMessage_mutex); + } +} + +int +vLogError( + int level, + char *subsystem, + char *fmt, + va_list arglist ) +{ + int rc = 0; + char *tmpFmt; + FILE * fp = NULL; + char *p, *sval; + int ival; + + char timeStr[100]; + struct tm *ltm; + time_t currentTime; + + tmpFmt = fmt; + fmt = (char*)ch_calloc(strlen(subsystem) + strlen(tmpFmt) + 3, 1); + sprintf(fmt, "%s: %s", subsystem, tmpFmt); + + InitMutex() ; + ldap_pvt_thread_mutex_lock( &PrintMessage_mutex ) ; + + /* for now, we log all severities */ + if ( 1 ) { + fp = fopen( LDAP_RUNDIR LDAP_DIRSEP "errors", "a" ); + if (fp == NULL) + fp = fopen( "errors", "a" ); + + if ( fp != NULL) { + while ( lockf(fileno(fp), F_LOCK, 0 ) != 0 ) {} + + time (¤tTime); + ltm = localtime( ¤tTime ); + strftime( timeStr, sizeof(timeStr), "%x %X ", ltm ); + fprintf(fp, timeStr); + for (p = fmt; *p; p++) { + if (*p != '%') { + fprintf(fp, "%c", *p); + continue; + } + switch(*++p) { + case 'd': + ival = va_arg( arglist, int); + fprintf(fp, "%d", ival); + break; + case 's': + for (sval = va_arg(arglist, char *); *sval; sval++) + fprintf(fp, "%c", *sval); + break; + default: + fprintf(fp, "%c", *p); + break; + + } + } + + fflush(fp); + + lockf( fileno(fp), F_ULOCK, 0 ); + + fclose(fp); + } else { +#if 0 /* unused */ + int save_errno = (int)errno; +#endif /* unused */ + rc = ( -1); + } + } else { + rc = ( -1); + } + + ldap_pvt_thread_mutex_unlock( &PrintMessage_mutex ); + ch_free(fmt); + + return (rc); +} diff --git a/servers/slapd/slapi/slapi-plugin.h b/servers/slapd/slapi/slapi-plugin.h new file mode 100644 index 0000000000..824e1dbf95 --- /dev/null +++ b/servers/slapd/slapi/slapi-plugin.h @@ -0,0 +1,379 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _SLAPI_PLUGIN_H +#define _SLAPI_PLUGIN_H + +#include "lber.h" +#include "ldap.h" + +typedef struct slapi_pblock Slapi_PBlock; +typedef struct slapi_entry Slapi_Entry; +typedef struct slapi_attr Slapi_Attr; +typedef struct slapi_filter Slapi_Filter; + + +/* pblock routines */ +int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ); +int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ); +Slapi_PBlock *slapi_pblock_new(); +void slapi_pblock_destroy( Slapi_PBlock* ); + +/* entry/attr/dn routines */ +Slapi_Entry *slapi_str2entry( char *s, int flags ); +char *slapi_entry2str( Slapi_Entry *e, int *len ); +char *slapi_entry_get_dn( Slapi_Entry *e ); +void slapi_entry_set_dn( Slapi_Entry *e, char *dn ); +Slapi_Entry *slapi_entry_dup( Slapi_Entry *e ); +int slapi_entry_attr_delete( Slapi_Entry *e, char *type ); +Slapi_Entry *slapi_entry_alloc(); +void slapi_entry_free( Slapi_Entry *e ); +int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals ); +int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr ); +int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals ); +char *slapi_dn_normalize( char *dn ); +char *slapi_dn_normalize_case( char *dn ); +int slapi_dn_issuffix( char *dn, char *suffix ); +char *slapi_dn_ignore_case( char *dn ); + +/* char routines */ +char *slapi_ch_malloc( unsigned long size ); +void slapi_ch_free( void *ptr ); +char *slapi_ch_calloc( unsigned long nelem, unsigned long size ); +char *slapi_ch_realloc( char *block, unsigned long size ); +char *slapi_ch_strdup( char *s ); + + +/* LDAP V3 routines */ +int slapi_control_present( LDAPControl **controls, char *oid, + struct berval **val, int *iscritical); +void slapi_register_supported_control(char *controloid, + unsigned long controlops); +#define SLAPI_OPERATION_BIND 0x00000001L +#define SLAPI_OPERATION_UNBIND 0x00000002L +#define SLAPI_OPERATION_SEARCH 0x00000004L +#define SLAPI_OPERATION_MODIFY 0x00000008L +#define SLAPI_OPERATION_ADD 0x00000010L +#define SLAPI_OPERATION_DELETE 0x00000020L +#define SLAPI_OPERATION_MODDN 0x00000040L +#define SLAPI_OPERATION_MODRDN SLAPI_OPERATION_MODDN +#define SLAPI_OPERATION_COMPARE 0x00000080L +#define SLAPI_OPERATION_ABANDON 0x00000100L +#define SLAPI_OPERATION_EXTENDED 0x00000200L +#define SLAPI_OPERATION_ANY 0xFFFFFFFFL +#define SLAPI_OPERATION_NONE 0x00000000L +int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp); +void slapi_register_supported_saslmechanism(char *mechanism); +char **slapi_get_supported_saslmechanisms(); +char **slapi_get_supported_extended_ops(void); + + +/* send ldap result back */ +void slapi_send_ldap_result( Slapi_PBlock *pb, int err, char *matched, + char *text, int nentries, struct berval **urls ); +int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, + LDAPControl **ectrls, char **attrs, int attrsonly ); + +/* filter routines */ +Slapi_Filter *slapi_str2filter( char *str ); +void slapi_filter_free( Slapi_Filter *f, int recurse ); +int slapi_filter_get_choice( Slapi_Filter *f); +int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval ); +Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f ); +Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev ); + +/* internal add/delete/search/modify routines */ +Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, + LDAPControl **controls, char **attrs, int attrsonly ); +Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods, + LDAPControl **controls, int log_change); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, + LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, + LDAPControl **controls, int log_changes ); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, + LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_delete_internal( char * dn, LDAPControl **controls, + int log_change ); +Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, + char *newParent, int deloldrdn, LDAPControl **controls, + int log_change); +void slapi_free_search_results_internal(Slapi_PBlock *pb); + +/* connection related routines */ +int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL); +int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort); + +/* parameters currently supported */ + + +/* plugin types supported */ + +#define SLAPI_PLUGIN_DATABASE 1 +#define SLAPI_PLUGIN_EXTENDEDOP 2 +#define SLAPI_PLUGIN_PREOPERATION 3 +#define SLAPI_PLUGIN_POSTOPERATION 4 +#define SLAPI_PLUGIN_AUDIT 7 + +/* misc params */ + +#define SLAPI_BACKEND 130 +#define SLAPI_CONNECTION 131 +#define SLAPI_OPERATION 132 +#define SLAPI_REQUESTOR_ISROOT 133 +#define SLAPI_BE_MONITORDN 134 +#define SLAPI_BE_TYPE 135 +#define SLAPI_BE_READONLY 136 +#define SLAPI_BE_LASTMOD 137 +#define SLAPI_CONN_ID 139 + +/* operation params */ +#define SLAPI_OPINITIATED_TIME 140 +#define SLAPI_REQUESTOR_DN 141 +#define SLAPI_REQUESTOR_ISUPDATEDN 142 + +/* connection structure params*/ +#define SLAPI_CONN_DN 143 +#define SLAPI_CONN_AUTHTYPE 144 + +/* Authentication types */ +#define SLAPD_AUTH_NONE "none" +#define SLAPD_AUTH_SIMPLE "simple" +#define SLAPD_AUTH_SSL "SSL" +#define SLAPD_AUTH_SASL "SASL " + +/* plugin configuration parmams */ +#define SLAPI_PLUGIN 3 +#define SLAPI_PLUGIN_PRIVATE 4 +#define SLAPI_PLUGIN_TYPE 5 +#define SLAPI_PLUGIN_ARGV 6 +#define SLAPI_PLUGIN_ARGC 7 +#define SLAPI_PLUGIN_VERSION 8 +#define SLAPI_PLUGIN_OPRETURN 9 +#define SLAPI_PLUGIN_OBJECT 10 +#define SLAPI_PLUGIN_DESTROY_FN 11 +#define SLAPI_PLUGIN_DESCRIPTION 12 + +/* internal opreations params */ +#define SLAPI_PLUGIN_INTOP_RESULT 15 +#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES 16 +#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS 17 + +/* function pointer params for backends */ +#define SLAPI_PLUGIN_DB_BIND_FN 200 +#define SLAPI_PLUGIN_DB_UNBIND_FN 201 +#define SLAPI_PLUGIN_DB_SEARCH_FN 202 +#define SLAPI_PLUGIN_DB_COMPARE_FN 203 +#define SLAPI_PLUGIN_DB_MODIFY_FN 204 +#define SLAPI_PLUGIN_DB_MODRDN_FN 205 +#define SLAPI_PLUGIN_DB_ADD_FN 206 +#define SLAPI_PLUGIN_DB_DELETE_FN 207 +#define SLAPI_PLUGIN_DB_ABANDON_FN 208 +#define SLAPI_PLUGIN_DB_CONFIG_FN 209 +#define SLAPI_PLUGIN_CLOSE_FN 210 +#define SLAPI_PLUGIN_DB_FLUSH_FN 211 +#define SLAPI_PLUGIN_START_FN 212 +#define SLAPI_PLUGIN_DB_SEQ_FN 213 +#define SLAPI_PLUGIN_DB_ENTRY_FN 214 +#define SLAPI_PLUGIN_DB_REFERRAL_FN 215 +#define SLAPI_PLUGIN_DB_RESULT_FN 216 +#define SLAPI_PLUGIN_DB_LDIF2DB_FN 217 +#define SLAPI_PLUGIN_DB_DB2LDIF_FN 218 +#define SLAPI_PLUGIN_DB_BEGIN_FN 219 +#define SLAPI_PLUGIN_DB_COMMIT_FN 220 +#define SLAPI_PLUGIN_DB_ABORT_FN 221 +#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN 222 +#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN 223 +#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN 224 +#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN 225 +#define SLAPI_PLUGIN_DB_SIZE_FN 226 +#define SLAPI_PLUGIN_DB_TEST_FN 227 + + +/* functions pointers for LDAP V3 extended ops */ +#define SLAPI_PLUGIN_EXT_OP_FN 300 +#define SLAPI_PLUGIN_EXT_OP_OIDLIST 301 + +/* functions for preoperation functions */ +#define SLAPI_PLUGIN_PRE_BIND_FN 401 +#define SLAPI_PLUGIN_PRE_UNBIND_FN 402 +#define SLAPI_PLUGIN_PRE_SEARCH_FN 403 +#define SLAPI_PLUGIN_PRE_COMPARE_FN 404 +#define SLAPI_PLUGIN_PRE_MODIFY_FN 405 +#define SLAPI_PLUGIN_PRE_MODRDN_FN 406 +#define SLAPI_PLUGIN_PRE_ADD_FN 407 +#define SLAPI_PLUGIN_PRE_DELETE_FN 408 +#define SLAPI_PLUGIN_PRE_ABANDON_FN 409 +#define SLAPI_PLUGIN_PRE_ENTRY_FN 410 +#define SLAPI_PLUGIN_PRE_REFERRAL_FN 411 +#define SLAPI_PLUGIN_PRE_RESULT_FN 412 + +/* functions for postoperation functions*/ +#define SLAPI_PLUGIN_POST_BIND_FN 501 +#define SLAPI_PLUGIN_POST_UNBIND_FN 502 +#define SLAPI_PLUGIN_POST_SEARCH_FN 503 +#define SLAPI_PLUGIN_POST_COMPARE_FN 504 +#define SLAPI_PLUGIN_POST_MODIFY_FN 505 +#define SLAPI_PLUGIN_POST_MODRDN_FN 506 +#define SLAPI_PLUGIN_POST_ADD_FN 507 +#define SLAPI_PLUGIN_POST_DELETE_FN 508 +#define SLAPI_PLUGIN_POST_ABANDON_FN 509 +#define SLAPI_PLUGIN_POST_ENTRY_FN 510 +#define SLAPI_PLUGIN_POST_REFERRAL_FN 511 +#define SLAPI_PLUGIN_POST_RESULT_FN 512 + +/* audit plugin defines */ +#define SLAPI_PLUGIN_AUDIT_DATA 1100 +#define SLAPI_PLUGIN_AUDIT_FN 1101 + +/* managedsait control */ +#define SLAPI_MANAGEDSAIT 1000 + +/* config stuff */ +#define SLAPI_CONFIG_FILENAME 40 +#define SLAPI_CONFIG_LINENO 41 +#define SLAPI_CONFIG_ARGC 42 +#define SLAPI_CONFIG_ARGV 43 + +/* operational params */ +#define SLAPI_TARGET_DN 50 +#define SLAPI_REQCONTROLS 51 + +/* server LDAPv3 controls */ +#define SLAPI_RESCONTROLS 55 +#define SLAPI_ADD_RESCONTROL 56 + +/* add params */ +#define SLAPI_ADD_TARGET SLAPI_TARGET_DN +#define SLAPI_ADD_ENTRY 60 + +/* bind params */ +#define SLAPI_BIND_TARGET SLAPI_TARGET_DN +#define SLAPI_BIND_METHOD 70 +#define SLAPI_BIND_CREDENTIALS 71 +#define SLAPI_BIND_SASLMECHANISM 72 +#define SLAPI_BIND_RET_SASLCREDS 73 + +/* compare params */ +#define SLAPI_COMPARE_TARGET SLAPI_TARGET_DN +#define SLAPI_COMPARE_TYPE 80 +#define SLAPI_COMPARE_VALUE 81 + +/* delete params */ +#define SLAPI_DELETE_TARGET SLAPI_TARGET_DN + +/* modify params */ +#define SLAPI_MODIFY_TARGET SLAPI_TARGET_DN +#define SLAPI_MODIFY_MODS 90 + +/* modrdn params */ +#define SLAPI_MODRDN_TARGET SLAPI_TARGET_DN +#define SLAPI_MODRDN_NEWRDN 100 +#define SLAPI_MODRDN_DELOLDRDN 101 +#define SLAPI_MODRDN_NEWSUPERIOR 102 /* v3 only */ + +/* search params */ +#define SLAPI_SEARCH_TARGET SLAPI_TARGET_DN +#define SLAPI_SEARCH_SCOPE 110 +#define SLAPI_SEARCH_DEREF 111 +#define SLAPI_SEARCH_SIZELIMIT 112 +#define SLAPI_SEARCH_TIMELIMIT 113 +#define SLAPI_SEARCH_FILTER 114 +#define SLAPI_SEARCH_STRFILTER 115 +#define SLAPI_SEARCH_ATTRS 116 +#define SLAPI_SEARCH_ATTRSONLY 117 + +/* abandon params */ +#define SLAPI_ABANDON_MSGID 120 + +/* extended operation params */ +#define SLAPI_EXT_OP_REQ_OID 160 +#define SLAPI_EXT_OP_REQ_VALUE 161 + +/* extended operation return codes */ +#define SLAPI_EXT_OP_RET_OID 162 +#define SLAPI_EXT_OP_RET_VALUE 163 + +#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT -1 + +/* Search result params */ +#define SLAPI_SEARCH_RESULT_SET 193 +#define SLAPI_SEARCH_RESULT_ENTRY 194 +#define SLAPI_NENTRIES 195 +#define SLAPI_SEARCH_REFERRALS 196 + + +/* filter types */ +#ifndef LDAP_FILTER_AND +#define LDAP_FILTER_AND 0xa0L +#endif +#ifndef LDAP_FILTER_OR +#define LDAP_FILTER_OR 0xa1L +#endif +#ifndef LDAP_FILTER_NOT +#define LDAP_FILTER_NOT 0xa2L +#endif +#ifndef LDAP_FILTER_EQUALITY +#define LDAP_FILTER_EQUALITY 0xa3L +#endif +#ifndef LDAP_FILTER_SUBSTRINGS +#define LDAP_FILTER_SUBSTRINGS 0xa4L +#endif +#ifndef LDAP_FILTER_GE +#define LDAP_FILTER_GE 0xa5L +#endif +#ifndef LDAP_FILTER_LE +#define LDAP_FILTER_LE 0xa6L +#endif +#ifndef LDAP_FILTER_PRESENT +#define LDAP_FILTER_PRESENT 0x87L +#endif +#ifndef LDAP_FILTER_APPROX +#define LDAP_FILTER_APPROX 0xa8L +#endif +#ifndef LDAP_FILTER_EXT_MATCH +#define LDAP_FILTER_EXT_MATCH 0xa9L +#endif + +int slapi_log_error( int severity, char *subsystem, char *fmt, ... ); +#define SLAPI_LOG_FATAL 0 +#define SLAPI_LOG_TRACE 1 +#define SLAPI_LOG_PACKETS 2 +#define SLAPI_LOG_ARGS 3 +#define SLAPI_LOG_CONNS 4 +#define SLAPI_LOG_BER 5 +#define SLAPI_LOG_FILTER 6 +#define SLAPI_LOG_CONFIG 7 +#define SLAPI_LOG_ACL 8 +#define SLAPI_LOG_SHELL 9 +#define SLAPI_LOG_PARSE 10 +#define SLAPI_LOG_HOUSE 11 +#define SLAPI_LOG_REPL 12 +#define SLAPI_LOG_CACHE 13 +#define SLAPI_LOG_PLUGIN 14 +#define SLAPI_LOG_TIMING 15 + +#define SLAPI_PLUGIN_DESCRIPTION 12 +typedef struct slapi_plugindesc { + char *spd_id; + char *spd_vendor; + char *spd_version; + char *spd_description; +} Slapi_PluginDesc; + +#define SLAPI_PLUGIN_VERSION_01 "01" +#define SLAPI_PLUGIN_VERSION_02 "02" +#define SLAPI_PLUGIN_VERSION_03 "03" +#define SLAPI_PLUGIN_CURRENT_VERSION SLAPI_PLUGIN_VERSION_03 + +#endif /* _SLAPI_PLUGIN_H */ + diff --git a/servers/slapd/slapi/slapi.h b/servers/slapd/slapi/slapi.h new file mode 100644 index 0000000000..e46f6c4afb --- /dev/null +++ b/servers/slapd/slapi/slapi.h @@ -0,0 +1,296 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _SLAPI_H +#define _SLAPI_H + +#include + +typedef struct slapi_pblock Slapi_PBlock; +typedef struct slap_entry Slapi_Entry; +typedef struct slap_attr Slapi_Attr; +typedef Filter Slapi_Filter; + +#include +#ifndef NO_PBLOCK_CLASS +#include +#endif /* NO_PBLOCK_CLASS */ +#include +#include +#include + +/* + * types of plugins + */ +#define SLAPI_PLUGIN_DATABASE 1 +#define SLAPI_PLUGIN_EXTENDEDOP 2 +#define SLAPI_PLUGIN_PREOPERATION 3 +#define SLAPI_PLUGIN_POSTOPERATION 4 +#define SLAPI_PLUGIN_MATCHINGRULE 5 +#define SLAPI_PLUGIN_SYNTAX 6 +#define SLAPI_PLUGIN_AUDIT 7 + +#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT -1 +#define SLAPI_PLUGIN_EXTENDED_NOT_HANDLED -2 + +#define SLAPI_BACKEND 130 +#define SLAPI_CONNECTION 131 +#define SLAPI_OPERATION 132 +#define SLAPI_REQUESTOR_ISROOT 133 +#define SLAPI_BE_MONITORDN 134 +#define SLAPI_BE_TYPE 135 +#define SLAPI_BE_READONLY 136 +#define SLAPI_BE_LASTMOD 137 +#define SLAPI_CONN_ID 139 + +#define SLAPI_OPINITIATED_TIME 140 +#define SLAPI_REQUESTOR_DN 141 +#define SLAPI_REQUESTOR_ISUPDATEDN 142 +#define SLAPI_CONN_DN 143 +#define SLAPI_CONN_AUTHTYPE 144 + +#define SLAPD_AUTH_NONE "none" +#define SLAPD_AUTH_SIMPLE "simple" +#define SLAPD_AUTH_SSL "SSL" +#define SLAPD_AUTH_SASL "SASL " + +#define SLAPI_PLUGIN 3 +#define SLAPI_PLUGIN_PRIVATE 4 +#define SLAPI_PLUGIN_TYPE 5 +#define SLAPI_PLUGIN_ARGV 6 +#define SLAPI_PLUGIN_ARGC 7 +#define SLAPI_PLUGIN_VERSION 8 + +#define SLAPI_PLUGIN_OPRETURN 9 +#define SLAPI_PLUGIN_OBJECT 10 +#define SLAPI_PLUGIN_DESTROY_FN 11 + +#define SLAPI_PLUGIN_DESCRIPTION 12 + +#define SLAPI_PLUGIN_INTOP_RESULT 15 +#define SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES 16 +#define SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS 17 + +#define SLAPI_PLUGIN_DB_BIND_FN 200 +#define SLAPI_PLUGIN_DB_UNBIND_FN 201 +#define SLAPI_PLUGIN_DB_SEARCH_FN 202 +#define SLAPI_PLUGIN_DB_COMPARE_FN 203 +#define SLAPI_PLUGIN_DB_MODIFY_FN 204 +#define SLAPI_PLUGIN_DB_MODRDN_FN 205 +#define SLAPI_PLUGIN_DB_ADD_FN 206 +#define SLAPI_PLUGIN_DB_DELETE_FN 207 +#define SLAPI_PLUGIN_DB_ABANDON_FN 208 +#define SLAPI_PLUGIN_DB_CONFIG_FN 209 +#define SLAPI_PLUGIN_CLOSE_FN 210 +#define SLAPI_PLUGIN_DB_FLUSH_FN 211 +#define SLAPI_PLUGIN_START_FN 212 +#define SLAPI_PLUGIN_DB_SEQ_FN 213 +#define SLAPI_PLUGIN_DB_ENTRY_FN 214 +#define SLAPI_PLUGIN_DB_REFERRAL_FN 215 +#define SLAPI_PLUGIN_DB_RESULT_FN 216 +#define SLAPI_PLUGIN_DB_LDIF2DB_FN 217 +#define SLAPI_PLUGIN_DB_DB2LDIF_FN 218 +#define SLAPI_PLUGIN_DB_BEGIN_FN 219 +#define SLAPI_PLUGIN_DB_COMMIT_FN 220 +#define SLAPI_PLUGIN_DB_ABORT_FN 221 +#define SLAPI_PLUGIN_DB_ARCHIVE2DB_FN 222 +#define SLAPI_PLUGIN_DB_DB2ARCHIVE_FN 223 +#define SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN 224 +#define SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN 225 +#define SLAPI_PLUGIN_DB_SIZE_FN 226 +#define SLAPI_PLUGIN_DB_TEST_FN 227 +#define SLAPI_PLUGIN_DB_NO_ACL 250 + +#define SLAPI_PLUGIN_EXT_OP_FN 300 +#define SLAPI_PLUGIN_EXT_OP_OIDLIST 301 +#define SLAPI_PLUGIN_PRE_BIND_FN 401 +#define SLAPI_PLUGIN_PRE_UNBIND_FN 402 +#define SLAPI_PLUGIN_PRE_SEARCH_FN 403 +#define SLAPI_PLUGIN_PRE_COMPARE_FN 404 +#define SLAPI_PLUGIN_PRE_MODIFY_FN 405 +#define SLAPI_PLUGIN_PRE_MODRDN_FN 406 +#define SLAPI_PLUGIN_PRE_ADD_FN 407 +#define SLAPI_PLUGIN_PRE_DELETE_FN 408 +#define SLAPI_PLUGIN_PRE_ABANDON_FN 409 +#define SLAPI_PLUGIN_PRE_ENTRY_FN 410 +#define SLAPI_PLUGIN_PRE_REFERRAL_FN 411 +#define SLAPI_PLUGIN_PRE_RESULT_FN 412 +#define SLAPI_PLUGIN_POST_BIND_FN 501 +#define SLAPI_PLUGIN_POST_UNBIND_FN 502 +#define SLAPI_PLUGIN_POST_SEARCH_FN 503 +#define SLAPI_PLUGIN_POST_COMPARE_FN 504 +#define SLAPI_PLUGIN_POST_MODIFY_FN 505 +#define SLAPI_PLUGIN_POST_MODRDN_FN 506 +#define SLAPI_PLUGIN_POST_ADD_FN 507 +#define SLAPI_PLUGIN_POST_DELETE_FN 508 +#define SLAPI_PLUGIN_POST_ABANDON_FN 509 +#define SLAPI_PLUGIN_POST_ENTRY_FN 510 +#define SLAPI_PLUGIN_POST_REFERRAL_FN 511 +#define SLAPI_PLUGIN_POST_RESULT_FN 512 + +#define SLAPI_PLUGIN_MR_FILTER_CREATE_FN 600 +#define SLAPI_PLUGIN_MR_INDEXER_CREATE_FN 601 +#define SLAPI_PLUGIN_MR_FILTER_MATCH_FN 602 +#define SLAPI_PLUGIN_MR_FILTER_INDEX_FN 603 +#define SLAPI_PLUGIN_MR_FILTER_RESET_FN 604 +#define SLAPI_PLUGIN_MR_INDEX_FN 605 +#define SLAPI_PLUGIN_MR_OID 610 +#define SLAPI_PLUGIN_MR_TYPE 611 +#define SLAPI_PLUGIN_MR_VALUE 612 +#define SLAPI_PLUGIN_MR_VALUES 613 +#define SLAPI_PLUGIN_MR_KEYS 614 +#define SLAPI_PLUGIN_MR_FILTER_REUSABLE 615 +#define SLAPI_PLUGIN_MR_QUERY_OPERATOR 616 +#define SLAPI_PLUGIN_MR_USAGE 617 + +#define SLAPI_OP_LESS 1 +#define SLAPI_OP_LESS_OR_EQUAL 2 +#define SLAPI_OP_EQUAL 3 +#define SLAPI_OP_GREATER_OR_EQUAL 4 +#define SLAPI_OP_GREATER 5 +#define SLAPI_OP_SUBSTRING 6 + +#define SLAPI_PLUGIN_MR_USAGE_INDEX 0 +#define SLAPI_PLUGIN_MR_USAGE_SORT 1 + +#define SLAPI_PLUGIN_SYNTAX_FILTER_AVA 700 +#define SLAPI_PLUGIN_SYNTAX_FILTER_SUB 701 +#define SLAPI_PLUGIN_SYNTAX_VALUES2KEYS 702 +#define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA 703 +#define SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB 704 +#define SLAPI_PLUGIN_SYNTAX_NAMES 705 +#define SLAPI_PLUGIN_SYNTAX_OID 706 +#define SLAPI_PLUGIN_SYNTAX_FLAGS 707 +#define SLAPI_PLUGIN_SYNTAX_COMPARE 708 + +#define SLAPI_PLUGIN_SYNTAX_FLAG_ORKEYS 1 +#define SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING 2 + +#define SLAPI_PLUGIN_AUDIT_DATA 1100 +#define SLAPI_PLUGIN_AUDIT_FN 1101 + +#define SLAPI_MANAGEDSAIT 1000 + +#define SLAPI_CONFIG_FILENAME 40 +#define SLAPI_CONFIG_LINENO 41 +#define SLAPI_CONFIG_ARGC 42 +#define SLAPI_CONFIG_ARGV 43 + +#define SLAPI_TARGET_DN 50 +#define SLAPI_REQCONTROLS 51 + +#define SLAPI_ENTRY_PRE_OP 52 +#define SLAPI_ENTRY_POST_OP 53 + +#define SLAPI_RESCONTROLS 55 +#define SLAPI_ADD_RESCONTROL 56 + +#define SLAPI_ADD_TARGET SLAPI_TARGET_DN +#define SLAPI_ADD_ENTRY 60 + +#define SLAPI_BIND_TARGET SLAPI_TARGET_DN +#define SLAPI_BIND_METHOD 70 +#define SLAPI_BIND_CREDENTIALS 71 +#define SLAPI_BIND_SASLMECHANISM 72 +#define SLAPI_BIND_RET_SASLCREDS 73 + +#define SLAPI_COMPARE_TARGET SLAPI_TARGET_DN +#define SLAPI_COMPARE_TYPE 80 +#define SLAPI_COMPARE_VALUE 81 + +#define SLAPI_DELETE_TARGET SLAPI_TARGET_DN + +#define SLAPI_MODIFY_TARGET SLAPI_TARGET_DN +#define SLAPI_MODIFY_MODS 90 + +#define SLAPI_MODRDN_TARGET SLAPI_TARGET_DN +#define SLAPI_MODRDN_NEWRDN 100 +#define SLAPI_MODRDN_DELOLDRDN 101 +#define SLAPI_MODRDN_NEWSUPERIOR 102 + +#define SLAPI_SEARCH_TARGET SLAPI_TARGET_DN +#define SLAPI_SEARCH_SCOPE 110 +#define SLAPI_SEARCH_DEREF 111 +#define SLAPI_SEARCH_SIZELIMIT 112 +#define SLAPI_SEARCH_TIMELIMIT 113 +#define SLAPI_SEARCH_FILTER 114 +#define SLAPI_SEARCH_STRFILTER 115 +#define SLAPI_SEARCH_ATTRS 116 +#define SLAPI_SEARCH_ATTRSONLY 117 + +#define SLAPI_ABANDON_MSGID 120 + +#define SLAPI_SEQ_TYPE 150 +#define SLAPI_SEQ_ATTRNAME 151 +#define SLAPI_SEQ_VAL 152 + +#define SLAPI_EXT_OP_REQ_OID 160 +#define SLAPI_EXT_OP_REQ_VALUE 161 +#define SLAPI_EXT_OP_RET_OID 162 +#define SLAPI_EXT_OP_RET_VALUE 163 + +#define SLAPI_MR_FILTER_ENTRY 170 +#define SLAPI_MR_FILTER_TYPE 171 +#define SLAPI_MR_FILTER_VALUE 172 +#define SLAPI_MR_FILTER_OID 173 +#define SLAPI_MR_FILTER_DNATTRS 174 + +#define SLAPI_LDIF2DB_FILE 180 +#define SLAPI_LDIF2DB_REMOVEDUPVALS 185 + +#define SLAPI_DB2LDIF_PRINTKEY 183 + +#define SLAPI_PARENT_TXN 190 +#define SLAPI_TXN 191 + +#define SLAPI_SEARCH_RESULT_SET 193 +#define SLAPI_SEARCH_RESULT_ENTRY 194 +#define SLAPI_NENTRIES 195 +#define SLAPI_SEARCH_REFERRALS 196 + +#define SLAPI_CHANGENUMBER 197 +#define SLAPI_LOG_OPERATION 198 + +#define SLAPI_DBSIZE 199 + +#define SLAPI_LOG_FATAL 0 +#define SLAPI_LOG_TRACE 1 +#define SLAPI_LOG_PACKETS 2 +#define SLAPI_LOG_ARGS 3 +#define SLAPI_LOG_CONNS 4 +#define SLAPI_LOG_BER 5 +#define SLAPI_LOG_FILTER 6 +#define SLAPI_LOG_CONFIG 7 +#define SLAPI_LOG_ACL 8 +#define SLAPI_LOG_SHELL 9 +#define SLAPI_LOG_PARSE 10 +#define SLAPI_LOG_HOUSE 11 +#define SLAPI_LOG_REPL 12 +#define SLAPI_LOG_CACHE 13 +#define SLAPI_LOG_PLUGIN 14 + +#define SLAPI_OPERATION_BIND 0x00000001L +#define SLAPI_OPERATION_UNBIND 0x00000002L +#define SLAPI_OPERATION_SEARCH 0x00000004L +#define SLAPI_OPERATION_MODIFY 0x00000008L +#define SLAPI_OPERATION_ADD 0x00000010L +#define SLAPI_OPERATION_DELETE 0x00000020L +#define SLAPI_OPERATION_MODDN 0x00000040L +#define SLAPI_OPERATION_MODRDN SLAPI_OPERATION_MODDN +#define SLAPI_OPERATION_COMPARE 0x00000080L +#define SLAPI_OPERATION_ABANDON 0x00000100L +#define SLAPI_OPERATION_EXTENDED 0x00000200L +#define SLAPI_OPERATION_ANY 0xFFFFFFFFL +#define SLAPI_OPERATION_NONE 0x00000000L + +#endif /* _SLAPI_H */ + diff --git a/servers/slapd/slapi/slapi_cl.h b/servers/slapd/slapi/slapi_cl.h new file mode 100644 index 0000000000..ad4ac6eb67 --- /dev/null +++ b/servers/slapd/slapi/slapi_cl.h @@ -0,0 +1,55 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _SLAPI_CL_H +#define _SLAPI_CL_H + +#define TIME_SIZE 20 +#define OBJECTCLASS "objectclass" +#define TOP "top" +#define CHANGE_TIME "changetime" +#define CHANGE_TYPE "changetype" +#define CHANGE_TARGETDN "targetdn" +#define CHANGES "changes" +#define CHANGE_NUMBER "changenumber" +/* + * FIXME: I get complaints like "ADD" being redefined - first definition + * being in "/usr/include/arpa/nameser.h:552" + */ +#undef ADD +#define ADD "add: " +#define ADDLEN 5 +#define DEL "delete: " +#define DELLEN 8 +#define REPLACE "replace: " +#define REPLEN 9 +#define MOD "modify" +#define MODRDN "modrdn" +#define CHANGE_LOGENTRY "changelogentry" +#define IBM_CHANGE_LOGENTRY "ibm-changelog" +#define CL_NEWRDN "newrdn" +#define CL_DELRDN "deleteoldrdn" +#define CHANGE_INITIATOR "ibm-changeInitiatorsName" + +void slapi_register_changelog_suffix(char *suffix); +char **slapi_get_changelog_suffixes(); +void slapi_update_changelog_counters(long curNum, long numEntries); +char *slapi_get_cl_firstNum(); +char *slapi_get_cl_lastNum(); +int slapi_add_to_changelog(Slapi_Entry *ent, char *suffix, char *chNum, Operation* op); +int slapi_delete_changelog(char *dn, char *suffix, char *chNum, Operation* op); +int slapi_modify_changelog(char *dn,LDAPMod *mods,char *suffix, char *chNum, Operation* op); +int slapi_modifyrdn_changelog(char *olddn, char *newRdn, int delRdn, char *suffix, char *chNum, Operation* op); +Backend * slapi_cl_get_be(char *dn); + +#endif /* _SLAPI_CL_H */ + diff --git a/servers/slapd/slapi/slapi_common.h b/servers/slapd/slapi/slapi_common.h new file mode 100644 index 0000000000..7a97d5d403 --- /dev/null +++ b/servers/slapd/slapi/slapi_common.h @@ -0,0 +1,40 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef SLAPI_COMMON_H +#define SLAPI_COMMON_H + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define dn_normalize_case dn_normalize +#define SLAPD_NO_MEMORY 7 +#define ANYBODY_STRING "CN=ANYBODY" + +extern int slap_debug; + +int +dn_check(char *, int *); + + +typedef struct strlist { + char *string; + struct strlist *next; +} StrList; + +#endif /* SLAPI_COMMON_H */ + diff --git a/servers/slapd/slapi/slapi_ops.c b/servers/slapd/slapi/slapi_ops.c new file mode 100644 index 0000000000..4ff9264c42 --- /dev/null +++ b/servers/slapd/slapi/slapi_ops.c @@ -0,0 +1,1269 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" +#include +#include +#include +#include "../../../libraries/liblber/lber-int.h" + + +int bvptr2obj( struct berval **bvptr, struct berval **bvobj ); + +int +internal_result_v3( + Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + char **referrals ) +{ + return LDAP_SUCCESS; +} + +int +internal_search_entry( + Backend *be, + Connection *conn, + Operation *op, + Entry *e, + char **attrs, + int attrsonly, + char **denied_attrs ) +{ + char *ent2str = NULL; + int nentries = 0, len = 0, i = 0; + Slapi_Entry **head = NULL, **tp; + + ent2str = slapi_entry2str( e, &len ); + if ( ent2str == NULL ) { + return SLAPD_NO_MEMORY; + } + + slapi_pblock_get( (Slapi_PBlock *)op->o_pb, + SLAPI_NENTRIES, &nentries ); + slapi_pblock_get( (Slapi_PBlock *)op->o_pb, + SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head ); + + i = nentries + 1; + if ( nentries == 0 ) { + tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) ); + if ( tp == NULL ) { + return SLAPD_NO_MEMORY; + } + + tp[ 0 ] = (Slapi_Entry *)str2entry( ent2str ); + if ( tp[ 0 ] == NULL ) { + return SLAPD_NO_MEMORY; + } + + } else { + tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head, + sizeof(Slapi_Entry *) * ( i + 1 ) ); + if ( tp == NULL ) { + return SLAPD_NO_MEMORY; + } + tp[ i - 1 ] = (Slapi_Entry *)str2entry( ent2str ); + if ( tp[ i - 1 ] == NULL ) { + return SLAPD_NO_MEMORY; + } + } + tp[ i ] = NULL; + + slapi_pblock_set( (Slapi_PBlock *)op->o_pb, + SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp ); + slapi_pblock_set( (Slapi_PBlock *)op->o_pb, + SLAPI_NENTRIES, (void *)i ); + slapi_ch_free( ent2str ); + + return LDAP_SUCCESS; +} + +int +internal_search_result( + Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + int nentries ) +{ + slapi_pblock_set( (Slapi_PBlock *)op->o_pb, + SLAPI_NENTRIES, (void *)nentries ); + + return LDAP_SUCCESS; +} + +int +internal_result_ext( + Connection *conn, + Operation *op, + int errnum, + char *respname, + struct berval *response ) +{ + return LDAP_SUCCESS; +} + +int +internal_search_reference( + Connection *conn, + Operation *op, + char **ref ) +{ + return LDAP_SUCCESS; +} + +static Connection * +fakeConnection( + char *DN, + int OpType ) +{ + Connection *pConn, *c; + ber_len_t max = sockbuf_max_incoming; + + pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection)); + if (pConn == NULL) { + return (Connection *)NULL; + } + + LDAP_STAILQ_INIT( &pConn->c_pending_ops ); + + pConn->c_pending_ops.stqh_first = + (Operation *) slapi_ch_calloc( 1, sizeof(Operation) ); + if ( pConn->c_pending_ops.stqh_first == NULL ) { + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + pConn->c_pending_ops.stqh_first->o_pb = + (Slapi_PBlock *) slapi_pblock_new(); + if ( pConn->c_pending_ops.stqh_first->o_pb == NULL ) { + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + c = pConn; + + /* operation object */ + c->c_pending_ops.stqh_first->o_tag = OpType; + c->c_pending_ops.stqh_first->o_protocol = LDAP_VERSION3; + c->c_pending_ops.stqh_first->o_authmech.bv_val = NULL; + c->c_pending_ops.stqh_first->o_authmech.bv_len = 0; + c->c_pending_ops.stqh_first->o_time = slap_get_time(); + + /* connection object */ + c->c_authmech.bv_val = NULL; + c->c_authmech.bv_len = 0; + c->c_dn.bv_val = NULL; + c->c_dn.bv_len = 0; + c->c_ndn.bv_val = NULL; + c->c_ndn.bv_len = 0; + c->c_groups = NULL; + + c->c_listener = NULL; + c->c_peer_domain.bv_val = NULL; + c->c_peer_domain.bv_len = 0; + c->c_peer_name.bv_val = NULL; + c->c_peer_name.bv_len = 0; + + LDAP_STAILQ_INIT( &c->c_ops ); + + c->c_sasl_bind_mech.bv_val = NULL; + c->c_sasl_bind_mech.bv_len = 0; + c->c_sasl_context = NULL; + c->c_sasl_extra = NULL; + + c->c_sb = ber_sockbuf_alloc( ); + + ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); + + c->c_currentber = NULL; + + /* should check status of thread calls */ + ldap_pvt_thread_mutex_init( &c->c_mutex ); + ldap_pvt_thread_mutex_init( &c->c_write_mutex ); + ldap_pvt_thread_cond_init( &c->c_write_cv ); + + c->c_n_ops_received = 0; + c->c_n_ops_executing = 0; + c->c_n_ops_pending = 0; + c->c_n_ops_completed = 0; + + c->c_n_get = 0; + c->c_n_read = 0; + c->c_n_write = 0; + + c->c_protocol = LDAP_VERSION3; + + c->c_activitytime = c->c_starttime = slap_get_time(); + + c->c_connid = 0; + + c->c_conn_state = 0x01; /* SLAP_C_ACTIVE */ + c->c_struct_state = 0x02; /* SLAP_C_USED */ + + c->c_ssf = c->c_transport_ssf = 0; + c->c_tls_ssf = 0; + + backend_connection_init( c ); + + pConn->c_send_ldap_result = + (SEND_LDAP_RESULT) internal_result_v3; + pConn->c_send_search_entry = + (SEND_SEARCH_ENTRY) internal_search_entry; + pConn->c_send_search_result = + (SEND_SEARCH_RESULT) internal_search_result; + pConn->c_send_ldap_extended = + (SEND_LDAP_EXTENDED) internal_result_ext; + pConn->c_send_search_reference = + (SEND_SEARCH_REFERENCE) internal_search_reference; + + return pConn; +} + +/* + * Function : ValuestoBValues + * Convert an array of char ptrs to an array of berval ptrs. + * return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ + +static int +ValuesToBValues( + char **ppValue, + struct berval ***pppBV ) +{ + int rc = LDAP_SUCCESS; + int i; + struct berval *pTmpBV; + struct berval **ppNewBV; + + /* count the number of char ptrs. */ + for ( i = 0; ppValue != NULL && ppValue[i] != NULL; i++ ) { + ; /* NULL */ + } + + if ( i == 0 ) { + rc = LDAP_OTHER; + } else { + *pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) ); + if ( *pppBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) { + pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + if ( pTmpBV == NULL) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_val = slapi_ch_strdup(*ppValue); + if ( pTmpBV->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_len = strlen(*ppValue); + *ppNewBV = pTmpBV; + ppNewBV++; + } + ppValue++; + } + } + /* null terminate the array of berval ptrs */ + *ppNewBV = NULL; + } + } + return( rc ); +} + + +/* + * Function : LDAPModToEntry + * convert a dn plus an array of LDAPMod struct ptrs to an entry structure + * with a link list of the correspondent attributes. + * Return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ +Entry * +LDAPModToEntry( + char *ldn, + LDAPMod **mods ) +{ + struct berval dn = { 0, NULL }; + Entry *pEntry=NULL; + LDAPMod *pMod; + struct berval *bv; + struct berval **ppBV; + Backend *be; + Operation *op; + + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + Modifications tmp; + + int rc = LDAP_SUCCESS; + int i; + + const char *text = NULL; + + + op = (Operation *) slapi_ch_calloc(1, sizeof(Operation)); + if ( pEntry == NULL) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + op->o_tag = LDAP_REQ_ADD; + + pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) ); + if ( pEntry == NULL) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + dn.bv_val = slapi_ch_strdup(ldn); + dn.bv_len = strlen(ldn); + + rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname ); + if (rc != LDAP_SUCCESS) goto cleanup; + + if ( rc == LDAP_SUCCESS ) { + for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) { + Modifications *mod; + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* attr values are in berval format */ + /* convert an array of pointers to bervals to an array of bervals */ + rc = bvptr2obj(pMod->mod_bvalues, &bv); + if (rc != LDAP_SUCCESS) goto cleanup; + tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type); + tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type); + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + } else { + /* attr values are in string format, need to be converted */ + /* to an array of bervals */ + if ( pMod->mod_values == NULL ) { + rc = LDAP_OTHER; + } else { + rc = ValuesToBValues( pMod->mod_values, &ppBV ); + if (rc != LDAP_SUCCESS) goto cleanup; + rc = bvptr2obj(ppBV, &bv); + if (rc != LDAP_SUCCESS) goto cleanup; + tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type); + tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type); + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + if ( ppBV != NULL ) { + ber_bvecfree( ppBV ); + } + } + } + } /* for each LDAPMod */ + } + + be = select_backend(&dn, 0, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + goto cleanup; + } + + if ( be ) { + int repl_user = be_isupdate(be, &be->be_rootdn ); + if ( !be->be_update_ndn.bv_len || repl_user ) { + int update = be->be_update_ndn.bv_len; + char textbuf[SLAP_TEXT_BUFLEN]; + size_t textlen = sizeof textbuf; + + rc = slap_mods_check( modlist, update, &text, + textbuf, textlen ); + if ( rc != LDAP_SUCCESS) { + goto cleanup; + } + + if ( !repl_user ) { + rc = slap_mods_opattrs( be, op, + modlist, modtail, &text, + textbuf, textlen ); + if ( rc != LDAP_SUCCESS) { + goto cleanup; + } + } + + /* + * FIXME: slap_mods2entry is declared static + * in servers/slapd/add.c + */ + rc = slap_mods2entry( modlist, &pEntry, repl_user, + &text, textbuf, textlen ); + if (rc != LDAP_SUCCESS) { + goto cleanup; + } + + } else { + rc = LDAP_REFERRAL; + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + + if ( dn.bv_val ) slapi_ch_free( dn.bv_val ); + if ( op ) slapi_ch_free( op ); + if ( modlist != NULL ) slap_mods_free( modlist ); + if ( rc != LDAP_SUCCESS ) { + if ( pEntry != NULL ) { + slapi_entry_free( pEntry ); + } + pEntry = NULL; + } + + return( pEntry ); +} + +/* Function : slapi_delete_internal + * + * Description : Plugin functions call this routine to delete an entry + * in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_delete_internal( + char *ldn, + LDAPControl **controls, + int log_change ) +{ +#if defined(LDAP_SLAPI) + Backend *be; + Connection *pConn = NULL; + Operation *op = NULL; + Slapi_PBlock *pPB = NULL; + Slapi_PBlock *pSavePB = NULL; + + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + int rc=LDAP_SUCCESS; + int manageDsaIt = 0; + int isCritical; + + if ( ldn == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + goto cleanup; + } + + pConn = fakeConnection( NULL, LDAP_REQ_DELETE ); + if (pConn == NULL) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + op = (Operation *)pConn->c_pending_ops.stqh_first; + pPB = (Slapi_PBlock *)op->o_pb; + op->o_ctrls = controls; + + dn.bv_val = slapi_ch_strdup(ldn); + dn.bv_len = slapi_strlen(ldn); + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + if ( rc != LDAP_SUCCESS ) goto cleanup; + + if ( slapi_control_present( controls, + SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) { + manageDsaIt = 1; + } + + be = select_backend( &dn, manageDsaIt, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + goto cleanup; + } + + op->o_ndn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val); + op->o_ndn.bv_len = be->be_rootdn.bv_len; + pConn->c_dn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val); + pConn->c_dn.bv_len = be->be_rootdn.bv_len; + + suffix_alias( be, &ndn ); + + if ( be->be_delete ) { + int repl_user = be_isupdate( be, &op->o_ndn ); + if ( !be->be_update_ndn.bv_len || repl_user ) { + rc = (*be->be_delete)( be, pConn, op, &pdn, &ndn ); + if ( rc == 0 ) { + if (log_change) { + replog( be, op, &pdn, &ndn, NULL ); + } + rc = LDAP_SUCCESS; + } else { + rc = LDAP_OPERATIONS_ERROR; + } + } else { + rc = LDAP_REFERRAL; + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + if (pPB != NULL) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + + if (dn.bv_val) slapi_ch_free(dn.bv_val); + if (pdn.bv_val) slapi_ch_free(pdn.bv_val); + if (ndn.bv_val) slapi_ch_free(ndn.bv_val); + + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val ); + if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val ); + if ( op ) slapi_ch_free( op ); + pSavePB = pPB; + free( pConn ); + } + + return (pSavePB); +#endif /* LDAP_SLAPI */ + return NULL; +} + +Slapi_PBlock * +slapi_add_entry_internal( + Slapi_Entry *e, + LDAPControl **controls, + int log_changes ) +{ +#if defined(LDAP_SLAPI) + Connection *pConn = NULL; + Operation *op = NULL; + Slapi_PBlock *pPB = NULL, *pSavePB = NULL; + Backend *be; + + int manageDsaIt = 0; + int isCritical; + int rc = LDAP_SUCCESS; + + if ( e == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + goto cleanup; + } + + pConn = fakeConnection( NULL, LDAP_REQ_ADD ); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, + NULL, &isCritical ) ) { + manageDsaIt = 1; + } + + op = (Operation *)pConn->c_pending_ops.stqh_first; + pPB = (Slapi_PBlock *)op->o_pb; + op->o_ctrls = controls; + + be = select_backend( &e->e_nname, manageDsaIt, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + goto cleanup; + } + + op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + op->o_ndn.bv_len = be->be_rootdn.bv_len; + pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + pConn->c_dn.bv_len = be->be_rootdn.bv_len; + + if ( be->be_add ) { + int repl_user = be_isupdate( be, &op->o_ndn ); + if ( !be->be_update_ndn.bv_len || repl_user ){ + if ( (*be->be_add)( be, pConn, op, e ) == 0 ) { + if ( log_changes ) { + replog( be, op, &e->e_name, + &e->e_nname, e ); + } + rc = LDAP_SUCCESS; + } + } else { + rc = LDAP_REFERRAL; + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val ); + if ( op ) { + if ( op->o_ndn.bv_val ) { + slapi_ch_free( op->o_ndn.bv_val ); + } + free(op); + } + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +#endif /* LDAP_SLAPI */ + return NULL; +} + + +Slapi_PBlock * +slapi_add_internal( + char *dn, + LDAPMod **mods, + LDAPControl **controls, + int log_changes ) +{ +#if defined(LDAP_SLAPI) + LDAPMod *pMod = NULL; + Slapi_PBlock *pb = NULL; + Entry *pEntry = NULL; + int i, rc=LDAP_SUCCESS; + + if ( mods == NULL || *mods == NULL || dn == NULL || *dn == '\0' ) { + rc = LDAP_OPERATIONS_ERROR ; + } + + if ( rc == LDAP_SUCCESS ) { + for ( i = 0, pMod = mods[0]; pMod != NULL; pMod = mods[++i] ) { + if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD ) { + rc = LDAP_OTHER; + break; + } + } + } + + if ( rc == LDAP_SUCCESS ) { + if((pEntry = LDAPModToEntry( dn, mods )) == NULL) { + rc = LDAP_OTHER; + } + } + + if ( rc != LDAP_SUCCESS ) { + pb = slapi_pblock_new(); + slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } else { + pb = slapi_add_entry_internal( pEntry, controls, log_changes ); + } + + if ( pEntry ) { + slapi_entry_free(pEntry); + } + + return(pb); +#endif /* LDAP_SLAPI */ + return NULL; +} + +/* Function : slapi_modrdn_internal + * + * Description : Plugin functions call this routine to modify the rdn + * of an entry in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM + * + * NOTE: This function does not support the "newSuperior" option from LDAP V3. + */ +Slapi_PBlock * +slapi_modrdn_internal( + char *olddn, + char *lnewrdn, + int deloldrdn, + LDAPControl **controls, + int log_change ) +{ +#if defined(LDAP_SLAPI) + int rc = LDAP_SUCCESS; + + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + struct berval newrdn = { 0, NULL }; + struct berval pnewrdn = { 0, NULL }; + struct berval nnewrdn = { 0, NULL }; + +#if 0 /* currently unused */ + struct berval newSuperior = { 0, NULL }; +#endif + struct berval pnewSuperior = { 0, NULL }; +#if 0 /* currently unused */ + struct berval nnewSuperior = { 0, NULL }; +#endif + + struct berval *pnewS = NULL; + struct berval *nnewS = NULL; + + Connection *pConn = NULL; + Operation *op = NULL; + Slapi_PBlock *pPB = NULL; + Slapi_PBlock *pSavePB = NULL; + + Backend *be; +#if 0 /* currently unused */ + Backend *newSuperior_be = NULL; +#endif + + int manageDsaIt = 0; + int isCritical; +#if 0 /* currently unused */ + const char *text = NULL; +#endif + + dn.bv_val = slapi_ch_strdup(olddn); + dn.bv_len = slapi_ch_stlen(olddn); + + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + + if ( rc != LDAP_SUCCESS ) goto cleanup; + + if ( ndn.bv_len == 0 ) { + rc = LDAP_UNWILLING_TO_PERFORM; + goto cleanup; + } + + newrdn.bv_val = slapi_ch_strdup( lnewrdn ); + newrdn.bv_len = slapi_ch_stlen( lnewrdn ); + + rc = dnPrettyNormal( NULL, &newrdn, &pnewrdn, &nnewrdn ); + + if ( rc != LDAP_SUCCESS ) goto cleanup; + + if ( rdnValidate( &pnewrdn ) != LDAP_SUCCESS ) goto cleanup; + + pConn = fakeConnection( NULL, LDAP_REQ_MODRDN); + if ( pConn == NULL) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + op = (Operation *)pConn->c_pending_ops.stqh_first; + pPB = (Slapi_PBlock *)op->o_pb; + op->o_ctrls = controls; + + if ( slapi_control_present( controls, + SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) { + manageDsaIt = 1; + } + + be = select_backend( &dn, manageDsaIt, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + goto cleanup; + } + + op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + op->o_ndn.bv_len = be->be_rootdn.bv_len; + pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + pConn->c_dn.bv_len = be->be_rootdn.bv_len; + + suffix_alias( be, &ndn ); + + if ( be->be_modrdn ) { + int repl_user = be_isupdate( be, &op->o_ndn ); + if ( !be->be_update_ndn.bv_len || repl_user ) { + rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn, + &pnewrdn, &nnewrdn, deloldrdn, pnewS, + nnewS ); + if ( rc == 0 ) { + struct slap_replog_moddn moddn; + moddn.newrdn = &pnewrdn; + moddn.deloldrdn = deloldrdn; + moddn.newsup = &pnewSuperior; + if ( log_change ) { + replog( be, op, &pdn, &ndn, &moddn ); + } + rc = LDAP_SUCCESS; + + } else { + rc = LDAP_OPERATIONS_ERROR; + } + + } else { + rc = LDAP_REFERRAL; + } + + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + + if ( dn.bv_val ) ch_free( dn.bv_val ); + if ( pdn.bv_val ) ch_free( pdn.bv_val ); + if ( ndn.bv_val ) ch_free( ndn.bv_val ); + + if ( newrdn.bv_val ) ch_free( newrdn.bv_val ); + if ( pnewrdn.bv_val ) ch_free( newrdn.bv_val ); + if ( nnewrdn.bv_val ) ch_free( newrdn.bv_val ); + + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val ); + if ( op ) { + if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val ); + slapi_ch_free( op ); + } + pSavePB = pPB; + free( pConn ); + } + + return( pSavePB ); +#endif /* LDAP_SLAPI */ + return NULL; +} + +/* Function : slapi_modify_internal + * + * Description: Plugin functions call this routine to modify an entry + * in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_modify_internal( + char *ldn, + LDAPMod **mods, + LDAPControl **controls, + int log_change ) +{ +#if defined(LDAP_SLAPI) + int i, rc = LDAP_SUCCESS; + Connection *pConn = NULL; + Operation *op = NULL; + Slapi_PBlock *pPB = NULL; + Slapi_PBlock *pSavePB = NULL; + + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + int manageDsaIt = 0; + int isCritical; + Backend *be; + struct berval *bv; + struct berval **ppBV; + LDAPMod *pMod; + + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + Modifications tmp; + + if ( mods == NULL || *mods == NULL || ldn == NULL ) { + rc = LDAP_OPERATIONS_ERROR ; + goto cleanup; + } + + pConn = fakeConnection( NULL, LDAP_REQ_MODIFY ); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + op = (Operation *)pConn->c_pending_ops.stqh_first; + pPB = (Slapi_PBlock *)op->o_pb; + op->o_ctrls = controls; + + dn.bv_val = slapi_ch_strdup( ldn ); + dn.bv_len = slapi_strlen( ldn ); + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + if ( rc != LDAP_SUCCESS ) goto cleanup; + + if ( slapi_control_present( controls, + SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) { + manageDsaIt = 1; + } + + be = select_backend( &dn, manageDsaIt, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + goto cleanup; + } + + op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + op->o_ndn.bv_len = be->be_rootdn.bv_len; + pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + pConn->c_dn.bv_len = be->be_rootdn.bv_len; + + suffix_alias( be, &ndn ); + + for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; + pMod = mods[++i] ) { + Modifications *mod; + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* + * attr values are in berval format + * convert an array of pointers to bervals + * to an array of bervals + */ + rc = bvptr2obj( pMod->mod_bvalues, &bv ); + if ( rc != LDAP_SUCCESS ) goto cleanup; + tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type ); + tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type ); + tmp.sml_bvalues = bv; + + mod = (Modifications *)ch_malloc( sizeof(Modifications) ); + + mod->sml_op = pMod->mod_op; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + } else { + rc = ValuesToBValues( pMod->mod_values, &ppBV ); + if ( rc != LDAP_SUCCESS ) goto cleanup; + rc = bvptr2obj( ppBV, &bv ); + if ( rc != LDAP_SUCCESS ) goto cleanup; + tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type ); + tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type ); + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = pMod->mod_op; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + if ( ppBV != NULL ) { + ber_bvecfree( ppBV ); + } + } + *modtail = mod; + modtail = &mod->sml_next; + + switch( pMod->mod_op ) { + case LDAP_MOD_ADD: + if ( mod->sml_bvalues == NULL ) { + rc = LDAP_PROTOCOL_ERROR; + goto cleanup; + } + + /* fall through */ + case LDAP_MOD_DELETE: + case LDAP_MOD_REPLACE: + break; + + default: + rc = LDAP_PROTOCOL_ERROR; + goto cleanup; + } + } + *modtail = NULL; + + if ( ndn.bv_len == 0 ) { + rc = LDAP_UNWILLING_TO_PERFORM; + goto cleanup; + } + + if ( be->be_modify ) { + int repl_user = be_isupdate( be, &op->o_ndn ); + if ( !be->be_update_ndn.bv_len || repl_user ) { + int update = be->be_update_ndn.bv_len; + const char *text = NULL; + char textbuf[SLAP_TEXT_BUFLEN]; + size_t textlen = sizeof( textbuf ); + + rc = slap_mods_check( modlist, update, + &text, textbuf, textlen ); + if (rc != LDAP_SUCCESS) { + goto cleanup; + } + + if ( !repl_user ) { + rc = slap_mods_opattrs( be, op, modlist, + modtail, &text, textbuf, + textlen ); + if (rc != LDAP_SUCCESS) { + goto cleanup; + } + } + rc = (*be->be_modify)( be, pConn, op, + &pdn, &ndn, modlist ); + if ( rc == 0 ) { + if ( log_change ) { + replog( be, op, &pdn, &ndn, modlist ); + } + rc = LDAP_SUCCESS; + } else { + rc = LDAP_OPERATIONS_ERROR; + } + } else { + rc = LDAP_REFERRAL; + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + + if ( pPB != NULL ) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + + if ( dn.bv_val ) ch_free( dn.bv_val ); + if ( pdn.bv_val ) ch_free( pdn.bv_val ); + if ( ndn.bv_val ) ch_free( ndn.bv_val ); + + if ( modlist != NULL ) slap_mods_free( modlist ); + + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) slapi_ch_free( pConn->c_dn.bv_val ); + if ( op ) { + if ( op->o_dn.bv_val ) slapi_ch_free( op->o_dn.bv_val ); + slapi_ch_free( op ); + } + pSavePB = pPB; + free( pConn ); + } + + return ( pSavePB ); + +#endif /* LDAP_SLAPI */ + return NULL; +} + +Slapi_PBlock * +slapi_search_internal_bind( + char *bindDN, + char *ldn, + int scope, + char *filStr, + LDAPControl **controls, + char **attrs, + int attrsonly ) +{ +#if defined(LDAP_SLAPI) + Backend *be; + Connection *c; + Operation *op = NULL; + Slapi_PBlock *ptr = NULL; + Slapi_PBlock *pSavePB = NULL; + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + Filter *filter=NULL; + struct berval fstr = { 0, NULL }; + AttributeName *an = NULL; + const char *text = NULL; + + int deref=0; + int sizelimit=-1, timelimit=-1; + + int manageDsaIt = 0; + int isCritical; + + int i, rc = LDAP_SUCCESS; + + c = fakeConnection( NULL, LDAP_REQ_SEARCH ); + if (c == NULL) { + rc = LDAP_NO_MEMORY; + goto cleanup; + } + + op = (Operation *)c->c_pending_ops.stqh_first; + ptr = (Slapi_PBlock *)op->o_pb; + op->o_ctrls = controls; + + dn.bv_val = slapi_ch_strdup(ldn); + dn.bv_len = slapi_strlen(ldn); + + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + if (rc != LDAP_SUCCESS) goto cleanup; + + if ( scope != LDAP_SCOPE_BASE && + scope != LDAP_SCOPE_ONELEVEL && + scope != LDAP_SCOPE_SUBTREE ) { + rc = LDAP_PROTOCOL_ERROR; + goto cleanup; + } + + filter = slapi_str2filter(filStr); + if ( filter == NULL ) { + rc = LDAP_PROTOCOL_ERROR; + goto cleanup; + } + + filter2bv( filter, &fstr ); + + for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) { + ; /* count the number of attributes */ + } + + if (i > 0) { + an = (AttributeName *)slapi_ch_calloc(1, sizeof(AttributeName)); + for (i = 0; attrs[i] != 0; i++) { + an[i].an_desc = NULL; + an[i].an_oc = NULL; + an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]); + an[i].an_name.bv_len = slapi_strlen(attrs[i]); + slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text ); + } + } + + if ( scope == LDAP_SCOPE_BASE ) { + Entry *entry = NULL; + + if ( ndn.bv_len == 0 ) { + rc = root_dse_info( c, &entry, &text ); + } + + if( rc != LDAP_SUCCESS ) { + send_ldap_result( c, op, rc, NULL, text, NULL, NULL ); + goto cleanup; + } else if ( entry != NULL ) { + rc = test_filter( NULL, c, op, entry, filter ); + + if( rc == LDAP_COMPARE_TRUE ) { + send_search_entry( NULL, c, op, entry, + an, attrsonly, NULL ); + } + + entry_free( entry ); + + send_ldap_result( c, op, LDAP_SUCCESS, + NULL, NULL, NULL, NULL ); + + rc = LDAP_SUCCESS; + + goto cleanup; + } + } + + if ( !ndn.bv_len && default_search_nbase.bv_len ) { + ch_free( pdn.bv_val ); + ch_free( ndn.bv_val ); + + ber_dupbv( &pdn, &default_search_base ); + ber_dupbv( &ndn, &default_search_nbase ); + } + + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; + } + + be = select_backend( &dn, manageDsaIt, 0 ); + if ( be == NULL ) { + if ( manageDsaIt == 1 ) { + rc = LDAP_NO_SUCH_OBJECT; + } else { + rc = LDAP_PARTIAL_RESULTS; + } + goto cleanup; + } + + op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + op->o_ndn.bv_len = be->be_rootdn.bv_len; + c->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val ); + c->c_dn.bv_len = be->be_rootdn.bv_len; + + if ( be->be_search ) { + rc = (*be->be_search)( be, c, op, &pdn, &ndn, + scope, deref, sizelimit, timelimit, + filter, &fstr, an, attrsonly ); + if ( rc == 0 ) { + rc = LDAP_SUCCESS; + } else { + rc = LDAP_OPERATIONS_ERROR; + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + +cleanup: + + if ( ptr != NULL ) + slapi_pblock_set( ptr, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + + if ( dn.bv_val ) free( dn.bv_val ); + if ( ndn.bv_val ) free( ndn.bv_val ); + if ( pdn.bv_val ) free( pdn.bv_val ); + + if ( filter ) slapi_filter_free( filter, 1 ); + if ( fstr.bv_val ) free ( fstr.bv_val ); + + if ( an != NULL ) free( an ); + + if ( c != NULL ) { + if ( c->c_dn.bv_val ) slapi_ch_free( c->c_dn.bv_val ); + if ( op ) { + if ( op->o_ndn.bv_val ) slapi_ch_free( op->o_ndn.bv_val ); + free( op ); + } + pSavePB = ptr; + free( c ); + } + return( pSavePB ); +#endif /* LDAP_SLAPI */ + return NULL; +} + +Slapi_PBlock * +slapi_search_internal( + char *base, + int scope, + char *filStr, + LDAPControl **controls, + char **attrs, + int attrsonly ) +{ +#if defined(LDAP_SLAPI) + return slapi_search_internal_bind( NULL, base, scope, filStr, + controls, attrs, attrsonly ); +#endif + return NULL; +} + diff --git a/servers/slapd/slapi/slapi_ops.c.all b/servers/slapd/slapi/slapi_ops.c.all new file mode 100644 index 0000000000..dcf16820c1 --- /dev/null +++ b/servers/slapd/slapi/slapi_ops.c.all @@ -0,0 +1,1303 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" +#include +#include +#include +#include "../../../libraries/liblber/lber-int.h" + +int +bvptr2obj( struct berval **bvptr, + struct berval **bvobj); + +Slapi_PBlock * +slapi_simple_bind_internal( char *dn, + struct berval *cred, + int method, + int version); + + +Connection * +fakeConnection( char *DN, + int OpType) +{ + Connection *pConn, *c; + + if((pConn = (Connection *) slapi_ch_calloc(sizeof(Connection))) == NULL) + return (Connection *)NULL; + + LDAP_STAILQ_INIT(&c->c_pending_ops); + LDAP_STAILQ_INIT(&c->c_ops); + + if((pConn->c_pending_ops.stqh_first=(Operation *) slapi_ch_calloc(sizeof(Operation))) == NULL) { + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + if((pConn->c_pending_ops.stqh_first->o_pb=(Slapi_PBlock *) slapi_pblock_new()) == NULL) { + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + c = pConn; + + c->c_ops->o_opid = 0; + c->c_ops->o_msgid = 0; + c->c_ops->o_next = NULL; + c->c_ops->o_tag = OpType; + i->c_ops->o_abandon = 0; + + c->c_authmech.bv_val = NULL; + c->c_authmech.bv_len = 0; + c->c_dn.bv_val = NULL; + c->c_dn.bv_len = 0; + c->c_ndn.bv_val = NULL; + c->c_ndn.bv_len = 0; + c->c_cdn.bv_val = NULL; + c->c_cdn.bv_len = 0; + c->c_groups = NULL; + + c->c_listener_url.bv_val = NULL; + c->c_listener_url.bv_len = 0; + c->c_peer_domain.bv_val = NULL; + c->c_peer_domain.bv_len = 0; + c->c_peer_name.bv_val = NULL; + c->c_peer_name.bv_len = 0; + c->c_sock_name.bv_val = NULL; + c->c_sock_name.bv_len = 0; + + c->c_sasl_bind_mech.bv_val = NULL; + c->c_sasl_bind_mech.bv_len = 0; + c->c_sasl_context = NULL; + c->c_sasl_extra = NULL; + + c->c_sb = ber_sockbuf_alloc( ); + + c->c_currentber = NULL; + + c->c_struct_state = SLAP_C_UNUSED; + + c->c_n_get = 0; + c->c_n_read = 0; + c->c_n_write = 0; + + c->c_protocol = LDAP_VERSION3; + + time(&pConn->c_pending_ops.stqh_first->o_time); + + pConn->c_send_ldap_result_v3 = (SEND_LDAP_RESULT_V3) internal_result_v3; + pConn->c_send_search_entry = (SEND_SEARCH_ENTRY) internal_search_entry; + pConn->c_send_ldap_search_result = (SEND_LDAP_SEARCH_RESULT) internal_search_result; + pConn->c_send_ldap_result_ext = (SEND_LDAP_RESULT_EXT) internal_result_ext; + pConn->c_send_ldap_search_reference = (SEND_SEARCH_REFERENCE) internal_search_reference; + + return pConn; +} + + +/* Function : slapi_delete_internal + * + * Description : Plugin functions call this routine to delete an entry + * in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_delete_internal( char *ldn, + LDAPControl **controls, + int log_change) +{ + + int rc=LDAP_SUCCESS; + Backend *be; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + Operation *op; + + int manageDsaIt = 0; + int isCritical; + + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + + if ( ldn == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + + if ( rc == LDAP_SUCCESS ) { + pConn = fakeConnection( NULL, LDAP_REQ_DELETE ); + } + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + + op->o_ndn.bv_val = slapi_strdup(be->be_update_ndn.bv_val); + op->o_ndn.bv_len = be->be_update_ndn.bv_len; + pConn->c_dn.bv_val = slapi_strdup(be->be_update_ndn.bv_val); + pConn->c_dn.bv_len = be->be_update_ndn.bv_len; + } + if ( rc == LDAP_SUCCESS ) { + dn.bv_val = slapi_strdup(ldn); + dn.bv_len = slapi_strlen(ldn); + + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "do_delete: conn %d invalid dn (%s)\n", + conn->c_connid, dn.bv_val )); +#else + Debug( LDAP_DEBUG_ANY, + "do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 ); +#endif + } + } + + if( ndn.bv_len == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: " + "Attempt to delete root DSE.\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "Attempt to delete root DSE.\n", 0, 0, 0 ); +#endif + rc = LDAP_UNWILLING_TO_PERFORM; + +#ifdef SLAPD_SCHEMA_DN + + } else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: " + "Attempt to delete subschema subentry.\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "Attempt to delete subschema subentry.\n", 0, 0, 0 ); +#endif + rc = LDAP_UNWILLING_TO_PERFORM; + +#endif + } + + if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){ + manageDsaIt = 1; /* turn off referral */ + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_referrals( be, conn, op, &pdn, &ndn ); + } + + suffix_alias( be, &ndn ); + + if ( be->be_delete ) { + /* do the update here */ + int repl_user = be_isupdate( be, &op->o_ndn ); +#ifndef SLAPD_MULTIMASTER + if ( !be->be_update_ndn.bv_len || repl_user ) +#endif + { + if ( (*be->be_delete)( be, conn, op, &pdn, &ndn ) == 0 ) { +#ifdef SLAPD_MULTIMASTER + if ( !be->be_update_ndn.bv_len || !repl_user ) +#endif + { + if (log_change) replog( be, op, &pdn, &ndn, NULL ); + } + } +#ifndef SLAPD_MULTIMASTER + } else { + rc = LDAP_REFERRAL; +#endif + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + if (dn.bv_val) + slapi_ch_free(dn.bv_val); + if (pdn.bv_val) + slapi_ch_free(pdn.bv_val); + if (ndn.bv_val) + slapi_ch_free(ndn_bv.val); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + +int +internal_result_v3( Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + char **referrals) +{ + return LDAP_SUCCESS; +} + +int +internal_result_ext( Connection *conn, + Operation *op, + int errnum, + char *respname, + struct berval *response ) +{ + return LDAP_SUCCESS; +} + +int +internal_search_reference( Connection *conn, + Operation *op, + char **ref) +{ + return LDAP_SUCCESS; +} + +int +internal_search_result( Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + int nentries) +{ + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)nentries); + return LDAP_SUCCESS; +} + + +int +internal_search_entry( Backend *be, + Connection *conn, + Operation *op, + Entry *e, + char **attrs, + int attrsonly, + char **denied_attrs) +{ + char *ent2str = NULL; + int nentries = 0, len = 0, i = 0; + Slapi_Entry **head = NULL, **tp; + + if((ent2str=slapi_entry2str(e,&len)) == NULL) { + return SLAPD_NO_MEMORY; + } + + slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_NENTRIES, &nentries); + slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head); + i=nentries + 1; + if(nentries == 0 ) { + if((tp=(Slapi_Entry **)slapi_ch_malloc(2 * sizeof(Slapi_Entry *))) == NULL) { + return SLAPD_NO_MEMORY; + } + if((tp[0]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { + return SLAPD_NO_MEMORY; + } + } else { + if((tp=(Slapi_Entry **)slapi_ch_realloc((char *)head, + (sizeof(Slapi_Entry *) * (i+1)))) == NULL) { + return SLAPD_NO_MEMORY; + } + if((tp[i-1]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { + return SLAPD_NO_MEMORY; + } + } + tp[i] = NULL; + + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,(void *)tp); + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)i); + slapi_ch_free(ent2str); + return LDAP_SUCCESS; +} + + +/* + * Function : freeModList + * Free a list of LDAPMod structures which has the bvalue defined. +*/ +static void +freeModList( LDAPMod *pMod ) +{ + LDAPMod *pNextMod; + + while ( pMod != NULL ) { + pNextMod = pMod->mod_next; + free( pMod->mod_type ); + ber_bvecfree( pMod->mod_bvalues ); + free( pMod ); + pMod = pNextMod; + } +} + + +/* + * Function : duplicateBVMod + * Duplicate a LDAPMod structure in which the bervals are defined. + * return code : LDAP_SUCEESS, + * LDAP_OTHER, + * LDAP_NO_MEMORY + */ + +int +duplicateBVMod( LDAPMod *pMod, + LDAPMod **ppNewMod ) +{ + int rc = LDAP_SUCCESS; + int i; + struct berval **ppNewBV; + struct berval *pNewBV; + + if ( pMod == NULL ) { + rc = LDAP_OTHER; + } else { + *ppNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod)); + if ( *ppNewMod == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset( (*ppNewMod),'\0',sizeof(LDAPMod) ); + (*ppNewMod)->mod_op = pMod->mod_op; + (*ppNewMod)->mod_type = slapi_ch_strdup( pMod->mod_type); + if ( (*ppNewMod)->mod_type == NULL) { + rc = LDAP_NO_MEMORY; + } else { + if ( pMod->mod_bvalues == NULL ) { + (*ppNewMod)->mod_values = NULL; + } else { + for ( i=0; pMod->mod_bvalues[i] != NULL; i++ ) { + ; + } + ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*sizeof(struct berval *)); + if ( ppNewBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + for ( i=0; pMod->mod_bvalues[i] != NULL && + rc == LDAP_SUCCESS; i++ ) { + pNewBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + if ( pNewBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pNewBV->bv_val = slapi_ch_malloc(pMod->mod_bvalues[i]->bv_len+1); + if ( pNewBV->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset(pNewBV->bv_val,'\0',pMod->mod_bvalues[i]->bv_len+1); + pNewBV->bv_len = pMod->mod_bvalues[i]->bv_len; + memcpy(pNewBV->bv_val,pMod->mod_bvalues[i]->bv_val,pNewBV->bv_len); + ppNewBV[i] = pNewBV; + } + } + } /* for each bvalue */ + if ( rc == LDAP_SUCCESS ) { + ppNewBV[i] = NULL; + (*ppNewMod)->mod_bvalues = ppNewBV; + } + } + } + } + } + } + return( rc ); +} + +/* + * Function : ValuestoBValues + * Convert an array of char ptrs to an array of berval ptrs. + * return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ +static int +ValuesToBValues( char **ppValue, + struct berval ***pppBV ) +{ + int rc = LDAP_SUCCESS; + int i; + struct berval *pTmpBV; + struct berval **ppNewBV; + + /* count the number of char ptrs. */ + for ( i=0; ppValue != NULL && ppValue[i] != NULL; i++ ) { + ; /* NULL */ + } + + if ( i == 0 ) { + rc = LDAP_OTHER; + } else { + *pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) ); + if ( *pppBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) { + pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + if ( pTmpBV == NULL) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_val = slapi_ch_strdup(*ppValue); + if ( pTmpBV->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_len = strlen(*ppValue); + *ppNewBV = pTmpBV; + ppNewBV++; + } + ppValue++; + } + } + /* null terminate the array of berval ptrs */ + *ppNewBV = NULL; + } + } + return( rc ); +} + + +/* + * Function : LDAPModToEntry + * convert a dn plus an array of LDAPMod struct ptrs to an entry structure + * with a link list of the correspondent attributes. + * Return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ +Entry * +LDAPModToEntry( char *ldn, + LDAPMod **mods ) +{ + int rc=LDAP_SUCCESS; + LDAPMod *pMod; + Entry *pEntry=NULL; + int i,j; + struct berval **ppSaveBV; + struct berval **ppBV; + struct berval *pTmpBV; + char **ppValue; + + + AttributeDescription *ad; + struct berval *bv; + const char *text; + + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + Modifications tmp; + + struct berval dn = { 0, NULL }; + + dn.ber_val = slapi_ch_strdup(ldn); + dn.ber_len = slapi_ch_strlen(ldn); + + pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) ); + if ( pEntry == NULL) { + rc = LDAP_NO_MEMORY; + } else { + rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname ); + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val )); +#else + Debug( LDAP_DEBUG_ANY, "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val, 0, 0 ); +#endif + rc = LDAP_INVALID_DN_SYNTAX; + } + } + if ( rc == LDAP_SUCCESS ) { + for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) { + Modifications *mod; + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* attr values are in berval format */ + /* convert an array of pointers to bervals to an array of bervals */ + rc = bvptr2obj(pMod->mod_bvalues, &bv); + if (rc != LDAP_SUCCESS) break; + tmp.sml_type = pMod->mod_type; + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + } else { + /* attr values are in string format, need to be converted */ + /* to an array of bervals */ + if ( pMod->mod_values == NULL ) { + rc = LDAP_OTHER; + } else { + rc = ValuesToBValues( pMod->mod_values, &ppBV ); + if (rc != LDAP_SUCCESS) break; + rc = bvptr2obj(ppBV, &bv); + if (rc != LDAP_SUCCESS) break; + tmp.sml_type = pMod->mod_type; + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + + if ( ppBV != NULL ) { + ber_bvecfree( ppBV ); + } + } + } + } /* for each LDAPMod */ + } + + if( e->e_nname.bv_len == 0 ) + rc = LDAP_ALREADY_EXISTS; + + /* check if ManageDsaIt control is set */ + if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){ + manageDsaIt = 1; /* turn off referral */ + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_referrals( be, conn, op, &pdn, &ndn ); + } + + + if ( rc != LDAP_SUCCESS ) { + if ( pEntry != NULL ) { + slapi_entry_free( pEntry ); + } + pEntry = NULL; + } + return( pEntry ); +} + +/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ + +Slapi_PBlock * +slapi_add_entry_internal( Slapi_Entry *e, + LDAPControl **controls, + int log_changes) +{ + int rc=LDAP_SUCCESS, i; + Backend *be; + Connection *pConn=NULL; + Operation *op; + Slapi_PBlock *pPB=NULL, *pSavePB=NULL; + char *pDn=NULL; + int manageDsaIt = 0; /* referral is on */ + int isCritical; + struct berval bv; + + /* check if ManageDsaIt control is set */ + if (slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical)) { + manageDsaIt = 1; /* turn off referral */ + } + + pConn = fakeConnection(NULL, LDAP_REQ_ADD); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if (e == NULL) { + rc = LDAP_OPERATIONS_ERROR; + } else { + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&e->e_nname, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_add == NULL) { + rc = LDAP_UNWILLING_TO_PERFORM; + } else { + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + rc = (*be->be_add)( be, pConn, op, e ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + } + } + } + if ( pPB != NULL ) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + if ( pDn != NULL ) + slapi_ch_free( pDn ); + if (bv.bv_val != NULL) + slapi_ch_free(bv.bv_val); + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first); + if (pConn->c_original_dn) + slapi_ch_free(pConn->c_original_dn); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + + + +Slapi_PBlock * +slapi_add_internal( char *dn, + LDAPMod **mods, + LDAPControl **controls, + int log_changes ) +{ + LDAPMod *pMod=NULL; + Slapi_PBlock *pb=NULL; + Entry *pEntry=NULL; + int i, rc=LDAP_SUCCESS; + + + if(mods == NULL || *mods == NULL || dn == NULL || *dn == NULL) + rc = LDAP_OPERATIONS_ERROR ; + + if (rc == LDAP_SUCCESS) { + for (i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) { + if ((pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD) { + rc = LDAP_OTHER; + break; + } + } + } + + if ( rc == LDAP_SUCCESS ) { + if((pEntry = LDAPModToEntry( dn, mods )) == NULL) { + rc = LDAP_OTHER; + } + } + + if(rc != LDAP_SUCCESS) { + pb = slapi_pblock_new(); + slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } else { + pb = slapi_add_entry_internal(pEntry, controls, log_changes); + } + + if(pEntry) + slapi_entry_free(pEntry); + + return(pb); +} + + +/*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd*/ +/* Function : slapi_modify_internal + * + * Description : Plugin functions call this routine to modify an entry in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change) +{ + int rc=LDAP_SUCCESS; + int i; + int dnBadChar; + LDAPMod *pMod; + LDAPMod *pNewMod; + LDAPMod *pTmpMod; + LDAPMod *pSaveMod; + LDAPMod *pModList=NULL; + Backend *be; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + + int manageDsaIt = 0; + int isCritical; + struct berval bv; + struct berval *pbv; + AttributeDescription *ad; + const char *text; + Operation *op; + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + + + pConn = fakeConnection( NULL, LDAP_REQ_MODIFY ); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if ( dn == NULL || mods == NULL || *mods == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + } + if ( rc == LDAP_SUCCESS ) { + dn_normalize( dn ); + + Debug(LDAP_DEBUG_TRACE,"slapi modifying object %s.\n", dn, 0, 0); + rc = dn_check(dn, &dnBadChar); + if ( rc == LDAP_SUCCESS ) { + + /* We could be serving multiple database backends. Select the + * appropriate one, or send a referral to our "referral server" + * if we don't hold it. + */ + + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + bv.bv_val = strdup(dn); + bv.bv_len = strlen(dn); + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_modify == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } + } + } + if ( rc == LDAP_SUCCESS ) { + for ( i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) { + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* attr values are in berval format, merge them with the Entry's attr list */ + rc = duplicateBVMod( pMod, &pNewMod ); + } else { + pNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod)); + if ( pNewMod == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset( pNewMod, '\0', sizeof(LDAPMod) ); + pNewMod->mod_op = pMod->mod_op | LDAP_MOD_BVALUES; + pNewMod->mod_type = slapi_ch_strdup( pMod->mod_type ); + if ( pNewMod->mod_type == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE ) { + rc = ValuesToBValues( pMod->mod_values, &(pNewMod->mod_bvalues) ); + } else { + if ( pMod->mod_values == NULL ) { + Debug(LDAP_DEBUG_TRACE, + "slapi_modify_internal:mod_values is null\n",0, 0, 0); + rc = LDAP_OTHER; + } else { + rc = ValuesToBValues( pMod->mod_values, + &(pNewMod->mod_bvalues) ); + } + } + } + } + } + if ( rc == LDAP_SUCCESS ) { + /* add the new mod to the end of mod list */ + if ( pModList == NULL ) { + pModList = pNewMod; + } else { + pTmpMod = pModList; + while ( pTmpMod != NULL ) { + pSaveMod = pTmpMod; + pTmpMod = pTmpMod->mod_next; + } + pSaveMod->mod_next = pNewMod; + } + } + } /* for each LDAPMod */ + } + + if ( rc == LDAP_SUCCESS ) { + /* convert LDAPModList to Modification list */ + pTmpMod = pModList; + while (pTmpMod != NULL) { + Modifications *mod; + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + mod->sml_type.bv_val = ch_strdup(pTmpMod->mod_type); + mod->sml_type.bv_len = strlen(pTmpMod->mod_type); + mod->sml_op = pTmpMod->mod_op; + pbv = NULL; + rc = bvptr2obj(pTmpMod->mod_bvalues, &pbv); + mod->sml_bvalues = pbv; + ad = NULL; + rc = slap_str2ad(pTmpMod->mod_type, &ad, &text ); + mod->sml_desc = ad; + *modtail = mod; + modtail = &mod->sml_next; + pTmpMod = pTmpMod->mod_next; + } + *modtail = NULL; + } + + if ( rc == LDAP_SUCCESS ) { + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0); + pdn.bv_val = ch_strdup(dn); + pdn.bv_len = strlen(dn); + ndn.bv_val = ch_strdup(dn); + ndn.bv_len = strlen(dn); + rc = (*be->be_modify)( be, pConn, op, &pdn, &ndn, modlist ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + + } else { + rc = LDAP_OPERATIONS_ERROR; + } + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if (pModList != NULL) { + freeModList( pModList ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_original_dn ) + slapi_ch_free( pConn->c_original_dn ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + + +/* Function : slapi_modrdn_internal + * + * Description : Plugin functions call this routine to modify the rdn + * of an entry in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_modrdn_internal( char *olddn, + char *newrdn, + int deloldrdn, + LDAPControl **controls, + int log_change) +{ + + int rc=LDAP_SUCCESS; + int dnBadChar; + Backend *be; + char *pDn=NULL; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + + int manageDsaIt = 0; + int isCritical; + struct berval bv = { 0, NULL }; + Operation *op; + + struct berval dn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + + struct berval newrdnO = { 0, NULL }; + struct berval nnewrdnO = { 0, NULL }; + struct berval pnewrdnO = { 0, NULL }; + + struct berval *nnewS = NULL; + struct berval *pnewS = NULL; + + + dn.bv_val = ch_strdup(olddn); + if (dn.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + } else { + dn.bv_len = strlen(olddn); + } + + if (rc == LDAP_SUCCESS) { + newrdnO.bv_val = ch_strdup(newrdn); + if (newrdnO.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + } else { + newrdnO.bv_len = strlen(newrdn); + } + } + + if (rc == LDAP_SUCCESS) { + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + } + + if (rc == LDAP_SUCCESS) { + rc = dnPrettyNormal( NULL, &newrdnO, &pnewrdnO, &nnewrdnO ); + } + + if ( rc == LDAP_SUCCESS ) { + pConn = fakeConnection(NULL, LDAP_REQ_MODRDN ); + } + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if ( olddn == NULL || newrdn == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + } + if ( rc == LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_TRACE,"slapi modify rdn %s new RDN: %s.\n", olddn, newrdn, 0); + rc = dn_check(olddn, &dnBadChar); + } + + if ( rc == LDAP_SUCCESS ) { + + /* We could be serving multiple database backends. Select the + * appropriate one, or send a referral to our "referral server" + * if we don't hold it. */ + + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } + } + + if ( rc == LDAP_SUCCESS ) { + if ( be->be_modrdn == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } else { + Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0); + rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn, + &pnewrdnO, &nnewrdnO, deloldrdn, pnewS, nnewS ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + } + + if (dn.bv_val) + ch_free(dn.bv_val); + if (pdn.bv_val) + ch_free(pdn.bv_val); + if (ndn.bv_val) + ch_free(ndn.bv_val); + if (newrdnO.bv_val) + ch_free(newrdnO.bv_val); + if (pnewrdnO.bv_val) + ch_free(newrdnO.bv_val); + if (nnewrdnO.bv_val) + ch_free(newrdnO.bv_val); + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if (pConn->c_original_dn) + slapi_ch_free(pConn->c_original_dn); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + +Slapi_PBlock * +slapi_search_internal( char *base, int scope, char *filStr, + LDAPControl **controls, char **attrs, int attrsonly ) +{ + return slapi_search_internal_bind(NULL,base,scope,filStr,controls, attrs,attrsonly); +} + +Slapi_PBlock * +slapi_search_internal_bind( char *bindDN, char *b, int scope, char *filStr, + LDAPControl **controls, char **attrs, int attrsonly ) +{ + Slapi_PBlock *ptr; + Connection *c; + Backend *be; + Filter *filter=NULL; + int i, deref=0, sizelimit=-1, timelimit=-1, rc, dnCheckJunk=0; + int manageDsaIt = 0; + int isCritical; + struct berval bv; + Operation *op; + + struct berval base = { 0, NULL }; + struct berval pbase = { 0, NULL }; + struct berval nbase = { 0, NULL }; + AttributeName *an; + const char *text; + struct berval fstr = { 0, NULL }; + + + + c=fakeConnection(bindDN,LDAP_REQ_SEARCH); + + if ( c == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + ptr = (Slapi_PBlock *)c->c_pending_ops.stqh_first->o_pb; + } + + /* check if ManageDsaIt control is set */ + if ( rc = slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL + && scope != LDAP_SCOPE_SUBTREE ) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR); + return ptr; + } + + dn_normalize( b ); + rc=dn_check(b, &dnCheckJunk); + if(rc != LDAP_SUCCESS) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); + return ptr; + } + + if ( attrs != NULL ) { + for ( i = 0; attrs[i] != NULL; i++ ) + attr_normalize( attrs[i] ); + } + if((filter=slapi_str2filter(filStr)) == NULL) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR); + return ptr; + } + bv.bv_val = ch_strdup(b); + bv.bv_len = strlen(b); + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + + if ((be = select_backend( &bv, manageDsaIt, 0 )) == NULL) { + if ( manageDsaIt == 1 ) { /* referral turned off */ + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_NO_SUCH_OBJECT); + } else { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PARTIAL_RESULTS); + } + return ptr; + } else if ( be->be_search == NULL ) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_UNWILLING_TO_PERFORM); + return ptr; + } else { + + base.bv_val = ch_strdup(b); + base.bv_len = strlen(b); + rc = dnPrettyNormal( NULL, &base, &pbase, &nbase ); + for (i = 0; attrs[i] != 0; i++) { + an[i].an_desc = NULL; + an[i].an_name.bv_val = ch_strdup(attrs[i]); + an[i].an_name.bv_len = strlen(attrs[i]); + slap_bv2ad(&an[i].an_name, &an[i].an_desc, &text); + } + fstr.bv_val = ch_strdup(filStr); + fstr.bv_len = strlen(filStr); + rc = (*be->be_search)( be, c, op, &pbase, &nbase, scope, deref, + sizelimit, timelimit, filter, &fstr, an, attrsonly ); + } + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); + if ( c->c_pending_ops.stqh_first ){ + if(c->c_dn.bv_val) + slapi_ch_free(c->c_dn.bv_val); + if (c->c_original_dn) + slapi_ch_free(c->c_original_dn); + if(c->c_pending_ops.stqh_first->o_dn.bv_val) + slapi_ch_free(c->c_pending_ops.stqh_first->o_dn.bv_val); + slapi_ch_free( c->c_pending_ops.stqh_first ); + } + slapi_ch_free((void **)c); + if (filter) + slapi_filter_free(filter,1); + return ptr; +} + +/* + Function : slapi_get_supported_extended_ops + Description : This function returns a pointer points to an array of Null terminated char pointers. + Each char pointer points to an oid of an extended operation. + If there is no defined extended operaitons, this routine returns NULL. + Input : none + Output : pointer to an null terminated char pointer array or null. + Notes: The caller of this routine needs to free the retuned array pointer, but + should not free the pointers inside the array. +*/ +char +**slapi_get_supported_extended_ops(void) +{ + + ExtendedOp *pTmpExtOp; + int numExtOps = 0; + int i=0; + char **ppExtOpOID = NULL; + + if ( pGExtendedOps != NULL ) { + pTmpExtOp = pGExtendedOps; + while ( pTmpExtOp != NULL ) { + numExtOps++; + pTmpExtOp = pTmpExtOp->ext_next; + } + + if ( numExtOps > 0 ) { + ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps+1) * sizeof(char *) ); + if ( ppExtOpOID != NULL ) { + pTmpExtOp = pGExtendedOps; + while ( pTmpExtOp != NULL ) { + ppExtOpOID[i] = pTmpExtOp->ext_oid; + i++; + pTmpExtOp = pTmpExtOp->ext_next; + } + ppExtOpOID[i] = NULL; + } + } + } + + return( ppExtOpOID ); +} + +Slapi_PBlock * +slapi_simple_bind_internal( char *d, struct berval *cred, int method, int version) +{ + + int rc=LDAP_SUCCESS; + Connection *pConn=NULL; + Backend *be; + Slapi_PBlock *pPB=NULL; + int dnBadChar; + + int isCritical; + struct berval bv; + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + Operation *op; + + + pConn = fakeConnection(NULL, LDAP_REQ_BIND ); + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + pConn->c_version = version; + op = (Operation *)pConn->c_pending_ops.stqh_first; + } + + if ( d == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } else { + dn.bv_val = ch_strdup (d); + dn.bv_len = strlen(d); + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&ndn, 0, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_bind == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } + } + + rc = (*be->be_bind)( be, pConn, op, + &pdn, &ndn, method, cred, NULL ); + + if (rc == LDAP_SUCCESS) { + pConn->c_version = version; + pConn->c_dn.bv_val = strdup( d ); + pConn->c_dn.bv_len = strlen( d ); + if (pConn->c_dn.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + Debug (LDAP_DEBUG_TRACE, " backend routine successful, but has no more memory \n",0, 0, 0); + } + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + + if ( pPB != NULL ) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + + return(pPB); + +} + diff --git a/servers/slapd/slapi/slapi_ops.c.save b/servers/slapd/slapi/slapi_ops.c.save new file mode 100644 index 0000000000..4833d005ae --- /dev/null +++ b/servers/slapd/slapi/slapi_ops.c.save @@ -0,0 +1,1271 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" +#include +#include +#include +#include "../../../libraries/liblber/lber-int.h" + + +int +bvptr2obj( struct berval **bvptr, + struct berval **bvobj); + +Slapi_PBlock * +slapi_simple_bind_internal( char *dn, + struct berval *cred, + int method, + int version); + +int +internal_result_v3( Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + char **referrals) +{ + return LDAP_SUCCESS; +} + + + +int +internal_search_entry( Backend *be, + Connection *conn, + Operation *op, + Entry *e, + char **attrs, + int attrsonly, + char **denied_attrs) +{ + char *ent2str = NULL; + int nentries = 0, len = 0, i = 0; + Slapi_Entry **head = NULL, **tp; + + if((ent2str=slapi_entry2str(e,&len)) == NULL) { + return SLAPD_NO_MEMORY; + } + + slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_NENTRIES, &nentries); + slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head); + i=nentries + 1; + if(nentries == 0 ) { + if((tp=(Slapi_Entry **)slapi_ch_malloc(2 * sizeof(Slapi_Entry *))) == NULL) { + return SLAPD_NO_MEMORY; + } + if((tp[0]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { + return SLAPD_NO_MEMORY; + } + } else { + if((tp=(Slapi_Entry **)slapi_ch_realloc((char *)head, + (sizeof(Slapi_Entry *) * (i+1)))) == NULL) { + return SLAPD_NO_MEMORY; + } + if((tp[i-1]=(Slapi_Entry *)str2entry(ent2str)) == NULL) { + return SLAPD_NO_MEMORY; + } + } + tp[i] = NULL; + + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,(void *)tp); + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)i); + slapi_ch_free(ent2str); + return LDAP_SUCCESS; +} + +int +internal_search_result( Connection *conn, + Operation *op, + int err, + char *matched, + char *text, + int nentries) +{ + slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)nentries); + return LDAP_SUCCESS; +} + + +int +internal_result_ext( Connection *conn, + Operation *op, + int errnum, + char *respname, + struct berval *response ) +{ + return LDAP_SUCCESS; +} + + +int +internal_search_reference( Connection *conn, + Operation *op, + char **ref) +{ + return LDAP_SUCCESS; +} + +Connection * +fakeConnection( char *DN, + int OpType) +{ + Connection *pConn, *c; + + if((pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection))) == NULL) + return (Connection *)NULL; + + LDAP_STAILQ_INIT(&c->c_pending_ops); + LDAP_STAILQ_INIT(&c->c_ops); + + if((pConn->c_pending_ops.stqh_first=(Operation *) slapi_ch_calloc(1, sizeof(Operation))) == NULL) { + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + if((pConn->c_pending_ops.stqh_first->o_pb=(Slapi_PBlock *) slapi_pblock_new()) == NULL) { + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + slapi_ch_free( pConn ); + return (Connection *)NULL; + } + + c = pConn; + + c->c_pending_ops.stqh_first->o_tag = OpType; + c->c_sb = ber_sockbuf_alloc( ); + c->c_protocol = LDAP_VERSION3; + + time(&pConn->c_pending_ops.stqh_first->o_time); + + pConn->c_send_ldap_result = (SEND_LDAP_RESULT) internal_result_v3; + pConn->c_send_search_entry = (SEND_SEARCH_ENTRY) internal_search_entry; + pConn->c_send_search_result = (SEND_SEARCH_RESULT) internal_search_result; + pConn->c_send_ldap_extended = (SEND_LDAP_EXTENDED) internal_result_ext; + pConn->c_send_search_reference = (SEND_SEARCH_REFERENCE) internal_search_reference; + + return pConn; +} + + +/* Function : slapi_delete_internal + * + * Description : Plugin functions call this routine to delete an entry + * in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_delete_internal( char *ldn, + LDAPControl **controls, + int log_change) +{ + + int rc=LDAP_SUCCESS; + Backend *be; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + Operation *op; + + int manageDsaIt = 0; + int isCritical; + + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + + if ( ldn == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + + if ( rc == LDAP_SUCCESS ) { + pConn = fakeConnection( NULL, LDAP_REQ_DELETE ); + } + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + + op->o_ndn.bv_val = slapi_strdup(be->be_update_ndn.bv_val); + op->o_ndn.bv_len = be->be_update_ndn.bv_len; + pConn->c_dn.bv_val = slapi_strdup(be->be_update_ndn.bv_val); + pConn->c_dn.bv_len = be->be_update_ndn.bv_len; + } + if ( rc == LDAP_SUCCESS ) { + dn.bv_val = slapi_strdup(ldn); + dn.bv_len = slapi_strlen(ldn); + + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "do_delete: conn %d invalid dn (%s)\n", + conn->c_connid, dn.bv_val )); +#else + Debug( LDAP_DEBUG_ANY, + "do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 ); +#endif + } + } + + if( ndn.bv_len == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: " + "Attempt to delete root DSE.\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "Attempt to delete root DSE.\n", 0, 0, 0 ); +#endif + rc = LDAP_UNWILLING_TO_PERFORM; + +#ifdef SLAPD_SCHEMA_DN + + } else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: " + "Attempt to delete subschema subentry.\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "Attempt to delete subschema subentry.\n", 0, 0, 0 ); +#endif + rc = LDAP_UNWILLING_TO_PERFORM; + +#endif + } + + if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){ + manageDsaIt = 1; /* turn off referral */ + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_referrals( be, conn, op, &pdn, &ndn ); + } + + suffix_alias( be, &ndn ); + + if ( be->be_delete ) { + /* do the update here */ + int repl_user = be_isupdate( be, &op->o_ndn ); +#ifndef SLAPD_MULTIMASTER + if ( !be->be_update_ndn.bv_len || repl_user ) +#endif + { + if ( (*be->be_delete)( be, conn, op, &pdn, &ndn ) == 0 ) { +#ifdef SLAPD_MULTIMASTER + if ( !be->be_update_ndn.bv_len || !repl_user ) +#endif + { + if (log_change) replog( be, op, &pdn, &ndn, NULL ); + } + } +#ifndef SLAPD_MULTIMASTER + } else { + rc = LDAP_REFERRAL; +#endif + } + } else { + rc = LDAP_UNWILLING_TO_PERFORM; + } + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + if (dn.bv_val) + slapi_ch_free(dn.bv_val); + if (pdn.bv_val) + slapi_ch_free(pdn.bv_val); + if (ndn.bv_val) + slapi_ch_free(ndn_bv.val); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + +#if 0 +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + +/* + * Function : freeModList + * Free a list of LDAPMod structures which has the bvalue defined. +*/ +static void +freeModList( LDAPMod *pMod ) +{ + LDAPMod *pNextMod; + + while ( pMod != NULL ) { + pNextMod = pMod->mod_next; + free( pMod->mod_type ); + ber_bvecfree( pMod->mod_bvalues ); + free( pMod ); + pMod = pNextMod; + } +} + + +/* + * Function : duplicateBVMod + * Duplicate a LDAPMod structure in which the bervals are defined. + * return code : LDAP_SUCEESS, + * LDAP_OTHER, + * LDAP_NO_MEMORY + */ + +int +duplicateBVMod( LDAPMod *pMod, + LDAPMod **ppNewMod ) +{ + int rc = LDAP_SUCCESS; + int i; + struct berval **ppNewBV; + struct berval *pNewBV; + + if ( pMod == NULL ) { + rc = LDAP_OTHER; + } else { + *ppNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod)); + if ( *ppNewMod == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset( (*ppNewMod),'\0',sizeof(LDAPMod) ); + (*ppNewMod)->mod_op = pMod->mod_op; + (*ppNewMod)->mod_type = slapi_ch_strdup( pMod->mod_type); + if ( (*ppNewMod)->mod_type == NULL) { + rc = LDAP_NO_MEMORY; + } else { + if ( pMod->mod_bvalues == NULL ) { + (*ppNewMod)->mod_values = NULL; + } else { + for ( i=0; pMod->mod_bvalues[i] != NULL; i++ ) { + ; + } + ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*sizeof(struct berval *)); + if ( ppNewBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + for ( i=0; pMod->mod_bvalues[i] != NULL && + rc == LDAP_SUCCESS; i++ ) { + pNewBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + if ( pNewBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pNewBV->bv_val = slapi_ch_malloc(pMod->mod_bvalues[i]->bv_len+1); + if ( pNewBV->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset(pNewBV->bv_val,'\0',pMod->mod_bvalues[i]->bv_len+1); + pNewBV->bv_len = pMod->mod_bvalues[i]->bv_len; + memcpy(pNewBV->bv_val,pMod->mod_bvalues[i]->bv_val,pNewBV->bv_len); + ppNewBV[i] = pNewBV; + } + } + } /* for each bvalue */ + if ( rc == LDAP_SUCCESS ) { + ppNewBV[i] = NULL; + (*ppNewMod)->mod_bvalues = ppNewBV; + } + } + } + } + } + } + return( rc ); +} + +/* + * Function : ValuestoBValues + * Convert an array of char ptrs to an array of berval ptrs. + * return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ + +static int +ValuesToBValues( char **ppValue, + struct berval ***pppBV ) +{ + int rc = LDAP_SUCCESS; + int i; + struct berval *pTmpBV; + struct berval **ppNewBV; + + /* count the number of char ptrs. */ + for ( i=0; ppValue != NULL && ppValue[i] != NULL; i++ ) { + ; /* NULL */ + } + + if ( i == 0 ) { + rc = LDAP_OTHER; + } else { + *pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) ); + if ( *pppBV == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) { + pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + if ( pTmpBV == NULL) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_val = slapi_ch_strdup(*ppValue); + if ( pTmpBV->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pTmpBV->bv_len = strlen(*ppValue); + *ppNewBV = pTmpBV; + ppNewBV++; + } + ppValue++; + } + } + /* null terminate the array of berval ptrs */ + *ppNewBV = NULL; + } + } + return( rc ); +} + + +/* + * Function : LDAPModToEntry + * convert a dn plus an array of LDAPMod struct ptrs to an entry structure + * with a link list of the correspondent attributes. + * Return value : LDAP_SUCCESS + * LDAP_NO_MEMORY + * LDAP_OTHER +*/ +Entry * +LDAPModToEntry( char *ldn, + LDAPMod **mods ) +{ + int rc=LDAP_SUCCESS; + LDAPMod *pMod; + Entry *pEntry=NULL; + int i,j; + struct berval **ppSaveBV; + struct berval **ppBV; + struct berval *pTmpBV; + char **ppValue; + + + AttributeDescription *ad; + struct berval *bv; + const char *text; + + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + Modifications tmp; + + struct berval dn = { 0, NULL }; + + dn.ber_val = slapi_ch_strdup(ldn); + dn.ber_len = slapi_ch_strlen(ldn); + + pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) ); + if ( pEntry == NULL) { + rc = LDAP_NO_MEMORY; + } else { + rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname ); + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val )); +#else + Debug( LDAP_DEBUG_ANY, "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val, 0, 0 ); +#endif + rc = LDAP_INVALID_DN_SYNTAX; + } + } + if ( rc == LDAP_SUCCESS ) { + for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) { + Modifications *mod; + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* attr values are in berval format */ + /* convert an array of pointers to bervals to an array of bervals */ + rc = bvptr2obj(pMod->mod_bvalues, &bv); + if (rc != LDAP_SUCCESS) break; + tmp.sml_type = pMod->mod_type; + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + } else { + /* attr values are in string format, need to be converted */ + /* to an array of bervals */ + if ( pMod->mod_values == NULL ) { + rc = LDAP_OTHER; + } else { + rc = ValuesToBValues( pMod->mod_values, &ppBV ); + if (rc != LDAP_SUCCESS) break; + rc = bvptr2obj(ppBV, &bv); + if (rc != LDAP_SUCCESS) break; + tmp.sml_type = pMod->mod_type; + tmp.sml_bvalues = bv; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + + mod->sml_op = LDAP_MOD_ADD; + mod->sml_next = NULL; + mod->sml_desc = NULL; + mod->sml_type = tmp.sml_type; + mod->sml_bvalues = tmp.sml_bvalues; + + *modtail = mod; + modtail = &mod->sml_next; + + + if ( ppBV != NULL ) { + ber_bvecfree( ppBV ); + } + } + } + } /* for each LDAPMod */ + } + + if( e->e_nname.bv_len == 0 ) + rc = LDAP_ALREADY_EXISTS; + + /* check if ManageDsaIt control is set */ + if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){ + manageDsaIt = 1; /* turn off referral */ + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; + } + + if ( rc == LDAP_SUCCESS ) { + rc = backend_check_referrals( be, conn, op, &pdn, &ndn ); + } + + + if ( rc != LDAP_SUCCESS ) { + if ( pEntry != NULL ) { + slapi_entry_free( pEntry ); + } + pEntry = NULL; + } + return( pEntry ); +} + +/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ + +Slapi_PBlock * +slapi_add_entry_internal( Slapi_Entry *e, + LDAPControl **controls, + int log_changes) +{ + int rc=LDAP_SUCCESS, i; + Backend *be; + Connection *pConn=NULL; + Operation *op; + Slapi_PBlock *pPB=NULL, *pSavePB=NULL; + char *pDn=NULL; + int manageDsaIt = 0; /* referral is on */ + int isCritical; + struct berval bv; + + /* check if ManageDsaIt control is set */ + if (slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical)) { + manageDsaIt = 1; /* turn off referral */ + } + + pConn = fakeConnection(NULL, LDAP_REQ_ADD); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if (e == NULL) { + rc = LDAP_OPERATIONS_ERROR; + } else { + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&e->e_nname, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_add == NULL) { + rc = LDAP_UNWILLING_TO_PERFORM; + } else { + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + rc = (*be->be_add)( be, pConn, op, e ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + } + } + } + if ( pPB != NULL ) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + if ( pDn != NULL ) + slapi_ch_free( pDn ); + if (bv.bv_val != NULL) + slapi_ch_free(bv.bv_val); + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first); + if (pConn->c_original_dn) + slapi_ch_free(pConn->c_original_dn); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + + + +Slapi_PBlock * +slapi_add_internal( char *dn, + LDAPMod **mods, + LDAPControl **controls, + int log_changes ) +{ + LDAPMod *pMod=NULL; + Slapi_PBlock *pb=NULL; + Entry *pEntry=NULL; + int i, rc=LDAP_SUCCESS; + + + if(mods == NULL || *mods == NULL || dn == NULL || *dn == NULL) + rc = LDAP_OPERATIONS_ERROR ; + + if (rc == LDAP_SUCCESS) { + for (i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) { + if ((pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD) { + rc = LDAP_OTHER; + break; + } + } + } + + if ( rc == LDAP_SUCCESS ) { + if((pEntry = LDAPModToEntry( dn, mods )) == NULL) { + rc = LDAP_OTHER; + } + } + + if(rc != LDAP_SUCCESS) { + pb = slapi_pblock_new(); + slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } else { + pb = slapi_add_entry_internal(pEntry, controls, log_changes); + } + + if(pEntry) + slapi_entry_free(pEntry); + + return(pb); +} + + +/*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd*/ +/* Function : slapi_modify_internal + * + * Description : Plugin functions call this routine to modify an entry in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change) +{ + int rc=LDAP_SUCCESS; + int i; + int dnBadChar; + LDAPMod *pMod; + LDAPMod *pNewMod; + LDAPMod *pTmpMod; + LDAPMod *pSaveMod; + LDAPMod *pModList=NULL; + Backend *be; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + + int manageDsaIt = 0; + int isCritical; + struct berval bv; + struct berval *pbv; + AttributeDescription *ad; + const char *text; + Operation *op; + Modifications *modlist = NULL; + Modifications **modtail = &modlist; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + + + + pConn = fakeConnection( NULL, LDAP_REQ_MODIFY ); + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if ( dn == NULL || mods == NULL || *mods == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + } + if ( rc == LDAP_SUCCESS ) { + dn_normalize( dn ); + + Debug(LDAP_DEBUG_TRACE,"slapi modifying object %s.\n", dn, 0, 0); + rc = dn_check(dn, &dnBadChar); + if ( rc == LDAP_SUCCESS ) { + + /* We could be serving multiple database backends. Select the + * appropriate one, or send a referral to our "referral server" + * if we don't hold it. + */ + + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + bv.bv_val = strdup(dn); + bv.bv_len = strlen(dn); + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_modify == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } + } + } + if ( rc == LDAP_SUCCESS ) { + for ( i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) { + if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) { + /* attr values are in berval format, merge them with the Entry's attr list */ + rc = duplicateBVMod( pMod, &pNewMod ); + } else { + pNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod)); + if ( pNewMod == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + memset( pNewMod, '\0', sizeof(LDAPMod) ); + pNewMod->mod_op = pMod->mod_op | LDAP_MOD_BVALUES; + pNewMod->mod_type = slapi_ch_strdup( pMod->mod_type ); + if ( pNewMod->mod_type == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE ) { + rc = ValuesToBValues( pMod->mod_values, &(pNewMod->mod_bvalues) ); + } else { + if ( pMod->mod_values == NULL ) { + Debug(LDAP_DEBUG_TRACE, + "slapi_modify_internal:mod_values is null\n",0, 0, 0); + rc = LDAP_OTHER; + } else { + rc = ValuesToBValues( pMod->mod_values, + &(pNewMod->mod_bvalues) ); + } + } + } + } + } + if ( rc == LDAP_SUCCESS ) { + /* add the new mod to the end of mod list */ + if ( pModList == NULL ) { + pModList = pNewMod; + } else { + pTmpMod = pModList; + while ( pTmpMod != NULL ) { + pSaveMod = pTmpMod; + pTmpMod = pTmpMod->mod_next; + } + pSaveMod->mod_next = pNewMod; + } + } + } /* for each LDAPMod */ + } + + if ( rc == LDAP_SUCCESS ) { + /* convert LDAPModList to Modification list */ + pTmpMod = pModList; + while (pTmpMod != NULL) { + Modifications *mod; + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + mod->sml_type.bv_val = ch_strdup(pTmpMod->mod_type); + mod->sml_type.bv_len = strlen(pTmpMod->mod_type); + mod->sml_op = pTmpMod->mod_op; + pbv = NULL; + rc = bvptr2obj(pTmpMod->mod_bvalues, &pbv); + mod->sml_bvalues = pbv; + ad = NULL; + rc = slap_str2ad(pTmpMod->mod_type, &ad, &text ); + mod->sml_desc = ad; + *modtail = mod; + modtail = &mod->sml_next; + pTmpMod = pTmpMod->mod_next; + } + *modtail = NULL; + } + + if ( rc == LDAP_SUCCESS ) { + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0); + pdn.bv_val = ch_strdup(dn); + pdn.bv_len = strlen(dn); + ndn.bv_val = ch_strdup(dn); + ndn.bv_len = strlen(dn); + rc = (*be->be_modify)( be, pConn, op, &pdn, &ndn, modlist ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + + } else { + rc = LDAP_OPERATIONS_ERROR; + } + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if (pModList != NULL) { + freeModList( pModList ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if ( pConn->c_original_dn ) + slapi_ch_free( pConn->c_original_dn ); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + + +/* Function : slapi_modrdn_internal + * + * Description : Plugin functions call this routine to modify the rdn + * of an entry in the backend directly + * Return values : LDAP_SUCCESS + * LDAP_OPERAITONS_ERROR + * LDAP_NO_MEMORY + * LDAP_OTHER + * LDAP_UNWILLING_TO_PERFORM +*/ +Slapi_PBlock * +slapi_modrdn_internal( char *olddn, + char *newrdn, + int deloldrdn, + LDAPControl **controls, + int log_change) +{ + + int rc=LDAP_SUCCESS; + int dnBadChar; + Backend *be; + char *pDn=NULL; + Slapi_PBlock *pPB=NULL; + Slapi_PBlock *pSavePB=NULL; + Connection *pConn=NULL; + + int manageDsaIt = 0; + int isCritical; + struct berval bv = { 0, NULL }; + Operation *op; + + struct berval dn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + + struct berval newrdnO = { 0, NULL }; + struct berval nnewrdnO = { 0, NULL }; + struct berval pnewrdnO = { 0, NULL }; + + struct berval *nnewS = NULL; + struct berval *pnewS = NULL; + + + dn.bv_val = ch_strdup(olddn); + if (dn.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + } else { + dn.bv_len = strlen(olddn); + } + + if (rc == LDAP_SUCCESS) { + newrdnO.bv_val = ch_strdup(newrdn); + if (newrdnO.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + } else { + newrdnO.bv_len = strlen(newrdn); + } + } + + if (rc == LDAP_SUCCESS) { + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + } + + if (rc == LDAP_SUCCESS) { + rc = dnPrettyNormal( NULL, &newrdnO, &pnewrdnO, &nnewrdnO ); + } + + if ( rc == LDAP_SUCCESS ) { + pConn = fakeConnection(NULL, LDAP_REQ_MODRDN ); + } + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + if ( olddn == NULL || newrdn == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } + } + if ( rc == LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_TRACE,"slapi modify rdn %s new RDN: %s.\n", olddn, newrdn, 0); + rc = dn_check(olddn, &dnBadChar); + } + + if ( rc == LDAP_SUCCESS ) { + + /* We could be serving multiple database backends. Select the + * appropriate one, or send a referral to our "referral server" + * if we don't hold it. */ + + op = (Operation *)pConn->c_pending_ops.stqh_first; + op->o_ctrls = controls; + + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + be = select_backend(&bv, manageDsaIt, 0); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } + } + + if ( rc == LDAP_SUCCESS ) { + if ( be->be_modrdn == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } else { + Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0); + rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn, + &pnewrdnO, &nnewrdnO, deloldrdn, pnewS, nnewS ); + if (rc == LDAP_SUCCESS) + Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0); + else + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + } + + if (dn.bv_val) + ch_free(dn.bv_val); + if (pdn.bv_val) + ch_free(pdn.bv_val); + if (ndn.bv_val) + ch_free(ndn.bv_val); + if (newrdnO.bv_val) + ch_free(newrdnO.bv_val); + if (pnewrdnO.bv_val) + ch_free(newrdnO.bv_val); + if (nnewrdnO.bv_val) + ch_free(newrdnO.bv_val); + + if ( pPB != NULL ) { + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + } + if ( pConn != NULL ) { + if ( pConn->c_dn.bv_val ) + slapi_ch_free( pConn->c_dn.bv_val ); + if (pConn->c_original_dn) + slapi_ch_free(pConn->c_original_dn); + if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val ) + slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val ); + if ( pConn->c_pending_ops.stqh_first ) + slapi_ch_free( pConn->c_pending_ops.stqh_first ); + pSavePB = pPB; + free( pConn ); + } + return( pSavePB ); +} + +Slapi_PBlock * +slapi_search_internal( char *base, int scope, char *filStr, + LDAPControl **controls, char **attrs, int attrsonly ) +{ + return slapi_search_internal_bind(NULL,base,scope,filStr,controls, attrs,attrsonly); +} + +Slapi_PBlock * +slapi_search_internal_bind( char *bindDN, char *b, int scope, char *filStr, + LDAPControl **controls, char **attrs, int attrsonly ) +{ + Slapi_PBlock *ptr; + Connection *c; + Backend *be; + Filter *filter=NULL; + int i, deref=0, sizelimit=-1, timelimit=-1, rc, dnCheckJunk=0; + int manageDsaIt = 0; + int isCritical; + struct berval bv; + Operation *op; + + struct berval base = { 0, NULL }; + struct berval pbase = { 0, NULL }; + struct berval nbase = { 0, NULL }; + AttributeName *an; + const char *text; + struct berval fstr = { 0, NULL }; + + + + c=fakeConnection(bindDN,LDAP_REQ_SEARCH); + + if ( c == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + ptr = (Slapi_PBlock *)c->c_pending_ops.stqh_first->o_pb; + } + + /* check if ManageDsaIt control is set */ + if ( rc = slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL + && scope != LDAP_SCOPE_SUBTREE ) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR); + return ptr; + } + + dn_normalize( b ); + rc=dn_check(b, &dnCheckJunk); + if(rc != LDAP_SUCCESS) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); + return ptr; + } + + if ( attrs != NULL ) { + for ( i = 0; attrs[i] != NULL; i++ ) + attr_normalize( attrs[i] ); + } + if((filter=slapi_str2filter(filStr)) == NULL) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR); + return ptr; + } + bv.bv_val = ch_strdup(b); + bv.bv_len = strlen(b); + /* check if ManageDsaIt control is set */ + if ( slapi_control_present( controls, + LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) { + manageDsaIt = 1; /* turn off referral */ + } + + if ((be = select_backend( &bv, manageDsaIt, 0 )) == NULL) { + if ( manageDsaIt == 1 ) { /* referral turned off */ + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_NO_SUCH_OBJECT); + } else { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PARTIAL_RESULTS); + } + return ptr; + } else if ( be->be_search == NULL ) { + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_UNWILLING_TO_PERFORM); + return ptr; + } else { + + base.bv_val = ch_strdup(b); + base.bv_len = strlen(b); + rc = dnPrettyNormal( NULL, &base, &pbase, &nbase ); + for (i = 0; attrs[i] != 0; i++) { + an[i].an_desc = NULL; + an[i].an_name.bv_val = ch_strdup(attrs[i]); + an[i].an_name.bv_len = strlen(attrs[i]); + slap_bv2ad(&an[i].an_name, &an[i].an_desc, &text); + } + fstr.bv_val = ch_strdup(filStr); + fstr.bv_len = strlen(filStr); + rc = (*be->be_search)( be, c, op, &pbase, &nbase, scope, deref, + sizelimit, timelimit, filter, &fstr, an, attrsonly ); + } + slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc); + if ( c->c_pending_ops.stqh_first ){ + if(c->c_dn.bv_val) + slapi_ch_free(c->c_dn.bv_val); + if (c->c_original_dn) + slapi_ch_free(c->c_original_dn); + if(c->c_pending_ops.stqh_first->o_dn.bv_val) + slapi_ch_free(c->c_pending_ops.stqh_first->o_dn.bv_val); + slapi_ch_free( c->c_pending_ops.stqh_first ); + } + slapi_ch_free((void **)c); + if (filter) + slapi_filter_free(filter,1); + return ptr; +} + +/* + Function : slapi_get_supported_extended_ops + Description : This function returns a pointer points to an array of Null terminated char pointers. + Each char pointer points to an oid of an extended operation. + If there is no defined extended operaitons, this routine returns NULL. + Input : none + Output : pointer to an null terminated char pointer array or null. + Notes: The caller of this routine needs to free the retuned array pointer, but + should not free the pointers inside the array. +*/ +char +**slapi_get_supported_extended_ops(void) +{ + + ExtendedOp *pTmpExtOp; + int numExtOps = 0; + int i=0; + char **ppExtOpOID = NULL; + + if ( pGExtendedOps != NULL ) { + pTmpExtOp = pGExtendedOps; + while ( pTmpExtOp != NULL ) { + numExtOps++; + pTmpExtOp = pTmpExtOp->ext_next; + } + + if ( numExtOps > 0 ) { + ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps+1) * sizeof(char *) ); + if ( ppExtOpOID != NULL ) { + pTmpExtOp = pGExtendedOps; + while ( pTmpExtOp != NULL ) { + ppExtOpOID[i] = pTmpExtOp->ext_oid; + i++; + pTmpExtOp = pTmpExtOp->ext_next; + } + ppExtOpOID[i] = NULL; + } + } + } + + return( ppExtOpOID ); +} + +Slapi_PBlock * +slapi_simple_bind_internal( char *d, struct berval *cred, int method, int version) +{ + + int rc=LDAP_SUCCESS; + Connection *pConn=NULL; + Backend *be; + Slapi_PBlock *pPB=NULL; + int dnBadChar; + + int isCritical; + struct berval bv; + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + Operation *op; + + + pConn = fakeConnection(NULL, LDAP_REQ_BIND ); + + if ( pConn == NULL ) { + rc = LDAP_NO_MEMORY; + } else { + pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb; + pConn->c_version = version; + op = (Operation *)pConn->c_pending_ops.stqh_first; + } + + if ( d == NULL ) { + rc = LDAP_OPERATIONS_ERROR; + } else { + dn.bv_val = ch_strdup (d); + dn.bv_len = strlen(d); + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + } + + if ( rc == LDAP_SUCCESS ) { + be = select_backend(&ndn, 0, 0 ); + if ( be == NULL ) { + rc = LDAP_PARTIAL_RESULTS; + } else if ( be->be_bind == NULL ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } + } + + rc = (*be->be_bind)( be, pConn, op, + &pdn, &ndn, method, cred, NULL ); + + if (rc == LDAP_SUCCESS) { + pConn->c_version = version; + pConn->c_dn.bv_val = strdup( d ); + pConn->c_dn.bv_len = strlen( d ); + if (pConn->c_dn.bv_val == NULL) { + rc = LDAP_NO_MEMORY; + Debug (LDAP_DEBUG_TRACE, " backend routine successful, but has no more memory \n",0, 0, 0); + } + Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0); + } + + if ( pPB != NULL ) + slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc ); + + return(pPB); + +} + +#endif diff --git a/servers/slapd/slapi/slapi_ops.h b/servers/slapd/slapi/slapi_ops.h new file mode 100644 index 0000000000..26adf35aa8 --- /dev/null +++ b/servers/slapd/slapi/slapi_ops.h @@ -0,0 +1,34 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef SLAPI_OPS_H +#define SLAPI_OPS_H + +Slapi_PBlock *slapi_search_internal( char *base, int scope, char *filter, + LDAPControl **controls, char **attrs, int attrsonly ); +Slapi_PBlock *slapi_search_internal_bind( char *bindDN, char *base, int scope, char *filter, + LDAPControl **controls, char **attrs, int attrsonly ); /* d58508 */ +Slapi_PBlock *slapi_modify_internal( char *dn, LDAPMod **mods, + LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_add_internal( char * dn, LDAPMod **attrs, LDAPControl **controls, int log_changes ); +Slapi_PBlock *slapi_add_entry_internal( Slapi_Entry * e, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_delete_internal( char * dn, LDAPControl **controls, int log_change ); +Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, int deloldrdn, LDAPControl **controls, int log_change); +/* +Slapi_PBlock *slapi_modrdn_internal( char * olddn, char * newrdn, char *newParent, int deloldrdn, LDAPControl **controls, int log_change); +*/ +char **slapi_get_supported_extended_ops(void); +int duplicateBVMod( LDAPMod *pMod, LDAPMod **ppNewMod ); + +#endif /* SLAPI_OPS_H */ + diff --git a/servers/slapd/slapi/slapi_pblock.c b/servers/slapd/slapi/slapi_pblock.c new file mode 100644 index 0000000000..03edd7ce4d --- /dev/null +++ b/servers/slapd/slapi/slapi_pblock.c @@ -0,0 +1,436 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" +#include +#include + +static int +isOkNetscapeParam( int param ) +{ + switch ( param ) { + case SLAPI_BACKEND: + case SLAPI_CONNECTION: + case SLAPI_OPERATION: + case SLAPI_REQUESTOR_ISROOT: + case SLAPI_BE_MONITORDN: + case SLAPI_BE_TYPE: + case SLAPI_BE_READONLY: + case SLAPI_BE_LASTMOD: + case SLAPI_CONN_ID: + case SLAPI_OPINITIATED_TIME: + case SLAPI_REQUESTOR_DN: + case SLAPI_REQUESTOR_ISUPDATEDN: + case SLAPI_CONN_DN: + case SLAPI_CONN_AUTHTYPE: + case SLAPI_IBM_CONN_DN_ALT: + case SLAPI_IBM_CONN_DN_ORIG: + case SLAPI_IBM_GSSAPI_CONTEXT: + case SLAPI_PLUGIN: + case SLAPI_PLUGIN_PRIVATE: + case SLAPI_PLUGIN_TYPE: + case SLAPI_PLUGIN_ARGV: + case SLAPI_PLUGIN_ARGC: + case SLAPI_PLUGIN_VERSION: + case SLAPI_PLUGIN_OPRETURN: + case SLAPI_PLUGIN_OBJECT: + case SLAPI_PLUGIN_DESTROY_FN: + case SLAPI_PLUGIN_DESCRIPTION: + case SLAPI_PLUGIN_INTOP_RESULT: + case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES: + case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS: + case SLAPI_PLUGIN_DB_BIND_FN: + case SLAPI_PLUGIN_DB_UNBIND_FN: + case SLAPI_PLUGIN_DB_SEARCH_FN: + case SLAPI_PLUGIN_DB_COMPARE_FN: + case SLAPI_PLUGIN_DB_MODIFY_FN: + case SLAPI_PLUGIN_DB_MODRDN_FN: + case SLAPI_PLUGIN_DB_ADD_FN: + case SLAPI_PLUGIN_DB_DELETE_FN: + case SLAPI_PLUGIN_DB_ABANDON_FN: + case SLAPI_PLUGIN_DB_CONFIG_FN: + case SLAPI_PLUGIN_CLOSE_FN: + case SLAPI_PLUGIN_DB_FLUSH_FN: + case SLAPI_PLUGIN_START_FN: + case SLAPI_PLUGIN_DB_SEQ_FN: + case SLAPI_PLUGIN_DB_ENTRY_FN: + case SLAPI_PLUGIN_DB_REFERRAL_FN: + case SLAPI_PLUGIN_DB_RESULT_FN: + case SLAPI_PLUGIN_DB_LDIF2DB_FN: + case SLAPI_PLUGIN_DB_DB2LDIF_FN: + case SLAPI_PLUGIN_DB_BEGIN_FN: + case SLAPI_PLUGIN_DB_COMMIT_FN: + case SLAPI_PLUGIN_DB_ABORT_FN: + case SLAPI_PLUGIN_DB_ARCHIVE2DB_FN: + case SLAPI_PLUGIN_DB_DB2ARCHIVE_FN: + case SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN: + case SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN: + case SLAPI_PLUGIN_DB_SIZE_FN: + case SLAPI_PLUGIN_DB_TEST_FN: + case SLAPI_PLUGIN_DB_NO_ACL: + case SLAPI_PLUGIN_EXT_OP_FN: + case SLAPI_PLUGIN_EXT_OP_OIDLIST: + case SLAPI_PLUGIN_PRE_BIND_FN: + case SLAPI_PLUGIN_PRE_UNBIND_FN: + case SLAPI_PLUGIN_PRE_SEARCH_FN: + case SLAPI_PLUGIN_PRE_COMPARE_FN: + case SLAPI_PLUGIN_PRE_MODIFY_FN: + case SLAPI_PLUGIN_PRE_MODRDN_FN: + case SLAPI_PLUGIN_PRE_ADD_FN: + case SLAPI_PLUGIN_PRE_DELETE_FN: + case SLAPI_PLUGIN_PRE_ABANDON_FN: + case SLAPI_PLUGIN_PRE_ENTRY_FN: + case SLAPI_PLUGIN_PRE_REFERRAL_FN: + case SLAPI_PLUGIN_PRE_RESULT_FN: + case SLAPI_PLUGIN_POST_BIND_FN: + case SLAPI_PLUGIN_POST_UNBIND_FN: + case SLAPI_PLUGIN_POST_SEARCH_FN: + case SLAPI_PLUGIN_POST_COMPARE_FN: + case SLAPI_PLUGIN_POST_MODIFY_FN: + case SLAPI_PLUGIN_POST_MODRDN_FN: + case SLAPI_PLUGIN_POST_ADD_FN: + case SLAPI_PLUGIN_POST_DELETE_FN: + case SLAPI_PLUGIN_POST_ABANDON_FN: + case SLAPI_PLUGIN_POST_ENTRY_FN: + case SLAPI_PLUGIN_POST_REFERRAL_FN: + case SLAPI_PLUGIN_POST_RESULT_FN: + case SLAPI_PLUGIN_MR_FILTER_CREATE_FN: + case SLAPI_PLUGIN_MR_INDEXER_CREATE_FN: + case SLAPI_PLUGIN_MR_FILTER_MATCH_FN: + case SLAPI_PLUGIN_MR_FILTER_INDEX_FN: + case SLAPI_PLUGIN_MR_FILTER_RESET_FN: + case SLAPI_PLUGIN_MR_INDEX_FN: + case SLAPI_PLUGIN_MR_OID: + case SLAPI_PLUGIN_MR_TYPE: + case SLAPI_PLUGIN_MR_VALUE: + case SLAPI_PLUGIN_MR_VALUES: + case SLAPI_PLUGIN_MR_KEYS: + case SLAPI_PLUGIN_MR_FILTER_REUSABLE: + case SLAPI_PLUGIN_MR_QUERY_OPERATOR: + case SLAPI_PLUGIN_MR_USAGE: + case SLAPI_OP_LESS: + case SLAPI_OP_LESS_OR_EQUAL: + case SLAPI_PLUGIN_MR_USAGE_INDEX: + case SLAPI_PLUGIN_SYNTAX_FILTER_AVA: + case SLAPI_PLUGIN_SYNTAX_FILTER_SUB: + case SLAPI_PLUGIN_SYNTAX_VALUES2KEYS: + case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA: + case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB: + case SLAPI_PLUGIN_SYNTAX_NAMES: + case SLAPI_PLUGIN_SYNTAX_OID: + case SLAPI_PLUGIN_SYNTAX_FLAGS: + case SLAPI_PLUGIN_SYNTAX_COMPARE: + case SLAPI_MANAGEDSAIT: + case SLAPI_CONFIG_FILENAME: + case SLAPI_CONFIG_LINENO: + case SLAPI_CONFIG_ARGC: + case SLAPI_CONFIG_ARGV: + case SLAPI_TARGET_DN: + case SLAPI_REQCONTROLS: + case SLAPI_ENTRY_PRE_OP: + case SLAPI_ENTRY_POST_OP: + case SLAPI_RESCONTROLS: + case SLAPI_ADD_RESCONTROL: + case SLAPI_ADD_ENTRY: + case SLAPI_BIND_METHOD: + case SLAPI_BIND_CREDENTIALS: + case SLAPI_BIND_SASLMECHANISM: + case SLAPI_BIND_RET_SASLCREDS: + case SLAPI_COMPARE_TYPE: + case SLAPI_COMPARE_VALUE: + case SLAPI_MODIFY_MODS: + case SLAPI_MODRDN_NEWRDN: + case SLAPI_MODRDN_DELOLDRDN: + case SLAPI_MODRDN_NEWSUPERIOR: + case SLAPI_SEARCH_SCOPE: + case SLAPI_SEARCH_DEREF: + case SLAPI_SEARCH_SIZELIMIT: + case SLAPI_SEARCH_TIMELIMIT: + case SLAPI_SEARCH_FILTER: + case SLAPI_SEARCH_STRFILTER: + case SLAPI_SEARCH_ATTRS: + case SLAPI_SEARCH_ATTRSONLY: + case SLAPI_ABANDON_MSGID: + case SLAPI_SEQ_TYPE: + case SLAPI_SEQ_ATTRNAME: + case SLAPI_SEQ_VAL: + case SLAPI_EXT_OP_REQ_OID: + case SLAPI_EXT_OP_REQ_VALUE: + case SLAPI_EXT_OP_RET_OID: + case SLAPI_EXT_OP_RET_VALUE: + case SLAPI_MR_FILTER_ENTRY: + case SLAPI_MR_FILTER_TYPE: + case SLAPI_MR_FILTER_VALUE: + case SLAPI_MR_FILTER_OID: + case SLAPI_MR_FILTER_DNATTRS: + case SLAPI_LDIF2DB_FILE: + case SLAPI_LDIF2DB_REMOVEDUPVALS: + case SLAPI_DB2LDIF_PRINTKEY: + case SLAPI_PARENT_TXN: + case SLAPI_TXN: + case SLAPI_SEARCH_RESULT_SET: + case SLAPI_SEARCH_RESULT_ENTRY: + case SLAPI_NENTRIES: + case SLAPI_SEARCH_REFERRALS: + case SLAPI_CHANGENUMBER: + case SLAPI_LOG_OPERATION: + case SLAPI_DBSIZE: + return LDAP_SUCCESS; + default: + return INVALID_PARAM; + } +} + +static int +isValidParam( Slapi_PBlock *pb, int param ) +{ + if ( pb->ckParams == TRUE ) { + if ( IBM_RESERVED( param ) ) return LDAP_SUCCESS; + if (param == SLAPI_PLUGIN_AUDIT_FN || + param == SLAPI_PLUGIN_AUDIT_DATA ) + return LDAP_SUCCESS; + if ( param < LAST_IBM_PARAM ) { + return INVALID_PARAM; + } else if ( NETSCAPE_RESERVED( param ) ) { + return INVALID_PARAM; + } else { + return isOkNetscapeParam(param); + } + } else { + return LDAP_SUCCESS; + } +} + +static void +Lock( Slapi_PBlock *pb ) +{ + ldap_pvt_thread_mutex_lock(&pb->pblockMutex); +} + +static void +unLock( Slapi_PBlock *pb ) +{ + ldap_pvt_thread_mutex_unlock(&pb->pblockMutex); +} + +static int +get( Slapi_PBlock *pb, int param, void **val ) +{ + int i; + + if ( isValidParam( pb, param ) == INVALID_PARAM ) { + return PBLOCK_ERROR; + } + + Lock( pb ); + + *val = NULL; + for ( i = 0; i < pb->numParams; i++ ) { + if ( pb->curParams[i] == param ) { + *val = pb->curVals[i]; + break; + } + } + unLock( pb ); + return LDAP_SUCCESS; +} + +static int +set( Slapi_PBlock *pb, int param, void *val ) +{ +#if defined(LDAP_SLAPI) + int i; + + if ( isValidParam( pb, param ) == INVALID_PARAM ) { + return PBLOCK_ERROR; + } + + Lock( pb ); + + if ( pb->numParams == MAX_PARAMS ) { + unLock( pb ); + return PBLOCK_ERROR; + } + + for( i = 0; i < pb->numParams; i++ ) { + if ( pb->curParams[i] == param ) { + break; + } + } + + if ( i >= pb->numParams ) { + pb->curParams[i] = param; + pb->numParams++; + } + pb->curVals[i] = val; + + unLock( pb ); + return LDAP_SUCCESS; +#endif /* LDAP_SLAPI */ + return PBLOCK_ERROR; +} + +static void +clearPB( Slapi_PBlock *pb ) +{ + pb->numParams = 1; +} + +static void +checkParams( Slapi_PBlock *pb, int flag ) +{ + pb->ckParams = flag; +} + +static int +deleteParam( Slapi_PBlock *p, int param ) +{ + int i; + + Lock(p); + for ( i = 0; i < p->numParams; i++ ) { + if ( p->curParams[i] == param ) { + break; + } + } + + if (i >= p->numParams ) { + unLock( p ); + return PBLOCK_ERROR; + } + if ( p->numParams > 1 ) { + p->curParams[i] = p->curParams[p->numParams]; + p->curVals[i] = p->curVals[p->numParams]; + } + p->numParams--; + unLock( p ); + return LDAP_SUCCESS; +} + +Slapi_PBlock * +slapi_pblock_new() +{ +#if defined(LDAP_SLAPI) + Slapi_PBlock *pb; + + pb = (Slapi_PBlock *) ch_malloc(sizeof(Slapi_PBlock)); + if ( pb != NULL ) { + pb->ckParams = TRUE; + ldap_pvt_thread_mutex_init( &pb->pblockMutex ); + memset( pb->curParams, 0, sizeof(pb->curParams) ); + memset( pb->curVals, 0, sizeof(pb->curVals) ); + pb->curParams[0] = SLAPI_IBM_PBLOCK; + pb->curVals[0] = NULL; + pb->numParams = 1; + } + return pb; +#endif /* LDAP_SLAPI */ + return NULL; +} + +void +slapi_pblock_destroy( Slapi_PBlock* pb ) +{ +#if defined(LDAP_SLAPI) + char *str = NULL; + + get( pb, SLAPI_CONN_DN,(void **)&str ); + if ( str != NULL ) { + ch_free( str ); + str = NULL; + } + + get( pb, SLAPI_CONN_AUTHTYPE, (void **)&str ); + if ( str != NULL ) { + ch_free( str ); + str = NULL; + } + + get( pb, SLAPI_IBM_CONN_DN_ALT, (void **)&str ); + if ( str != NULL ) { + ch_free( str ); + str = NULL; + } + + get( pb, SLAPI_IBM_CONN_DN_ORIG, (void **)&str ); + if ( str != NULL ) { + ch_free( str ); + } + + ldap_pvt_thread_mutex_destroy( &pb->pblockMutex ); + + ch_free( pb ); +#endif /* LDAP_SLAPI */ +} + +int +slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ) +{ +#if defined(LDAP_SLAPI) + return get( pb, arg, (void **)value ); +#endif /* LDAP_SLAPI */ + return PBLOCK_ERROR; +} + +int +slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ) +{ +#if defined(LDAP_SLAPI) + void *pTmp = NULL; + + switch ( arg ) { + case SLAPI_CONN_DN: + case SLAPI_CONN_AUTHTYPE: + case SLAPI_IBM_CONN_DN_ALT: + case SLAPI_IBM_CONN_DN_ORIG: + if ( value != NULL ) { + pTmp = (void *)slapi_ch_strdup((char *)value); + if ( pTmp == NULL ) { + return LDAP_NO_MEMORY; + } + } + break; + default: + pTmp = value; + break; + } + return set( pb, arg, pTmp ); +#endif /* LDAP_SLAPI */ + return LDAP_NO_MEMORY; +} + +void +slapi_pblock_clear( Slapi_PBlock *pb ) +{ +#if defined(LDAP_SLAPI) + clearPB( pb ); +#endif /* LDAP_SLAPI */ +} + +int +slapi_pblock_delete_param( Slapi_PBlock *p, int param ) +{ +#if defined(LDAP_SLAPI) + return deleteParam( p, param ); +#endif /* LDAP_SLAPI */ + return PBLOCK_ERROR; +} + +void +slapi_pblock_check_params( Slapi_PBlock *pb, int flag ) +{ +#if defined(LDAP_SLAPI) + checkParams( pb, flag ); +#endif /* LDAP_SLAPI */ +} + diff --git a/servers/slapd/slapi/slapi_pblock.h b/servers/slapd/slapi/slapi_pblock.h new file mode 100644 index 0000000000..d5087a8d6c --- /dev/null +++ b/servers/slapd/slapi/slapi_pblock.h @@ -0,0 +1,40 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef SLAPI_PBLOCK_H +#define SLAPI_PBLOCK_H + +#define CMP_EQUAL 0 +#define CMP_GREATER 1 +#define CMP_LOWER (-1) +#define PBLOCK_ERROR (-1) +#define INVALID_PARAM PBLOCK_ERROR +#define MAX_PARAMS 100 + +struct slapi_pblock { + ldap_pvt_thread_mutex_t pblockMutex; + int ckParams; + int numParams; + int curParams[MAX_PARAMS]; + void *curVals[MAX_PARAMS]; +}; + +Slapi_PBlock *slapi_pblock_new(); +void slapi_pblock_destroy( Slapi_PBlock* ); +int slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value ); +int slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value ); +void slapi_pblock_check_params(Slapi_PBlock *pb, int flag); +int slapi_pblock_delete_param(Slapi_PBlock *p, int param); +void slapi_pblock_clear(Slapi_PBlock *pb); + +#endif /* SLAPI_PBLOCK_H */ + diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c new file mode 100644 index 0000000000..2c90e82b99 --- /dev/null +++ b/servers/slapd/slapi/slapi_utils.c @@ -0,0 +1,1132 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#include "portable.h" +#include "slapi_common.h" + +#include +#include +#include +#include +#include +#include +#include + +struct berval *ns_get_supported_extop( int ); + +#ifdef _SPARC +#include +#endif + +#include + +/* + * server start time (should we use a struct timeval also in slapd? + */ +static struct timeval base_time; +ldap_pvt_thread_mutex_t slapi_hn_mutex; +ldap_pvt_thread_mutex_t slapi_time_mutex; + +/* + * This function converts an array of pointers to berval objects to + * an array of berval objects. + */ + +int +bvptr2obj( + struct berval **bvptr, + BerVarray *bvobj ) +{ + int rc = LDAP_SUCCESS; + int i; + BerVarray tmpberval; + + if ( bvptr == NULL || *bvptr == NULL ) { + return LDAP_OTHER; + } + + for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) { + ; /* EMPTY */ + } + + tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval)); + if ( tmpberval == NULL ) { + return LDAP_NO_MEMORY; + } + + for ( i = 0; bvptr[i] != NULL; i++ ) { + tmpberval[i].bv_val = bvptr[i]->bv_val; + tmpberval[i].bv_len = bvptr[i]->bv_len; + } + + if ( rc == LDAP_SUCCESS ) { + *bvobj = tmpberval; + } + + return rc; +} + +Slapi_Entry * +slapi_str2entry( + char *s, + int check_dup ) +{ +#if defined(LDAP_SLAPI) + Slapi_Entry *e = NULL; + char *pTmpS; + + pTmpS = slapi_ch_strdup( s ); + if ( pTmpS != NULL ) { + e = str2entry( pTmpS ); + slapi_ch_free( pTmpS ); + } + + return e; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_entry2str( + Slapi_Entry *e, + int *len ) +{ +#if defined(LDAP_SLAPI) + char *ret; + + ldap_pvt_thread_mutex_lock( &entry2str_mutex ); + ret = entry2str( e, len ); + ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); + + return ret; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_entry_get_dn( Slapi_Entry *e ) +{ +#if defined(LDAP_SLAPI) + return e->e_name.bv_val; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_entry_set_dn( + Slapi_Entry *e, + char *ldn ) +{ +#if defined(LDAP_SLAPI) + struct berval dn = { 0, NULL }; + + dn.bv_val = ldn; + dn.bv_len = strlen( ldn ); + + dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname ); +#endif /* defined(LDAP_SLAPI) */ +} + +Slapi_Entry * +slapi_entry_dup( Slapi_Entry *e ) +{ +#if defined(LDAP_SLAPI) + char *tmp = NULL; + Slapi_Entry *tmpEnt; + int len = 0; + + tmp = slapi_entry2str( e, &len ); + if ( tmp == NULL ) { + return (Slapi_Entry *)NULL; + } + + tmpEnt = (Slapi_Entry *)str2entry( tmp ); + if ( tmpEnt == NULL ) { + slapi_ch_free( tmp ); + return (Slapi_Entry *)NULL; + } + + if (tmp != NULL) { + slapi_ch_free( tmp ); + } + + return tmpEnt; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_entry_attr_delete( + Slapi_Entry *e, + char *type ) +{ +#if defined(LDAP_SLAPI) + AttributeDescription *ad; + const char *text; + + if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) { + return 1; /* LDAP_NO_SUCH_ATTRIBUTE */ + } + + if ( attr_delete( &e->e_attrs, ad ) == LDAP_SUCCESS ) { + return 0; /* attribute is deleted */ + } else { + return -1; /* something went wrong */ + } +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +Slapi_Entry * +slapi_entry_alloc( void ) +{ +#if defined(LDAP_SLAPI) + return (Slapi_Entry *)slapi_ch_calloc( 1, sizeof(Slapi_Entry) ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_entry_free( Slapi_Entry *e ) +{ +#if defined(LDAP_SLAPI) + entry_free( e ); +#endif /* defined(LDAP_SLAPI) */ +} + +int +slapi_entry_attr_merge( + Slapi_Entry *e, + char *type, + struct berval **vals ) +{ +#if defined(LDAP_SLAPI) + AttributeDescription *ad; + const char *text; + BerVarray bv; + int rc; + + rc = bvptr2obj( vals, &bv ); + if ( rc != LDAP_SUCCESS ) { + return -1; + } + + rc = slap_str2ad( type, &ad, &text ); + if ( rc != LDAP_SUCCESS ) { + return -1; + } + + rc = attr_merge( e, ad, bv ); + ch_free( bv ); + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_entry_attr_find( + Slapi_Entry *e, + char *type, + Slapi_Attr **attr ) +{ +#if defined(LDAP_SLAPI) + AttributeDescription *ad; + const char *text; + int rc; + + rc = slap_str2ad( type, &ad, &text ); + if ( rc != LDAP_SUCCESS ) { + return -1; + } + + *attr = attr_find( e->e_attrs, ad ); + if ( *attr == NULL ) { + return -1; + } + + return 0; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +/* + * FIXME -- The caller must free the allocated memory. + * In Netscape they do not have to. + */ +int +slapi_attr_get_values( + Slapi_Attr *attr, + struct berval ***vals ) +{ +#if defined(LDAP_SLAPI) + int i, j; + struct berval **bv; + + if ( attr == NULL ) { + return 1; + } + + for ( i = 0; attr->a_vals[i].bv_val != NULL; i++ ) { + ; /* EMPTY */ + } + + bv = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) ); + for ( j = 0; j < i; j++ ) { + bv[j] = (struct berval *)ch_malloc( sizeof(struct berval) ); + bv[j]->bv_val = ch_strdup( attr->a_vals[j].bv_val ); + bv[j]->bv_len = attr->a_vals[j].bv_len; + } + bv[j] = NULL; + + *vals = (struct berval **)bv; + + return 0; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_dn_normalize( char *dn ) +{ +#if defined(LDAP_SLAPI) + struct berval bdn; + struct berval ndn; + + assert( dn != NULL ); + + bdn.bv_val = dn; + bdn.bv_len = strlen( dn ); + + dnNormalize2( NULL, &bdn, &ndn ); + + /* + * FIXME: ain't it safe to set dn = ndn.bv_val ? + */ + dn = ch_strdup( ndn.bv_val ); + ch_free( ndn.bv_val ); + + return dn; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +/* + * FIXME: this function is dangerous and should be deprecated; + * DN normalization is a lot more than lower-casing, and BTW + * OpenLDAP's DN normalization for case insensitive attributes + * is already lower case + */ +char * +slapi_dn_normalize_case( char *dn ) +{ +#if defined(LDAP_SLAPI) + slapi_dn_normalize( dn ); + ldap_pvt_str2lower( dn ); + + return dn; +#else /* defined(LDAP_SLAPI) */ + return NULL; +#endif /* defined(LDAP_SLAPI) */ +} + +int +slapi_dn_issuffix( + char *dn, + char *suffix ) +{ +#if defined(LDAP_SLAPI) + struct berval bdn, ndn; + struct berval bsuffix, nsuffix; + + assert( dn != NULL ); + assert( suffix != NULL ); + + bdn.bv_val = dn; + bdn.bv_len = strlen( dn ); + + bsuffix.bv_val = suffix; + bsuffix.bv_len = strlen( suffix ); + + dnNormalize2( NULL, &bdn, &ndn ); + dnNormalize2( NULL, &bsuffix, &nsuffix ); + + return dnIsSuffix( &ndn, &nsuffix ); +#else /* !defined(LDAP_SLAPI) */ + return 0; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_dn_ignore_case( char *dn ) +{ +#if defined(LDAP_SLAPI) + return slapi_dn_normalize_case( dn ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_ch_malloc( unsigned long size ) +{ +#if defined(LDAP_SLAPI) + return ch_malloc( size ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_ch_free( void *ptr ) +{ +#if defined(LDAP_SLAPI) +#if 0 + if ( ptr != NULL ) /* not required ... */ +#endif /* 0 */ + ch_free( ptr ); +#endif /* defined(LDAP_SLAPI) */ +} + +char * +slapi_ch_calloc( + unsigned long nelem, + unsigned long size ) +{ +#if defined(LDAP_SLAPI) + return ch_calloc( nelem, size ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_ch_realloc( + char *block, + unsigned long size ) +{ +#if defined(LDAP_SLAPI) + return ch_realloc( block, size ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_ch_strdup( char *s ) +{ +#if defined(LDAP_SLAPI) + return ch_strdup( (const char *)s ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +size_t +slapi_ch_stlen( char *s ) +{ +#if defined(LDAP_SLAPI) + return strlen( (const char *)s ); +#else /* !defined(LDAP_SLAPI) */ + return 0; +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_control_present( + LDAPControl **controls, + char *oid, + struct berval **val, + int *iscritical ) +{ +#if defined(LDAP_SLAPI) + int i; + int rc = 0; + + if ( val ) { + *val = NULL; + } + + if ( iscritical ) { + *iscritical = 0; + } + + for ( i = 0; controls != NULL && controls[i] != NULL; i++ ) { + if ( strcmp( controls[i]->ldctl_oid, oid ) != 0 ) { + continue; + } + + rc = 1; + if ( controls[i]->ldctl_value.bv_len != 0 ) { + /* + * FIXME: according to 6.1 specification, + * "The val output parameter is set + * to point into the controls array. + * A copy of the control value is + * not made." + */ +#if 0 + struct berval *pTmpBval; + + pTmpBval = (struct berval *)slapi_ch_malloc( sizeof(struct berval)); + if ( pTmpBval == NULL ) { + rc = 0; + } else { + pTmpBval->bv_len = controls[i]->ldctl_value.bv_len; + pTmpBval->bv_val = controls[i]->ldctl_value.bv_val; + if ( val ) { + *val = pTmpBval; + } else { + slapi_ch_free( pTmpBval ); + rc = 0; + } + } +#endif /* 0 */ + if ( val ) { + *val = &controls[i]->ldctl_value; + } + } + + if ( iscritical ) { + *iscritical = controls[i]->ldctl_iscritical; + } + + break; + } + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return 0; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_register_supported_control( + char *controloid, + unsigned long controlops ) +{ +#if defined(LDAP_SLAPI) + /* FIXME -- can not add controls to openLDAP dynamically */ + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_CONTROLS", + "can not add controls to openLDAP dynamically\n" ); +#endif /* defined(LDAP_SLAPI) */ +} + +int +slapi_get_supported_controls( + char ***ctrloidsp, + unsigned long **ctrlopsp ) +{ +#if defined(LDAP_SLAPI) + int i, n; + int rc = 1; + char **oids = NULL; + unsigned long *masks = NULL; + + for (n = 0; get_supported_ctrl( n ) != NULL; n++) { + ; /* count them */ + } + + if ( n == 0 ) { + /* no controls */ + *ctrloidsp = NULL; + *ctrlopsp = NULL; + return LDAP_SUCCESS; + } + + + oids = (char **)slapi_ch_malloc( (n + 1) * sizeof(char *) ); + if ( oids == NULL ) { + rc = LDAP_NO_MEMORY; + goto error_return; + } + + masks = (unsigned long *)slapi_ch_malloc( n * sizeof(int) ); + if ( masks == NULL ) { + rc = LDAP_NO_MEMORY; + goto error_return; + } + + for ( i = 0; i < n; i++ ) { + /* + * FIXME: Netscape's specification says nothing about + * memory; should we copy the OIDs or return pointers + * to internal values? In OpenLDAP the latter is safe + * since we do not allow to register coltrols runtime + */ + oids[ i ] = ch_strdup( get_supported_ctrl( i ) ); + if ( oids[ i ] == NULL ) { + rc = LDAP_NO_MEMORY; + goto error_return; + } + masks[ i ] = (unsigned long)get_supported_ctrl_mask( i ); + } + + *ctrloidsp = oids; + *ctrlopsp = masks; + return LDAP_SUCCESS; + +error_return: + if ( rc != LDAP_SUCCESS ) { + for ( i = 0; oids != NULL && oids[ i ] != NULL; i++ ) { + ch_free( oids[ i ] ); + } + ch_free( oids ); + ch_free( masks ); + } + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return 1; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_register_supported_saslmechanism( char *mechanism ) +{ +#if defined(LDAP_SLAPI) + /* FIXME -- can not add saslmechanism to openLDAP dynamically */ + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SASL", + "can not add saslmechanism to openLDAP dynamically\n" ); +#endif /* defined(LDAP_SLAPI) */ +} + +char ** +slapi_get_supported_saslmechanisms( void ) +{ +#if defined(LDAP_SLAPI) + /* FIXME -- can not get the saslmechanism wihtout a connection. */ + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SASL", + "can not get the saslmechanism " + "wihtout a connection\n" ); + return NULL; +#else /* defined(LDAP_SLAPI) */ + return NULL; +#endif /* defined(LDAP_SLAPI) */ +} + +char ** +slapi_get_supported_extended_ops( void ) +{ +#if defined(LDAP_SLAPI) + int i, j, k; + char **ppExtOpOID = NULL; + int numExtOps = 0; + + for ( i = 0; get_supported_extop( i ) != NULL; i++ ) { + ; + } + + for ( j = 0; ns_get_supported_extop( j ) != NULL; j++ ) { + ; + } + + numExtOps = i + j; + if ( numExtOps == 0 ) { + return NULL; + } + + ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps + 1) * sizeof(char *) ); + for ( k = 0; k < i; k++ ) { + struct berval *bv; + + bv = get_supported_extop( k ); + assert( bv != NULL ); + + ppExtOpOID[ k ] = bv->bv_val; + } + + for ( ; k < j; k++ ) { + struct berval *bv; + + bv = ns_get_supported_extop( k ); + assert( bv != NULL ); + + ppExtOpOID[ i + k ] = bv->bv_val; + } + ppExtOpOID[ i + k ] = NULL; + + return ppExtOpOID; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_send_ldap_result( + Slapi_PBlock *pb, + int err, + char *matched, + char *text, + int nentries, + struct berval **urls ) +{ +#if defined(LDAP_SLAPI) + Connection *conn; + Operation *op; + struct berval *s; + char *extOID = NULL; + struct berval *extValue = NULL; + int rc; + + slapi_pblock_get( pb, SLAPI_CONNECTION, &conn ); + slapi_pblock_get( pb, SLAPI_OPERATION, &op ); + if ( err == LDAP_SASL_BIND_IN_PROGRESS ) { + slapi_pblock_get( pb, SLAPI_BIND_RET_SASLCREDS, &s ); + rc = LDAP_SASL_BIND_IN_PROGRESS; + send_ldap_sasl( conn, op, rc, NULL, NULL, NULL, NULL, s ); + return; + } + + slapi_pblock_get( pb, SLAPI_EXT_OP_RET_OID, &extOID ); + if ( extOID != NULL ) { + slapi_pblock_get( pb, SLAPI_EXT_OP_RET_VALUE, &extValue ); + slapi_send_ldap_extended_response( conn, op, err, extOID, + extValue ); + return; + } + + send_ldap_result( conn, op, err, matched, text, NULL, NULL ); +#endif /* defined(LDAP_SLAPI) */ +} + +int +slapi_send_ldap_search_entry( + Slapi_PBlock *pb, + Slapi_Entry *e, + LDAPControl **ectrls, + char **attrs, + int attrsonly ) +{ +#if defined(LDAP_SLAPI) + Backend *be; + Connection *pConn; + Operation *pOp; + int rc; + + int i; + AttributeName *an = NULL; + const char *text; + + for ( i = 0; attrs[ i ] != NULL; i++ ) { + ; /* empty */ + } + + if ( i > 0 ) { + an = (AttributeName *) ch_malloc( i * sizeof(AttributeName) ); + for ( i = 0; attrs[i] != NULL; i++ ) { + an[i].an_name.bv_val = ch_strdup( attrs[i] ); + an[i].an_name.bv_len = strlen( attrs[i] ); + an[i].an_desc = NULL; + if( slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text ) != LDAP_SUCCESS) + return -1; + } + } + + if ( ( rc = slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&be ) != 0 ) || + ( rc = slapi_pblock_get( pb, SLAPI_CONNECTION, (void *)&pConn) != 0 ) || + ( rc = slapi_pblock_get( pb, SLAPI_OPERATION, (void *)&pOp) != 0 ) ) { + rc = LDAP_OTHER; + } else { + rc = send_search_entry( be, pConn, pOp, e, an, attrsonly, NULL ); + } + + return rc; + +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + + +Slapi_Filter * +slapi_str2filter( char *str ) +{ +#if defined(LDAP_SLAPI) + return str2filter( str ); +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +void +slapi_filter_free( + Slapi_Filter *f, + int recurse ) +{ +#if defined(LDAP_SLAPI) + filter_free( f ); +#endif /* defined(LDAP_SLAPI) */ +} + +int +slapi_filter_get_choice( Slapi_Filter *f ) +{ +#if defined(LDAP_SLAPI) + int rc; + + if ( f != NULL ) { + rc = f->f_choice; + } else { + rc = 0; + } + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return -1; /* invalid filter type */ +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_filter_get_ava( + Slapi_Filter *f, + char **type, + struct berval **bval ) +{ +#if defined(LDAP_SLAPI) + int ftype; + int rc = LDAP_SUCCESS; + + assert( type != NULL ); + assert( bval != NULL ); + + *type = NULL; + *bval = NULL; + + ftype = f->f_choice; + if ( ftype == LDAP_FILTER_EQUALITY + || ftype == LDAP_FILTER_GE + || ftype == LDAP_FILTER_LE + || ftype == LDAP_FILTER_APPROX ) { + *type = slapi_ch_strdup( f->f_un.f_un_ava->aa_desc->ad_cname.bv_val ); + if ( *type == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + *bval = (struct berval *)slapi_ch_malloc( sizeof(struct berval) ); + if ( *bval == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + (*bval)->bv_len = f->f_un.f_un_ava->aa_value.bv_len; + (*bval)->bv_val = slapi_ch_strdup( f->f_un.f_un_ava->aa_value.bv_val ); + if ( (*bval)->bv_val == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + } else { /* filter type not supported */ + rc = -1; + } + +done: + if ( rc != LDAP_SUCCESS ) { + if ( *bval ) { + ch_free( *bval ); + *bval = NULL; + } + + if ( *type ) { + ch_free( *type ); + *type = NULL; + } + } + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +Slapi_Filter * +slapi_filter_list_first( Slapi_Filter *f ) +{ +#if defined(LDAP_SLAPI) + int ftype; + + if ( f == NULL ) { + return NULL; + } + + ftype = f->f_choice; + if ( ftype == LDAP_FILTER_AND + || ftype == LDAP_FILTER_OR + || ftype == LDAP_FILTER_NOT ) { + return (Slapi_Filter *)f->f_and; + } else { + return NULL; + } +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +Slapi_Filter * +slapi_filter_list_next( + Slapi_Filter *f, + Slapi_Filter *fprev ) +{ +#if defined(LDAP_SLAPI) + int ftype; + + if ( f == NULL ) { + return NULL; + } + + ftype = f->f_choice; + if ( ftype == LDAP_FILTER_AND + || ftype == LDAP_FILTER_OR + || ftype == LDAP_FILTER_NOT ) { + if ( f->f_and == fprev ) { + return f->f_and->f_next; + } + } + + return NULL; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_send_ldap_extended_response( + Connection *conn, + Operation *op, + int errornum, + char *respName, + struct berval *response ) +{ +#if defined(LDAP_SLAPI) + send_ldap_extended( conn,op, errornum, NULL, NULL, NULL, + respName,response, NULL ); + return LDAP_SUCCESS; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + +int +slapi_pw_find( + struct berval **vals, + struct berval *v ) +{ +#if defined(LDAP_SLAPI) + /* + * FIXME: what's the point? + */ + return 1; +#else /* !defined(LDAP_SLAPI) */ + return 1; +#endif /* !defined(LDAP_SLAPI) */ +} + +char * +slapi_get_hostname( void ) +{ +#if defined(LDAP_SLAPI) + char *hn = NULL; + + /* + * FIXME: I'd prefer a different check ... + */ +#if defined _SPARC + hn = (char *)slapi_ch_malloc( MAX_HOSTNAME ); + if ( hn == NULL) { + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO", + "can't malloc memory for hostname\n" ); + hn = NULL; + + } else if ( sysinfo( SI_HOSTNAME, hn, MAX_HOSTNAME ) < 0 ) { + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO", + "can't get hostname\n" ); + slapi_ch_free( hn ); + hn = NULL; + } +#else /* !_SPARC */ + static int been_here = 0; + static char *static_hn = NULL; + + ldap_pvt_thread_mutex_lock( &slapi_hn_mutex ); + if ( !been_here ) { + static_hn = (char *)slapi_ch_malloc( MAX_HOSTNAME ); + if ( static_hn == NULL) { + slapi_log_error( SLAPI_LOG_FATAL, "SLAPI_SYSINFO", + "can't malloc memory for hostname\n" ); + static_hn = NULL; + ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex ); + + return hn; + + } else { + if ( gethostname( static_hn, MAX_HOSTNAME ) != 0 ) { + slapi_log_error( SLAPI_LOG_FATAL, + "SLAPI_SYSINFO", + "can't get hostname\n" ); + slapi_ch_free( static_hn ); + static_hn = NULL; + ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex ); + + return hn; + + } else { + been_here = 1; + } + } + } + ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex ); + + hn = ch_strdup( static_hn ); +#endif /* !_SPARC */ + + return hn; +#else /* !defined(LDAP_SLAPI) */ + return NULL; +#endif /* !defined(LDAP_SLAPI) */ +} + +/* + * FIXME: this should go in an appropriate header ... + */ +extern int vLogError( int level, char *subsystem, char *fmt, va_list arglist ); + +int +slapi_log_error( + int severity, + char *subsystem, + char *fmt, + ... ) +{ +#if defined(LDAP_SLAPI) + int rc = LDAP_SUCCESS; + va_list arglist; + + va_start( arglist, fmt ); + rc = vLogError( severity, subsystem, fmt, arglist ); + va_end( arglist ); + + return rc; +#else /* !defined(LDAP_SLAPI) */ + return -1; +#endif /* !defined(LDAP_SLAPI) */ +} + + +unsigned long +slapi_timer_current_time( void ) +{ +#if defined(LDAP_SLAPI) + static int first_time = 1; +#if !defined (_WIN32) + struct timeval now; + unsigned long ret; + + ldap_pvt_thread_mutex_lock( &slapi_time_mutex ); + if (first_time) { + first_time = 0; + gettimeofday( &base_time, NULL ); + } + gettimeofday( &now, NULL ); + ret = ( now.tv_sec - base_time.tv_sec ) * 1000000 + + (now.tv_usec - base_time.tv_usec); + ldap_pvt_thread_mutex_unlock( &slapi_time_mutex ); + + return ret; + + /* + * Ain't it better? + return (slap_get_time() - starttime) * 1000000; + */ +#else /* _WIN32 */ + LARGE_INTEGER now; + + if ( first_time ) { + first_time = 0; + performance_counter_present = QueryPerformanceCounter( &base_time ); + QueryPerformanceFrequency( &performance_freq ); + } + + if ( !performance_counter_present ) + return 0; + + QueryPerformanceCounter( &now ); + return (1000000*(now.QuadPart-base_time.QuadPart))/performance_freq.QuadPart; +#endif /* _WIN32 */ +#else /* !defined(LDAP_SLAPI) */ + return 0; +#endif /* !defined(LDAP_SLAPI) */ +} + +/* + * FIXME ? + */ +unsigned long +slapi_timer_get_time( char *label ) +{ +#if defined(LDAP_SLAPI) + unsigned long start = slapi_timer_current_time(); + printf("%10ld %10ld usec %s\n", start, 0, label); + return start; +#else /* !defined(LDAP_SLAPI) */ + return 0; +#endif /* !defined(LDAP_SLAPI) */ +} + +/* + * FIXME ? + */ +void +slapi_timer_elapsed_time( + char *label, + unsigned long start ) +{ +#if defined(LDAP_SLAPI) + unsigned long stop = slapi_timer_current_time(); + printf ("%10ld %10ld usec %s\n", stop, stop - start, label); +#endif /* defined(LDAP_SLAPI) */ +} + +void +slapi_free_search_results_internal( Slapi_PBlock *pb ) +{ +#if defined(LDAP_SLAPI) + Slapi_Entry **entries; + int k = 0, nEnt = 0; + + slapi_pblock_get( pb, SLAPI_NENTRIES, &nEnt ); + slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries ); + if ( nEnt == 0 ) { + return; + } + + if ( entries == NULL ) { + return; + } + + for ( k = 0; k < nEnt; k++ ) { + slapi_entry_free( entries[k] ); + } + + slapi_ch_free( entries ); +#endif /* defined(LDAP_SLAPI) */ +} + diff --git a/servers/slapd/slapi/slapi_utils.h b/servers/slapd/slapi/slapi_utils.h new file mode 100644 index 0000000000..9bdd05b4d3 --- /dev/null +++ b/servers/slapd/slapi/slapi_utils.h @@ -0,0 +1,115 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * (C) Copyright IBM Corp. 1997,2002 + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is + * given to IBM Corporation. This software is provided ``as is'' + * without express or implied warranty. + */ + +#ifndef _SLAPI_UTILS_H +#define _SLAPI_UTILS_H + +struct _Audit_record; +typedef struct _Audit_record Audit_record; + +#define SLAPI_CONTROL_MANAGEDSAIT_OID "2.16.840.1.113730.3.4.2" +#define SLAPI_CONTROL_SORTEDSEARCH_OID "1.2.840.113556.1.4.473" +#define SLAPI_CONTROL_PAGED_RESULTS_OID "1.2.840.113556.1.4.319" + +typedef int (*SLAPI_FUNC)(Slapi_PBlock *pb); + +#define MAX_HOSTNAME 512 + +#define DOMAIN "Domain" +#define TCPIPPATH "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters" + +typedef struct _slapi_control { + int s_ctrl_num; + char **s_ctrl_oids; + unsigned long *s_ctrl_ops; +} Slapi_Control; + +typedef struct _ExtendedOp { + struct berval ext_oid; + SLAPI_FUNC ext_func; + Backend *ext_be; + struct _ExtendedOp *ext_next; +} ExtendedOp; + +int slapi_log_error( int severity, char *subsystem, char *fmt, ... ); +Slapi_Entry *slapi_str2entry( char *s, int flags ); +char *slapi_entry2str( Slapi_Entry *e, int *len ); +int slapi_entry_attr_merge( Slapi_Entry *e, char *type, struct berval **vals ); +int slapi_entry_attr_find( Slapi_Entry *e, char *type, Slapi_Attr **attr ); +int slapi_entry_attr_delete( Slapi_Entry *e, char *type ); +char *slapi_entry_get_dn( Slapi_Entry *e ); +void slapi_entry_set_dn( Slapi_Entry *e, char *dn ); +Slapi_Entry *slapi_entry_dup( Slapi_Entry *e ); +Slapi_Entry *slapi_entry_alloc(); +void slapi_entry_free( Slapi_Entry *e ); +int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals ); +char *slapi_ch_malloc( unsigned long size ); +void slapi_ch_free( void *ptr ); +char *slapi_ch_calloc( unsigned long nelem, unsigned long size ); +char *slapi_ch_realloc( char *block, unsigned long size ); +char *slapi_ch_strdup( char *s ); +/* + * FIXME: these two were missing, but widely used in a couple of .c files + */ +size_t slapi_strlen(char *s ); +#define slapi_ch_stlen(s) slapi_strlen(s) +/* end of FIXME */ +char *slapi_dn_normalize( char *dn ); +char *slapi_dn_normalize_case( char *dn ); +char * slapi_esc_dn_normalize( char *dn ); +char * slapi_esc_dn_normalize_case( char *dn ); +int slapi_dn_isroot( Slapi_PBlock *pb, char *dn ); +int slapi_dn_issuffix( char *dn, char *suffix ); +char *slapi_dn_ignore_case( char *dn ); +char *slapi_get_hostname(); +void slapi_register_supported_saslmechanism( char *mechanism ); +void slapi_send_ldap_result( Slapi_PBlock *pb, int err, + char *matched, char *text, int nentries, struct berval **urls ); +int slapi_send_ldap_extended_response(Connection *conn, Operation *op, + int errornum, char *respName, struct berval *response); +int slapi_send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, + LDAPControl **ectrls, char **attrs, int attrsonly ); +void slapi_register_supported_control(char *controloid, + unsigned long controlops); +int slapi_get_supported_controls(char ***ctrloidsp, unsigned long **ctrlopsp); +int slapi_control_present( LDAPControl **controls, char *oid, + struct berval **val, int *iscritical); +void slapi_register_supported_saslmechanism(char *mechanism); +char **slapi_get_supported_saslmechanisms(); +char **slapi_get_supported_extended_ops(void); +int checkControlHonored(LDAPControl **controls, char *pControlOid, + unsigned long operation, int *isHonored ); +void slapi_broadcast_be(int funcType, Slapi_PBlock *pPB); +Slapi_Filter *slapi_str2filter( char *str ); +void slapi_filter_free( Slapi_Filter *f, int recurse ); +int slapi_filter_get_choice( Slapi_Filter *f); +int slapi_filter_get_ava( Slapi_Filter *f, char **type, struct berval **bval ); +Slapi_Filter *slapi_filter_list_first( Slapi_Filter *f ); +Slapi_Filter *slapi_filter_list_next( Slapi_Filter *f, Slapi_Filter *fprev ); +void slapi_free_search_results_internal(Slapi_PBlock *pb); +int slapi_is_connection_ssl(Slapi_PBlock *pPB, int *isSSL); +int slapi_get_client_port(Slapi_PBlock *pPB, int *fromPort); +int slapi_get_num_be(char *type); +unsigned long slapi_timer_current_time(); +unsigned long slapi_timer_get_time(char *label); +void slapi_timer_elapsed_time(char *label,unsigned long start); +int slapi_audit_init_header( Connection *conn, Operation *op, + Audit_record **arp, void **audit_op_str, + int audit_op, int audit_ext_op, int audit_op_str_len); +int slapi_audit_send_record( Slapi_PBlock *pb, Connection *conn, + Operation *op, int rc); + +extern ldap_pvt_thread_mutex_t slapi_hn_mutex; +extern ldap_pvt_thread_mutex_t slapi_time_mutex; + +#endif /* _SLAPI_UTILS_H */ + diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in index bed694b502..c700c8816f 100644 --- a/servers/slapd/tools/Makefile.in +++ b/servers/slapd/tools/Makefile.in @@ -27,7 +27,8 @@ XLIBS = $(SLAPD_L) $(LDBM_LIBS) XXLIBS = $(SLAPD_LIBS) \ $(LDBM_LIBS) $(SECURITY_LIBS) \ $(LDIF_LIBS) $(LUTIL_LIBS) -XXXLIBS = $(MODULES_LIBS) $(LTHREAD_LIBS) +XXXLIBS = $(MODULES_LIBS) $(LTHREAD_LIBS) \ + $(SLAPI_LIBS) ../libslapi.a STATIC_DEPENDS=@SLAPD_NO_STATIC@ ../libbackends.a diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index 70f87c3ddd..355752ac71 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -42,7 +42,7 @@ send_ldap_disconnect( } void -send_ldap_extended( +slap_send_ldap_extended( Connection *conn, Operation *op, ber_int_t err, @@ -73,7 +73,7 @@ send_ldap_sasl( } void -send_ldap_result( +slap_send_ldap_result( Connection *conn, Operation *op, ber_int_t err, @@ -87,7 +87,7 @@ send_ldap_result( } void -send_search_result( +slap_send_search_result( Connection *conn, Operation *op, ber_int_t err, @@ -102,7 +102,7 @@ send_search_result( } int -send_search_entry( +slap_send_search_entry( Backend *be, Connection *conn, Operation *op, @@ -116,7 +116,8 @@ send_search_entry( return -1; } -int send_search_reference( +int +slap_send_search_reference( Backend *be, Connection *conn, Operation *op, @@ -270,6 +271,17 @@ slap_modrdn2mods( return 0; } +int +slap_mods2entry( + Modifications *mods, + Entry **e, + int repl_user, + const char **text, + char *textbuf, size_t textlen ) +{ + return 0; +} + int slap_sasl_getdn( Connection *conn, char *id, int len, char *user_realm, struct berval *dn, int flags ) { -- 2.39.5