Have not completed work on backends other than LDBM.
All send_() routines have new parameters (which will likely change
some more to support responses with controls).
slapd/back-ldbm only compiles. NOT TESTED. This is a work in progress.
/*
+ * Copyright 1998,1999 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+/* Portions
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
#ifndef _LDAP_H
#define _LDAP_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
+#include <ldap_cdefs.h>
-#ifdef WINSOCK
-#include "msdos.h"
-#include <winsock.h>
-#endif
+/* draft spec requires ldap.h include lber declarations */
+#include <lber.h>
-#if !defined( NEEDPROTOS ) && defined(__STDC__)
-#define NEEDPROTOS 1
-#endif
+LDAP_BEGIN_DECL
-#define LDAP_PORT 389
#define LDAP_VERSION1 1
#define LDAP_VERSION2 2
-#define LDAP_VERSION LDAP_VERSION2
+#define LDAP_VERSION3 3
+
+#define LDAP_VERSION_MIN LDAP_VERSION2
+#define LDAP_VERSION LDAP_VERSION2
+#define LDAP_VERSION_MAX LDAP_VERSION3
-#define COMPAT20
-#define COMPAT30
-#if defined(COMPAT20) || defined(COMPAT30)
-#define COMPAT
+/*
+ * We'll use 2000+draft revision for our API version number
+ * As such, the number will be above the old RFC but below
+ * whatever number does finally get assigned
+ */
+#define LDAP_API_VERSION 2003
+#define LDAP_VENDOR_NAME "OpenLDAP"
+/* We'll eventually release as 200 */
+#define LDAP_VENDOR_VERSION 192
+
+/* OpenLDAP API Features */
+#define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION
+
+/* include LDAP_API_FEATURE defines */
+#include <ldap_features.h>
+
+#if defined( LDAP_API_FEATURE_X_OPENLDAP_REENTRANT ) || \
+ ( defined( LDAP_THREAD_SAFE ) && \
+ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
+ /* -lldap may or may not be thread safe */
+ /* -lldap_r, if available, is always thread safe */
+# define LDAP_API_FEATURE_THREAD_SAFE 1
+#endif
+#if defined( LDAP_THREAD_SAFE ) && \
+ defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE )
+/* #define LDAP_API_FEATURE_SESSION_SAFE 1 */
+/* #define LDAP_API_OPERATION_SESSION_SAFE 1 */
#endif
-#define LDAP_MAX_ATTR_LEN 100
+#define LDAP_PORT 389
+
+#define LDAP_ROOT_DSE ""
+#define LDAP_NO_ATTRS "1.1"
+#define LDAP_ALL_USER_ATTRIBUTES "*"
+
+/*
+ * LDAP_OPTions defined by draft-ldapext-ldap-c-api-02
+ * 0x0000 - 0x0fff reserved for api options
+ * 0x1000 - 0x3fff reserved for api extended options
+ * 0x4000 - 0x7fff reserved for private and experimental options
+ */
+#define LDAP_OPT_API_INFO 0x0000
+#define LDAP_OPT_DESC 0x0001
+#define LDAP_OPT_DEREF 0x0002
+#define LDAP_OPT_SIZELIMIT 0x0003
+#define LDAP_OPT_TIMELIMIT 0x0004
+/* 0x05 - 0x07 not defined by current draft */
+#define LDAP_OPT_REFERRALS 0x0008
+#define LDAP_OPT_RESTART 0x0009
+/* 0x0a - 0x10 not defined by current draft */
+#define LDAP_OPT_PROTOCOL_VERSION 0x0011
+#define LDAP_OPT_SERVER_CONTROLS 0x0012
+#define LDAP_OPT_CLIENT_CONTROLS 0x0013
+/* 0x14 not defined by current draft */
+#define LDAP_OPT_API_FEATURE_INFO 0x0015
+
+/* 0x16 - 0x2f not defined by current draft */
+#define LDAP_OPT_HOST_NAME 0x0030
+#define LDAP_OPT_ERROR_NUMBER 0x0031
+#define LDAP_OPT_ERROR_STRING 0x0032
+
+/* 0x33 - 0x0fff not defined by current draft */
+
+/* extended options - none */
+
+/* private and experimental options */
+#define LDAP_OPT_DNS 0x4001 /* use DN & DNS */
+
+/* OpenLDAP specific options */
+#define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */
+#define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */
+#define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */
+#define LDAP_OPT_MATCHED_DN 0x5004 /* should have been in draft */
+
+/* on/off values */
+#define LDAP_OPT_ON ((void *) 1)
+#define LDAP_OPT_OFF ((void *) 0)
+
+#define LDAP_OPT_SUCCESS 0
+#define LDAP_OPT_ERROR (-1)
+
+#define LDAP_API_INFO_VERSION (1)
+typedef struct ldapapiinfo {
+ int ldapai_info_version; /* version of LDAPAPIInfo (1) */
+ int ldapai_api_version; /* revision of API supported */
+ int ldapai_protocol_version; /* highest LDAP version supported */
+ char **ldapai_extensions; /* names of API extensions */
+ char *ldapai_vendor_name; /* name of supplier */
+ int ldapai_vendor_version; /* supplier-specific version * 100 */
+} LDAPAPIInfo;
+
+#define LDAP_FEATURE_INFO_VERSION (1) /* version of api feature structure */
+typedef struct ldap_apifeature_info {
+ int ldapaif_info_version; /* version of this struct (1) */
+ char* ldapaif_name; /* matches LDAP_API_FEATURE_... less the prefix */
+ int ldapaif_version; /* matches the value LDAP_API_FEATURE_... */
+} LDAPAPIFeatureInfo;
+
+typedef struct ldapcontrol {
+ char * ldctl_oid;
+ struct berval ldctl_value;
+ char ldctl_iscritical;
+} LDAPControl;
+
+/* LDAP Controls */
+ /* chase referrals controls */
+#define LDAP_CONTROL_REFERRALS "1.2.840.113666.1.4.616"
+#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x0020
+#define LDAP_CHASE_EXTERNAL_REFERRALS 0x0040
+
+#define LDAP_CONTROL_MANAGEDSAIT "2.16.16.840.1.113730.3.4.2"
+
+/* LDAP Unsolicited Notifications */
+#define LDAP_NOTICE_DISCONNECT "1.3.6.1.4.1.1466.20036"
+
+/* LDAP Extended Operations */
-/* debugging stuff */
-#ifdef LDAP_DEBUG
-extern int ldap_debug;
-#ifdef LDAP_SYSLOG
-extern int ldap_syslog;
-extern int ldap_syslog_level;
-#endif
-#define LDAP_DEBUG_TRACE 0x001
-#define LDAP_DEBUG_PACKETS 0x002
-#define LDAP_DEBUG_ARGS 0x004
-#define LDAP_DEBUG_CONNS 0x008
-#define LDAP_DEBUG_BER 0x010
-#define LDAP_DEBUG_FILTER 0x020
-#define LDAP_DEBUG_CONFIG 0x040
-#define LDAP_DEBUG_ACL 0x080
-#define LDAP_DEBUG_STATS 0x100
-#define LDAP_DEBUG_STATS2 0x200
-#define LDAP_DEBUG_SHELL 0x400
-#define LDAP_DEBUG_PARSE 0x800
-#define LDAP_DEBUG_ANY 0xffff
-
-#ifdef LDAP_SYSLOG
-#define Debug( level, fmt, arg1, arg2, arg3 ) \
- { \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, arg1, arg2, arg3 ); \
- if ( ldap_syslog & level ) \
- syslog( ldap_syslog_level, fmt, arg1, arg2, arg3 ); \
- }
-#else /* LDAP_SYSLOG */
-#ifndef WINSOCK
-#define Debug( level, fmt, arg1, arg2, arg3 ) \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, arg1, arg2, arg3 );
-#else /* !WINSOCK */
-extern void Debug( int level, char* fmt, ... );
-#endif /* !WINSOCK */
-#endif /* LDAP_SYSLOG */
-#else /* LDAP_DEBUG */
-#define Debug( level, fmt, arg1, arg2, arg3 )
-#endif /* LDAP_DEBUG */
/*
* specific LDAP instantiations of BER types we know about
*/
+/* Overview of LBER tag construction
+ *
+ * Bits
+ * ______
+ * 8 7 | CLASS
+ * 0 0 = UNIVERSAL
+ * 0 1 = APPLICATION
+ * 1 0 = CONTEXT-SPECIFIC
+ * 1 1 = PRIVATE
+ * _____
+ * | 6 | DATA-TYPE
+ * 0 = PRIMITIVE
+ * 1 = CONSTRUCTED
+ * ___________
+ * | 5 ... 1 | TAG-NUMBER
+ */
+
/* general stuff */
-#define LDAP_TAG_MESSAGE 0x30L /* tag is 16 + constructed bit */
-#define OLD_LDAP_TAG_MESSAGE 0x10L /* forgot the constructed bit */
-#define LDAP_TAG_MSGID 0x02L
+#define LDAP_TAG_MESSAGE (ber_tag_t) 0x30U /* constructed + 16 */
+#define LDAP_TAG_MSGID (ber_tag_t) 0x02U /* integer */
+#define LDAP_TAG_LDAPDN (ber_tag_t) 0x04U /* octect string */
+#define LDAP_TAG_LDAPCRED (ber_tag_t) 0x04U /* octect string */
+#define LDAP_TAG_CONTROLS (ber_tag_t) 0xa0U /* context specific + constructed + 0 */
+#define LDAP_TAG_REFERRAL (ber_tag_t) 0xa3U /* context specific + constructed + 3 */
-/* possible operations a client can invoke */
-#define LDAP_REQ_BIND 0x60L /* application + constructed */
-#define LDAP_REQ_UNBIND 0x42L /* application + primitive */
-#define LDAP_REQ_SEARCH 0x63L /* application + constructed */
-#define LDAP_REQ_MODIFY 0x66L /* application + constructed */
-#define LDAP_REQ_ADD 0x68L /* application + constructed */
-#define LDAP_REQ_DELETE 0x4aL /* application + primitive */
-#define LDAP_REQ_MODRDN 0x6cL /* application + constructed */
-#define LDAP_REQ_COMPARE 0x6eL /* application + constructed */
-#define LDAP_REQ_ABANDON 0x50L /* application + primitive */
-
-/* version 3.0 compatibility stuff */
-#define LDAP_REQ_UNBIND_30 0x62L
-#define LDAP_REQ_DELETE_30 0x6aL
-#define LDAP_REQ_ABANDON_30 0x70L
+#define LDAP_TAG_NEWSUPERIOR (ber_tag_t) 0x80U /* context-specific + primitive + 0 */
-/*
- * old broken stuff for backwards compatibility - forgot application tag
- * and constructed/primitive bit
- */
-#define OLD_LDAP_REQ_BIND 0x00L
-#define OLD_LDAP_REQ_UNBIND 0x02L
-#define OLD_LDAP_REQ_SEARCH 0x03L
-#define OLD_LDAP_REQ_MODIFY 0x06L
-#define OLD_LDAP_REQ_ADD 0x08L
-#define OLD_LDAP_REQ_DELETE 0x0aL
-#define OLD_LDAP_REQ_MODRDN 0x0cL
-#define OLD_LDAP_REQ_COMPARE 0x0eL
-#define OLD_LDAP_REQ_ABANDON 0x10L
+#define LDAP_TAG_EXOP_REQ_OID (ber_tag_t) 0x80U /* context specific + primitive */
+#define LDAP_TAG_EXOP_REQ_VALUE (ber_tag_t) 0x81U /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_OID (ber_tag_t) 0x8aU /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_VALUE (ber_tag_t) 0x8bU /* context specific + primitive */
+
+#define LDAP_TAG_SASL_RES_CREDS (ber_tag_t) 0x87U /* context specific + primitive */
+
+
+
+
+/* possible operations a client can invoke */
+#define LDAP_REQ_BIND (ber_tag_t) 0x60U /* application + constructed */
+#define LDAP_REQ_UNBIND (ber_tag_t) 0x42U /* application + primitive */
+#define LDAP_REQ_SEARCH (ber_tag_t) 0x63U /* application + constructed */
+#define LDAP_REQ_MODIFY (ber_tag_t) 0x66U /* application + constructed */
+#define LDAP_REQ_ADD (ber_tag_t) 0x68U /* application + constructed */
+#define LDAP_REQ_DELETE (ber_tag_t) 0x4aU /* application + primitive */
+#define LDAP_REQ_MODRDN (ber_tag_t) 0x6cU /* application + constructed */
+#define LDAP_REQ_MODDN LDAP_REQ_MODRDN
+#define LDAP_REQ_RENAME LDAP_REQ_MODRDN
+#define LDAP_REQ_COMPARE (ber_tag_t) 0x6eU /* application + constructed */
+#define LDAP_REQ_ABANDON (ber_tag_t) 0x50U /* application + primitive */
+#define LDAP_REQ_EXTENDED (ber_tag_t) 0x77U /* application + constructed */
/* possible result types a server can return */
-#define LDAP_RES_BIND 0x61L /* application + constructed */
-#define LDAP_RES_SEARCH_ENTRY 0x64L /* application + constructed */
-#define LDAP_RES_SEARCH_RESULT 0x65L /* application + constructed */
-#define LDAP_RES_MODIFY 0x67L /* application + constructed */
-#define LDAP_RES_ADD 0x69L /* application + constructed */
-#define LDAP_RES_DELETE 0x6bL /* application + constructed */
-#define LDAP_RES_MODRDN 0x6dL /* application + constructed */
-#define LDAP_RES_COMPARE 0x6fL /* application + constructed */
-#define LDAP_RES_ANY (-1L)
-
-/* old broken stuff for backwards compatibility */
-#define OLD_LDAP_RES_BIND 0x01L
-#define OLD_LDAP_RES_SEARCH_ENTRY 0x04L
-#define OLD_LDAP_RES_SEARCH_RESULT 0x05L
-#define OLD_LDAP_RES_MODIFY 0x07L
-#define OLD_LDAP_RES_ADD 0x09L
-#define OLD_LDAP_RES_DELETE 0x0bL
-#define OLD_LDAP_RES_MODRDN 0x0dL
-#define OLD_LDAP_RES_COMPARE 0x0fL
+#define LDAP_RES_BIND (ber_tag_t) 0x61U /* application + constructed */
+#define LDAP_RES_SEARCH_ENTRY (ber_tag_t) 0x64U /* application + constructed */
+#define LDAP_RES_SEARCH_REFERENCE (ber_tag_t) 0x73U /* V3: application + constructed */
+#define LDAP_RES_SEARCH_RESULT (ber_tag_t) 0x65U /* application + constructed */
+#define LDAP_RES_MODIFY (ber_tag_t) 0x67U /* application + constructed */
+#define LDAP_RES_ADD (ber_tag_t) 0x69U /* application + constructed */
+#define LDAP_RES_DELETE (ber_tag_t) 0x6bU /* application + constructed */
+#define LDAP_RES_MODRDN (ber_tag_t) 0x6dU /* application + constructed */
+#define LDAP_RES_MODDN LDAP_RES_MODRDN /* application + constructed */
+#define LDAP_RES_RENAME LDAP_RES_MODRDN /* application + constructed */
+#define LDAP_RES_COMPARE (ber_tag_t) 0x6fU /* application + constructed */
+#define LDAP_RES_EXTENDED (ber_tag_t) 0x78U /* V3: application + constructed */
+#define LDAP_RES_ANY ((ber_tag_t)(~0))
+
+
+/* sasl methods */
+#define LDAP_SASL_SIMPLE NULL
/* authentication methods available */
-#define LDAP_AUTH_NONE 0x00L /* no authentication */
-#define LDAP_AUTH_SIMPLE 0x80L /* context specific + primitive */
-#define LDAP_AUTH_KRBV4 0xffL /* means do both of the following */
-#define LDAP_AUTH_KRBV41 0x81L /* context specific + primitive */
-#define LDAP_AUTH_KRBV42 0x82L /* context specific + primitive */
-
-/* 3.0 compatibility auth methods */
-#define LDAP_AUTH_SIMPLE_30 0xa0L /* context specific + constructed */
-#define LDAP_AUTH_KRBV41_30 0xa1L /* context specific + constructed */
-#define LDAP_AUTH_KRBV42_30 0xa2L /* context specific + constructed */
-
-/* old broken stuff */
-#define OLD_LDAP_AUTH_SIMPLE 0x00L
-#define OLD_LDAP_AUTH_KRBV4 0x01L
-#define OLD_LDAP_AUTH_KRBV42 0x02L
+#define LDAP_AUTH_NONE (ber_tag_t) 0x00U /* no authentication */
+#define LDAP_AUTH_SIMPLE (ber_tag_t) 0x80U /* context specific + primitive */
+#define LDAP_AUTH_SASL (ber_tag_t) 0xa3U /* context specific + primitive */
+#define LDAP_AUTH_KRBV4 (ber_tag_t) 0xffU /* means do both of the following */
+#define LDAP_AUTH_KRBV41 (ber_tag_t) 0x81U /* context specific + primitive */
+#define LDAP_AUTH_KRBV42 (ber_tag_t) 0x82U /* context specific + primitive */
+
/* filter types */
-#define LDAP_FILTER_AND 0xa0L /* context specific + constructed */
-#define LDAP_FILTER_OR 0xa1L /* context specific + constructed */
-#define LDAP_FILTER_NOT 0xa2L /* context specific + constructed */
-#define LDAP_FILTER_EQUALITY 0xa3L /* context specific + constructed */
-#define LDAP_FILTER_SUBSTRINGS 0xa4L /* context specific + constructed */
-#define LDAP_FILTER_GE 0xa5L /* context specific + constructed */
-#define LDAP_FILTER_LE 0xa6L /* context specific + constructed */
-#define LDAP_FILTER_PRESENT 0x87L /* context specific + primitive */
-#define LDAP_FILTER_APPROX 0xa8L /* context specific + constructed */
-
-/* 3.0 compatibility filter types */
-#define LDAP_FILTER_PRESENT_30 0xa7L /* context specific + constructed */
-
-/* old broken stuff */
-#define OLD_LDAP_FILTER_AND 0x00L
-#define OLD_LDAP_FILTER_OR 0x01L
-#define OLD_LDAP_FILTER_NOT 0x02L
-#define OLD_LDAP_FILTER_EQUALITY 0x03L
-#define OLD_LDAP_FILTER_SUBSTRINGS 0x04L
-#define OLD_LDAP_FILTER_GE 0x05L
-#define OLD_LDAP_FILTER_LE 0x06L
-#define OLD_LDAP_FILTER_PRESENT 0x07L
-#define OLD_LDAP_FILTER_APPROX 0x08L
+#define LDAP_FILTER_AND (ber_tag_t) 0xa0U /* context specific + constructed */
+#define LDAP_FILTER_OR (ber_tag_t) 0xa1U /* context specific + constructed */
+#define LDAP_FILTER_NOT (ber_tag_t) 0xa2U /* context specific + constructed */
+#define LDAP_FILTER_EQUALITY (ber_tag_t) 0xa3U /* context specific + constructed */
+#define LDAP_FILTER_SUBSTRINGS (ber_tag_t) 0xa4U /* context specific + constructed */
+#define LDAP_FILTER_GE (ber_tag_t) 0xa5U /* context specific + constructed */
+#define LDAP_FILTER_LE (ber_tag_t) 0xa6U /* context specific + constructed */
+#define LDAP_FILTER_PRESENT (ber_tag_t) 0x87U /* context specific + primitive */
+#define LDAP_FILTER_APPROX (ber_tag_t) 0xa8U /* context specific + constructed */
+#define LDAP_FILTER_EXTENDED (ber_tag_t) 0xa9U /* context specific + constructed */
+
+/* extended filter component types */
+#define LDAP_FILTER_EXTENDED_OID (ber_tag_t) 0x81U /* context specific */
+#define LDAP_FILTER_EXTENDED_TYPE (ber_tag_t) 0x82U /* context specific */
+#define LDAP_FILTER_EXTENDED_VALUE (ber_tag_t) 0x83U /* context specific */
+#define LDAP_FILTER_EXTENDED_DNATTRS (ber_tag_t) 0x84U /* context specific */
/* substring filter component types */
-#define LDAP_SUBSTRING_INITIAL 0x80L /* context specific */
-#define LDAP_SUBSTRING_ANY 0x81L /* context specific */
-#define LDAP_SUBSTRING_FINAL 0x82L /* context specific */
-
-/* 3.0 compatibility substring filter component types */
-#define LDAP_SUBSTRING_INITIAL_30 0xa0L /* context specific */
-#define LDAP_SUBSTRING_ANY_30 0xa1L /* context specific */
-#define LDAP_SUBSTRING_FINAL_30 0xa2L /* context specific */
-
-/* old broken stuff */
-#define OLD_LDAP_SUBSTRING_INITIAL 0x00L
-#define OLD_LDAP_SUBSTRING_ANY 0x01L
-#define OLD_LDAP_SUBSTRING_FINAL 0x02L
+#define LDAP_SUBSTRING_INITIAL (ber_tag_t) 0x80U /* context specific */
+#define LDAP_SUBSTRING_ANY (ber_tag_t) 0x81U /* context specific */
+#define LDAP_SUBSTRING_FINAL (ber_tag_t) 0x82U /* context specific */
/* search scopes */
-#define LDAP_SCOPE_BASE 0x00
-#define LDAP_SCOPE_ONELEVEL 0x01
-#define LDAP_SCOPE_SUBTREE 0x02
+#define LDAP_SCOPE_BASE (ber_int_t) 0x0000
+#define LDAP_SCOPE_ONELEVEL (ber_int_t) 0x0001
+#define LDAP_SCOPE_SUBTREE (ber_int_t) 0x0002
/* for modifications */
typedef struct ldapmod {
int mod_op;
-#define LDAP_MOD_ADD 0x00
-#define LDAP_MOD_DELETE 0x01
-#define LDAP_MOD_REPLACE 0x02
-#define LDAP_MOD_BVALUES 0x80
+#define LDAP_MOD_ADD (ber_int_t) 0x0000
+#define LDAP_MOD_DELETE (ber_int_t) 0x0001
+#define LDAP_MOD_REPLACE (ber_int_t) 0x0002
+#define LDAP_MOD_BVALUES (ber_int_t) 0x0080
+/* IMPORTANT: do not use code 0x1000 (or above),
+ * it is used internally by the backends!
+ * (see ldap/servers/slapd/slap.h)
+ * JCG 05/1999 (gomez@engr.sgi.com)
+ */
char *mod_type;
- union {
+ union mod_vals_u {
char **modv_strvals;
struct berval **modv_bvals;
} mod_vals;
#define mod_values mod_vals.modv_strvals
#define mod_bvalues mod_vals.modv_bvals
- struct ldapmod *mod_next;
} LDAPMod;
/*
* possible error codes we can return
*/
+#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y)))
+
#define LDAP_SUCCESS 0x00
#define LDAP_OPERATIONS_ERROR 0x01
#define LDAP_PROTOCOL_ERROR 0x02
#define LDAP_SIZELIMIT_EXCEEDED 0x04
#define LDAP_COMPARE_FALSE 0x05
#define LDAP_COMPARE_TRUE 0x06
-#define LDAP_STRONG_AUTH_NOT_SUPPORTED 0x07
+#define LDAP_AUTH_METHOD_NOT_SUPPORTED 0x07
+#define LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_AUTH_METHOD_NOT_SUPPORTED
#define LDAP_STRONG_AUTH_REQUIRED 0x08
-#define LDAP_PARTIAL_RESULTS 0x09
+#define LDAP_PARTIAL_RESULTS 0x09 /* not listed in v3 */
+
+#define LDAP_REFERRAL 0x0a /* LDAPv3 */
+#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */
+#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */
+#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */
+#define LDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */
+
+#define LDAP_ATTR_ERROR(n) LDAP_RANGE((n),0x10,0x15) /* 16-21 */
#define LDAP_NO_SUCH_ATTRIBUTE 0x10
#define LDAP_UNDEFINED_TYPE 0x11
#define LDAP_TYPE_OR_VALUE_EXISTS 0x14
#define LDAP_INVALID_SYNTAX 0x15
+#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
+
#define LDAP_NO_SUCH_OBJECT 0x20
#define LDAP_ALIAS_PROBLEM 0x21
#define LDAP_INVALID_DN_SYNTAX 0x22
-#define LDAP_IS_LEAF 0x23
+#define LDAP_IS_LEAF 0x23 /* not LDAPv3 */
#define LDAP_ALIAS_DEREF_PROBLEM 0x24
-#define NAME_ERROR(n) ((n & 0xf0) == 0x20)
+#define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x30,0x32) /* 48-50 */
#define LDAP_INAPPROPRIATE_AUTH 0x30
#define LDAP_INVALID_CREDENTIALS 0x31
#define LDAP_INSUFFICIENT_ACCESS 0x32
+
+#define LDAP_SERVICE_ERROR(n) LDAP_RANGE((n),0x33,0x36) /* 51-54 */
+
#define LDAP_BUSY 0x33
#define LDAP_UNAVAILABLE 0x34
#define LDAP_UNWILLING_TO_PERFORM 0x35
#define LDAP_LOOP_DETECT 0x36
+#define LDAP_UPDATE_ERROR(n) LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */
+
#define LDAP_NAMING_VIOLATION 0x40
#define LDAP_OBJECT_CLASS_VIOLATION 0x41
#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42
#define LDAP_NOT_ALLOWED_ON_RDN 0x43
#define LDAP_ALREADY_EXISTS 0x44
#define LDAP_NO_OBJECT_CLASS_MODS 0x45
-#define LDAP_RESULTS_TOO_LARGE 0x46
+#define LDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */
+#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* LDAPv3 */
#define LDAP_OTHER 0x50
+
+#define LDAP_API_ERROR(n) LDAP_RANGE((n),0x51,0xff) /* 81+ */
+
#define LDAP_SERVER_DOWN 0x51
#define LDAP_LOCAL_ERROR 0x52
#define LDAP_ENCODING_ERROR 0x53
#define LDAP_PARAM_ERROR 0x59
#define LDAP_NO_MEMORY 0x5a
-
-/* default limit on nesting of referrals */
-#define LDAP_DEFAULT_REFHOPLIMIT 5
+#define LDAP_CONNECT_ERROR 0x5b /* new */
+#define LDAP_NOT_SUPPORTED 0x5c /* new */
+#define LDAP_CONTROL_NOT_FOUND 0x5d /* new */
+#define LDAP_NO_RESULTS_RETURNED 0x5e /* new */
+#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* new */
+#define LDAP_CLIENT_LOOP 0x60 /* new */
+#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* new */
/*
* This structure represents both ldap messages and ldap responses.
* where a response has multiple messages.
*/
-typedef struct ldapmsg {
- int lm_msgid; /* the message id */
- int lm_msgtype; /* the message type */
- BerElement *lm_ber; /* the ber encoded message contents */
- struct ldapmsg *lm_chain; /* for search - next msg in the resp */
- struct ldapmsg *lm_next; /* next response */
- unsigned long lm_time; /* used to maintain cache */
-} LDAPMessage;
-#define NULLMSG ((LDAPMessage *) NULL)
-
-
-#ifdef LDAP_REFERRALS
-/*
- * structure for tracking LDAP server host, ports, DNs, etc.
- */
-typedef struct ldap_server {
- char *lsrv_host;
- char *lsrv_dn; /* if NULL, use default */
- int lsrv_port;
- struct ldap_server *lsrv_next;
-} LDAPServer;
-
-
-/*
- * structure for representing an LDAP server connection
- */
-typedef struct ldap_conn {
- Sockbuf *lconn_sb;
- int lconn_refcnt;
- unsigned long lconn_lastused; /* time */
- int lconn_status;
-#define LDAP_CONNST_NEEDSOCKET 1
-#define LDAP_CONNST_CONNECTING 2
-#define LDAP_CONNST_CONNECTED 3
- LDAPServer *lconn_server;
- char *lconn_krbinstance;
- struct ldap_conn *lconn_next;
-} LDAPConn;
-
-
-/*
- * structure used to track outstanding requests
- */
-typedef struct ldapreq {
- int lr_msgid; /* the message id */
- int lr_status; /* status of request */
-#define LDAP_REQST_INPROGRESS 1
-#define LDAP_REQST_CHASINGREFS 2
-#define LDAP_REQST_NOTCONNECTED 3
-#define LDAP_REQST_WRITING 4
- int lr_outrefcnt; /* count of outstanding referrals */
- int lr_origid; /* original request's message id */
- int lr_parentcnt; /* count of parent requests */
- int lr_res_msgtype; /* result message type */
- int lr_res_errno; /* result LDAP errno */
- char *lr_res_error; /* result error string */
- char *lr_res_matched;/* result matched DN string */
- BerElement *lr_ber; /* ber encoded request contents */
- LDAPConn *lr_conn; /* connection used to send request */
- struct ldapreq *lr_parent; /* request that spawned this referral */
- struct ldapreq *lr_refnext; /* next referral spawned */
- struct ldapreq *lr_prev; /* previous request */
- struct ldapreq *lr_next; /* next request */
-} LDAPRequest;
-#endif /* LDAP_REFERRALS */
-
-
-/*
- * structure for client cache
- */
-#define LDAP_CACHE_BUCKETS 31 /* cache hash table size */
-typedef struct ldapcache {
- LDAPMessage *lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */
- LDAPMessage *lc_requests; /* unfulfilled reqs */
- long lc_timeout; /* request timeout */
- long lc_maxmem; /* memory to use */
- long lc_memused; /* memory in use */
- int lc_enabled; /* enabled? */
- unsigned long lc_options; /* options */
-#define LDAP_CACHE_OPT_CACHENOERRS 0x00000001
-#define LDAP_CACHE_OPT_CACHEALLERRS 0x00000002
-} LDAPCache;
-#define NULLLDCACHE ((LDAPCache *)NULL)
+typedef struct ldapmsg LDAPMessage;
/*
* structures for ldap getfilter routines
* structure representing an ldap connection
*/
-typedef struct ldap {
- Sockbuf ld_sb; /* socket descriptor & buffer */
- char *ld_host;
- int ld_version;
- char ld_lberoptions;
- int ld_deref;
-#define LDAP_DEREF_NEVER 0
-#define LDAP_DEREF_SEARCHING 1
-#define LDAP_DEREF_FINDING 2
-#define LDAP_DEREF_ALWAYS 3
+typedef struct ldap LDAP;
- int ld_timelimit;
- int ld_sizelimit;
-#define LDAP_NO_LIMIT 0
+#define LDAP_DEREF_NEVER 0x00
+#define LDAP_DEREF_SEARCHING 0x01
+#define LDAP_DEREF_FINDING 0x02
+#define LDAP_DEREF_ALWAYS 0x03
- LDAPFiltDesc *ld_filtd; /* from getfilter for ufn searches */
- char *ld_ufnprefix; /* for incomplete ufn's */
-
- int ld_errno;
- char *ld_error;
- char *ld_matched;
- int ld_msgid;
-
- /* do not mess with these */
-#ifdef LDAP_REFERRALS
- LDAPRequest *ld_requests; /* list of outstanding requests */
-#else /* LDAP_REFERRALS */
- LDAPMessage *ld_requests; /* list of outstanding requests */
-#endif /* LDAP_REFERRALS */
- LDAPMessage *ld_responses; /* list of outstanding responses */
- int *ld_abandoned; /* array of abandoned requests */
- char ld_attrbuffer[LDAP_MAX_ATTR_LEN];
- LDAPCache *ld_cache; /* non-null if cache is initialized */
- char *ld_cldapdn; /* DN used in connectionless search */
-
- /* it is OK to change these next four values directly */
- int ld_cldaptries; /* connectionless search retry count */
- int ld_cldaptimeout;/* time between retries */
- int ld_refhoplimit; /* limit on referral nesting */
- unsigned long ld_options; /* boolean options */
-#ifdef LDAP_DNS
-#define LDAP_OPT_DNS 0x00000001 /* use DN & DNS */
-#endif /* LDAP_DNS */
-#ifdef LDAP_REFERRALS
-#define LDAP_OPT_REFERRALS 0x00000002 /* chase referrals */
-#endif /* LDAP_REFERRALS */
-#define LDAP_OPT_RESTART 0x00000004 /* restart if EINTR occurs */
-
- /* do not mess with the rest though */
- char *ld_defhost; /* full name of default server */
- int ld_defport; /* port of default server */
- BERTranslateProc ld_lber_encode_translate_proc;
- BERTranslateProc ld_lber_decode_translate_proc;
-#ifdef LDAP_REFERRALS
- LDAPConn *ld_defconn; /* default connection */
- LDAPConn *ld_conns; /* list of server connections */
- void *ld_selectinfo; /* platform specifics for select */
- int (*ld_rebindproc)( struct ldap *ld, char **dnp,
- char **passwdp, int *authmethodp, int freeit );
- /* routine to get info needed for re-bind */
-#endif /* LDAP_REFERRALS */
-} LDAP;
+#define LDAP_NO_LIMIT 0
+/* how many messages to retrieve results for */
+#define LDAP_MSG_ONE 0x00
+#define LDAP_MSG_ALL 0x01
+#define LDAP_MSG_RECEIVED 0x02
/*
* structure for ldap friendly mapping routines
*/
-typedef struct friendly {
- char *f_unfriendly;
- char *f_friendly;
-} FriendlyMap;
-
-
-/*
- * handy macro to check whether LDAP struct is set up for CLDAP or not
- */
-#define LDAP_IS_CLDAP( ld ) ( ld->ld_sb.sb_naddr > 0 )
-
+typedef struct ldap_friendly {
+ char *lf_unfriendly;
+ char *lf_friendly;
+} LDAPFriendlyMap;
/*
* types for ldap URL handling
char *lud_filter;
char *lud_string; /* for internal use only */
} LDAPURLDesc;
-#define NULLLDAPURLDESC ((LDAPURLDesc *)NULL)
-
-#define LDAP_URL_ERR_NOTLDAP 1 /* URL doesn't begin with "ldap://" */
-#define LDAP_URL_ERR_NODN 2 /* URL has no DN (required) */
-#define LDAP_URL_ERR_BADSCOPE 3 /* URL scope string is invalid */
-#define LDAP_URL_ERR_MEM 4 /* can't allocate memory space */
-
-
-#ifndef NEEDPROTOS
-extern LDAP *ldap_open();
-extern LDAP *ldap_init();
-#ifdef STR_TRANSLATION
-extern void ldap_set_string_translators();
-#ifdef LDAP_CHARSET_8859
-extern int ldap_t61_to_8859();
-extern int ldap_8859_to_t61();
-#endif /* LDAP_CHARSET_8859 */
-#endif /* STR_TRANSLATION */
-extern LDAPMessage *ldap_first_entry();
-extern LDAPMessage *ldap_next_entry();
-extern char *ldap_get_dn();
-extern char *ldap_dn2ufn();
-extern char **ldap_explode_dn();
-extern char *ldap_first_attribute();
-extern char *ldap_next_attribute();
-extern char **ldap_get_values();
-extern struct berval **ldap_get_values_len();
-extern void ldap_value_free();
-extern void ldap_value_free_len();
-extern int ldap_count_values();
-extern int ldap_count_values_len();
-extern char *ldap_err2string();
-extern void ldap_getfilter_free();
-extern LDAPFiltDesc *ldap_init_getfilter();
-extern LDAPFiltDesc *ldap_init_getfilter_buf();
-extern LDAPFiltInfo *ldap_getfirstfilter();
-extern LDAPFiltInfo *ldap_getnextfilter();
-extern void ldap_setfilteraffixes();
-extern void ldap_build_filter();
-extern void ldap_flush_cache();
-extern void ldap_set_cache_options();
-extern void ldap_uncache_entry();
-extern void ldap_uncache_request();
-extern char *ldap_friendly_name();
-extern void ldap_free_friendlymap();
-extern LDAP *cldap_open();
-extern void cldap_setretryinfo();
-extern void cldap_close();
-extern LDAPFiltDesc *ldap_ufn_setfilter();
-extern int ldap_ufn_timeout();
-extern int ldap_sort_entries();
-extern int ldap_sort_values();
-extern int ldap_sort_strcasecmp();
-void ldap_free_urldesc();
-void ldap_set_rebind_proc();
-void ldap_enable_translation();
-
-
-#if defined(ultrix) || defined(VMS) || defined( nextstep )
-extern char *strdup();
-#endif
-#else /* NEEDPROTOS */
-#if !defined(MACOS) && !defined(DOS) && !defined(_WIN32) && !defined(WINSOCK)
-#include <sys/time.h>
-#endif
-#if defined(WINSOCK)
-#include "proto-ld.h"
-#else
-#include "proto-ldap.h"
-#endif
+#define LDAP_URL_ERR_NOTLDAP 0x01 /* URL doesn't begin with "ldap://" */
+#define LDAP_URL_ERR_NODN 0x02 /* URL has no DN (required) */
+#define LDAP_URL_ERR_BADSCOPE 0x03 /* URL scope string is invalid */
+#define LDAP_URL_ERR_MEM 0x04 /* can't allocate memory space */
-#ifdef VMS
-extern char *strdup( const char *s );
-#endif
-#if defined(ultrix) || defined( nextstep )
-extern char *strdup();
-#endif
+/*
+ * The API draft spec says we should declare (or cause to be declared)
+ * 'struct timeval'. We don't. See LDAPext discussions.
+ */
+struct timeval;
-#endif /* NEEDPROTOS */
+/*
+ * in options.c:
+ */
+LDAP_F( int )
+ldap_get_option LDAP_P((
+ LDAP_CONST LDAP *ld,
+ int option,
+ void *outvalue));
+
+LDAP_F( int )
+ldap_set_option LDAP_P((
+ LDAP *ld,
+ int option,
+ LDAP_CONST void *invalue));
+
+
+/*
+ * in controls.c:
+ */
+LDAP_F( void )
+ldap_control_free LDAP_P((
+ LDAPControl *ctrl ));
+
+LDAP_F( void )
+ldap_controls_free LDAP_P((
+ LDAPControl **ctrls ));
+
+
+/*
+ * in extended.c:
+ */
+LDAP_F( int )
+ldap_extended_operation LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_extended_operation_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ char **retoidp,
+ struct berval **retdatap ));
+
+LDAP_F( int )
+ldap_parse_extended_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ char **retoidp,
+ struct berval **retdatap,
+ int freeit ));
+
+/*
+ * in abandon.c:
+ */
+LDAP_F( int )
+ldap_abandon LDAP_P((
+ LDAP *ld,
+ int msgid ));
+
+LDAP_F( int )
+ldap_abandon_ext LDAP_P((
+ LDAP *ld,
+ int msgid,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+
+/*
+ * in add.c:
+ */
+LDAP_F( int )
+ldap_add_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_add_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_add LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs ));
+
+LDAP_F( int )
+ldap_add_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs ));
+
+
+/*
+ * in sasl.c:
+ */
+LDAP_F( int )
+ldap_sasl_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_sasl_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp ));
+
+LDAP_F( int )
+ldap_parse_sasl_bind_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ struct berval **servercredp,
+ int freeit ));
+
+/*
+ * in bind.c:
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd,
+ int authmethod ));
+
+LDAP_F( int )
+ldap_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *cred,
+ int authmethod ));
+
+LDAP_F( void )
+ldap_set_rebind_proc LDAP_P((
+ LDAP *ld,
+ int (*rebindproc) LDAP_P((
+ LDAP *ld,
+ char **dnp,
+ char **passwdp,
+ int *authmethodp,
+ int freeit ))));
+
+
+/*
+ * in sbind.c:
+ */
+LDAP_F( int )
+ldap_simple_bind LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd ));
+
+LDAP_F( int )
+ldap_simple_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd ));
+
+
+/*
+ * in kbind.c:
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_kerberos_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+/*
+ * in cache.c
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_enable_cache LDAP_P(( LDAP *ld, long timeout, ber_len_t maxmem ));
+
+LDAP_F( void )
+ldap_disable_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_set_cache_options LDAP_P(( LDAP *ld, unsigned long opts ));
+
+LDAP_F( void )
+ldap_destroy_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_flush_cache LDAP_P(( LDAP *ld ));
+
+LDAP_F( void )
+ldap_uncache_entry LDAP_P(( LDAP *ld, LDAP_CONST char *dn ));
+
+LDAP_F( void )
+ldap_uncache_request LDAP_P(( LDAP *ld, int msgid ));
+
+
+/*
+ * in compare.c:
+ */
+LDAP_F( int )
+ldap_compare_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ struct berval *bvalue,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_compare_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ struct berval *bvalue,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_compare LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value ));
+
+LDAP_F( int )
+ldap_compare_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value ));
+
+
+/*
+ * in delete.c:
+ */
+LDAP_F( int )
+ldap_delete_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_delete_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_delete LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn ));
+
+LDAP_F( int )
+ldap_delete_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn ));
+
+
+/*
+ * in error.c:
+ */
+LDAP_F( int )
+ldap_parse_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ int *errcodep,
+ char **matcheddnp,
+ char **errmsgp,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit ));
+
+LDAP_F( char *)
+ldap_err2string LDAP_P((
+ int err ));
+
+LDAP_F( int )
+ldap_result2error LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAPMessage *r,
+ int freeit ));
+
+LDAP_F( void )
+ldap_perror LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *s ));
+
+
+/*
+ * in modify.c:
+ */
+LDAP_F( int )
+ldap_modify_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_modify_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_modify LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+LDAP_F( int )
+ldap_modify_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+
+/*
+ * in modrdn.c:
+ */
+LDAP_F( int )
+ldap_rename_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newparent,
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_rename_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newparent,
+ int deleteoldrdn,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_rename2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn,
+ LDAP_CONST char *newSuperior ));
+
+LDAP_F( int )
+ldap_rename2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn,
+ LDAP_CONST char *newSuperior));
+
+LDAP_F( int )
+ldap_modrdn LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn2 LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn ));
+
+LDAP_F( int )
+ldap_modrdn2_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn));
+
+
+/*
+ * in open.c:
+ */
+LDAP_F( LDAP *)
+ldap_open LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( LDAP *)
+ldap_init LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+
+/*
+ * in messages.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *msg ));
+
+LDAP_F( int )
+ldap_count_messages LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+
+/*
+ * in references.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref ));
+
+LDAP_F( int )
+ldap_count_references LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_parse_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit));
+
+
+/*
+ * in getentry.c:
+ */
+LDAP_F( LDAPMessage *)
+ldap_first_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage *)
+ldap_next_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+LDAP_F( int )
+ldap_count_entries LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_get_entry_controls LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAPControl ***serverctrls));
+
+
+/*
+ * in addentry.c
+ */
+LDAP_F( LDAPMessage *)
+ldap_delete_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+LDAP_F( void )
+ldap_add_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+
+/*
+ * in getdn.c
+ */
+LDAP_F( char *)
+ldap_get_dn LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+LDAP_F( char *)
+ldap_dn2ufn LDAP_P((
+ LDAP_CONST char *dn ));
+
+LDAP_F( char **)
+ldap_explode_dn LDAP_P((
+ LDAP_CONST char *dn,
+ int notypes ));
+
+LDAP_F( char **)
+ldap_explode_rdn LDAP_P((
+ LDAP_CONST char *rdn,
+ int notypes ));
+
+LDAP_F( char *)
+ldap_parent_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char *)
+ldap_relative_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char *)
+ldap_normalize_dn LDAP_P(( /* new (from slapd) */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char **)
+ldap_explode_dns LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn ));
+
+LDAP_F( int )
+ldap_is_dns_dn LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn ));
+
+
+/*
+ * in getattr.c
+ */
+LDAP_F( char *)
+ldap_first_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement **ber ));
+
+LDAP_F( char *)
+ldap_next_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement *ber ));
+
+
+/*
+ * in getvalues.c
+ */
+LDAP_F( char **)
+ldap_get_values LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( struct berval **)
+ldap_get_values_len LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( int )
+ldap_count_values LDAP_P((
+ char **vals ));
+
+LDAP_F( int )
+ldap_count_values_len LDAP_P((
+ struct berval **vals ));
+
+LDAP_F( void )
+ldap_value_free LDAP_P((
+ char **vals ));
+
+LDAP_F( void )
+ldap_value_free_len LDAP_P((
+ struct berval **vals ));
+
+/*
+ * in result.c:
+ */
+LDAP_F( int )
+ldap_result LDAP_P((
+ LDAP *ld,
+ int msgid,
+ int all,
+ struct timeval *timeout,
+ LDAPMessage **result ));
+
+LDAP_F( int )
+ldap_msgtype LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgid LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgfree LDAP_P((
+ LDAPMessage *lm ));
+
+LDAP_F( int )
+ldap_msgdelete LDAP_P((
+ LDAP *ld,
+ int msgid ));
+
+
+/*
+ * in search.c:
+ */
+LDAP_F( int )
+ldap_search_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_search_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct timeval *timeout,
+ int sizelimit,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_search LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly ));
+
+LDAP_F( int )
+ldap_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_search_st LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res ));
+
+
+/*
+ * in ufn.c
+ */
+LDAP_F( int )
+ldap_ufn_search_c LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ int (*cancelproc)( void *cl ),
+ void *cancelparm ));
+
+LDAP_F( int )
+ldap_ufn_search_ct LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ int (*cancelproc)( void *cl ),
+ void *cancelparm,
+ char *tag1,
+ char *tag2,
+ char *tag3 ));
+
+LDAP_F( int )
+ldap_ufn_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *ufn,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( LDAPFiltDesc *)
+ldap_ufn_setfilter LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *fname ));
+
+LDAP_F( void )
+ldap_ufn_setprefix LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *prefix ));
+
+LDAP_F( int )
+ldap_ufn_timeout LDAP_P((
+ void *tvparam ));
+
+
+/*
+ * in unbind.c
+ */
+LDAP_F( int )
+ldap_unbind LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+ldap_unbind_s LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+ldap_unbind_ext LDAP_P((
+ LDAP *ld,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls));
+
+LDAP_F( int )
+ldap_unbind_ext_s LDAP_P((
+ LDAP *ld,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls));
+
+/*
+ * in getfilter.c
+ */
+LDAP_F( LDAPFiltDesc *)
+ldap_init_getfilter LDAP_P((
+ LDAP_CONST char *fname ));
+
+LDAP_F( LDAPFiltDesc *)
+ldap_init_getfilter_buf LDAP_P((
+ /* LDAP_CONST */ char *buf,
+ ber_len_t buflen ));
+
+LDAP_F( LDAPFiltInfo *)
+ldap_getfirstfilter LDAP_P((
+ LDAPFiltDesc *lfdp,
+ /* LDAP_CONST */ char *tagpat,
+ /* LDAP_CONST */ char *value ));
+
+LDAP_F( LDAPFiltInfo *)
+ldap_getnextfilter LDAP_P((
+ LDAPFiltDesc *lfdp ));
+
+LDAP_F( void )
+ldap_setfilteraffixes LDAP_P((
+ LDAPFiltDesc *lfdp,
+ LDAP_CONST char *prefix,
+ LDAP_CONST char *suffix ));
+
+LDAP_F( void )
+ldap_build_filter LDAP_P((
+ char *buf,
+ ber_len_t buflen,
+ LDAP_CONST char *pattern,
+ LDAP_CONST char *prefix,
+ LDAP_CONST char *suffix,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value,
+ char **valwords ));
+
+
+/*
+ * in free.c
+ */
+
+LDAP_F( void * )
+ldap_memalloc LDAP_P((
+ ber_len_t s ));
+
+LDAP_F( void * )
+ldap_memrealloc LDAP_P((
+ void* p,
+ ber_len_t s ));
+
+LDAP_F( void * )
+ldap_memcalloc LDAP_P((
+ ber_len_t n,
+ ber_len_t s ));
+
+LDAP_F( void )
+ldap_memfree LDAP_P((
+ void* p ));
+
+LDAP_F( void )
+ldap_memvfree LDAP_P((
+ void** v ));
+
+LDAP_F( char * )
+ldap_strdup LDAP_P((
+ LDAP_CONST char * ));
+
+LDAP_F( void )
+ldap_getfilter_free LDAP_P((
+ LDAPFiltDesc *lfdp ));
+
+LDAP_F( void )
+ldap_mods_free LDAP_P((
+ LDAPMod **mods,
+ int freemods ));
+
+
+/*
+ * in friendly.c
+ */
+LDAP_F( char * )
+ldap_friendly_name LDAP_P((
+ LDAP_CONST char *filename,
+ /* LDAP_CONST */ char *uname,
+ LDAPFriendlyMap **map ));
+
+LDAP_F( void )
+ldap_free_friendlymap LDAP_P((
+ LDAPFriendlyMap **map ));
+
+
+/*
+ * in cldap.c
+ */
+LDAP_F( LDAP * )
+cldap_open LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( void )
+cldap_close LDAP_P((
+ LDAP *ld ));
+
+LDAP_F( int )
+cldap_search_s LDAP_P(( LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res,
+ char *logdn ));
+
+LDAP_F( void )
+cldap_setretryinfo LDAP_P((
+ LDAP *ld,
+ int tries,
+ int timeout ));
+
+
+/*
+ * in sort.c
+ */
+LDAP_F( int )
+ldap_sort_entries LDAP_P(( LDAP *ld,
+ LDAPMessage **chain,
+ LDAP_CONST char *attr,
+ int (*cmp) (LDAP_CONST char *, LDAP_CONST char *) ));
+
+LDAP_F( int )
+ldap_sort_values LDAP_P((
+ LDAP *ld,
+ char **vals,
+ int (*cmp) (LDAP_CONST void *, LDAP_CONST void *) ));
+
+LDAP_F( int )
+ldap_sort_strcasecmp LDAP_P((
+ LDAP_CONST void *a,
+ LDAP_CONST void *b ));
+
+
+/*
+ * in url.c
+ *
+ * need _ext varients
+ */
+LDAP_F( int )
+ldap_is_ldap_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_url_parse LDAP_P((
+ LDAP_CONST char *url,
+ LDAPURLDesc **ludpp ));
+
+LDAP_F( void )
+ldap_free_urldesc LDAP_P((
+ LDAPURLDesc *ludp ));
+
+LDAP_F( int )
+ldap_url_search LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly ));
+
+LDAP_F( int )
+ldap_url_search_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_url_search_st LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *url,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res ));
+
+
+/*
+ * in charset.c
+ * DEPRECATED
+ */
+LDAP_F( void )
+ldap_set_string_translators LDAP_P((
+ LDAP *ld,
+ BERTranslateProc encode_proc,
+ BERTranslateProc decode_proc ));
+
+LDAP_F( int )
+ldap_translate_from_t61 LDAP_P((
+ LDAP *ld,
+ char **bufp,
+ ber_len_t *lenp,
+ int free_input ));
+
+LDAP_F( int )
+ldap_translate_to_t61 LDAP_P((
+ LDAP *ld,
+ char **bufp,
+ ber_len_t *lenp,
+ int free_input ));
+
+LDAP_F( void )
+ldap_enable_translation LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ int enable ));
+
+LDAP_F( int )
+ldap_t61_to_8859 LDAP_P((
+ char **bufp,
+ ber_len_t *buflenp,
+ int free_input ));
+
+LDAP_F( int )
+ldap_8859_to_t61 LDAP_P((
+ char **bufp,
+ ber_len_t *buflenp,
+ int free_input ));
+
+LDAP_END_DECL
-#ifdef __cplusplus
-}
-#endif
#endif /* _LDAP_H */
* is provided ``as is'' without express or implied warranty.
*/
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
+#include "portable.h"
-extern Backend *select_backend();
+#include <stdio.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_abandon(
Connection *conn,
Operation *op
)
{
- int id;
- Backend *be;
+ ber_int_t id;
Operation *o;
+ Operation **oo;
+ int rc, notfound;
Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
*/
if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0 ,0 );
- return;
+ Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
+ if( (rc = get_ctrls( conn, op, 0 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
+ return rc;
+ }
+
Debug( LDAP_DEBUG_ARGS, "do_abandon: id %d\n", id, 0 ,0 );
+ if( id <= 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+ return LDAP_SUCCESS;
+ }
+
+ notfound = 1; /* not found */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/*
* find the operation being abandoned and set the o_abandon
* flag. It's up to the backend to periodically check this
* flag and abort the operation at a convenient time.
*/
- pthread_mutex_lock( &conn->c_opsmutex );
for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
- if ( o->o_msgid == id )
- break;
+ if ( o->o_msgid == id ) {
+ ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
+ o->o_abandon = 1;
+ ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
+
+ notfound = 0;
+ goto done;
+ }
+ }
+
+ for ( oo = &conn->c_pending_ops;
+ (*oo != NULL) && ((*oo)->o_msgid != id);
+ oo = &(*oo)->o_next )
+ {
+ /* EMPTY */ ;
}
- if ( o != NULL ) {
- pthread_mutex_lock( &o->o_abandonmutex );
- o->o_abandon = 1;
- pthread_mutex_unlock( &o->o_abandonmutex );
- } else {
- Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0,
- 0 );
+ if( *oo != NULL ) {
+ o = *oo;
+ *oo = (*oo)->o_next;
+ slap_op_free( o );
+ notfound = 0;
}
- pthread_mutex_unlock( &conn->c_opsmutex );
+
+done:
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
+ id, notfound ? "not " : "", 0 );
+
+ return LDAP_SUCCESS;
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
-extern char *dn_normalize();
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/socket.h>
-extern char *default_referral;
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-extern int global_lastmod;
+#include "slap.h"
-static void add_created_attrs();
+static void add_created_attrs(Operation *op, Entry *e);
-void
-do_add( conn, op )
- Connection *conn;
- Operation *op;
+int
+do_add( Connection *conn, Operation *op )
{
BerElement *ber = op->o_ber;
char *dn, *last;
- unsigned long len, tag;
+ ber_len_t len;
+ ber_tag_t tag;
Entry *e;
Backend *be;
+ int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
+ "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the add request. It looks like this:
*
* }
*/
- e = (Entry *) ch_calloc( 1, sizeof(Entry) );
-
/* get the name */
- if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- return;
+ if ( ber_scanf( ber, "{a", /*}*/ &dn ) == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
e->e_dn = dn;
- dn = dn_normalize( strdup( dn ) );
- Debug( LDAP_DEBUG_ARGS, " do_add: dn (%s)\n", dn, 0, 0 );
+ e->e_ndn = dn_normalize_case( ch_strdup( dn ) );
+ e->e_private = NULL;
+
+ dn = NULL;
+
+ Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 );
/* get the attrs */
e->e_attrs = NULL;
struct berval **vals;
if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
- NULL, "decoding error" );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
entry_free( e );
- return;
+ return -1;
}
if ( vals == NULL ) {
Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type,
0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- NULL );
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "no values for type", NULL );
+ free( type );
entry_free( e );
- return;
+ return LDAP_PROTOCOL_ERROR;
}
attr_merge( e, type, vals );
ber_bvecfree( vals );
}
+ if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
+ entry_free( e );
+ Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ entry_free( e );
+ Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d ADD dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ conn->c_connid, op->o_opid, e->e_ndn, 0, 0 );
/*
* 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.
*/
- if ( (be = select_backend( dn )) == NULL ) {
+ be = select_backend( e->e_ndn );
+ if ( be == NULL ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ send_ldap_result( conn, op, LDAP_REFERRAL, NULL,
+ NULL, default_referral );
+ return rc;
}
/*
* 2) this backend is master for what it holds;
* 3) it's a replica and the dn supplied is the updatedn.
*/
- if ( be->be_add != NULL ) {
+ if ( be->be_add ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
- global_lastmod == ON) && be->be_updatedn == NULL ) {
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+ {
+ if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED &&
+ global_lastmod == ON)) && be->be_update_ndn == NULL ) {
+
add_created_attrs( op, e );
}
if ( (*be->be_add)( be, conn, op, e ) == 0 ) {
replog( be, LDAP_REQ_ADD, e->e_dn, e, 0 );
+ be_entry_release_w( be, e );
}
+
} else {
entry_free( e );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL,
+ NULL, default_referral );
}
} else {
+ Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 );
entry_free( e );
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
+
+ return rc;
}
static void
add_created_attrs( Operation *op, Entry *e )
{
- char buf[20];
+ char buf[22];
struct berval bv;
struct berval *bvals[2];
Attribute **a, **next;
Attribute *tmp;
struct tm *ltm;
+ time_t currenttime;
Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
/* remove any attempts by the user to add these attrs */
for ( a = &e->e_attrs; *a != NULL; a = next ) {
- if ( strcasecmp( (*a)->a_type, "createtimestamp" ) == 0
- || strcasecmp( (*a)->a_type, "creatorsname" ) == 0 ) {
+ if ( oc_check_no_usermod_attr( (*a)->a_type ) ) {
tmp = *a;
*a = (*a)->a_next;
attr_free( tmp );
}
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
- bv.bv_val = "NULLDN";
+ bv.bv_val = "<anonymous>";
bv.bv_len = strlen( bv.bv_val );
} else {
bv.bv_val = op->o_dn;
}
attr_merge( e, "creatorsname", bvals );
- pthread_mutex_lock( ¤ttime_mutex );
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_unlock( ¤ttime_mutex );
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
bv.bv_val = buf;
bv.bv_len = strlen( bv.bv_val );
--- /dev/null
+/* search.c - bdb2 backend search function */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static ID_BLOCK *base_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
+static ID_BLOCK *onelevel_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
+static ID_BLOCK *subtree_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
+
+#define GRABSIZE BUFSIZ
+
+#define MAKE_SPACE( n ) { \
+ if ( rcur + (n) > rbuf + rmaxsize ) { \
+ int offset = rcur - rbuf; \
+ rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
+ rmaxsize += GRABSIZE; \
+ rcur = rbuf + offset; \
+ } \
+}
+
+static int
+bdb2i_back_search_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int slimit,
+ int tlimit,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int err;
+ time_t stoptime;
+ ID_BLOCK *candidates;
+ ID id;
+ Entry *e;
+ Attribute *ref;
+ char *matched = NULL;
+ int rmaxsize, nrefs;
+ char *rbuf, *rcur;
+ int nentries = 0;
+ char *realBase;
+
+ Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
+
+ if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
+ tlimit = -1; /* allow root to set no limit */
+ } else {
+ tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
+ be->be_timelimit : tlimit;
+ stoptime = op->o_time + tlimit;
+ }
+ if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
+ slimit = -1; /* allow root to set no limit */
+ } else {
+ slimit = (slimit > be->be_sizelimit || slimit < 1) ?
+ be->be_sizelimit : slimit;
+ }
+
+ /*
+ * check and apply aliasing where the dereferencing applies to
+ * the subordinates of the base
+ */
+
+ switch ( deref ) {
+ case LDAP_DEREF_FINDING:
+ case LDAP_DEREF_ALWAYS:
+ realBase = bdb2i_derefDN ( be, conn, op, base );
+ break;
+ default:
+ realBase = ch_strdup(base);
+ }
+
+ (void) dn_normalize_case( realBase );
+
+ Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
+ realBase, 0, 0 );
+
+ switch ( scope ) {
+ case LDAP_SCOPE_BASE:
+ candidates = base_candidates( be, conn, op, realBase, filter,
+ attrs, attrsonly, &matched, &err );
+ break;
+
+ case LDAP_SCOPE_ONELEVEL:
+ candidates = onelevel_candidates( be, conn, op, realBase, filter,
+ attrs, attrsonly, &matched, &err );
+ break;
+
+ case LDAP_SCOPE_SUBTREE:
+ candidates = subtree_candidates( be, conn, op, realBase, filter,
+ attrs, attrsonly, &matched, NULL, &err, 1 );
+ break;
+
+ default:
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
+ "Bad scope" );
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( -1 );
+ }
+
+ /* null candidates means we could not find the base object */
+ if ( candidates == NULL ) {
+ send_ldap_result( conn, op, err, matched, "" );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( -1 );
+ }
+
+ if ( matched != NULL ) {
+ free( matched );
+ }
+
+ rmaxsize = 0;
+ nrefs = 0;
+ rbuf = rcur = NULL;
+ MAKE_SPACE( sizeof("Referral:") + 1 );
+ strcpy( rbuf, "Referral:" );
+ rcur = strchr( rbuf, '\0' );
+ for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
+ id = bdb2i_idl_nextid( candidates, id ) ) {
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ bdb2i_idl_free( candidates );
+ free( rbuf );
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( 0 );
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* check time limit */
+ if ( tlimit != -1 && slap_get_time() > stoptime ) {
+ send_search_result( conn, op,
+ LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
+ NULL, nentries );
+ bdb2i_idl_free( candidates );
+ free( rbuf );
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( 0 );
+ }
+
+ /* get the entry with reader lock */
+ if ( (e = bdb2i_id2entry_r( be, id )) == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
+ id, 0, 0 );
+ continue;
+ }
+
+ /*
+ * if it's a referral, add it to the list of referrals. only do
+ * this for subtree searches, and don't check the filter explicitly
+ * here since it's only a candidate anyway.
+ */
+ if ( scope == LDAP_SCOPE_SUBTREE &&
+ e->e_ndn != NULL &&
+ strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
+ (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+ {
+ int i;
+
+ if ( ref->a_vals == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
+ e->e_dn, 0, 0 );
+ } else {
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
+ /* referral + newline + null */
+ MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
+ *rcur++ = '\n';
+ strncpy( rcur, ref->a_vals[i]->bv_val,
+ ref->a_vals[i]->bv_len );
+ rcur = rcur + ref->a_vals[i]->bv_len;
+ *rcur = '\0';
+ nrefs++;
+ }
+ } else {
+ send_search_reference( conn, op, ref->a_vals );
+ }
+ }
+
+ /* otherwise it's an entry - see if it matches the filter */
+ } else {
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ int scopeok;
+ char *dn;
+
+ /* check scope */
+ scopeok = 1;
+ if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realBase)
+ ? 1
+ : (strcmp( dn, realBase ) ? 0 : 1 );
+ free( dn );
+ } else {
+ scopeok = (realBase == NULL || *realBase == '\0');
+ }
+ } else if ( scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realBase );
+ free( dn );
+ }
+
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL,
+ nrefs > 0 ? rbuf : NULL, nentries );
+ bdb2i_idl_free( candidates );
+ free( rbuf );
+
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( 0 );
+ }
+
+ /*
+ * check and apply aliasing where the dereferencing applies to
+ * the subordinates of the base
+ */
+ switch ( deref ) {
+ case LDAP_DEREF_SEARCHING:
+ case LDAP_DEREF_ALWAYS:
+ {
+ Entry *newe = bdb2i_derefAlias_r( be, conn, op, e );
+ if ( newe == NULL ) { /* problem with the alias */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ e = NULL;
+ }
+ else if ( newe != e ) { /* reassign e */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ e = newe;
+ }
+ }
+ break;
+ }
+
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, 0 ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ bdb2i_idl_free( candidates );
+ free( rbuf );
+
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( 0 );
+ }
+ }
+ }
+ }
+ }
+
+ if( e != NULL ) {
+ /* free reader lock */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ }
+
+ ldap_pvt_thread_yield();
+ }
+ bdb2i_idl_free( candidates );
+ if ( nrefs > 0 ) {
+ send_search_result( conn, op, LDAP_REFERRALS, NULL,
+ rbuf, nentries );
+ } else {
+ send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
+ nentries );
+ }
+ free( rbuf );
+
+ if( realBase != NULL) {
+ free( realBase );
+ }
+
+ return( 0 );
+}
+
+
+int
+bdb2_back_search(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int slimit,
+ int tlimit,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ return( -1 );
+
+ }
+
+ ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref,
+ slimit, tlimit, filter, filterstr, attrs, attrsonly );
+
+ (void) bdb2i_leave_backend_r( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "SRCH", conn, op );
+
+ return( ret );
+}
+
+
+static ID_BLOCK *
+base_candidates(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ Filter *filter,
+ char **attrs,
+ int attrsonly,
+ char **matched,
+ int *err
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID_BLOCK *idl;
+ Entry *e;
+
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
+
+ *err = LDAP_SUCCESS;
+
+ /* get entry with reader lock */
+ if ( (e = bdb2i_dn2entry_r( be, base, matched )) == NULL ) {
+ *err = LDAP_NO_SUCH_OBJECT;
+ return( NULL );
+ }
+
+ /* check for deleted */
+
+ idl = bdb2i_idl_alloc( 1 );
+ bdb2i_idl_insert( &idl, e->e_id, 1 );
+
+
+ /* free reader lock */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ return( idl );
+}
+
+static ID_BLOCK *
+onelevel_candidates(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ Filter *filter,
+ char **attrs,
+ int attrsonly,
+ char **matched,
+ int *err
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e = NULL;
+ Filter *f;
+ char buf[20];
+ ID_BLOCK *candidates;
+
+ Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+
+ *err = LDAP_SUCCESS;
+
+ /* get the base object with reader lock */
+ if ( base != NULL && *base != '\0' &&
+ (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
+ {
+ *err = LDAP_NO_SUCH_OBJECT;
+ return( NULL );
+ }
+
+ /*
+ * modify the filter to be something like this:
+ *
+ * parent=baseobject & originalfilter
+ */
+
+ f = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_next = NULL;
+ f->f_choice = LDAP_FILTER_AND;
+ f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_and->f_choice = LDAP_FILTER_EQUALITY;
+ f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+ sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+ f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+ f->f_and->f_ava.ava_value.bv_len = strlen( buf );
+ f->f_and->f_next = filter;
+
+ /* from here, it's just like subtree_candidates */
+ candidates = subtree_candidates( be, conn, op, base, f, attrs,
+ attrsonly, matched, e, err, 0 );
+
+ /* free up just the filter stuff we allocated above */
+ f->f_and->f_next = NULL;
+ filter_free( f );
+
+ /* free entry and reader lock */
+ if( e != NULL ) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ }
+ return( candidates );
+}
+
+static ID_BLOCK *
+subtree_candidates(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ Filter *filter,
+ char **attrs,
+ int attrsonly,
+ char **matched,
+ Entry *e,
+ int *err,
+ int lookupbase
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Filter *f, **filterarg_ptr;
+ ID_BLOCK *candidates;
+
+ Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
+ base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
+
+ /*
+ * get the base object - unless we already have it (from one-level).
+ * also, unless this is a one-level search or a subtree search
+ * starting at the very top of our subtree, we need to modify the
+ * filter to be something like this:
+ *
+ * dn=*baseobjectdn & (originalfilter | ref=*)
+ *
+ * the "objectclass=referral" part is used to select referrals to return
+ */
+
+ *err = LDAP_SUCCESS;
+ f = NULL;
+ if ( lookupbase ) {
+ e = NULL;
+
+ if ( base != NULL && *base != '\0' &&
+ (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
+ {
+ *err = LDAP_NO_SUCH_OBJECT;
+ return( NULL );
+ }
+
+ if (e) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ }
+
+ f = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_next = NULL;
+ f->f_choice = LDAP_FILTER_OR;
+ f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ f->f_or->f_avtype = ch_strdup( "objectclass" );
+ /* Patch to use normalized uppercase */
+ f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
+ filterarg_ptr = &f->f_or->f_next;
+ *filterarg_ptr = filter;
+ filter = f;
+
+ if ( ! be_issuffix( be, base ) ) {
+ f = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_next = NULL;
+ f->f_choice = LDAP_FILTER_AND;
+ f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+ f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+ f->f_and->f_sub_type = ch_strdup( "dn" );
+ f->f_and->f_sub_initial = NULL;
+ f->f_and->f_sub_any = NULL;
+ f->f_and->f_sub_final = ch_strdup( base );
+ value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
+ f->f_and->f_next = filter;
+ filter = f;
+ }
+ }
+
+ candidates = bdb2i_filter_candidates( be, filter );
+
+ /* free up just the parts we allocated above */
+ if ( f != NULL ) {
+ *filterarg_ptr = NULL;
+ filter_free( f );
+ }
+
+ return( candidates );
+}
--- /dev/null
+/* search.c - ldap backend search function */
+
+/*
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits should appear in the documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "slap.h"
+#include "back-ldap.h"
+
+int
+ldap_back_search(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int size,
+ int time,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ struct ldapinfo *li = (struct ldapinfo *) be->be_private;
+ struct ldapconn *lc;
+ struct timeval tv;
+ LDAPMessage *res, *e;
+ int i, rc, msgid, sres = LDAP_SUCCESS;
+ char *match = NULL, *err = NULL;
+
+ lc = ldap_back_getconn(li, conn, op);
+ if (!lc)
+ return( -1 );
+
+ if (deref != -1)
+ ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
+ if (time != -1)
+ ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
+ if (size != -1)
+ ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
+ if (!lc->bound) {
+ ldap_back_dobind(lc, op);
+ if (!lc->bound)
+ return( -1 );
+ }
+
+ if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
+ attrsonly)) == -1)
+fail: return( ldap_back_op_result(lc, op) );
+
+ /* We pull apart the ber result, stuff it into a slapd entry, and
+ * let send_search_entry stuff it back into ber format. Slow & ugly,
+ * but this is necessary for version matching, and for ACL processing.
+ */
+
+ for (i=0, rc=0; rc != -1;
+ rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) {
+ int ab;
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ ab = op->o_abandon;
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ if (ab) {
+ ldap_abandon(lc->ld, msgid);
+ } else if (rc == 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ ldap_pvt_thread_yield();
+ continue;
+ } else if (rc == LDAP_RES_SEARCH_ENTRY) {
+ e = ldap_first_entry(lc->ld,res);
+ ldap_send_entry(be, op, lc, e, attrs, attrsonly);
+ i++;
+ } else {
+ sres = ldap_result2error(lc->ld, res, 1);
+ ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err);
+ ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
+ rc = 0;
+ }
+ ldap_msgfree(res);
+ if (ab)
+ return (0);
+ else if (rc == 0)
+ break;
+ }
+
+ if (rc == -1)
+ goto fail;
+
+ send_search_result( conn, op, sres, match, err, i );
+ if (match)
+ free(match);
+ if (err)
+ free(err);
+ return( 0 );
+}
+
+ldap_send_entry(
+ Backend *be,
+ Operation *op,
+ struct ldapconn *lc,
+ LDAPMessage *e,
+ char **attrs,
+ int attrsonly
+)
+{
+ char *a;
+ Entry ent;
+ BerElement *ber = NULL;
+ Attribute *attr;
+ struct berval *dummy = NULL;
+
+ ent.e_dn = ldap_get_dn(lc->ld, e);
+ ent.e_ndn = dn_normalize_case( ch_strdup( ent.e_dn));
+ ent.e_id = 0;
+ ent.e_attrs = 0;
+ ent.e_private = 0;
+ attr = (Attribute *)4;
+ attr = (Attribute *)((long)&ent.e_attrs - ((long)&attr->a_next-4));
+
+ for (a = ldap_first_attribute(lc->ld, e, &ber); a;
+ a = ldap_next_attribute(lc->ld, e, ber)) {
+ attr->a_next = (Attribute *)ch_malloc( sizeof(Attribute) );
+ attr=attr->a_next;
+ attr->a_next = 0;
+ attr->a_type = ch_strdup(a);
+ attr->a_syntax = attr_syntax(a);
+ attr->a_vals = ldap_get_values_len(lc->ld, e, a);
+ if (!attr->a_vals)
+ attr->a_vals = &dummy;
+ }
+ send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0 );
+ for (;ent.e_attrs;) {
+ attr=ent.e_attrs;
+ ent.e_attrs = attr->a_next;
+ free(attr->a_type);
+ if (attr->a_vals != &dummy)
+ ber_bvecfree(attr->a_vals);
+ free(attr);
+ }
+ if (ber)
+ ber_free(ber,0);
+}
/* add.c - ldap ldbm back-end add routine */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern int global_schemacheck;
-extern char *dn_parent();
-extern char *dn_normalize();
-extern Entry *dn2entry();
+#include "proto-back-ldbm.h"
int
ldbm_back_add(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
- char *dn = NULL, *pdn = NULL;
- Entry *p;
-
- dn = dn_normalize( strdup( e->e_dn ) );
- matched = NULL;
- if ( (p = dn2entry( be, dn, &matched )) != NULL ) {
- cache_return_entry( &li->li_cache, p );
+ char *pdn;
+ Entry *p = NULL;
+ int rootlock = 0;
+ int rc;
+
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
+
+ /* nobody else can add until we lock our parent */
+ ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
+
+ if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL );
return( -1 );
}
- if ( matched != NULL ) {
- free( matched );
- }
- /* XXX race condition here til we cache_add_entry_lock below XXX */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
- Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0,
- 0 );
- entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
- "" );
- return( -1 );
- }
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
- /*
- * Try to add the entry to the cache, assign it a new dnid
- * and mark it locked. This should only fail if the entry
- * already exists.
- */
+ Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
+ 0, 0, 0 );
- e->e_id = next_id( be );
- if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING )
- != 0 ) {
- Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
- 0 );
- next_id_return( be, e->e_id );
entry_free( e );
- free( dn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL );
return( -1 );
}
* add the entry.
*/
- if ( (pdn = dn_parent( be, dn )) != NULL ) {
- /* no parent */
- matched = NULL;
- if ( (p = dn2entry( be, pdn, &matched )) == NULL ) {
+ pdn = dn_parent( be, e->e_ndn );
+
+ if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
+ char *matched = NULL;
+
+ assert( *pdn != '\0' );
+
+ /* get parent with writer lock */
+ if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
+ 0, 0 );
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, "" );
+ matched, NULL, NULL );
+
if ( matched != NULL ) {
free( matched );
}
- Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
- 0, 0 );
- goto error_return;
+
+ entry_free( e );
+ free( pdn );
+ return -1;
}
+
+ /* don't need the add lock anymore */
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+
+ free(pdn);
+
if ( matched != NULL ) {
free( matched );
}
- if ( ! access_allowed( be, conn, op, p, "children", NULL,
- op->o_dn, ACL_WRITE ) ) {
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
- goto error_return;
+ NULL, NULL, NULL );
+
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
+ entry_free( e );
+ return -1;
}
+
} else {
- if ( ! be_isroot( be, op->o_dn ) ) {
- Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0,
- 0, 0 );
+ if(pdn != NULL) {
+ assert( *pdn == '\0' );
+ free(pdn);
+ }
+
+ /* no parent, must be adding entry to root */
+ if ( ! be_isroot( be, op->o_ndn ) ) {
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+
+ Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
+ pdn == NULL ? "suffix" : "entry at root",
+ 0, 0 );
+
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
- goto error_return;
+ NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+ /*
+ * no parent, acquire the root write lock
+ * and release the add lock.
+ */
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
+ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
+ }
+
+ e->e_id = next_id( be );
+
+ /*
+ * Try to add the entry to the cache, assign it a new dnid.
+ */
+ rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
+
+ if ( rc != 0 ) {
+ if( p != NULL) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
+ 0 );
+
+ /* return the id */
+ next_id_return( be, e->e_id );
+
+ /* free the entry */
+ entry_free( e );
+
+ if(rc > 0) {
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ } else {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
}
- p = NULL;
+
+ return( -1 );
}
+ rc = -1;
+
/*
* add it to the id2children index for the parent
*/
if ( id2children_add( be, p, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
- "" );
- goto error_return;
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ goto return_results;
}
/*
if ( index_add_entry( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ goto return_results;
}
/* dn2id index */
- if ( dn2id_add( be, dn, e->e_id ) != 0 ) {
+ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ goto return_results;
}
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
0, 0 );
- (void) dn2id_delete( be, dn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- goto error_return;
+ (void) dn2id_delete( be, e->e_ndn );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ goto return_results;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if (p != NULL) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ if ( rc ) {
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
}
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
- if ( dn != NULL )
- free( dn );
- if ( pdn != NULL )
- free( pdn );
- cache_set_state( &li->li_cache, e, 0 );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
-
-error_return:;
- if ( dn != NULL )
- free( dn );
- if ( pdn != NULL )
- free( pdn );
- next_id_return( be, e->e_id );
- cache_delete_entry( &li->li_cache, e );
- cache_return_entry( &li->li_cache, e );
-
- return( -1 );
+ return( rc );
}
--- /dev/null
+/*
+ * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to ITSD, Government of BC. The name of ITSD
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+/*
+ * given an alias object, dereference it to its end point.
+ * Entry returned has reader lock or is NULL. Starting entry is not released.
+ */
+Entry *derefAlias_r ( Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private; /* to free cache entries */
+ Attribute *a;
+ int depth;
+ char *matched;
+ Entry *origDN = e;
+
+ if (!e) return NULL; /* be sure we have a starting entry */
+
+ Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
+
+ /*
+ * try to deref fully, up to a maximum depth. If the max depth exceeded
+ * then send an error
+ */
+ for ( depth = 0;
+ ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
+ ( depth < be->be_maxDerefDepth );
+ ++depth)
+ {
+
+ /*
+ * make sure there is a defined aliasedobjectname.
+ * can only have one value so just use first value (0) in the attr list.
+ */
+ if (a->a_vals[0] && a->a_vals[0]->bv_val) {
+ char *newDN, *oldDN;
+
+ Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
+ e->e_dn, a->a_vals[0]->bv_val, 0 );
+ newDN = ch_strdup (a->a_vals[0]->bv_val);
+ oldDN = ch_strdup (e->e_ndn);
+
+ /*
+ * release past lock if not original
+ */
+ if ( (depth > 0) && e ) {
+ cache_return_entry_r(&li->li_cache, e);
+ }
+
+ /* make sure new and old DN are not same to avoid loops */
+ dn_normalize_case (newDN);
+ if ( strcmp (newDN, oldDN) == 0 ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s alias is same as current %s\n",
+ oldDN, newDN, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "circular alias", NULL );
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ /* make sure new and original are not same to avoid deadlocks */
+ if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s alias is same as original %s\n",
+ oldDN, origDN->e_ndn, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "circular alias", NULL );
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ /*
+ * ok, so what happens if there is an alias in the DN of a dereferenced
+ * alias object?
+ */
+ if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) {
+
+ /* could not deref return error */
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s is a dangling alias to %s\n",
+ oldDN, newDN, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "dangling alias", NULL );
+
+ if (matched != NULL) free(matched);
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ free (newDN);
+ free (oldDN);
+ }
+ else {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ * this can't happen, right?
+ */
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s has no data in aliasedobjectname attribute\n",
+ (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, "alias missing aliasedObjectName", NULL );
+ break;
+ }
+ }
+
+ /*
+ * warn if we pulled out due to exceeding the maximum deref depth
+ */
+ if ( depth >= be->be_maxDerefDepth ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
+ origDN->e_dn ? origDN->e_dn : "(null)",
+ be->be_maxDerefDepth,
+ (e && e->e_ndn) ? e->e_ndn : "(null)");
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "maximum alias dereference depth exceeded", NULL );
+ }
+
+ return e;
+}
+
+/*
+ * given a DN fully deref it and return the real DN or original DN if it fails
+ * This involves finding the last matched part then reconstructing forward
+ * e.g.
+ * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
+ * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
+ * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
+ * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
+ * remainder is ou=MyOU
+ * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
+ * release lock on o=MyAliasedOrg,c=MyCountry entry
+ * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
+ * release lock on o=MyOrg,c=MyCountry entry
+ */
+char *derefDN ( Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched = 0;
+ char *newDN = NULL;
+ int depth, i;
+ Entry *eMatched;
+ Entry *eDeref;
+ Entry *eNew;
+
+ if (!dn) return NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "<= dereferencing dn: \"%s\"\n",
+ dn, 0, 0 );
+
+ newDN = ch_strdup ( dn );
+
+ /* while we don't have a matched dn, deref the DN */
+ for ( depth = 0;
+ ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) &&
+ (depth < be->be_maxDerefDepth);
+ ++depth ) {
+
+ if ((matched != NULL) && *matched) {
+ char *submatch;
+
+ /*
+ * make sure there actually is an entry for the matched part
+ */
+ if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) {
+ char *remainder; /* part before the aliased part */
+ int rlen = strlen(newDN) - strlen(matched);
+
+ Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
+
+ remainder = ch_malloc (rlen + 1);
+ strncpy ( remainder, newDN, rlen );
+ remainder[rlen] = '\0';
+
+ Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
+
+ if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) {
+ free (matched);
+ matched = NULL;
+ free (newDN);
+ newDN = NULL;
+ free (remainder);
+ remainder = NULL;
+
+ cache_return_entry_r(&li->li_cache, eMatched);
+ eMatched = NULL;
+ break; /* no associated entry, dont deref */
+ }
+ else {
+
+ Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
+
+ i = strcasecmp (matched, eNew->e_dn);
+ /* free reader lock */
+ cache_return_entry_r(&li->li_cache, eNew);
+
+ free (matched);
+ matched = NULL;
+
+ if (! i) {
+ /* newDN same as old so not an alias, no need to go further */
+ free (newDN);
+ newDN = NULL;
+ free (remainder);
+
+ cache_return_entry_r(&li->li_cache, eMatched);
+ eMatched = NULL;
+ break;
+ }
+
+ /*
+ * we have dereferenced the aliased part so put
+ * the new dn together
+ */
+ free (newDN);
+ newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
+ strcpy (newDN, remainder);
+ strcat (newDN, eMatched->e_dn);
+ Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
+
+ free (remainder);
+ }
+ /* free reader lock */
+ cache_return_entry_r(&li->li_cache, eMatched);
+ }
+ else {
+ if(submatch != NULL) free(submatch);
+ break; /* there was no entry for the matched part */
+ }
+ }
+ else {
+ break; /* there was no matched part */
+ }
+ }
+
+ /* release lock if a match terminated the loop, there should be no
+ * outstanding locks at this point
+ */
+ if(eMatched != NULL) {
+ /* free reader lock */
+ cache_return_entry_r(&li->li_cache, eMatched);
+ }
+
+ /*
+ * the final part of the DN might be an alias so try to dereference it.
+ * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
+ * and the above loop complete but we would still be left with an aliased DN.
+ */
+ if (newDN != NULL) {
+ if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) {
+ if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) {
+ free (newDN);
+ newDN = ch_strdup (eDeref->e_dn);
+ /* free reader lock */
+ cache_return_entry_r(&li->li_cache, eDeref);
+ }
+ /* free reader lock */
+ cache_return_entry_r(&li->li_cache, eNew);
+ }
+ }
+ if (matched != NULL) free(matched);
+
+ /*
+ * warn if we exceeded the max depth as the resulting DN may not be dereferenced
+ */
+ if (depth >= be->be_maxDerefDepth) {
+ if (newDN) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
+ dn, newDN, 0 );
+ free (newDN);
+ newDN = NULL;
+ }
+ else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
+ dn, 0, 0 );
+ }
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "maximum alias dereference depth exceeded for base", NULL );
+ }
+
+ if (newDN == NULL) {
+ newDN = ch_strdup ( dn );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
+
+ return newDN;
+}
/* bind.c - ldbm backend bind and unbind routines */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
#include "slap.h"
#include "back-ldbm.h"
-#ifdef KERBEROS
-#include "krb.h"
-#endif
+#include "proto-back-ldbm.h"
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include <lutil.h>
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
extern int krbv4_ldap_auth();
#endif
+static int
+crypted_value_find(
+ struct berval **vals,
+ struct berval *v,
+ int syntax,
+ int normalize,
+ struct berval *cred
+)
+{
+ int i;
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ if ( syntax != SYNTAX_BIN ) {
+ int result;
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
+#endif
+
+ result = lutil_passwd(
+ (char*) cred->bv_val,
+ (char*) vals[i]->bv_val,
+ NULL );
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+#endif
+
+ return result;
+
+ } else {
+ if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
+ return( 0 );
+ }
+ }
+ }
+
+ return( 1 );
+}
+
int
ldbm_back_bind(
Backend *be,
Operation *op,
char *dn,
int method,
- struct berval *cred
+ char *mech,
+ struct berval *cred,
+ char** edn
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Entry *e;
Attribute *a;
int rc;
- char *matched = NULL;
-#ifdef KERBEROS
+ char *matched;
+#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
#endif
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn, 0, 0);
+
+ *edn = NULL;
+
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
/* allow noauth binds */
- if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
- /*
- * bind successful, but return 1 so we don't
- * authorize based on noauth credentials
- */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- rc = 1;
- } else if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- rc = 0;
+ rc = 1;
+ if ( method == LDAP_AUTH_SIMPLE ) {
+ if( cred->bv_len == 0 ) {
+ /* SUCCESS */
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+
+ } else if ( be_isroot_pw( be, dn, cred ) ) {
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0; /* front end will send result */
+
+ } else {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ }
+
+ } else if ( method == LDAP_AUTH_SASL ) {
+ if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
+ /* insert DIGEST calls here */
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL );
+ }
+
} else {
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL );
- rc = 1;
+ matched, NULL, NULL );
}
+
if ( matched != NULL ) {
free( matched );
}
return( rc );
}
+ *edn = ch_strdup( e->e_dn );
+
+ /* check for deleted */
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
switch ( method ) {
case LDAP_AUTH_SIMPLE:
if ( cred->bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return( 1 );
- } else if ( be_isroot_pw( be, dn, cred ) ) {
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+ }
+
+ /* check for root dn/passwd */
+ if ( be_isroot_pw( be, dn, cred ) ) {
/* front end will send result */
- return( 0 );
+ if(*edn != NULL) free( *edn );
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0;
+ goto return_results;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "userpassword", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
- }
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL );
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
}
- if ( value_find( a->a_vals, cred, a->a_syntax, 0 ) != 0 ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
- }
+ if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
+ {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, NULL, NULL );
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
}
+
+ rc = 0;
break;
-#ifdef KERBEROS
+#ifdef HAVE_KERBEROS
case LDAP_AUTH_KRBV41:
+ if ( ! access_allowed( be, conn, op, e,
+ "krbname", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "krbname", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ rc = 1;
+ goto return_results;
}
+
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
: "", ad.pinst, ad.prealm );
+
+
if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
/*
* no krbName values present: check against DN
*/
if ( strcasecmp( dn, krbname ) == 0 ) {
+ rc = 0;
break;
}
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ rc = 1;
+ goto return_results;
+
} else { /* look for krbName match */
struct berval krbval;
krbval.bv_val = krbname;
krbval.bv_len = strlen( krbname );
- if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 )
- != 0 ) {
+ if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
send_ldap_result( conn, op,
LDAP_INVALID_CREDENTIALS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ rc = 1;
+ goto return_results;
}
}
+ rc = 0;
break;
case LDAP_AUTH_KRBV42:
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
#endif
+ case LDAP_AUTH_SASL:
+ /* insert SASL code here */
+
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "auth method not supported" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ NULL, "auth method not supported", NULL );
+ rc = 1;
+ goto return_results;
}
- cache_return_entry( &li->li_cache, e );
+return_results:;
+ /* free entry and reader lock */
+ cache_return_entry_r( &li->li_cache, e );
- /* success: front end will send result */
- return( 0 );
+ /* front end with send result on success (rc==0) */
+ return( rc );
}
+
/* compare.c - ldbm backend compare routine */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include "proto-back-ldbm.h"
int
ldbm_back_compare(
char *matched;
Entry *e;
Attribute *a;
- int i;
+ int rc;
+
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ if(matched == NULL) free(matched);
return( 1 );
}
- if ( ! access_allowed( be, conn, op, e, ava->ava_type, &ava->ava_value,
- op->o_dn, ACL_COMPARE ) ) {
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ /* check for deleted */
+ if ( ! access_allowed( be, conn, op, e,
+ ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
}
- if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 ) {
- send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
- }
+ if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+ NULL, NULL, NULL );
+ else
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+ NULL, NULL, NULL );
+
+ rc = 0;
- send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( 0 );
+return_results:;
+ cache_return_entry_r( &li->li_cache, e );
+ return( rc );
}
/* delete.c - ldbm backend delete routine */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+#include "proto-back-ldbm.h"
int
ldbm_back_delete(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
- Entry *e;
+ char *matched = NULL;
+ char *pdn = NULL;
+ Entry *e, *p = NULL;
+ int rootlock = 0;
+ int rc = -1;
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0);
+
+ /* get entry with writer lock */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
if ( matched != NULL ) {
free( matched );
}
return( -1 );
}
+ /* check for deleted */
+
if ( has_children( be, e ) ) {
- send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
- "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL );
+ goto return_results;
}
- if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
- ACL_WRITE ) ) {
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: insufficient access %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+#endif
+
+ /* delete from parent's id2children entry */
+ if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
+ if( (p = dn2entry_w( be, pdn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: parent does not exist\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ } else {
+ /* no parent, must be root to delete */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- ldbm_back_delete: no parent & not root\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
}
- /* XXX delete from parent's id2children entry XXX */
+ if ( id2children_remove( be, p, e ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
/* delete from dn2id mapping */
- if ( dn2id_delete( be, e->e_dn ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
}
/* delete from disk and cache */
if ( id2entry_delete( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- ldbm_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
}
- cache_return_entry( &li->li_cache, e );
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if ( pdn != NULL ) free(pdn);
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
+ }
+
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
+
+ if ( matched != NULL ) free(matched);
- return( 0 );
+ return rc;
}
/* modify.c - ldbm backend modify routine */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
#include "slap.h"
#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
-extern int global_schemacheck;
-extern Entry *dn2entry();
-extern Attribute *attr_find();
+static void add_lastmods(Operation *op, LDAPModList **ml);
-static int add_values();
-static int delete_values();
-static int replace_values();
-int
-ldbm_back_modify(
+static void
+add_lastmods( Operation *op, LDAPModList **modlist )
+{
+ char buf[22];
+ struct berval bv;
+ struct berval *bvals[2];
+ LDAPModList **m;
+ LDAPModList *tmp;
+ struct tm *ltm;
+ time_t currenttime;
+
+ Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
+
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ /* remove any attempts by the user to modify these attrs */
+ for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) {
+ if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "add_lastmods: found no user mod attr: %s\n",
+ (*m)->ml_type, 0, 0 );
+ tmp = *m;
+ *m = (*m)->ml_next;
+ free( tmp->ml_type );
+ if ( tmp->ml_bvalues != NULL ) {
+ ber_bvecfree( tmp->ml_bvalues );
+ }
+ free( tmp );
+ if (!*m)
+ break;
+ }
+ }
+
+ if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
+ bv.bv_val = "NULLDN";
+ bv.bv_len = strlen( bv.bv_val );
+ } else {
+ bv.bv_val = op->o_dn;
+ bv.bv_len = strlen( bv.bv_val );
+ }
+ tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ tmp->ml_type = ch_strdup( "modifiersname" );
+ tmp->ml_op = LDAP_MOD_REPLACE;
+ tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ tmp->ml_bvalues[0] = ber_bvdup( &bv );
+ tmp->ml_next = *modlist;
+ *modlist = tmp;
+
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
+ bv.bv_val = buf;
+ bv.bv_len = strlen( bv.bv_val );
+ tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ tmp->ml_type = ch_strdup( "modifytimestamp" );
+ tmp->ml_op = LDAP_MOD_REPLACE;
+ tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ tmp->ml_bvalues[0] = ber_bvdup( &bv );
+ tmp->ml_next = *modlist;
+ *modlist = tmp;
+
+}
+
+/* We need this function because of LDAP modrdn. If we do not
+ * add this there would be a bunch of code replication here
+ * and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ */
+
+int ldbm_modify_internal(
Backend *be,
Connection *conn,
Operation *op,
char *dn,
- LDAPMod *mods
+ LDAPModList *modlist,
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
- Entry *e;
- int i, err, modtype;
+ int err;
LDAPMod *mod;
+ LDAPModList *ml;
+ Attribute *a;
+
+ if ( ((be->be_lastmod == ON)
+ || ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
+ && (be->be_update_ndn == NULL)) {
+
+ /* XXX: It may be wrong, it changes mod time even if
+ * mod fails!
+ */
+ add_lastmods( op, &modlist );
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
- NULL );
- if ( matched != NULL ) {
- free( matched );
- }
- return( -1 );
}
- /* lock entry */
- if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
- send_ldap_result( conn, op, err, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+
+ if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
+ != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ return -1;
}
- for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+
+ mod = &ml->ml_mod;
+
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
- err = add_values( e, mod, op->o_dn );
+ err = add_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_DELETE:
- err = delete_values( e, mod, op->o_dn );
+ err = delete_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_REPLACE:
- err = replace_values( e, mod, op->o_dn );
+ /* Need to remove all values from indexes before they
+ * are lost.
+ */
+ if( e->e_attrs
+ && ((a = attr_find( e->e_attrs, mod->mod_type ))
+ != NULL) ) {
+
+ (void) index_change_values( be,
+ mod->mod_type,
+ a->a_vals,
+ e->e_id,
+ __INDEX_DELETE_OP);
+ }
+
+ err = replace_values( e, mod, op->o_ndn );
break;
+
+ case LDAP_MOD_SOFTADD:
+ /* Avoid problems in index_add_mods()
+ * We need to add index if necessary.
+ */
+ mod->mod_op = LDAP_MOD_ADD;
+ if ( (err = add_values( e, mod, op->o_ndn ))
+ == LDAP_TYPE_OR_VALUE_EXISTS ) {
+
+ err = LDAP_SUCCESS;
+ mod->mod_op = LDAP_MOD_SOFTADD;
+
+ }
+ break;
}
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ return -1;
}
}
- /* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
- if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
- }
- pthread_mutex_unlock( &op->o_abandonmutex );
-
/* check that the entry still obeys the schema */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL,
- NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL );
+ return -1;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return -1;
}
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* modify indexes */
- if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return -1;
}
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- cache_return_entry( &li->li_cache, e );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ return -1;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ return 0;
+
+}/* int ldbm_modify_internal() */
+
+
+int
+ldbm_back_modify(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched;
+ Entry *e;
+
+ Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
+
+ /* acquire and lock entry */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ if ( matched != NULL ) {
+ free( matched );
+ }
return( -1 );
}
- pthread_mutex_unlock( &op->o_abandonmutex );
+
+ /* Modify the entry */
+ if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) {
+ goto error_return;
+ }
/* change the entry itself */
if ( id2entry_add( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto error_return;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
-
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+ cache_return_entry_w( &li->li_cache, e );
return( 0 );
+
+error_return:;
+ cache_return_entry_w( &li->li_cache, e );
+ return( -1 );
}
-static int
+int
add_values(
Entry *e,
LDAPMod *mod,
return( LDAP_SUCCESS );
}
-static int
+int
delete_values(
Entry *e,
LDAPMod *mod,
return( LDAP_SUCCESS );
}
-static int
+int
replace_values(
Entry *e,
LDAPMod *mod,
char *dn
)
{
+
+ /* XXX: BEFORE YOU GET RID OF PREVIOUS VALUES REMOVE FROM INDEX
+ * FILES
+ */
+
(void) attr_delete( &e->e_attrs, mod->mod_type );
if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
/* modrdn.c - ldbm backend modrdn routine */
+/*
+ * LDAP v3 newSuperior support. Add new rdn as an attribute.
+ * (Full support for v2 also used software/ideas contributed
+ * by Roy Hooper rhooper@cyberus.ca, thanks to him for his
+ * submission!.)
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
-
-extern Entry *dn2entry();
-extern char *dn_parent();
+#include "proto-back-ldbm.h"
int
ldbm_back_modrdn(
Operation *op,
char *dn,
char *newrdn,
- int deleteoldrdn
+ int deleteoldrdn,
+ char *newSuperior
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
- char *pdn, *newdn, *p;
- char sep[2];
- Entry *e, *e2;
-
- matched = NULL;
- if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char *matched = NULL;
+ char *p_dn = NULL, *p_ndn = NULL;
+ char *new_dn = NULL, *new_ndn = NULL;
+ Entry *e, *p = NULL;
+ int rootlock = 0;
+ int rc = -1;
+ /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
+ char *new_rdn_val = NULL; /* Val of new rdn */
+ char *new_rdn_type = NULL; /* Type of new rdn */
+ char *old_rdn; /* Old rdn's attr type & val */
+ char *old_rdn_type = NULL; /* Type of old rdn attr. */
+ char *old_rdn_val = NULL; /* Old rdn attribute value */
+ /* Added to support newSuperior */
+ Entry *np = NULL; /* newSuperior Entry */
+ char *np_dn = NULL; /* newSuperior dn */
+ char *np_ndn = NULL; /* newSuperior ndn */
+ char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
+ /* Used to interface with ldbm_modify_internal() */
+ struct berval add_bv; /* Stores new rdn att */
+ struct berval *add_bvals[2]; /* Stores new rdn att */
+ struct berval del_bv; /* Stores old rdn att */
+ struct berval *del_bvals[2]; /* Stores old rdn att */
+ LDAPModList mod[2]; /* Used to delete old rdn */
+
+
+ Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
+ (newSuperior ? newSuperior : "NULL"),
+ 0, 0 );
+
+ /* get entry with writer lock */
+ if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
if ( matched != NULL ) {
free( matched );
}
return( -1 );
}
- if ( (pdn = dn_parent( be, dn )) != NULL ) {
- /* parent + rdn + separator(s) + null */
- newdn = (char *) ch_malloc( strlen( pdn ) + strlen( newrdn )
- + 3 );
- if ( dn_type( dn ) == DN_X500 ) {
- strcpy( newdn, newrdn );
- strcat( newdn, ", " );
- strcat( newdn, pdn );
- } else {
- strcpy( newdn, newrdn );
- p = strchr( newrdn, '\0' );
- p--;
- if ( *p != '.' && *p != '@' ) {
- if ( (p = strpbrk( dn, ".@" )) != NULL ) {
- sep[0] = *p;
- sep[1] = '\0';
- strcat( newdn, sep );
- }
- }
- strcat( newdn, pdn );
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ "", "" );
+ goto return_results;
+ }
+#endif
+
+ if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
+
+ /* Make sure parent entry exist and we can write its
+ * children.
+ */
+
+ if( (p = dn2entry_w( be, p_ndn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
}
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to children of entry %s OK\n",
+ p_ndn, 0, 0 );
+
+ p_dn = dn_parent( be, e->e_dn );
+
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
+ p_dn, 0, 0 );
+
} else {
- newdn = strdup( newrdn );
- }
- (void) dn_normalize( newdn );
+ /* no parent, modrdn entry directly under root */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
+ rootlock = 1;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no parent, locked root\n",
+ 0, 0, 0 );
+
+ }/* if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) else */
+
+ new_parent_dn = p_dn; /* New Parent unless newSuperior given */
+
+ if ( (np_dn = newSuperior) != NULL) {
+
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new parent requested...\n",
+ 0, 0, 0 );
+
+ np_ndn = dn_normalize_case( ch_strdup( np_dn ) );
+
+ /* newSuperior == oldParent?, if so ==> ERROR */
+
+ /* newSuperior == entry being moved?, if so ==> ERROR */
+
+ /* Get Entry with dn=newSuperior. Does newSuperior exist? */
+
+ if( (np = dn2entry_w( be, np_ndn, &matched )) == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
+ np_ndn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent OK np=%p, id=%d\n",
+ np, np->e_id, 0 );
+
+ /* check newSuperior for "children" acl */
+ if ( !access_allowed( be, conn, op, np, "children", NULL,
+ ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no wr to newSup children\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent's children OK\n",
+ 0, 0 , 0 );
+
+
+ new_parent_dn = np_dn;
- matched = NULL;
- if ( (e2 = dn2entry( be, newdn, &matched )) != NULL ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
- cache_return_entry( &li->li_cache, e2 );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
}
- if ( matched != NULL ) {
- free( matched );
+
+ /* Build target dn and make sure target entry doesn't exist already. */
+
+ build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
+
+
+ new_ndn = dn_normalize_case( ch_strdup(new_dn) );
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
+ new_ndn, 0, 0 );
+
+ if (dn2id ( be, new_ndn ) != NOID) {
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL );
+ goto return_results;
}
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new ndn=%s does not exist\n",
+ new_ndn, 0, 0 );
+
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
- free( newdn );
- free( pdn );
- cache_return_entry( &li->li_cache, e2 );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
- }
- pthread_mutex_unlock( &op->o_abandonmutex );
-
- /* add new one */
- if ( dn2id_add( be, newdn, e->e_id ) != 0 ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto return_results;
}
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* delete old one */
- if ( dn2id_delete( be, dn ) != 0 ) {
- free( newdn );
- free( pdn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( -1 );
+ if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
}
(void) cache_delete_entry( &li->li_cache, e );
free( e->e_dn );
- e->e_dn = newdn;
-
- /* XXX
- * At some point here we need to update the attribute values in
- * the entry itself that were effected by this RDN change
- * (respecting the value of the deleteoldrdn parameter).
- *
- * Since the code to do this has not yet been written, treat this
- * omission as a (documented) bug.
+ free( e->e_ndn );
+ e->e_dn = new_dn;
+ e->e_ndn = new_ndn;
+
+ /* add new one */
+ if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
+ */
+
+ if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out type of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out val of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
+ new_rdn_val, new_rdn_type, 0 );
+
+ /* Retrieve the old rdn from the entry's dn */
+
+ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out the old_rdn type\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+
+ /* Not a big deal but we may say something */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+ old_rdn_type, new_rdn_type, 0 );
+
+ }
+
+ if ( dn_type( old_rdn ) == DN_X500 ) {
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
+ 0, 0, 0 );
+
+ /* Add new attribute value to the entry.
+ */
+
+ add_bvals[0] = &add_bv; /* Array of bervals */
+ add_bvals[1] = NULL;
+
+ add_bv.bv_val = new_rdn_val;
+ add_bv.bv_len = strlen(new_rdn_val);
+
+ mod[0].ml_type = new_rdn_type;
+ mod[0].ml_bvalues = add_bvals;
+ mod[0].ml_op = LDAP_MOD_SOFTADD;
+ mod[0].ml_next = NULL;
+
+ /* Remove old rdn value if required */
+
+ if (deleteoldrdn) {
+
+ /* Get value of old rdn */
+
+ if ((old_rdn_val = rdn_attr_value( old_rdn ))
+ == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op,
+ LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+
+ }
+
+ del_bvals[0] = &del_bv; /* Array of bervals */
+ del_bvals[1] = NULL;
+
+ /* Remove old value of rdn as an attribute. */
+
+ del_bv.bv_val = old_rdn_val;
+ del_bv.bv_len = strlen(old_rdn_val);
+
+ /* No need to normalize old_rdn_type, delete_values()
+ * does that for us
+ */
+ mod[0].ml_next = &mod[1];
+ mod[1].ml_type = old_rdn_type;
+ mod[1].ml_bvalues = del_bvals;
+ mod[1].ml_op = LDAP_MOD_DELETE;
+ mod[1].ml_next = NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: removing old_rdn_val=%s\n",
+ old_rdn_val, 0, 0 );
+
+ }/* if (deleteoldrdn) */
+
+
+ } else {
+
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
+ 0, 0, 0 );
+ /* XXXV3: not sure of what to do here */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: not fully implemented...\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ /* modify memory copy of entry */
+ if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e )
+ != 0 ) {
+
+ goto return_results;
+
+ }
+
+ (void) cache_update_entry( &li->li_cache, e );
+
+ /* NOTE: after this you must not free new_dn or new_ndn!
+ * They are used by cache.
*/
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results_after;
+ }
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- return( -1 );
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ rc = 0;
+ goto return_results_after;
+
+return_results:
+ if( new_dn != NULL ) free( new_dn );
+ if( new_ndn != NULL ) free( new_ndn );
+return_results_after:
+ /* NOTE:
+ * new_dn and new_ndn are not deallocated because they are used by
+ * the cache entry.
+ */
+ if( p_dn != NULL ) free( p_dn );
+ if( p_ndn != NULL ) free( p_ndn );
+
+ if( matched != NULL ) free( matched );
+
+ /* LDAP v2 supporting correct attribute handling. */
+ if( new_rdn_type != NULL ) free(new_rdn_type);
+ if( new_rdn_val != NULL ) free(new_rdn_val);
+ if( old_rdn != NULL ) free(old_rdn);
+ if( old_rdn_type != NULL ) free(old_rdn_type);
+ if( old_rdn_val != NULL ) free(old_rdn_val);
+
+
+ /* LDAP v3 Support */
+ if ( np_dn != NULL ) free( np_dn );
+ if ( np_ndn != NULL ) free( np_ndn );
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rootlock ) {
+ /* release root writer lock */
+ ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
}
- free( pdn );
- cache_return_entry( &li->li_cache, e );
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return( 0 );
+ /* free entry and writer lock */
+ cache_return_entry_w( &li->li_cache, e );
+ return( rc );
}
/* search.c - ldbm backend search function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-
-extern ID dn2id();
-extern IDList *idl_alloc();
-extern Entry *id2entry();
-extern Entry *dn2entry();
-extern Attribute *attr_find();
-extern IDList *filter_candidates();
-extern char *ch_realloc();
-extern char *dn_parent();
-
-static IDList *base_candidates();
-static IDList *onelevel_candidates();
-static IDList *subtree_candidates();
-
-#define GRABSIZE BUFSIZ
-
-#define MAKE_SPACE( n ) { \
- if ( rcur + n > rbuf + rmaxsize ) { \
- int offset = rcur - rbuf; \
- rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
- rmaxsize += GRABSIZE; \
- rcur = rbuf + offset; \
- } \
-}
+static ID_BLOCK *base_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
+static ID_BLOCK *onelevel_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
+static ID_BLOCK *subtree_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
int
ldbm_back_search(
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
int err;
time_t stoptime;
- IDList *candidates;
+ ID_BLOCK *candidates;
ID id;
Entry *e;
Attribute *ref;
+ struct berval **refs;
char *matched = NULL;
- int rmaxsize, nrefs;
- char *rbuf, *rcur, *r;
int nentries = 0;
+ char *realBase;
- if ( tlimit == 0 && be_isroot( be, op->o_dn ) ) {
+ Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
+
+ if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
tlimit = -1; /* allow root to set no limit */
} else {
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
- if ( slimit == 0 && be_isroot( be, op->o_dn ) ) {
+ if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
slimit = -1; /* allow root to set no limit */
} else {
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
be->be_sizelimit : slimit;
}
+ /*
+ * check and apply aliasing where the dereferencing applies to
+ * the subordinates of the base
+ */
+
+ switch ( deref ) {
+ case LDAP_DEREF_FINDING:
+ case LDAP_DEREF_ALWAYS:
+ realBase = derefDN ( be, conn, op, base );
+ break;
+ default:
+ realBase = ch_strdup(base);
+ }
+
+ (void) dn_normalize_case( realBase );
+
+ Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
+ realBase, 0, 0 );
+
switch ( scope ) {
case LDAP_SCOPE_BASE:
- candidates = base_candidates( be, conn, op, base, filter,
+ candidates = base_candidates( be, conn, op, realBase, filter,
attrs, attrsonly, &matched, &err );
break;
case LDAP_SCOPE_ONELEVEL:
- candidates = onelevel_candidates( be, conn, op, base, filter,
+ candidates = onelevel_candidates( be, conn, op, realBase, filter,
attrs, attrsonly, &matched, &err );
break;
case LDAP_SCOPE_SUBTREE:
- candidates = subtree_candidates( be, conn, op, base, filter,
+ candidates = subtree_candidates( be, conn, op, realBase, filter,
attrs, attrsonly, &matched, NULL, &err, 1 );
break;
default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
- "Bad scope" );
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ "", "Bad search scope", NULL );
+ if( realBase != NULL) {
+ free( realBase );
+ }
return( -1 );
}
/* null candidates means we could not find the base object */
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, "" );
+ send_ldap_result( conn, op, err,
+ matched, NULL, NULL );
if ( matched != NULL ) {
free( matched );
}
+ if( realBase != NULL) {
+ free( realBase );
+ }
return( -1 );
}
- rmaxsize = 0;
- nrefs = 0;
- rbuf = rcur = NULL;
- MAKE_SPACE( sizeof("Referral:") + 1 );
- strcpy( rbuf, "Referral:" );
- rcur = strchr( rbuf, '\0' );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+
+ refs = NULL;
+
for ( id = idl_firstid( candidates ); id != NOID;
id = idl_nextid( candidates, id ) ) {
+
/* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
+ if( realBase != NULL) {
+ free( realBase );
+ }
return( 0 );
}
- pthread_mutex_unlock( &op->o_abandonmutex );
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
- pthread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- if ( tlimit != -1 && currenttime > stoptime ) {
- pthread_mutex_unlock( ¤ttime_mutex );
- send_ldap_search_result( conn, op,
- LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
- NULL, nentries );
+ if ( tlimit != -1 && slap_get_time() > stoptime ) {
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, refs, nentries );
idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
+ if( realBase != NULL) {
+ free( realBase );
+ }
return( 0 );
}
- pthread_mutex_unlock( ¤ttime_mutex );
- /* get the entry */
- if ( (e = id2entry( be, id )) == NULL ) {
- Debug( LDAP_DEBUG_ARGS, "candidate %d not found\n", id,
- 0, 0 );
+ /* get the entry with reader lock */
+ if ( (e = id2entry_r( be, id )) == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
+ id, 0, 0 );
continue;
}
/*
* if it's a referral, add it to the list of referrals. only do
- * this for subtree searches, and don't check the filter explicitly
- * here since it's only a candidate anyway.
+ * this for subtree searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
*/
- if ( e->e_dn != NULL && strncasecmp( e->e_dn, "ref=", 4 )
- == 0 && (ref = attr_find( e->e_attrs, "ref" )) != NULL &&
- scope == LDAP_SCOPE_SUBTREE )
+ if ( scope == LDAP_SCOPE_SUBTREE &&
+ e->e_ndn != NULL &&
+ strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
+ (ref = attr_find( e->e_attrs, "ref" )) != NULL )
{
- int i, len;
-
- if ( ref->a_vals == NULL ) {
- Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0,
- 0, 0 );
- } else {
- for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
- /* referral + newline + null */
- MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
- *rcur++ = '\n';
- strncpy( rcur, ref->a_vals[i]->bv_val,
- ref->a_vals[i]->bv_len );
- rcur = rcur + ref->a_vals[i]->bv_len;
- *rcur = '\0';
- nrefs++;
- }
- }
+ send_search_reference( be, conn, op,
+ e, ref->a_vals, &refs );
/* otherwise it's an entry - see if it matches the filter */
} else {
scopeok = 1;
if ( scope == LDAP_SCOPE_ONELEVEL ) {
if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
- (void) dn_normalize( dn );
- scopeok = (dn == base) ? 1 : (! strcasecmp( dn, base ));
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realBase)
+ ? 1
+ : (strcmp( dn, realBase ) ? 0 : 1 );
+ free( dn );
} else {
- scopeok = (base == NULL || *base == '\0');
+ scopeok = (realBase == NULL || *realBase == '\0');
}
- free( dn );
} else if ( scope == LDAP_SCOPE_SUBTREE ) {
- dn = strdup( e->e_dn );
- (void) dn_normalize( dn );
- scopeok = dn_issuffix( dn, base );
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realBase );
free( dn );
}
if ( scopeok ) {
/* check size limit */
if ( --slimit == -1 ) {
- cache_return_entry( &li->li_cache, e );
- send_ldap_search_result( conn, op,
- LDAP_SIZELIMIT_EXCEEDED, NULL,
- nrefs > 0 ? rbuf : NULL, nentries );
+ cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ refs, nentries );
idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
+
+ if( realBase != NULL) {
+ free( realBase );
+ }
return( 0 );
}
- switch ( send_search_entry( be, conn, op, e,
- attrs, attrsonly ) ) {
- case 0: /* entry sent ok */
- nentries++;
+ /*
+ * check and apply aliasing where the dereferencing applies to
+ * the subordinates of the base
+ */
+ switch ( deref ) {
+ case LDAP_DEREF_SEARCHING:
+ case LDAP_DEREF_ALWAYS:
+ {
+ Entry *newe = derefAlias_r( be, conn, op, e );
+ if ( newe == NULL ) { /* problem with the alias */
+ cache_return_entry_r( &li->li_cache, e );
+ e = NULL;
+ }
+ else if ( newe != e ) { /* reassign e */
+ cache_return_entry_r( &li->li_cache, e );
+ e = newe;
+ }
+ }
break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- cache_return_entry( &li->li_cache, e );
- idl_free( candidates );
- free( rbuf );
- return( 0 );
+ }
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, 0 ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ cache_return_entry_r( &li->li_cache, e );
+ idl_free( candidates );
+ ber_bvecfree( refs );
+
+ if( realBase != NULL) {
+ free( realBase );
+ }
+ return( 0 );
+ }
}
}
}
}
- cache_return_entry( &li->li_cache, e );
+ if( e != NULL ) {
+ /* free reader lock */
+ cache_return_entry_r( &li->li_cache, e );
+ }
- pthread_yield();
+ ldap_pvt_thread_yield();
}
idl_free( candidates );
- if ( nrefs > 0 ) {
- send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- rbuf, nentries );
- } else {
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
- nentries );
+
+ send_search_result( conn, op,
+ refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, refs, nentries );
+
+ ber_bvecfree( refs );
+
+ if( realBase != NULL) {
+ free( realBase );
}
- free( rbuf );
return( 0 );
}
-static IDList *
+static ID_BLOCK *
base_candidates(
Backend *be,
Connection *conn,
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int rc;
- ID id;
- IDList *idl;
+ ID_BLOCK *idl;
Entry *e;
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
+
*err = LDAP_SUCCESS;
- if ( (e = dn2entry( be, base, matched )) == NULL ) {
+
+ /* get entry with reader lock */
+ if ( (e = dn2entry_r( be, base, matched )) == NULL ) {
*err = LDAP_NO_SUCH_OBJECT;
return( NULL );
}
+ /* check for deleted */
+
idl = idl_alloc( 1 );
idl_insert( &idl, e->e_id, 1 );
- cache_return_entry( &li->li_cache, e );
+
+ /* free reader lock */
+ cache_return_entry_r( &li->li_cache, e );
return( idl );
}
-static IDList *
+static ID_BLOCK *
onelevel_candidates(
Backend *be,
Connection *conn,
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e;
+ Entry *e = NULL;
Filter *f;
char buf[20];
- IDList *candidates;
+ ID_BLOCK *candidates;
+
+ Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
*err = LDAP_SUCCESS;
- e = NULL;
- /* get the base object */
- if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
- matched )) == NULL ) {
+
+ /* get the base object with reader lock */
+ if ( base != NULL && *base != '\0' &&
+ (e = dn2entry_r( be, base, matched )) == NULL )
+ {
*err = LDAP_NO_SUCH_OBJECT;
return( NULL );
}
f->f_choice = LDAP_FILTER_AND;
f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
f->f_and->f_choice = LDAP_FILTER_EQUALITY;
- f->f_and->f_ava.ava_type = strdup( "id2children" );
- sprintf( buf, "%d", e != NULL ? e->e_id : 0 );
- f->f_and->f_ava.ava_value.bv_val = strdup( buf );
+ f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+ sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+ f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
f->f_and->f_ava.ava_value.bv_len = strlen( buf );
f->f_and->f_next = filter;
f->f_and->f_next = NULL;
filter_free( f );
+ /* free entry and reader lock */
+ if( e != NULL ) {
+ cache_return_entry_r( &li->li_cache, e );
+ }
return( candidates );
}
-static IDList *
+static ID_BLOCK *
subtree_candidates(
Backend *be,
Connection *conn,
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Filter *f;
- IDList *candidates;
+ Filter *f, **filterarg_ptr;
+ ID_BLOCK *candidates;
+
+ Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
+ base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
/*
* get the base object - unless we already have it (from one-level).
*err = LDAP_SUCCESS;
f = NULL;
if ( lookupbase ) {
- if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
- matched )) == NULL ) {
+ e = NULL;
+
+ if ( base != NULL && *base != '\0' &&
+ (e = dn2entry_r( be, base, matched )) == NULL )
+ {
*err = LDAP_NO_SUCH_OBJECT;
return( NULL );
}
+ if (e) {
+ cache_return_entry_r( &li->li_cache, e );
+ }
+
f = (Filter *) ch_malloc( sizeof(Filter) );
f->f_next = NULL;
f->f_choice = LDAP_FILTER_OR;
f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
f->f_or->f_choice = LDAP_FILTER_EQUALITY;
- f->f_or->f_avtype = strdup( "objectclass" );
- f->f_or->f_avvalue.bv_val = strdup( "referral" );
- f->f_or->f_avvalue.bv_len = strlen( "referral" );
- f->f_or->f_next = filter;
+ f->f_or->f_avtype = ch_strdup( "objectclass" );
+ /* Patch to use normalized uppercase */
+ f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
+ filterarg_ptr = &f->f_or->f_next;
+ *filterarg_ptr = filter;
filter = f;
if ( ! be_issuffix( be, base ) ) {
f->f_choice = LDAP_FILTER_AND;
f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_and->f_sub_type = strdup( "dn" );
+ f->f_and->f_sub_type = ch_strdup( "dn" );
f->f_and->f_sub_initial = NULL;
f->f_and->f_sub_any = NULL;
- f->f_and->f_sub_final = strdup( base );
+ f->f_and->f_sub_final = ch_strdup( base );
value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
f->f_and->f_next = filter;
filter = f;
/* free up just the parts we allocated above */
if ( f != NULL ) {
- f->f_and->f_next = NULL;
+ *filterarg_ptr = NULL;
filter_free( f );
}
- if ( e != NULL ) {
- cache_return_entry( &li->li_cache, e );
- }
-
return( candidates );
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+char *supportedSASLMechanisms[] = {
+ "X-DIGEST-MD5",
+ NULL
+};
+
+int
do_bind(
Connection *conn,
Operation *op
)
{
BerElement *ber = op->o_ber;
- int version, method, len, rc;
- char *dn;
+ ber_int_t version;
+ ber_tag_t method;
+ char *mech;
+ char *cdn, *ndn;
+ ber_tag_t tag;
+ int rc = LDAP_SUCCESS;
struct berval cred;
Backend *be;
Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
+ cdn = NULL;
+ ndn = NULL;
+ mech = NULL;
+ cred.bv_val = NULL;
+
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ /* Force to connection to "anonymous" until bind succeeds.
+ * This may need to be relocated or done on a case by case basis
+ * to handle certain SASL mechanisms.
+ */
+
+ if ( conn->c_cdn != NULL ) {
+ free( conn->c_cdn );
+ conn->c_cdn = NULL;
+ }
+
+ if ( conn->c_dn != NULL ) {
+ free( conn->c_dn );
+ conn->c_dn = NULL;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ if ( op->o_dn != NULL ) {
+ free( op->o_dn );
+ op->o_dn = ch_strdup( "" );
+ }
+
+ if ( op->o_ndn != NULL ) {
+ free( op->o_ndn );
+ op->o_ndn = ch_strdup( "" );
+ }
+
/*
* Parse the bind request. It looks like this:
*
* authentication CHOICE {
* simple [0] OCTET STRING -- passwd
* krbv42ldap [1] OCTET STRING
- * krbv42dsa [1] OCTET STRING
+ * krbv42dsa [2] OCTET STRING
+ * SASL [3] SaslCredentials
* }
+ * }
+ *
+ * SaslCredentials ::= SEQUENCE {
+ * mechanism LDAPString,
+ * credentials OCTET STRING OPTIONAL
* }
*/
-#ifdef COMPAT30
- /*
- * in version 3.0 there is an extra SEQUENCE tag after the
- * BindRequest SEQUENCE tag.
- */
+ tag = ber_scanf( ber, "{iat" /*}*/, &version, &cdn, &method );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto cleanup;
+ }
+
+ op->o_protocol = version;
- {
- BerElement tber;
- unsigned long tlen, ttag;
+ if( method != LDAP_AUTH_SASL ) {
+ tag = ber_scanf( ber, /*{*/ "o}", &cred );
- tber = *op->o_ber;
- ttag = ber_skip_tag( &tber, &tlen );
- if ( ber_peek_tag( &tber, &tlen ) == LBER_SEQUENCE ) {
- Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n", 0, 0, 0 );
- conn->c_version = 30;
- rc = ber_scanf(ber, "{{iato}}", &version, &dn, &method, &cred);
} else {
- rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
+ tag = ber_scanf( ber, "{a" /*}*/, &mech );
+
+ if ( tag != LBER_ERROR ) {
+ ber_len_t len;
+ tag = ber_peek_tag( ber, &len );
+
+ if ( tag == LDAP_TAG_LDAPCRED ) {
+ tag = ber_scanf( ber, "o", &cred );
+ }
+
+ if ( tag != LBER_ERROR ) {
+ tag = ber_scanf( ber, /*{{*/ "}}" );
+ }
+ }
}
+
+ if ( tag == LBER_ERROR ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR,
+ "decoding error" );
+ rc = -1;
+ goto cleanup;
}
-#else
- rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
-#endif
- if ( rc == LBER_ERROR ) {
- Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- return;
- }
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- switch ( method ) {
- case LDAP_AUTH_SIMPLE_30:
- method = LDAP_AUTH_SIMPLE;
- break;
-#ifdef KERBEROS
- case LDAP_AUTH_KRBV41_30:
- method = LDAP_AUTH_KRBV41;
- break;
- case LDAP_AUTH_KRBV42_30:
- method = LDAP_AUTH_KRBV42;
- break;
-#endif
- }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
+ goto cleanup;
+ }
+
+ if( method == LDAP_AUTH_SASL ) {
+ Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
+ cdn, mech, NULL );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
+ version, cdn, method );
}
-#endif /* compat30 */
- dn_normalize( dn );
+
+ ndn = dn_normalize_case( ch_strdup( cdn ) );
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
- conn->c_connid, op->o_opid, dn, method, 0 );
+ conn->c_connid, op->o_opid, ndn, method, 0 );
- if ( version != LDAP_VERSION2 ) {
- if ( dn != NULL ) {
- free( dn );
+ if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
+ Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "version not supported", NULL );
+ goto cleanup;
+ }
+
+ if ( method == LDAP_AUTH_SASL ) {
+ if ( version < LDAP_VERSION3 ) {
+ Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%d\n",
+ version, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "sasl bind requires LDAPv3" );
+ rc = -1;
+ goto cleanup;
}
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
+
+ if( mech == NULL || *mech == '\0' ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_bind: no sasl mechanism provided\n",
+ version, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, "no sasl mechanism provided", NULL );
+ goto cleanup;
}
- Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "version not supported" );
- return;
- }
+ if( !charray_inlist( supportedSASLMechanisms, mech ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_bind: sasl mechanism \"%s\" not supported.\n",
+ mech, 0, 0 );
+ send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, "sasl mechanism not supported", NULL );
+ goto cleanup;
+ }
- Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
- version, dn, method );
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
- /* accept null binds */
- if ( dn == NULL || *dn == '\0' ) {
- if ( dn != NULL ) {
- free( dn );
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ if((strcmp(conn->c_authmech, mech) != 0)) {
+ /* mechanism changed, cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
+ }
+
+#ifdef LDAP_DEBUG
+ } else {
+ assert( !conn->c_bind_in_progress );
+ assert( conn->c_authmech == NULL );
+ assert( conn->c_authstate == NULL );
+#endif
}
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
+
+ } else {
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ /* cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
}
+ }
+
+ conn->c_protocol = version;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- return;
+ /* accept null binds */
+ if ( ndn == NULL || *ndn == '\0' ) {
+ /*
+ * we already forced connection to "anonymous", we just
+ * need to send success
+ */
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ goto cleanup;
}
/*
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- if ( cred.bv_val != NULL ) {
- free( cred.bv_val );
- }
+ if ( (be = select_backend( ndn )) == NULL ) {
if ( cred.bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+
+ } else if ( default_referral ) {
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL );
}
- return;
+
+ goto cleanup;
}
- if ( be->be_bind != NULL ) {
- if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
- pthread_mutex_lock( &conn->c_dnmutex );
- if ( conn->c_dn != NULL ) {
- free( conn->c_dn );
+ if ( be->be_bind ) {
+ /* alias suffix */
+ char *edn;
+
+ ndn = suffixAlias( ndn, op, be );
+
+ if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ conn->c_cdn = cdn;
+ cdn = NULL;
+
+ if(edn != NULL) {
+ conn->c_dn = edn;
+ } else {
+ conn->c_dn = ndn;
+ ndn = NULL;
}
- conn->c_dn = strdup( dn );
- pthread_mutex_unlock( &conn->c_dnmutex );
+
+ Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
+ conn->c_cdn, conn->c_dn, method );
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
/* send this here to avoid a race condition */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL );
+
+ } else if (edn != NULL) {
+ free( edn );
}
+
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( dn );
+cleanup:
+ if( cdn != NULL ) {
+ free( cdn );
+ }
+ if( ndn != NULL ) {
+ free( ndn );
+ }
+ if ( mech != NULL ) {
+ free( mech );
+ }
if ( cred.bv_val != NULL ) {
free( cred.bv_val );
}
+
+ return rc;
}
/* charray.c - routines for dealing with char * arrays */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
void
(n + 2) * sizeof(char *) );
}
- (*a)[n++] = s;
+ (*a)[n++] = ch_strdup(s);
(*a)[n] = NULL;
}
*a = (char **) ch_realloc( (char *) *a, (n + nn + 1) * sizeof(char *) );
for ( i = 0; i < nn; i++ ) {
- (*a)[n + i] = s[i];
+ (*a)[n + i] = ch_strdup(s[i]);
}
(*a)[n + nn] = NULL;
}
new = (char **) ch_malloc( (i + 1) * sizeof(char *) );
for ( i = 0; a[i] != NULL; i++ ) {
- new[i] = strdup( a[i] );
+ new[i] = ch_strdup( a[i] );
}
new[i] = NULL;
return( new );
}
+
+char *
+charray2str( char **a )
+{
+ char *s;
+ int i;
+ size_t cur, len = 0;
+
+ if( a == NULL ) return NULL;
+
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len += strlen( a[i] );
+ }
+
+ if( len == 0 ) return NULL;
+
+ s = ch_malloc( len + 1 );
+
+ cur = 0;
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len = strlen( a[i] );
+ strncpy( &s[cur], a[i], len );
+ cur += len;
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
char **
str2charray( char *str, char *brkstr )
{
char **res;
char *s;
+ char *lasts;
int i;
+ /* protect the input string from strtok */
+ str = ch_strdup( str );
+
i = 1;
for ( s = str; *s; s++ ) {
if ( strchr( brkstr, *s ) != NULL ) {
res = (char **) ch_malloc( (i + 1) * sizeof(char *) );
i = 0;
- for ( s = strtok( str, brkstr ); s != NULL; s = strtok( NULL,
- brkstr ) ) {
- res[i++] = strdup( s );
+
+ for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
+ s != NULL;
+ s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
+ {
+ res[i++] = ch_strdup( s );
}
+
res[i] = NULL;
+ free( str );
return( res );
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_compare(
Connection *conn,
Operation *op
)
{
- char *dn;
+ char *ndn;
Ava ava;
- int rc;
Backend *be;
+ int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the compare request. It looks like this:
*
* }
*/
- if ( ber_scanf( op->o_ber, "{a{ao}}", &dn, &ava.ava_type,
+ if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type,
&ava.ava_value ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
+
+ if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ ava_free( &ava, 0 );
+ Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
value_normalize( ava.ava_value.bv_val, attr_syntax( ava.ava_type ) );
- dn_normalize( dn );
Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
- dn, ava.ava_type, ava.ava_value.bv_val );
+ ndn, ava.ava_type, ava.ava_value.bv_val );
+
+ ndn = dn_normalize_case( ndn );
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d CMP dn=\"%s\" attr=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, ava.ava_type, 0 );
+ conn->c_connid, op->o_opid, ndn, ava.ava_type, 0 );
/*
* 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.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
ava_free( &ava, 0 );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+ return 1;
}
- if ( be->be_compare != NULL ) {
- (*be->be_compare)( be, conn, op, dn, &ava );
+ /* alias suffix if approp */
+ ndn = suffixAlias( ndn, op, be );
+
+ if ( be->be_compare ) {
+ (*be->be_compare)( be, conn, op, ndn, &ava );
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( dn );
+ free( ndn );
ava_free( &ava, 0 );
+
+ return rc;
}
/* config.c - configuration file handling routines */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
#define MAXARGS 100
-extern Backend *new_backend();
-extern char *default_referral;
-extern int ldap_syslog;
-extern int global_schemacheck;
-
/*
* defaults for various global variables
*/
int global_default_access = ACL_READ;
char *replogfile;
int global_lastmod;
+int global_idletimeout = 0;
+char *global_realm = NULL;
char *ldap_srvtab = "";
-static char *fp_getline();
-static void fp_getline_init();
-static void fp_parse_line();
+char *slapd_pid_file = NULL;
+char *slapd_args_file = NULL;
-static char *strtok_quote();
+static char *fp_getline(FILE *fp, int *lineno);
+static void fp_getline_init(int *lineno);
+static int fp_parse_line(char *line, int *argcp, char **argv);
-void
-read_config( char *fname, Backend **bep, FILE *pfp )
+static char *strtok_quote(char *line, char *sep);
+
+int
+read_config( char *fname )
{
FILE *fp;
- char *line, *savefname, *dn;
+ char *line, *savefname, *saveline;
int cargc, savelineno;
char *cargv[MAXARGS];
int lineno, i;
- Backend *be;
- if ( (fp = pfp) == NULL && (fp = fopen( fname, "r" )) == NULL ) {
+ struct berval *vals[2];
+ struct berval val;
+
+ static BackendInfo *bi = NULL;
+ static BackendDB *be = NULL;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ if ( (fp = fopen( fname, "r" )) == NULL ) {
ldap_syslog = 1;
Debug( LDAP_DEBUG_ANY,
"could not open config file \"%s\" - absolute path?\n",
fname, 0, 0 );
perror( fname );
- exit( 1 );
+ return 1;
}
Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
- be = *bep;
+
+ if ( schema_init( ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "error initializing the schema\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
fp_getline_init( &lineno );
+
while ( (line = fp_getline( fp, &lineno )) != NULL ) {
/* skip comments and blank lines */
if ( line[0] == '#' || line[0] == '\0' ) {
Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, line, 0 );
- fp_parse_line( line, &cargc, cargv );
+ /* fp_parse_line is destructive, we save a copy */
+ saveline = ch_strdup( line );
+
+ if ( fp_parse_line( line, &cargc, cargv ) != 0 ) {
+ return( 1 );
+ }
if ( cargc < 1 ) {
Debug( LDAP_DEBUG_ANY,
continue;
}
+ if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing type in \"backend <type>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ if( be != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: backend line must appear before any database definition\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ bi = backend_info( cargv[1] );
+
/* start of a new database definition */
- if ( strcasecmp( cargv[0], "database" ) == 0 ) {
+ } else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing type in \"database <type>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- *bep = new_backend( cargv[1] );
- be = *bep;
+ bi = NULL;
+ be = backend_db_init( cargv[1] );
- /* set size limit */
+ /* assign a default depth limit for alias deref */
+ be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH;
+
+ /* get pid file name */
+ } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing file name in \"pidfile <file>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ slapd_pid_file = ch_strdup( cargv[1] );
+
+ /* get args file name */
+ } else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing file name in \"argsfile <file>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ slapd_args_file = ch_strdup( cargv[1] );
+
+ /* set DIGEST realm */
+ } else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing realm in \"digest-realm <realm>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be != NULL ) {
+ be->be_realm = ch_strdup( cargv[1] );
+
+ } else if ( global_realm != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: already set global realm!\n",
+ fname, lineno, 0 );
+ return 1;
+
+ } else {
+ global_realm = ch_strdup( cargv[1] );
+ }
+
+ /* set time limit */
} else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
defsize = atoi( cargv[1] );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"timelimit <limit>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
deftime = atoi( cargv[1] );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"suffix <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
} else if ( cargc > 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: extra cruft after <dn> in \"suffix %s\" line (ignored)\n",
"%s: line %d: suffix line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- dn = strdup( cargv[1] );
+ char *dn = ch_strdup( cargv[1] );
(void) dn_normalize( dn );
charray_add( &be->be_suffix, dn );
- }
+ (void) dn_upcase( dn );
+ charray_add( &be->be_nsuffix, dn );
+ free( dn );
+ }
+
+ /* set database suffixAlias */
+ } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ } else if ( cargc < 3 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ } else if ( cargc > 3 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
+ fname, lineno, 0 );
+ }
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: suffixAlias line must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else {
+ char *alias, *aliased_dn;
+
+ alias = ch_strdup( cargv[1] );
+ (void) dn_normalize( alias );
+
+ aliased_dn = ch_strdup( cargv[2] );
+ (void) dn_normalize( aliased_dn );
+
+
+ if ( strcasecmp( alias, aliased_dn) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: suffixAlias %s is not different from aliased dn (ignored)\n",
+ fname, lineno, alias );
+ } else {
+ (void) dn_normalize_case( alias );
+ (void) dn_normalize_case( aliased_dn );
+ charray_add( &be->be_suffixAlias, alias );
+ charray_add( &be->be_suffixAlias, aliased_dn );
+ }
+
+ free(alias);
+ free(aliased_dn);
+ }
+
+ /* set max deref depth */
+ } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth line must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else {
+ be->be_maxDerefDepth = atoi (cargv[1]);
+ }
+
/* set magic "root" dn for this database */
} else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"rootdn <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: rootdn line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- dn = strdup( cargv[1] );
- (void) dn_normalize( dn );
- be->be_rootdn = dn;
+ be->be_root_dn = ch_strdup( cargv[1] );
+ be->be_root_ndn = dn_normalize_case( ch_strdup( cargv[1] ) );
}
/* set super-secret magic database password */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing passwd in \"rootpw <passwd>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: rootpw line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- be->be_rootpw = strdup( cargv[1] );
+ be->be_root_pw = ch_strdup( cargv[1] );
}
/* make this database read-only */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing URL in \"referral <URL>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
+ }
+
+ vals[0]->bv_val = cargv[1];
+ vals[0]->bv_len = strlen( vals[0]->bv_val );
+ value_add( &default_referral, vals );
+
+ /* specify locale */
+ } else if ( strcasecmp( cargv[0], "locale" ) == 0 ) {
+#ifdef HAVE_LOCALE_H
+ char *locale;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing locale in \"locale <name | on | off>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
}
- default_referral = (char *) malloc( strlen( cargv[1] )
- + sizeof("Referral:\n") + 1 );
- strcpy( default_referral, "Referral:\n" );
- strcat( default_referral, cargv[1] );
+ locale = (strcasecmp( cargv[1], "on" ) == 0 ? ""
+ : strcasecmp( cargv[1], "off" ) == 0 ? "C"
+ : ch_strdup( cargv[1] ) );
+
+ if ( setlocale( LC_CTYPE, locale ) == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ (*locale
+ ? "%s: line %d: bad locale \"%s\"\n"
+ : "%s: line %d: bad locale\n"),
+ fname, lineno, locale );
+ return( 1 );
+ }
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"locale\" unsupported\n",
+ fname, lineno, 0 );
+ return( 1 );
+#endif
/* specify an objectclass */
} else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
- parse_oc( be, fname, lineno, cargc, cargv );
+ if ( *cargv[1] == '(' ) {
+ char * p;
+ p = strchr(saveline,'(');
+ parse_oc( fname, lineno, p );
+ } else {
+ parse_oc_old( be, fname, lineno, cargc, cargv );
+ }
/* specify an attribute */
} else if ( strcasecmp( cargv[0], "attribute" ) == 0 ) {
- attr_syntax_config( fname, lineno, cargc - 1,
- &cargv[1] );
+ if ( *cargv[1] == '(' ) {
+ char * p;
+ p = strchr(saveline,'(');
+ parse_at( fname, lineno, p );
+ } else {
+ attr_syntax_config( fname, lineno, cargc - 1,
+ &cargv[1] );
+ }
/* turn on/off schema checking */
} else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- if ( strcasecmp( cargv[1], "on" ) == 0 ) {
- global_schemacheck = 1;
- } else {
+ if ( strcasecmp( cargv[1], "off" ) == 0 ) {
global_schemacheck = 0;
+ } else {
+ global_schemacheck = 1;
}
/* specify access control info */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"defaultaccess <access>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
- if ( (global_default_access =
- str2access( cargv[1] )) == -1 ) {
+ if ( ACL_IS_INVALID(ACL_SET(global_default_access,
+ str2access(cargv[1]))) )
+ {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
fname, lineno, cargv[1] );
- exit( 1 );
+ return( 1 );
}
} else {
- if ( (be->be_dfltaccess =
- str2access( cargv[1] )) == -1 ) {
+ if ( ACL_IS_INVALID(ACL_SET(be->be_dfltaccess,
+ str2access(cargv[1]))) )
+ {
Debug( LDAP_DEBUG_ANY,
-"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
+ "%s: line %d: bad access \"%s\", "
+ "expecting [self]{none|compare|search|read|write}\n",
fname, lineno, cargv[1] );
- exit( 1 );
+ return( 1 );
}
}
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing level in \"loglevel <level>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
ldap_syslog = atoi( cargv[1] );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing host in \"replica <host[:port]>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
if ( strncasecmp( cargv[i], "host=", 5 )
== 0 ) {
charray_add( &be->be_replica,
- strdup( cargv[i] + 5 ) );
+ cargv[i] + 5 );
break;
}
}
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"updatedn <dn>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: updatedn line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
} else {
- be->be_updatedn = strdup( cargv[1] );
- (void) dn_normalize( be->be_updatedn );
+ be->be_update_ndn = ch_strdup( cargv[1] );
+ (void) dn_normalize_case( be->be_update_ndn );
}
/* replication log file to which changes are appended */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing dn in \"replogfile <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( be ) {
- be->be_replogfile = strdup( cargv[1] );
+ be->be_replogfile = ch_strdup( cargv[1] );
} else {
- replogfile = strdup( cargv[1] );
+ replogfile = ch_strdup( cargv[1] );
}
/* maintain lastmodified{by,time} attributes */
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
if ( strcasecmp( cargv[1], "on" ) == 0 ) {
if ( be )
global_lastmod = OFF;
}
+ /* set idle timeout value */
+ } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
+ int i;
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+
+ i = atoi( cargv[1] );
+
+ if( i < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
+ fname, lineno, i );
+ return( 1 );
+ }
+
+ global_idletimeout = i;
+
/* include another config file */
} else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing filename in \"include <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
+ return( 1 );
}
- savefname = strdup( cargv[1] );
+ savefname = ch_strdup( cargv[1] );
savelineno = lineno;
- read_config( savefname, bep, NULL );
- be = *bep;
+
+ if ( read_config( savefname ) != 0 ) {
+ return( 1 );
+ }
+
free( savefname );
lineno = savelineno - 1;
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing filename in \"srvtab <filename>\" line\n",
fname, lineno, 0 );
- exit( 1 );
- }
- ldap_srvtab = strdup( cargv[1] );
-
- /* pass anything else to the current backend config routine */
+ return( 1 );
+ }
+ ldap_srvtab = ch_strdup( cargv[1] );
+
+#ifdef SLAPD_MODULES
+ } else if (strcasecmp( cargv[0], "loadmodule") == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing filename in \"loadmodule <filename>\" line\n",
+ fname, lineno, 0 );
+ exit( 1 );
+ }
+ if (!load_module(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: failed to load or initialize module %s\n",
+ fname, lineno, cargv[1]);
+ exit( 1 );
+ }
+
+#endif /*SLAPD_MODULES*/
+
+ /* pass anything else to the current backend info/db config routine */
} else {
- if ( be == NULL ) {
- Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" outside database definition (ignored)\n",
- fname, lineno, cargv[0] );
- } else if ( be->be_config == NULL ) {
+ if ( bi != NULL ) {
+ if ( bi->bi_config == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
+ fname, lineno, cargv[0] );
+ } else {
+ if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
+ != 0 )
+ {
+ return( 1 );
+ }
+ }
+ } else if ( be != NULL ) {
+ if ( be->be_config == 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
+ fname, lineno, cargv[0] );
+ } else {
+ if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
+ != 0 )
+ {
+ return( 1 );
+ }
+ }
+ } else {
Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" inside database definition (ignored)\n",
+"%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
fname, lineno, cargv[0] );
- } else {
- (*be->be_config)( be, fname, lineno, cargc,
- cargv );
}
}
+ free( saveline );
}
fclose( fp );
+ return( 0 );
}
-static void
+static int
fp_parse_line(
char *line,
int *argcp,
if ( *argcp == MAXARGS ) {
Debug( LDAP_DEBUG_ANY, "Too many tokens (max %d)\n",
MAXARGS, 0, 0 );
- exit( 1 );
+ return( 1 );
}
argv[(*argcp)++] = token;
}
argv[*argcp] = NULL;
+ return 0;
}
static char *
} else {
inquote = 1;
}
- strcpy( next, next + 1 );
+ SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
break;
case '\\':
- strcpy( next, next + 1 );
+ if ( next[1] )
+ SAFEMEMCPY( next,
+ next + 1, strlen( next + 1 ) + 1 );
+ next++; /* dont parse the escaped character */
break;
default:
if ( (p = strchr( buf, '\n' )) != NULL ) {
*p = '\0';
}
- if ( ! isspace( buf[0] ) ) {
+ if ( ! isspace( (unsigned char) buf[0] ) ) {
return( line );
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_defaults.h"
#include "slap.h"
-#include "ldapconfig.h"
#if defined( SLAPD_CONFIG_DN )
-extern int nbackends;
-extern Backend *backends;
-extern char *default_referral;
-
/*
* no mutex protection in here - take our chances!
*/
vals[1] = NULL;
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
e->e_attrs = NULL;
- e->e_dn = strdup( SLAPD_CONFIG_DN );
+ e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
+ e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_CONFIG_DN ));
+ e->e_private = NULL;
for ( i = 0; i < nbackends; i++ ) {
strcpy( buf, backends[i].be_type );
attr_merge( e, "database", vals );
}
- if ( default_referral != NULL ) {
- strcpy( buf, default_referral );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attr_merge( e, "database", vals );
- }
-
- send_search_entry( &backends[0], conn, op, e, NULL, 0 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
+ send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
entry_free( e );
}
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+
+#include "../../libraries/liblber/lber-int.h"
+
+char *supportedControls[] = {
+ LDAP_CONTROL_MANAGEDSAIT,
+ NULL
+};
+
+int get_ctrls(
+ Connection *conn,
+ Operation *op,
+ int sendres )
+{
+ int nctrls;
+ ber_tag_t tag;
+ ber_len_t len;
+ char *opaque;
+ BerElement *ber = op->o_ber;
+ LDAPControl ***ctrls = &op->o_ctrls;
+ int rc = LDAP_SUCCESS;
+ char *errmsg = NULL;
+
+ len = ber_pvt_ber_remaining(ber);
+
+ if( len == 0) {
+ /* no controls */
+ rc = LDAP_SUCCESS;
+ goto return_results;
+ }
+
+ if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
+ if( tag == LBER_ERROR ) {
+ rc = -1;
+ errmsg = "unexpected data in PDU";
+ }
+
+ goto return_results;
+ }
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ rc = -1;
+ errmsg = "controls require LDAPv3";
+ goto return_results;
+ }
+
+ /* set through each element */
+ nctrls = 0;
+ *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
+
+#if 0
+ if( *ctrls == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ errmsg = "no memory";
+ goto return_results;
+ }
+#endif
+
+ ctrls[nctrls] = NULL;
+
+ for( tag = ber_first_element( ber, &len, &opaque );
+ tag != LBER_ERROR;
+ tag = ber_next_element( ber, &len, opaque ) )
+ {
+ LDAPControl *tctrl;
+ LDAPControl **tctrls;
+
+ tctrl = ch_calloc( 1, sizeof(LDAPControl) );
+
+ /* allocate pointer space for current controls (nctrls)
+ * + this control + extra NULL
+ */
+ tctrls = (tctrl == NULL) ? NULL :
+ ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
+
+#if 0
+ if( tctrls == NULL ) {
+ /* one of the above allocation failed */
+
+ if( tctrl != NULL ) {
+ ch_free( tctrl );
+ }
+
+ ldap_controls_free(*ctrls);
+ *ctrls = NULL;
+
+ rc = LDAP_NO_MEMORY;
+ errmsg = "no memory";
+ goto return_results;
+ }
+#endif
+
+
+ tctrls[nctrls++] = tctrl;
+ tctrls[nctrls] = NULL;
+
+ tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
+
+ if( tag != LBER_ERROR ) {
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if( tag == LBER_BOOLEAN ) {
+ ber_int_t crit;
+ tag = ber_scanf( ber, "b", &crit );
+ tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
+ }
+
+ if( tag != LBER_ERROR ) {
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if( tag == LBER_OCTETSTRING ) {
+ tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
+
+ } else {
+ tctrl->ldctl_value.bv_val = NULL;
+ }
+
+ if( tag == LBER_ERROR ) {
+ *ctrls = NULL;
+ ldap_controls_free( tctrls );
+ rc = -1;
+ errmsg = "decoding controls error";
+ goto return_results;
+ }
+
+ if( tctrl->ldctl_iscritical &&
+ !charray_inlist( supportedControls, tctrl->ldctl_oid ) )
+ {
+ rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ errmsg = "critical extension is unavailable ";
+ goto return_results;
+ }
+
+ *ctrls = tctrls;
+ }
+
+return_results:
+ if( sendres && rc != LDAP_SUCCESS ) {
+ if( rc == -1 ) {
+ send_ldap_disconnect( conn, op, rc, errmsg );
+ } else {
+ send_ldap_result( conn, op, rc, NULL, errmsg, NULL );
+ }
+ }
+
+ return rc;
+}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_delete(
Connection *conn,
Operation *op
)
{
- char *dn, *odn;
+ char *ndn;
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_delete: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the delete request. It looks like this:
*
* DelRequest := DistinguishedName
*/
- if ( ber_scanf( op->o_ber, "a", &dn ) == LBER_ERROR ) {
+ if ( ber_scanf( op->o_ber, "a", &ndn ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
- odn = strdup( dn );
- dn_normalize( dn );
- Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", dn, 0, 0 );
+ if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) {
+ free( ndn );
+ Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
+ Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", ndn, 0, 0 );
- Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", dn, 0, 0 );
+ dn_normalize_case( ndn );
+
+ Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", ndn, 0, 0 );
/*
* 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.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+ return rc;
}
+ /* alias suffix if approp */
+ ndn = suffixAlias( ndn, op, be );
+
/*
* do the delete if 1 && (2 || 3)
* 1) there is a delete function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_delete != NULL ) {
+ if ( be->be_delete ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (*be->be_delete)( be, conn, op, dn ) == 0 ) {
- replog( be, LDAP_REQ_DELETE, odn, NULL, 0 );
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+ {
+ if ( (*be->be_delete)( be, conn, op, ndn ) == 0 ) {
+ replog( be, LDAP_REQ_DELETE, ndn, NULL, 0 );
}
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
}
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( dn );
- free( odn );
+ free( ndn );
+ return rc;
}
--- /dev/null
+/*
+ * Copyright 1999 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/*
+ * LDAPv3 Extended Operation Request
+ * ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+ * requestName [0] LDAPOID,
+ * requestValue [1] OCTET STRING OPTIONAL
+ * }
+ *
+ * LDAPv3 Extended Operation Response
+ * ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ * COMPONENTS OF LDAPResult,
+ * responseName [10] LDAPOID OPTIONAL,
+ * response [11] OCTET STRING OPTIONAL
+ * }
+ *
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+
+char *supportedExtensions[] = {
+ NULL
+};
+
+
+int
+do_extended(
+ Connection *conn,
+ Operation *op
+)
+{
+ int rc = LDAP_SUCCESS;
+ char* reqoid ;
+ struct berval reqdata;
+ ber_tag_t tag;
+ ber_len_t len;
+
+ Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
+
+ reqoid = NULL;
+ reqdata.bv_val = NULL;
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ Debug( LDAP_DEBUG_ANY, "do_extended: protocol version (%d) too low\n",
+ op->o_protocol, 0 ,0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "requires LDAPv3" );
+ rc = -1;
+ goto done;
+ }
+
+ if ( ber_scanf( op->o_ber, "a", &reqoid ) == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto done;
+ }
+
+ if( !charray_inlist( supportedExtensions, reqoid ) ) {
+ Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
+ reqoid, 0 ,0 );
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "unsuppored extended operation", NULL );
+ goto done;
+ }
+
+ tag = ber_peek_tag( op->o_ber, &len );
+
+ if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
+ if( ber_scanf( op->o_ber, "o", &reqdata ) != LBER_ERROR ) {
+ Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto done;
+ }
+ }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_extended: get_ctrls failed\n", 0, 0 ,0 );
+ return rc;
+ }
+
+ Debug( LDAP_DEBUG_ARGS, "do_extended: oid \"%s\"\n", reqoid, 0 ,0 );
+
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "unsupported extended operation", NULL );
+
+done:
+ if ( reqoid != NULL ) {
+ free( reqoid );
+ }
+ if ( reqdata.bv_val != NULL ) {
+ free( reqdata.bv_val );
+ }
+
+ return rc;
+}
\ No newline at end of file
/* init.c - initialize various things */
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include "slap.h"
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern pthread_mutex_t currenttime_mutex;
-extern pthread_mutex_t entry2str_mutex;
-extern pthread_mutex_t replog_mutex;
-extern pthread_mutex_t ops_mutex;
-extern pthread_mutex_t num_sent_mutex;
-#ifndef sunos5
-extern pthread_mutex_t regex_mutex;
+/*
+ * read-only global variables or variables only written by the listener
+ * thread (after they are initialized) - no need to protect them with a mutex.
+ */
+int slap_debug = 0;
+
+#ifdef LDAP_DEBUG
+int ldap_syslog = LDAP_DEBUG_STATS;
+#else
+int ldap_syslog;
#endif
-init()
+int ldap_syslog_level = LOG_DEBUG;
+struct berval **default_referral = NULL;
+int g_argc;
+char **g_argv;
+
+/*
+ * global variables that need mutex protection
+ */
+int active_threads;
+ldap_pvt_thread_mutex_t active_threads_mutex;
+ldap_pvt_thread_cond_t active_threads_cond;
+
+ldap_pvt_thread_mutex_t gmtime_mutex;
+#ifdef SLAPD_CRYPT
+ldap_pvt_thread_mutex_t crypt_mutex;
+#endif
+
+int num_conns;
+long num_ops_initiated;
+long num_ops_completed;
+ldap_pvt_thread_mutex_t num_ops_mutex;
+
+long num_entries_sent;
+long num_refs_sent;
+long num_bytes_sent;
+long num_pdu_sent;
+ldap_pvt_thread_mutex_t num_sent_mutex;
+/*
+ * these mutexes must be used when calling the entry2str()
+ * routine since it returns a pointer to static data.
+ */
+ldap_pvt_thread_mutex_t entry2str_mutex;
+ldap_pvt_thread_mutex_t replog_mutex;
+
+static char* slap_name;
+int slapMode = SLAP_UNDEFINED_MODE;
+
+static ldap_pvt_thread_mutex_t currenttime_mutex;
+
+int
+slap_init( int mode, char *name )
{
- pthread_mutex_init( &active_threads_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &new_conn_mutex, pthread_mutexattr_default );
- pthread_mutex_init( ¤ttime_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &entry2str_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &replog_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &ops_mutex, pthread_mutexattr_default );
- pthread_mutex_init( &num_sent_mutex, pthread_mutexattr_default );
-#ifndef sunos5
- pthread_mutex_init( ®ex_mutex, pthread_mutexattr_default );
+ int rc;
+
+ if( slapMode != SLAP_UNDEFINED_MODE ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s init: init called twice (old=%d, new=%d)\n",
+ name, slapMode, mode );
+ return 1;
+ }
+
+ slapMode = mode;
+
+ switch ( slapMode ) {
+
+ case SLAP_SERVER_MODE:
+ case SLAP_TOOL_MODE:
+#ifdef SLAPD_BDB2
+ case SLAP_TIMEDSERVER_MODE:
+ case SLAP_TOOLID_MODE:
+#endif
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s init: initiated %s.\n",
+ name, mode == SLAP_TOOL_MODE ? "tool" : "server", 0 );
+
+ slap_name = name;
+
+ (void) ldap_pvt_thread_initialize();
+
+ ldap_pvt_thread_mutex_init( &active_threads_mutex );
+ ldap_pvt_thread_cond_init( &active_threads_cond );
+
+ ldap_pvt_thread_mutex_init( ¤ttime_mutex );
+ ldap_pvt_thread_mutex_init( &entry2str_mutex );
+ ldap_pvt_thread_mutex_init( &replog_mutex );
+ ldap_pvt_thread_mutex_init( &num_ops_mutex );
+ ldap_pvt_thread_mutex_init( &num_sent_mutex );
+
+ ldap_pvt_thread_mutex_init( &gmtime_mutex );
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_init( &crypt_mutex );
#endif
+
+ rc = backend_init();
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY,
+ "%s init: undefined mode (%d).\n", name, mode, 0 );
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+int slap_startup(int dbnum)
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s startup: initiated.\n",
+ slap_name, 0, 0 );
+
+ rc = backend_startup(dbnum);
+
+ return rc;
+}
+
+int slap_shutdown(int dbnum)
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s shutdown: initiated\n",
+ slap_name, 0, 0 );
+
+ /* let backends do whatever cleanup they need to do */
+ rc = backend_shutdown(dbnum);
+
+ return rc;
+}
+
+int slap_destroy(void)
+{
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "%s shutdown: freeing system resources.\n",
+ slap_name, 0, 0 );
+
+ rc = backend_destroy();
+
+ ldap_pvt_thread_destroy();
+
+ /* should destory the above mutex */
+ return rc;
+}
+
+/* should create a utils.c for these */
+time_t slap_get_time(void)
+{
+ time_t t;
+ ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
+ time( &t );
+ ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
+ return t;
}
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
-extern char *default_referral;
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
-extern int global_lastmod;
+#include "slap.h"
-static void modlist_free();
-static void add_lastmods();
+static void modlist_free(LDAPModList *ml);
-void
+int
do_modify(
Connection *conn,
Operation *op
)
{
- char *dn, *odn;
+ char *ndn;
char *last;
- unsigned long tag, len;
- LDAPMod *mods, *tmp;
- LDAPMod **modtail;
+ ber_tag_t tag;
+ ber_len_t len;
+ LDAPModList *modlist;
+ LDAPModList **modtail;
+#ifdef LDAP_DEBUG
+ LDAPModList *tmp;
+#endif
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_modify: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
+ "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the modify request. It looks like this:
*
* }
*/
- if ( ber_scanf( op->o_ber, "{a", &dn ) == LBER_ERROR ) {
+ if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
}
- odn = strdup( dn );
- dn_normalize( dn );
- Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 );
+
+ (void) dn_normalize_case( ndn );
/* collect modifications & save for later */
- mods = NULL;
- modtail = &mods;
+ modlist = NULL;
+ modtail = &modlist;
+
for ( tag = ber_first_element( op->o_ber, &len, &last );
tag != LBER_DEFAULT;
tag = ber_next_element( op->o_ber, &len, last ) )
{
- (*modtail) = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
+ ber_int_t mop;
- if ( ber_scanf( op->o_ber, "{i{a[V]}}", &(*modtail)->mod_op,
- &(*modtail)->mod_type, &(*modtail)->mod_bvalues )
+ (*modtail) = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+
+ if ( ber_scanf( op->o_ber, "{i{a[V]}}", &mop,
+ &(*modtail)->ml_type, &(*modtail)->ml_bvalues )
== LBER_ERROR )
{
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "decoding error" );
- free( dn );
- free( odn );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding modlist error" );
+ free( ndn );
free( *modtail );
- modlist_free( mods );
- return;
+ *modtail = NULL;
+ modlist_free( modlist );
+ return -1;
}
- if ( (*modtail)->mod_op != LDAP_MOD_ADD &&
- (*modtail)->mod_op != LDAP_MOD_DELETE &&
- (*modtail)->mod_op != LDAP_MOD_REPLACE )
+ (*modtail)->ml_op = mop;
+
+ if ( (*modtail)->ml_op != LDAP_MOD_ADD &&
+ (*modtail)->ml_op != LDAP_MOD_DELETE &&
+ (*modtail)->ml_op != LDAP_MOD_REPLACE )
{
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "unrecognized modify operation" );
- free( dn );
- free( odn );
- modlist_free( mods );
- return;
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "unrecognized modify operation", NULL );
+ free( ndn );
+ modlist_free( modlist );
+ return LDAP_PROTOCOL_ERROR;
}
- if ( (*modtail)->mod_bvalues == NULL && (*modtail)->mod_op
- != LDAP_MOD_DELETE ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "no values given" );
- free( dn );
- free( odn );
- modlist_free( mods );
- return;
+ if ( (*modtail)->ml_bvalues == NULL
+ && (*modtail)->ml_op != LDAP_MOD_DELETE )
+ {
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "unrecognized modify operation", NULL );
+ free( ndn );
+ modlist_free( modlist );
+ return LDAP_PROTOCOL_ERROR;
}
- attr_normalize( (*modtail)->mod_type );
+ attr_normalize( (*modtail)->ml_type );
- modtail = &(*modtail)->mod_next;
+ modtail = &(*modtail)->ml_next;
}
*modtail = NULL;
#ifdef LDAP_DEBUG
Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
- for ( tmp = mods; tmp != NULL; tmp = tmp->mod_next ) {
- Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->mod_op
- == LDAP_MOD_ADD ? "add" : (tmp->mod_op == LDAP_MOD_DELETE ?
- "delete" : "replace"), tmp->mod_type, 0 );
+ for ( tmp = modlist; tmp != NULL; tmp = tmp->ml_next ) {
+ Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
+ tmp->ml_op == LDAP_MOD_ADD
+ ? "add" : (tmp->ml_op == LDAP_MOD_DELETE
+ ? "delete" : "replace"), tmp->ml_type, 0 );
}
#endif
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ modlist_free( modlist );
+ Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MOD dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ conn->c_connid, op->o_opid, ndn, 0, 0 );
/*
* 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.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
- modlist_free( mods );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
+ modlist_free( modlist );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+ return rc;
}
+ /* alias suffix if approp */
+ ndn = suffixAlias ( ndn, op, be );
+
/*
* do the modify if 1 && (2 || 3)
* 1) there is a modify function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_modify != NULL ) {
+ if ( be->be_modify ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
- global_lastmod == ON) && be->be_updatedn == NULL ) {
- add_lastmods( op, &mods );
- }
- if ( (*be->be_modify)( be, conn, op, odn, mods )
- == 0 ) {
- replog( be, LDAP_REQ_MODIFY, dn, mods, 0 );
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+ {
+ if ( (*be->be_modify)( be, conn, op, ndn, modlist ) == 0 ) {
+ replog( be, LDAP_REQ_MODIFY, ndn, modlist, 0 );
}
/* send a referral */
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
}
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( dn );
- free( odn );
- modlist_free( mods );
+ free( ndn );
+ modlist_free( modlist );
+ return rc;
}
static void
modlist_free(
- LDAPMod *mods
+ LDAPModList *ml
)
{
- LDAPMod *next;
-
- for ( ; mods != NULL; mods = next ) {
- next = mods->mod_next;
- free( mods->mod_type );
- if ( mods->mod_bvalues != NULL )
- ber_bvecfree( mods->mod_bvalues );
- free( mods );
- }
-}
-
-static void
-add_lastmods( Operation *op, LDAPMod **mods )
-{
- char buf[20];
- struct berval bv;
- struct berval *bvals[2];
- LDAPMod **m;
- LDAPMod *tmp;
- struct tm *ltm;
+ LDAPModList *next;
- Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
+ for ( ; ml != NULL; ml = next ) {
+ next = ml->ml_next;
- bvals[0] = &bv;
- bvals[1] = NULL;
+ free( ml->ml_type );
+ if ( ml->ml_bvalues != NULL )
+ ber_bvecfree( ml->ml_bvalues );
- /* remove any attempts by the user to modify these attrs */
- for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
- if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0
- || strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ) {
- tmp = *m;
- *m = (*m)->mod_next;
- free( tmp->mod_type );
- if ( tmp->mod_bvalues != NULL ) {
- ber_bvecfree( tmp->mod_bvalues );
- }
- free( tmp );
- }
- }
-
- if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
- bv.bv_val = "NULLDN";
- bv.bv_len = strlen( bv.bv_val );
- } else {
- bv.bv_val = op->o_dn;
- bv.bv_len = strlen( bv.bv_val );
+ free( ml );
}
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = strdup( "modifiersname" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
- 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
-
- pthread_mutex_lock( ¤ttime_mutex );
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_unlock( ¤ttime_mutex );
- bv.bv_val = buf;
- bv.bv_len = strlen( bv.bv_val );
- tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
- tmp->mod_type = strdup( "modifytimestamp" );
- tmp->mod_op = LDAP_MOD_REPLACE;
- tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
- 2 * sizeof(struct berval *) );
- tmp->mod_bvalues[0] = ber_bvdup( &bv );
- tmp->mod_next = *mods;
- *mods = tmp;
}
* is provided ``as is'' without express or implied warranty.
*/
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Backend *select_backend();
+#include <ac/socket.h>
+#include <ac/string.h>
-extern char *default_referral;
+#include "slap.h"
-void
+int
do_modrdn(
Connection *conn,
Operation *op
)
{
- char *dn, *odn, *newrdn;
- int deloldrdn;
+ char *ndn, *newrdn;
+ ber_int_t deloldrdn;
Backend *be;
+ /* Vars for LDAP v3 newSuperior support */
+ char *newSuperior = NULL;
+ char *nnewSuperior = NULL;
+ Backend *newSuperior_be = NULL;
+ ber_len_t length;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
+ "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the modrdn request. It looks like this:
*
* ModifyRDNRequest := SEQUENCE {
* entry DistinguishedName,
* newrdn RelativeDistinguishedName
+ * deleteoldrdn BOOLEAN,
+ * newSuperior [0] LDAPDN OPTIONAL (v3 Only!)
* }
*/
- if ( ber_scanf( op->o_ber, "{aab}", &dn, &newrdn, &deloldrdn )
+ if ( ber_scanf( op->o_ber, "{aab", &ndn, &newrdn, &deloldrdn )
== LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ /* Check for newSuperior parameter, if present scan it */
+
+ if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
+
+ if ( op->o_protocol == 0 ) {
+ /*
+ * Promote to LDAPv3
+ */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ conn->c_protocol = LDAP_VERSION3;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ op->o_protocol = LDAP_VERSION3;
+
+ } else if ( op->o_protocol < LDAP_VERSION3 ) {
+ /* Conection record indicates v2 but field
+ * newSuperior is present: report error.
+ */
+ Debug( LDAP_DEBUG_ANY,
+ "modrdn(v2): invalid field newSuperior!\n",
+ 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
+ return -1;
+ }
+
+ if ( ber_scanf( op->o_ber, "a", &newSuperior )
+ == LBER_ERROR ) {
+
+ Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\"}) failed\n",
+ 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+
+ }
+
}
- odn = strdup( dn );
- dn_normalize( dn );
Debug( LDAP_DEBUG_ARGS,
- "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
- deloldrdn );
+ "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n",
+ ndn, newrdn,
+ newSuperior != NULL ? newSuperior : "" );
+
+ if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ return -1;
+ }
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
+ return rc;
+ }
+
+ if( newSuperior != NULL ) {
+ /* GET BACKEND FOR NEW SUPERIOR */
+
+ nnewSuperior = strdup( newSuperior );
+ dn_normalize_case( nnewSuperior );
+
+ if ( (newSuperior_be = select_backend( nnewSuperior ))
+ == NULL ) {
+
+ /* We do not have a backend for newSuperior so we send
+ * a referral.
+ * XXX: We may need to do something else here, not sure
+ * what though.
+ */
+
+ Debug( LDAP_DEBUG_ARGS,
+ "do_modrdn: cant find backend for=(%s)\n",
+ newSuperior, 0, 0 );
+
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+ return 0;
+ }
+ }
+
+ dn_normalize_case( ndn );
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MODRDN dn=\"%s\"\n",
- conn->c_connid, op->o_opid, dn, 0, 0 );
+ conn->c_connid, op->o_opid, ndn, 0, 0 );
/*
* We could be serving multiple database backends. Select the
* if we don't hold it.
*/
- if ( (be = select_backend( dn )) == NULL ) {
- free( dn );
- free( odn );
+ if ( (be = select_backend( ndn )) == NULL ) {
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+ return rc;
+ }
+
+ /* Make sure that the entry being changed and the newSuperior are in
+ * the same backend, otherwise we return an error.
+ */
+
+ if ( (newSuperior_be != NULL) && ( be != newSuperior_be) ) {
+
+ Debug( LDAP_DEBUG_ANY, "dn=(%s), newSuperior=(%s)\n", ndn,
+ newSuperior, 0 );
+
+ free( ndn );
free( newrdn );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
- return;
+ free( newSuperior );
+ free( nnewSuperior );
+
+ send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS,
+ NULL, NULL, NULL );
+
+ return rc;
+
}
+
+ /* alias suffix if approp */
+ ndn = suffixAlias( ndn, op, be );
+
/*
* do the add if 1 && (2 || 3)
* 1) there is an add function implemented in this backend;
* 2) this backend is master for what it holds;
- * 3) it's a replica and the dn supplied is the updatedn.
+ * 3) it's a replica and the dn supplied is the update_ndn.
*/
- if ( be->be_modrdn != NULL ) {
+ if ( be->be_modrdn ) {
/* do the update here */
- if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
- op->o_dn ) == 0 ) {
- if ( (*be->be_modrdn)( be, conn, op, dn, newrdn,
- deloldrdn ) == 0 ) {
- replog( be, LDAP_REQ_MODRDN, odn, newrdn,
+ if ( be->be_update_ndn == NULL ||
+ strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
+ {
+ if ( (*be->be_modrdn)( be, conn, op, ndn, newrdn,
+ deloldrdn, newSuperior ) == 0 ) {
+ /* XXX: MAY NEED TO ADD newSuperior HERE */
+ replog( be, LDAP_REQ_MODRDN, ndn, newrdn,
deloldrdn );
}
} else {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
}
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( dn );
- free( odn );
- free( newrdn );
+ free( ndn );
+ free( newrdn );
+ free( newSuperior );
+ free( nnewSuperior );
+ return rc;
}
* is provided ``as is'' without express or implied warranty.
*/
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "ldapconfig.h"
+#include "portable.h"
-#if defined( SLAPD_MONITOR_DN )
-
-extern int nbackends;
-extern Backend *backends;
-extern int active_threads;
-extern int dtblsize;
-extern Connection *c;
-extern long ops_initiated;
-extern long ops_completed;
-extern long num_entries_sent;
-extern long num_bytes_sent;
-extern time_t currenttime;
-extern time_t starttime;
-extern int num_conns;
+#include <stdio.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
-extern char Versionstr[];
+#include "ldap_defaults.h"
+#include "slap.h"
-/*
- * no mutex protection in here - take our chances!
- */
+#if defined( SLAPD_MONITOR_DN )
void
monitor_info( Connection *conn, Operation *op )
{
Entry *e;
- char buf[BUFSIZ], buf2[20];
+ char buf[BUFSIZ];
struct berval val;
struct berval *vals[2];
- int i, nconns, nwritewaiters, nreadwaiters;
+ int nconns, nwritewaiters, nreadwaiters;
struct tm *ltm;
- char *p, *tmpdn;
+ char *p;
+ char buf2[22];
+ char buf3[22];
+ Connection *c;
+ int connindex;
+ time_t currenttime;
vals[0] = &val;
vals[1] = NULL;
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+ /* initialize reader/writer lock */
e->e_attrs = NULL;
- e->e_dn = strdup( SLAPD_MONITOR_DN );
+ e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
+ e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) );
+ e->e_private = NULL;
- val.bv_val = Versionstr;
+ val.bv_val = (char *) Versionstr;
if (( p = strchr( Versionstr, '\n' )) == NULL ) {
val.bv_len = strlen( Versionstr );
} else {
}
attr_merge( e, "version", vals );
+ ldap_pvt_thread_mutex_lock( &active_threads_mutex );
sprintf( buf, "%d", active_threads );
+ ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "threads", vals );
nconns = 0;
nwritewaiters = 0;
nreadwaiters = 0;
- for ( i = 0; i < dtblsize; i++ ) {
- if ( c[i].c_sb.sb_sd != -1 ) {
- nconns++;
- if ( c[i].c_writewaiter ) {
- nwritewaiters++;
- }
- if ( c[i].c_gettingber ) {
- nreadwaiters++;
- }
- ltm = localtime( &c[i].c_starttime );
- strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
- pthread_mutex_lock( &c[i].c_dnmutex );
- sprintf( buf, "%d : %s : %ld : %ld : %s : %s%s", i,
- buf2, c[i].c_opsinitiated, c[i].c_opscompleted,
- c[i].c_dn ? c[i].c_dn : "NULLDN",
- c[i].c_gettingber ? "r" : "",
- c[i].c_writewaiter ? "w" : "" );
- pthread_mutex_unlock( &c[i].c_dnmutex );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attr_merge( e, "connection", vals );
+
+ /* loop through the connections */
+ for ( c = connection_first( &connindex );
+ c != NULL;
+ c = connection_next( c, &connindex ))
+ {
+ nconns++;
+ if ( c->c_writewaiter ) {
+ nwritewaiters++;
+ }
+ if ( c->c_currentber != NULL ) {
+ nreadwaiters++;
}
+
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( &c->c_starttime );
+ strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+
+ ltm = gmtime( &c->c_activitytime );
+ strftime( buf3, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( &c->.c_starttime );
+ strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
+
+ ltm = localtime( &c->c_activitytime );
+ strftime( buf3, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
+#endif
+
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
+ sprintf( buf,
+ "%ld : %ld "
+ ": %ld/%ld/%ld/%ld "
+ ": %ld/%ld/%ld "
+ ": %s%s%s%s%s%s "
+ ": %s : %s : %s "
+ ": %s : %s",
+
+ c->c_connid,
+ (long) c->c_protocol,
+
+ c->c_n_ops_received, c->c_n_ops_executing,
+ c->c_n_ops_pending, c->c_n_ops_completed,
+
+ /* add low-level counters here */
+ c->c_n_get, c->c_n_read, c->c_n_write,
+
+ c->c_currentber ? "r" : "",
+ c->c_writewaiter ? "w" : "",
+ c->c_ops != NULL ? "x" : "",
+ c->c_pending_ops != NULL ? "p" : "",
+ connection_state2str( c->c_conn_state ),
+ c->c_bind_in_progress ? "S" : "",
+
+ c->c_cdn ? c->c_cdn : "<anonymous>",
+ c->c_client_addr ? c->c_client_addr : "unknown",
+ c->c_client_name ? c->c_client_name : "unknown",
+
+ buf2,
+ buf3
+ );
+
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "connection", vals );
}
+ connection_done(c);
+
sprintf( buf, "%d", nconns );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "currentconnections", vals );
+ attr_merge( e, "currentConnections", vals );
- sprintf( buf, "%d", num_conns );
+ sprintf( buf, "%ld", connections_nextid() );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "totalconnections", vals );
+ attr_merge( e, "totalConnections", vals );
- sprintf( buf, "%d", dtblsize );
+ sprintf( buf, "%ld", (long) dtblsize );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "dtablesize", vals );
+ attr_merge( e, "dTableSize", vals );
sprintf( buf, "%d", nwritewaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "writewaiters", vals );
+ attr_merge( e, "writeWaiters", vals );
sprintf( buf, "%d", nreadwaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "readwaiters", vals );
+ attr_merge( e, "readWaiters", vals );
- sprintf( buf, "%ld", ops_initiated );
+ ldap_pvt_thread_mutex_lock(&num_ops_mutex);
+ sprintf( buf, "%ld", num_ops_initiated );
+ ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opsinitiated", vals );
+ attr_merge( e, "opsInitiated", vals );
- sprintf( buf, "%ld", ops_completed );
+ ldap_pvt_thread_mutex_lock(&num_ops_mutex);
+ sprintf( buf, "%ld", num_ops_completed );
+ ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opscompleted", vals );
+ attr_merge( e, "opsCompleted", vals );
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_entries_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "entriessent", vals );
+ attr_merge( e, "entriesSent", vals );
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_refs_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "referencesSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_pdu_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "pduSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_bytes_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "bytessent", vals );
+ attr_merge( e, "bytesSent", vals );
- ltm = localtime( ¤ttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+ currenttime = slap_get_time();
+
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "currenttime", vals );
- ltm = localtime( &starttime );
- strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( &starttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( &starttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "starttime", vals );
val.bv_len = strlen( buf );
attr_merge( e, "nbackends", vals );
-#ifdef THREAD_SUNOS5_LWP
- sprintf( buf, "%d", thr_getconcurrency() );
+#ifdef HAVE_THREAD_CONCURRENCY
+ sprintf( buf, "%d", ldap_pvt_thread_get_concurrency() );
val.bv_val = buf;
val.bv_len = strlen( buf );
attr_merge( e, "concurrency", vals );
#endif
- send_search_entry( &backends[0], conn, op, e, NULL, 0 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
+ send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
entry_free( e );
}
#ifndef _PROTO_SLAP
#define _PROTO_SLAP
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
+
/*
* acl.c
*/
-int access_allowed( Backend *be, Connection *conn, Operation *op, Entry *e,
- char *attr, struct berval *val, char *dn, int access );
-struct acl * acl_get_applicable( Backend *be, Operation *op, Entry *e,
- char *attr );
-int acl_access_allowed( struct acl *a, Backend *be, Connection *conn, Entry *e,
- struct berval *val, Operation *op, int access );
-int acl_check_mods( Backend *be, Connection *conn, Operation *op, Entry *e,
- LDAPMod *mods );
+int access_allowed LDAP_P(( Backend *be, Connection *conn,
+ Operation *op, Entry *e,
+ char *attr, struct berval *val, int access ));
+
+struct acl * acl_get_applicable LDAP_P(( Backend *be,
+ Operation *op, Entry *e,
+ char *attr, int nmatches, regmatch_t *matches ));
+
+int acl_access_allowed LDAP_P(( struct acl *a, Backend *be, Connection *conn, Entry *e,
+ struct berval *val, Operation *op, int access, char *edn,
+ regmatch_t *matches ));
+
+int acl_check_modlist LDAP_P(( Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ LDAPModList *ml ));
/*
* aclparse.c
*/
-void parse_acl( Backend *be, char *fname, int lineno, int argc, char **argv );
-char * access2str( int access );
-int str2access( char *str );
+void parse_acl LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
+char * access2str LDAP_P(( int access ));
+int str2access LDAP_P(( char *str ));
/*
* attr.c
*/
-void attr_free( Attribute *a );
-char * attr_normalize( char *s );
-int attr_merge_fast( Entry *e, char *type, struct berval **vals, int nvals,
- int naddvals, int *maxvals, Attribute ***a );
-int attr_merge( Entry *e, char *type, struct berval **vals );
-Attribute * attr_find( Attribute *a, char *type );
-int attr_delete( Attribute **attrs, char *type );
-int attr_syntax( char *type );
-void attr_syntax_config( char *fname, int lineno, int argc, char **argv );
+void attr_free LDAP_P(( Attribute *a ));
+char * attr_normalize LDAP_P(( char *s ));
+int attr_merge_fast LDAP_P(( Entry *e, char *type, struct berval **vals, int nvals,
+ int naddvals, int *maxvals, Attribute ***a ));
+int attr_merge LDAP_P(( Entry *e, char *type, struct berval **vals ));
+Attribute * attr_find LDAP_P(( Attribute *a, char *type ));
+int attr_delete LDAP_P(( Attribute **attrs, char *type ));
+int attr_syntax LDAP_P(( char *type ));
+void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
+AttributeType * at_find LDAP_P(( const char *name ));
+int at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **list ));
+int at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
+int at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
+int at_fake_if_needed LDAP_P(( char *name ));
+int at_schema_info LDAP_P(( Entry *e ));
+int at_add LDAP_P(( LDAP_ATTRIBUTE_TYPE *at, const char **err ));
+char * at_canonical_name LDAP_P(( char * a_type ));
/*
* ava.c
*/
-int get_ava( BerElement *ber, Ava *ava );
-void ava_free( Ava *ava, int freeit );
+int get_ava LDAP_P(( BerElement *ber, Ava *ava ));
+void ava_free LDAP_P(( Ava *ava, int freeit ));
/*
* backend.c
*/
-Backend * new_backend( char *type );
-Backend * select_backend( char * dn );
-int be_issuffix( Backend *be, char *suffix );
-int be_isroot( Backend *be, char *dn );
-int be_isroot_pw( Backend *be, char *dn, struct berval *cred );
-void be_close();
+int backend_init LDAP_P((void));
+int backend_add LDAP_P((BackendInfo *aBackendInfo));
+int backend_startup LDAP_P((int dbnum));
+int backend_shutdown LDAP_P((int dbnum));
+int backend_destroy LDAP_P((void));
+
+BackendInfo * backend_info LDAP_P(( char *type ));
+BackendDB * backend_db_init LDAP_P(( char *type ));
+
+BackendDB * select_backend LDAP_P(( char * dn ));
+
+int be_issuffix LDAP_P(( Backend *be, char *suffix ));
+int be_isroot LDAP_P(( Backend *be, char *ndn ));
+int be_isroot_pw LDAP_P(( Backend *be, char *ndn, struct berval *cred ));
+char* be_root_dn LDAP_P(( Backend *be ));
+int be_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw ));
+#define be_entry_release_r( be, e ) be_entry_release_rw( be, e, 0 )
+#define be_entry_release_w( be, e ) be_entry_release_rw( be, e, 1 )
+
+
+extern int backend_unbind LDAP_P((Connection *conn, Operation *op));
+
+extern int backend_connection_init LDAP_P((Connection *conn));
+extern int backend_connection_destroy LDAP_P((Connection *conn));
+
+extern int backend_group LDAP_P((Backend *be,
+ Entry *target,
+ char *gr_ndn, char *op_ndn,
+ char *objectclassValue, char *groupattrName));
/*
* ch_malloc.c
*/
-char * ch_malloc( unsigned long size );
-char * ch_realloc( char *block, unsigned long size );
-char * ch_calloc( unsigned long nelem, unsigned long size );
+void * ch_malloc LDAP_P(( ber_len_t size ));
+void * ch_realloc LDAP_P(( void *block, ber_len_t size ));
+void * ch_calloc LDAP_P(( ber_len_t nelem, ber_len_t size ));
+char * ch_strdup LDAP_P(( const char *string ));
+void ch_free LDAP_P(( void * ));
+#define free ch_free
/*
* charray.c
*/
-void charray_add( char ***a, char *s );
-void charray_merge( char ***a, char **s );
-void charray_free( char **array );
-int charray_inlist( char **a, char *s );
-char ** charray_dup( char **a );
-char ** str2charray( char *str, char *brkstr );
+void charray_add LDAP_P(( char ***a, char *s ));
+void charray_merge LDAP_P(( char ***a, char **s ));
+void charray_free LDAP_P(( char **array ));
+int charray_inlist LDAP_P(( char **a, char *s ));
+char ** charray_dup LDAP_P(( char **a ));
+char ** str2charray LDAP_P(( char *str, char *brkstr ));
+char * charray2str LDAP_P(( char **a ));
+
+/*
+ * controls.c
+ */
+int get_ctrls LDAP_P((
+ Connection *co,
+ Operation *op,
+ int senderrors ));
/*
* config.c
*/
-void read_config( char *fname, Backend **bep, FILE *pfp );
+int read_config LDAP_P(( char *fname ));
/*
* connection.c
*/
+int connections_init LDAP_P((void));
+int connections_shutdown LDAP_P((void));
+int connections_destroy LDAP_P((void));
+int connections_timeout_idle LDAP_P((time_t));
+
+long connection_init LDAP_P((
+ ber_socket_t s,
+ const char* name, const char* addr));
-void connection_activity( Connection *conn );
+void connection_closing LDAP_P(( Connection *c ));
+int connection_state_closing LDAP_P(( Connection *c ));
+char *connection_state2str LDAP_P(( int state ));
+
+int connection_write LDAP_P((ber_socket_t s));
+int connection_read LDAP_P((ber_socket_t s));
+
+unsigned long connections_nextid(void);
+
+Connection* connection_first LDAP_P((ber_socket_t *));
+Connection* connection_next LDAP_P((Connection *, ber_socket_t *));
+void connection_done LDAP_P((Connection *));
/*
* dn.c
*/
-char * dn_normalize( char *dn );
-char * dn_normalize_case( char *dn );
-char * dn_parent( Backend *be, char *dn );
-int dn_issuffix( char *dn, char *suffix );
-int dn_type( char *dn );
-char * dn_upcase( char *dn );
-
+char * dn_normalize LDAP_P(( char *dn ));
+char * dn_normalize_case LDAP_P(( char *dn ));
+char * dn_parent LDAP_P(( Backend *be, char *dn ));
+char * dn_rdn LDAP_P(( Backend *be, char *dn ));
+int dn_issuffix LDAP_P(( char *dn, char *suffix ));
+int dn_type LDAP_P(( char *dn ));
+char * dn_upcase LDAP_P(( char *dn ));
+char * rdn_attr_value LDAP_P(( char * rdn ));
+char * rdn_attr_type LDAP_P(( char * rdn ));
+void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
+ char * newrdn ));
/*
* entry.c
*/
-Entry * str2entry( char *s );
-char * entry2str( Entry *e, int *len, int printid );
-void entry_free( Entry *e );
+Entry * str2entry LDAP_P(( char *s ));
+char * entry2str LDAP_P(( Entry *e, int *len, int printid ));
+void entry_free LDAP_P(( Entry *e ));
+
+int entry_cmp LDAP_P(( Entry *a, Entry *b ));
+int entry_dn_cmp LDAP_P(( Entry *a, Entry *b ));
+int entry_id_cmp LDAP_P(( Entry *a, Entry *b ));
/*
* filter.c
*/
-int get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr );
-void filter_free( Filter *f );
-void filter_print( Filter *f );
+int get_filter LDAP_P(( Connection *conn, BerElement *ber, Filter **filt, char **fstr ));
+void filter_free LDAP_P(( Filter *f ));
+void filter_print LDAP_P(( Filter *f ));
/*
* filterentry.c
*/
-int test_filter( Backend *be, Connection *conn, Operation *op, Entry *e,
- Filter *f );
+int test_filter LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e,
+ Filter *f ));
/*
* lock.c
*/
-FILE * lock_fopen( char *fname, char *type, FILE **lfp );
-int lock_fclose( FILE *fp, FILE *lfp );
+FILE * lock_fopen LDAP_P(( char *fname, char *type, FILE **lfp ));
+int lock_fclose LDAP_P(( FILE *fp, FILE *lfp ));
+
+/*
+ * module.c
+ */
+
+#ifdef SLAPD_MODULES
+int load_module LDAP_P(( const char* file_name, int argc, char *argv[] ));
+#endif /* SLAPD_MODULES */
/*
* monitor.c
*/
+extern char *supportedExtensions[];
+extern char *supportedControls[];
+extern char *supportedSASLMechanisms[];
-void monitor_info( Connection *conn, Operation *op );
+void monitor_info LDAP_P(( Connection *conn, Operation *op ));
/*
* operation.c
*/
-void op_free( Operation *op );
-Operation * op_add( Operation **olist, BerElement *ber, unsigned long msgid,
- unsigned long tag, char *dn, int id, int connid );
-void op_delete( Operation **olist, Operation *op );
+void slap_op_free LDAP_P(( Operation *op ));
+Operation * slap_op_alloc LDAP_P((
+ BerElement *ber, ber_int_t msgid,
+ ber_tag_t tag, ber_int_t id ));
+
+int slap_op_add LDAP_P(( Operation **olist, Operation *op ));
+int slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
+Operation * slap_op_pop LDAP_P(( Operation **olist ));
/*
* phonetic.c
*/
-char * first_word( char *s );
-char * next_word( char *s );
-char * word_dup( char *w );
-char * phonetic( char *s );
+char * first_word LDAP_P(( char *s ));
+char * next_word LDAP_P(( char *s ));
+char * word_dup LDAP_P(( char *w ));
+char * phonetic LDAP_P(( char *s ));
/*
* repl.c
*/
-void replog( Backend *be, int optype, char *dn, void *change, int flag );
+void replog LDAP_P(( Backend *be, int optype, char *dn, void *change, int flag ));
/*
* result.c
*/
-void send_ldap_result( Connection *conn, Operation *op, int err, char *matched,
- char *text );
-void send_ldap_search_result( Connection *conn, Operation *op, int err,
- char *matched, char *text, int nentries );
-void close_connection( Connection *conn, int opconnid, int opid );
+void send_ldap_result LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *matched, char *text,
+ struct berval **refs ));
+
+void send_ldap_disconnect LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *text ));
+
+void send_search_result LDAP_P((
+ Connection *conn, Operation *op,
+ int err, char *matched, char *text,
+ struct berval **refs,
+ int nentries ));
+
+int send_search_reference LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, struct berval **refs,
+ struct berval ***v2refs ));
+
+int send_search_entry LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, char **attrs, int attrsonly, int opattrs ));
+
+int str2result LDAP_P(( char *s,
+ int *code, char **matched, char **info ));
/*
* schema.c
*/
-int oc_schema_check( Entry *e );
+int oc_schema_check LDAP_P(( Entry *e ));
+int oc_check_operational_attr LDAP_P(( char *type ));
+int oc_check_usermod_attr LDAP_P(( char *type ));
+int oc_check_no_usermod_attr LDAP_P(( char *type ));
+ObjectClass *oc_find LDAP_P((const char *ocname));
+int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, const char **err));
+Syntax *syn_find LDAP_P((const char *synname));
+int syn_add LDAP_P((LDAP_SYNTAX *syn, slap_syntax_check_func *check, const char **err));
+MatchingRule *mr_find LDAP_P((const char *mrname));
+int mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, slap_mr_compare_func *compare, const char **err));
+void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
+int schema_init LDAP_P((void));
+
/*
* schemaparse.c
*/
-void parse_oc( Backend *be, char *fname, int lineno, int argc, char **argv );
-
+void parse_oc_old LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
+void parse_oc LDAP_P(( char *fname, int lineno, char *line ));
+void parse_at LDAP_P(( char *fname, int lineno, char *line ));
+char *scherr2str LDAP_P((int code));
/*
* str2filter.c
*/
-Filter * str2filter( char *str );
+Filter * str2filter LDAP_P(( char *str ));
/*
* value.c
*/
-int value_add_fast( struct berval ***vals, struct berval **addvals, int nvals,
- int naddvals, int *maxvals );
-int value_add( struct berval ***vals, struct berval **addvals );
-void value_normalize( char *s, int syntax );
-int value_cmp( struct berval *v1, struct berval *v2, int syntax,
- int normalize );
-int value_ncmp( struct berval *v1, struct berval *v2, int syntax, int len,
- int normalize );
-int value_find( struct berval **vals, struct berval *v, int syntax,
- int normalize );
+int value_add_fast LDAP_P(( struct berval ***vals, struct berval **addvals, int nvals,
+ int naddvals, int *maxvals ));
+int value_add LDAP_P(( struct berval ***vals, struct berval **addvals ));
+void value_normalize LDAP_P(( char *s, int syntax ));
+int value_cmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax,
+ int normalize ));
+int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax,
+ int normalize ));
+
+/*
+ * suffixAlias.c
+ */
+char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be ));
+
+/*
+ * user.c
+ */
+#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
+void slap_init_user LDAP_P(( char *username, char *groupname ));
+#endif
+
+/*
+ * Other...
+ */
+
+extern struct berval **default_referral;
+extern char *replogfile;
+extern const char Versionstr[];
+extern int active_threads;
+extern int defsize;
+extern int deftime;
+extern int g_argc;
+extern int global_default_access;
+extern int global_lastmod;
+extern int global_idletimeout;
+extern int global_schemacheck;
+extern char *global_realm;
+extern int lber_debug;
+extern int ldap_syslog;
+
+extern ldap_pvt_thread_mutex_t num_sent_mutex;
+extern long num_bytes_sent;
+extern long num_pdu_sent;
+extern long num_entries_sent;
+extern long num_refs_sent;
+
+extern ldap_pvt_thread_mutex_t num_ops_mutex;
+extern long num_ops_completed;
+extern long num_ops_initiated;
+
+extern char *slapd_pid_file;
+extern char *slapd_args_file;
+extern char **g_argv;
+extern time_t starttime;
+
+time_t slap_get_time LDAP_P((void));
+
+extern ldap_pvt_thread_mutex_t active_threads_mutex;
+extern ldap_pvt_thread_cond_t active_threads_cond;
+
+extern ldap_pvt_thread_mutex_t entry2str_mutex;
+extern ldap_pvt_thread_mutex_t replog_mutex;
+
+#ifdef SLAPD_CRYPT
+extern ldap_pvt_thread_mutex_t crypt_mutex;
+#endif
+extern ldap_pvt_thread_mutex_t gmtime_mutex;
+
+extern struct acl *global_acl;
+
+int slap_init LDAP_P((int mode, char* name));
+int slap_startup LDAP_P((int dbnum));
+int slap_shutdown LDAP_P((int dbnum));
+int slap_destroy LDAP_P((void));
+
+struct sockaddr_in;
+
+struct slapd_args {
+ struct sockaddr_in *addr;
+ int tcps;
+};
+
+extern int slapd_daemon LDAP_P((struct slapd_args *args));
+extern int set_socket LDAP_P((struct sockaddr_in *addr));
+
+extern void slapd_set_write LDAP_P((ber_socket_t s, int wake));
+extern void slapd_clr_write LDAP_P((ber_socket_t s, int wake));
+extern void slapd_set_read LDAP_P((ber_socket_t s, int wake));
+extern void slapd_clr_read LDAP_P((ber_socket_t s, int wake));
+
+extern void slapd_remove LDAP_P((ber_socket_t s, int wake));
+
+extern void slap_set_shutdown LDAP_P((int sig));
+extern void slap_do_nothing LDAP_P((int sig));
+
+extern void config_info LDAP_P((Connection *conn, Operation *op));
+extern void root_dse_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
+
+extern int do_abandon LDAP_P((Connection *conn, Operation *op));
+extern int do_add LDAP_P((Connection *conn, Operation *op));
+extern int do_bind LDAP_P((Connection *conn, Operation *op));
+extern int do_compare LDAP_P((Connection *conn, Operation *op));
+extern int do_delete LDAP_P((Connection *conn, Operation *op));
+extern int do_modify LDAP_P((Connection *conn, Operation *op));
+extern int do_modrdn LDAP_P((Connection *conn, Operation *op));
+extern int do_search LDAP_P((Connection *conn, Operation *op));
+extern int do_unbind LDAP_P((Connection *conn, Operation *op));
+extern int do_extended LDAP_P((Connection *conn, Operation *op));
+
+
+extern ber_socket_t dtblsize;
+
+LDAP_END_DECL
#endif /* _proto_slap */
+
/* result.c - routines to send ldap results, errors, and referrals */
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <signal.h>
#include "portable.h"
-#include "slap.h"
-#ifndef SYSERRLIST_IN_STDIO
-extern int sys_nerr;
-extern char *sys_errlist[];
-#endif
-extern int active_threads;
-extern pthread_mutex_t active_threads_mutex;
-extern pthread_mutex_t new_conn_mutex;
-extern pthread_t listener_tid;
-extern struct acl *acl_get_applicable();
-extern long num_entries_sent;
-extern long num_bytes_sent;
-extern pthread_mutex_t num_sent_mutex;
+#include <stdio.h>
-void close_connection();
+#include <ac/socket.h>
+#include <ac/errno.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
-static void
-send_ldap_result2(
- Connection *conn,
- Operation *op,
- int err,
- char *matched,
- char *text,
- int nentries
-)
+#include "slap.h"
+
+/* we need LBER internals */
+#include "../../libraries/liblber/lber-int.h"
+
+static char *v2ref( struct berval **ref )
{
- BerElement *ber;
- int rc, sd;
- unsigned long tag, bytes;
+ size_t len, i;
+ char *v2;
- Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", err, matched ?
- matched : "", text ? text : "" );
+ if(ref == NULL) return NULL;
- switch ( op->o_tag ) {
- case LBER_DEFAULT:
- tag = LBER_SEQUENCE;
- break;
+ len = sizeof("Referral:");
+ v2 = ch_strdup("Referral:");
+
+ for( i=0; ref[i] != NULL; i++ ) {
+ v2 = ch_realloc( v2, len + ref[i]->bv_len + 1 );
+ v2[len-1] = '\n';
+ memcpy(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
+ len += ref[i]->bv_len;
+ }
- case LDAP_REQ_SEARCH:
- tag = LDAP_RES_SEARCH_RESULT;
+ v2[len-1] = '\0';
+ return v2;
+}
+
+static ber_tag_t req2res( ber_tag_t tag )
+{
+ switch( tag ) {
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_COMPARE:
+ case LDAP_REQ_EXTENDED:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_MODRDN:
+ tag++;
break;
case LDAP_REQ_DELETE:
tag = LDAP_RES_DELETE;
break;
- default:
- tag = op->o_tag + 1;
+ case LDAP_REQ_ABANDON:
+ case LDAP_REQ_UNBIND:
+ tag = LBER_SEQUENCE;
break;
}
+ return tag;
+}
-#ifdef COMPAT30
- if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
- == NULLBER ) {
-#else
- if ( (ber = der_alloc()) == NULLBER ) {
-#endif
- Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- return;
- }
-#ifdef CLDAP
- if ( op->o_cldap ) {
- rc = ber_printf( ber, "{is{t{ess}}}", op->o_msgid, "", tag,
- err, matched ? matched : "", text ? text : "" );
- } else
-#endif
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "{it{{ess}}}", op->o_msgid, tag, err,
- matched ? matched : "", text ? text : "" );
- } else
-#endif
- rc = ber_printf( ber, "{it{ess}}", op->o_msgid, tag, err,
- matched ? matched : "", text ? text : "" );
-
- if ( rc == -1 ) {
- Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
- return;
- }
+long send_ldap_ber(
+ Connection *conn,
+ BerElement *ber )
+{
+ ber_len_t bytes = ber_pvt_ber_bytes( ber );
/* write only one pdu at a time - wait til it's our turn */
- pthread_mutex_lock( &conn->c_pdumutex );
+ ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+
+ /* lock the connection */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/* write the pdu */
- bytes = ber->ber_ptr - ber->ber_buf;
- pthread_mutex_lock( &new_conn_mutex );
- while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
- 1 ) != 0 ) {
- pthread_mutex_unlock( &new_conn_mutex );
+ while( 1 ) {
+ int err;
+
+ if ( connection_state_closing( conn ) ) {
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ return 0;
+ }
+
+ if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
+ break;
+ }
+
+ err = errno;
+
/*
* we got an error. if it's ewouldblock, we need to
* wait on the socket being writable. otherwise, figure
*/
Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
+ err, err > -1 && err < sys_nerr ? sys_errlist[err]
: "unknown", 0 );
- if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
- close_connection( conn, op->o_connid, op->o_opid );
+ if ( err != EWOULDBLOCK && err != EAGAIN ) {
+ connection_closing( conn );
- pthread_mutex_unlock( &conn->c_pdumutex );
- return;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ return( -1 );
}
/* wait for socket to be write-ready */
- pthread_mutex_lock( &active_threads_mutex );
- active_threads--;
conn->c_writewaiter = 1;
- pthread_kill( listener_tid, SIGUSR1 );
- pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
- pthread_mutex_unlock( &active_threads_mutex );
+ slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
- pthread_yield();
- pthread_mutex_lock( &new_conn_mutex );
+ ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+ conn->c_writewaiter = 0;
}
- pthread_mutex_unlock( &new_conn_mutex );
- pthread_mutex_unlock( &conn->c_pdumutex );
- pthread_mutex_lock( &num_sent_mutex );
- num_bytes_sent += bytes;
- pthread_mutex_unlock( &num_sent_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d op=%d RESULT err=%d tag=%d nentries=%d\n", conn->c_connid,
- op->o_opid, err, tag, nentries );
+ Debug( LDAP_DEBUG_TRACE, "<= send_ldap_ber\n", 0, 0, 0 );
+ return bytes;
+}
+
+static void
+send_ldap_response(
+ Connection *conn,
+ Operation *op,
+ ber_tag_t tag,
+ ber_int_t msgid,
+ ber_int_t err,
+ char *matched,
+ char *text,
+ struct berval **ref,
+ char *resoid,
+ struct berval *resdata
+)
+{
+ BerElement *ber;
+ int rc;
+ long bytes;
+
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
+ return;
+ }
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
+ err, matched ? matched : "", text ? text : "" );
+ } else
+#endif
+ {
+ rc = ber_printf( ber, "{it{ess",
+ msgid, tag, err,
+ matched == NULL ? "" : matched,
+ text == NULL ? "" : text );
+
+ if( rc != -1 && ref != NULL ) {
+ rc = ber_printf( ber, "{v}", ref );
+ }
+
+ if( rc != -1 && resoid != NULL ) {
+ rc = ber_printf( ber, "s", resoid );
+ }
+
+ if( rc != -1 && resdata != NULL ) {
+ rc = ber_printf( ber, "O", resdata );
+
+ }
+
+ if( rc != -1 ) {
+ rc = ber_printf( ber, "}}" );
+ }
+ }
+
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ return;
+ }
+
+ /* send BER */
+ bytes = send_ldap_ber( conn, ber );
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return;
+ }
+
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
return;
}
+
void
-send_ldap_result(
+send_ldap_disconnect(
Connection *conn,
Operation *op,
- int err,
- char *matched,
+ ber_int_t err,
char *text
)
{
-#ifdef CLDAP
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *reqoid;
+
+#define LDAP_UNSOLICITED_ERROR(e) \
+ ( (e) == LDAP_PROTOCOL_ERROR \
+ || (e) == LDAP_STRONG_AUTH_REQUIRED \
+ || (e) == LDAP_UNAVAILABLE )
+
+ assert( LDAP_UNSOLICITED_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "send_ldap_disconnect %d:%s\n",
+ err, text ? text : "", NULL );
+
+ if ( op->o_protocol < LDAP_VERSION3 ) {
+ reqoid = NULL;
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+ } else {
+ reqoid = LDAP_NOTICE_DISCONNECT;
+ tag = LDAP_RES_EXTENDED;
+ msgid = 0;
+ }
+
+#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- SAFEMEMCPY( (char *)conn->c_sb.sb_useaddr, &op->o_clientaddr,
- sizeof( struct sockaddr ));
+ ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
- conn->c_sb.sb_useaddr)->sin_addr ),
- ((struct sockaddr_in *) conn->c_sb.sb_useaddr)->sin_port,
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
0 );
}
#endif
- send_ldap_result2( conn, op, err, matched, text, 0 );
+ send_ldap_response( conn, op, tag, msgid,
+ err, NULL, text, NULL,
+ reqoid, NULL );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) tag, (long) err, text );
}
void
-send_ldap_search_result(
+send_ldap_result(
Connection *conn,
Operation *op,
- int err,
+ ber_int_t err,
char *matched,
char *text,
+ struct berval **ref
+)
+{
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+
+ assert( !LDAP_API_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
+ err, matched ? matched : "", text ? text : "" );
+
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ if ( err == LDAP_REFERRAL ) {
+ if( ref == NULL ) {
+ err = LDAP_NO_SUCH_OBJECT;
+ } else if ( op->o_protocol < LDAP_VERSION3 ) {
+ err = LDAP_PARTIAL_RESULTS;
+ tmp = text = v2ref( ref );
+ ref = NULL;
+ }
+ }
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
+ Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
+ inet_ntoa(((struct sockaddr_in *)
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+ 0 );
+ }
+#endif
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, ref,
+ NULL, NULL );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld RESULT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) err, (long) tag, text );
+
+ if( tmp != NULL ) {
+ free(tmp);
+ }
+}
+
+
+void
+send_search_result(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ char *matched,
+ char *text,
+ struct berval **refs,
int nentries
)
{
- send_ldap_result2( conn, op, err, matched, text, nentries );
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+ assert( !LDAP_API_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_search_result %d:%s:%s\n",
+ err, matched ? matched : "", text ? text : "" );
+
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* send references in search results */
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_PARTIAL_RESULTS;
+ tmp = text = v2ref( refs );
+ refs = NULL;
+ }
+
+ } else {
+ /* don't send references in search results */
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_SUCCESS;
+ refs = NULL;
+ }
+ }
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
+ Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
+ inet_ntoa(((struct sockaddr_in *)
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+ 0 );
+ }
+#endif
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, refs,
+ NULL, NULL );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld SEARCH RESULT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) err, (long) tag, text );
+
}
+
int
send_search_entry(
Backend *be,
Operation *op,
Entry *e,
char **attrs,
- int attrsonly
+ int attrsonly,
+ int opattrs
)
{
BerElement *ber;
Attribute *a;
- int i, rc, bytes, sd;
+ int i, rc=-1, bytes;
struct acl *acl;
+ char *edn;
Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
- if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
- ACL_READ ) ) {
+#if defined( SLAPD_SCHEMA_DN )
+ {
+ /* this could be backend specific */
+ struct berval val;
+ val.bv_val = SLAPD_SCHEMA_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "subschemaSubentry", vals );
+ ldap_memfree( val.bv_val );
+ }
+#endif
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_READ ) )
+ {
Debug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n",
0, 0, 0 );
return( 1 );
}
-#ifdef COMPAT30
- if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
- == NULLBER ) {
-#else
- if ( (ber = der_alloc()) == NULLBER ) {
-#endif
+ edn = e->e_ndn;
+
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ if ( ber == NULL ) {
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_alloc" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "allocating BER error", NULL );
+ goto error_return;
}
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "{it{{s{", op->o_msgid,
- LDAP_RES_SEARCH_ENTRY, e->e_dn );
- } else
-#endif
- rc = ber_printf( ber, "{it{s{", op->o_msgid,
- LDAP_RES_SEARCH_ENTRY, e->e_dn );
+ rc = ber_printf( ber, "{it{s{", op->o_msgid,
+ LDAP_RES_SEARCH_ENTRY, e->e_dn );
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf dn" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding dn error", NULL );
+ goto error_return;
}
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( attrs != NULL && ! charray_inlist( attrs, a->a_type ) ) {
- continue;
+ regmatch_t matches[MAXREMATCHES];
+
+ if ( attrs == NULL ) {
+ /* all addrs request, skip operational attributes */
+ if( !opattrs && oc_check_operational_attr( a->a_type )) {
+ continue;
+ }
+
+ } else {
+ /* specific addrs requested */
+ if ( !charray_inlist( attrs, a->a_type )
+ && !charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES ) )
+ {
+ continue;
+ }
}
- acl = acl_get_applicable( be, op, e, a->a_type );
+ acl = acl_get_applicable( be, op, e, a->a_type,
+ MAXREMATCHES, matches );
- if ( ! acl_access_allowed( acl, be, conn, e, NULL, op,
- ACL_READ ) ) {
+ if ( ! acl_access_allowed( acl, be, conn, e,
+ NULL, op, ACL_READ, edn, matches ) )
+ {
continue;
}
- if ( ber_printf( ber, "{s[", a->a_type ) == -1 ) {
+ if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type" );
- return( 1 );
+ NULL, "encoding type error", NULL );
+ goto error_return;
}
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
- if ( a->a_syntax & SYNTAX_DN &&
- ! acl_access_allowed( acl, be, conn, e,
- a->a_vals[i], op, ACL_READ ) )
+ if ( a->a_syntax & SYNTAX_DN &&
+ ! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
+ ACL_READ, edn, matches) )
{
continue;
}
- if ( ber_printf( ber, "o",
- a->a_vals[i]->bv_val,
- a->a_vals[i]->bv_len ) == -1 )
- {
+ if (( rc = ber_printf( ber, "O", a->a_vals[i] )) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op,
- LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf value" );
- return( 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding value error", NULL );
+ goto error_return;
}
}
}
- if ( ber_printf( ber, "]}" ) == -1 ) {
+ if (( rc = ber_printf( ber, /*{[*/ "]}" )) == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type end" );
- return( 1 );
+ NULL, "encode end error", NULL );
+ goto error_return;
}
}
-#ifdef COMPAT30
- if ( conn->c_version == 30 ) {
- rc = ber_printf( ber, "}}}}" );
- } else
-#endif
- rc = ber_printf( ber, "}}}" );
+ rc = ber_printf( ber, /*{{{*/ "}}}" );
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf entry end" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode entry end error", NULL );
return( 1 );
}
- /* write only one pdu at a time - wait til it's our turn */
- pthread_mutex_lock( &conn->c_pdumutex );
+ bytes = send_ldap_ber( conn, ber );
- bytes = ber->ber_ptr - ber->ber_buf;
- pthread_mutex_lock( &new_conn_mutex );
- while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
- 1 ) != 0 ) {
- pthread_mutex_unlock( &new_conn_mutex );
- /*
- * we got an error. if it's ewouldblock, we need to
- * wait on the socket being writable. otherwise, figure
- * it's a hard error and return.
- */
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
- Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
- errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
- : "unknown", 0 );
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_entries_sent++;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
- if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
- close_connection( conn, op->o_connid, op->o_opid );
+ Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+ (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
- pthread_mutex_unlock( &conn->c_pdumutex );
- return( -1 );
+ Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
+
+ rc = 0;
+
+error_return:;
+ return( rc );
+}
+
+int
+send_search_reference(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ struct berval **refs,
+ struct berval ***v2refs
+)
+{
+ BerElement *ber;
+ int rc;
+ int bytes;
+
+ Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to entry not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "ref", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to reference not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ if( refs == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: null ref in (%s)\n",
+ e->e_dn, 0, 0 );
+ return( 1 );
+ }
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* save the references for the result */
+ if( *refs == NULL ) {
+ value_add( v2refs, refs );
}
+ return 0;
+ }
- /* wait for socket to be write-ready */
- pthread_mutex_lock( &active_threads_mutex );
- active_threads--;
- conn->c_writewaiter = 1;
- pthread_kill( listener_tid, SIGUSR1 );
- pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
- pthread_mutex_unlock( &active_threads_mutex );
+ ber = ber_alloc_t( LBER_USE_DER );
- pthread_yield();
- pthread_mutex_lock( &new_conn_mutex );
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_alloc failed\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "alloc BER error", NULL );
+ return -1;
}
- pthread_mutex_unlock( &new_conn_mutex );
- pthread_mutex_unlock( &conn->c_pdumutex );
- pthread_mutex_lock( &num_sent_mutex );
- num_bytes_sent += bytes;
- num_entries_sent++;
- pthread_mutex_unlock( &num_sent_mutex );
+ rc = ber_printf( ber, "{it{V}}", op->o_msgid,
+ LDAP_RES_SEARCH_REFERENCE, refs );
- pthread_mutex_lock( &new_conn_mutex );
- if ( conn->c_connid == op->o_connid ) {
- rc = 0;
- Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
- conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
- } else {
- rc = -1;
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode dn error", NULL );
+ return -1;
}
- pthread_mutex_unlock( &new_conn_mutex );
+
+ bytes = send_ldap_ber( conn, ber );
+
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_refs_sent++;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+
+ Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+ (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
- return( rc );
+ return 0;
}
+
int
str2result(
char *s,
return( rc );
}
-
-/*
- * close_connection - close a connection. takes the connection to close,
- * the connid associated with the operation generating the close (so we
- * don't accidentally close a connection that's not ours), and the opid
- * of the operation generating the close (for logging purposes).
- */
-void
-close_connection( Connection *conn, int opconnid, int opid )
-{
- pthread_mutex_lock( &new_conn_mutex );
- if ( conn->c_sb.sb_sd != -1 && conn->c_connid == opconnid ) {
- Statslog( LDAP_DEBUG_STATS,
- "conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid,
- opid, conn->c_sb.sb_sd, errno, 0 );
- close( conn->c_sb.sb_sd );
- conn->c_sb.sb_sd = -1;
- conn->c_version = 0;
- }
- pthread_mutex_unlock( &new_conn_mutex );
-}
--- /dev/null
+/* root_dse.c - Provides the ROOT DSA-Specific Entry
+ *
+ * Copyright 1999 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "ldap_defaults.h"
+#include "slap.h"
+
+void
+root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
+{
+ char buf[BUFSIZ];
+ Entry *e;
+ struct berval val;
+ struct berval *vals[2];
+ int i, j;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+ e->e_attrs = NULL;
+ e->e_dn = ch_strdup( LDAP_ROOT_DSE );
+ e->e_ndn = dn_normalize_case( ch_strdup( LDAP_ROOT_DSE ));
+ e->e_private = NULL;
+
+ for ( i = 0; i < nbackends; i++ ) {
+ for ( j = 0; backends[i].be_suffix[j] != NULL; j++ ) {
+ val.bv_val = backends[i].be_suffix[j];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+ }
+ }
+
+#if defined( SLAPD_MONITOR_DN )
+ val.bv_val = SLAPD_MONITOR_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+ /* subschemasubentry is added by send_search_entry() */
+#endif
+
+#if defined( SLAPD_CONFIG_DN )
+ val.bv_val = SLAPD_CONFIG_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+#endif
+
+#if defined( SLAPD_SCHEMA_DN )
+ val.bv_val = SLAPD_SCHEMA_DN;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "namingContexts", vals );
+#endif
+
+ /* altServer unsupported */
+
+ /* supportedControl */
+ for ( i=0; supportedControls[i] != NULL; i++ ) {
+ val.bv_val = supportedControls[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedControl", vals );
+ }
+
+ /* supportedExtension */
+ for ( i=0; supportedExtensions[i] != NULL; i++ ) {
+ val.bv_val = supportedExtensions[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedExtension", vals );
+ }
+
+ /* supportedLDAPVersion */
+ for ( i=LDAP_VERSION_MIN; i<=LDAP_VERSION_MAX; i++ ) {
+ sprintf(buf,"%d",i);
+ val.bv_val = buf;
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedLDAPVersion", vals );
+ }
+
+ /* supportedSASLMechanism */
+ for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
+ val.bv_val = supportedSASLMechanisms[i];
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "supportedSASLMechanism", vals );
+ }
+
+ if ( default_referral != NULL ) {
+ attr_merge( e, "ref", default_referral );
+ }
+
+ send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 1 );
+ send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
+
+ entry_free( e );
+}
+
/* schema.c - routines to enforce schema definitions */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-extern Attribute *attr_find();
-extern char **str2charray();
-extern void charray_merge();
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
-extern struct objclass *global_oc;
-extern int global_schemacheck;
+#include "ldap_defaults.h"
+#include "slap.h"
-static struct objclass *oc_find();
-static int oc_check_required();
-static int oc_check_allowed();
+static char * oc_check_required(Entry *e, char *ocname);
+static int oc_check_allowed(char *type, struct berval **ocl);
/*
* oc_check - check that entry e conforms to the schema required by
oc_schema_check( Entry *e )
{
Attribute *a, *aoc;
- struct objclass *oc;
int i;
int ret = 0;
if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n",
e->e_dn, 0, 0 );
- return( 0 );
+ return( 1 );
}
/* check that the entry has required attrs for each oc */
for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
- if ( oc_check_required( e, aoc->a_vals[i]->bv_val ) != 0 ) {
+ char *s = oc_check_required( e, aoc->a_vals[i]->bv_val );
+
+ if (s != NULL) {
Debug( LDAP_DEBUG_ANY,
- "Entry (%s), required attr (%s) missing\n",
- e->e_dn, aoc->a_vals[i]->bv_val, 0 );
+ "Entry (%s), oc \"%s\" requires attr \"%s\"\n",
+ e->e_dn, aoc->a_vals[i]->bv_val, s );
ret = 1;
}
}
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) {
Debug( LDAP_DEBUG_ANY,
- "Entry (%s), attr (%s) not allowed\n",
+ "Entry (%s), attr \"%s\" not allowed\n",
e->e_dn, a->a_type, 0 );
ret = 1;
}
return( ret );
}
-static int
+static char *
oc_check_required( Entry *e, char *ocname )
{
- struct objclass *oc;
+ ObjectClass *oc;
+ AttributeType *at;
int i;
Attribute *a;
+ char **pp;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "oc_check_required entry (%s), objectclass \"%s\"\n",
+ e->e_dn, ocname, 0 );
/* find global oc defn. it we don't know about it assume it's ok */
if ( (oc = oc_find( ocname )) == NULL ) {
return( 0 );
}
+ /* check for empty oc_required */
+ if(oc->soc_required == NULL) {
+ return( 0 );
+ }
+
/* for each required attribute */
- for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
+ for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
+ at = oc->soc_required[i];
/* see if it's in the entry */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( strcasecmp( a->a_type, oc->oc_required[i] )
- == 0 ) {
+ if ( at->sat_oid &&
+ strcmp( a->a_type, at->sat_oid ) == 0 ) {
+ break;
+ }
+ pp = at->sat_names;
+ if ( pp == NULL ) {
+ /* Empty name list => not found */
+ a = NULL;
+ break;
+ }
+ while ( *pp ) {
+ if ( strcasecmp( a->a_type, *pp ) == 0 ) {
+ break;
+ }
+ pp++;
+ }
+ if ( *pp ) {
break;
}
}
-
/* not there => schema violation */
if ( a == NULL ) {
- return( 1 );
+ if ( at->sat_names && at->sat_names[0] ) {
+ return at->sat_names[0];
+ } else {
+ return at->sat_oid;
+ }
}
}
- return( 0 );
+ return( NULL );
+}
+
+static char *oc_usermod_attrs[] = {
+ /*
+ * OpenLDAP doesn't support any user modification of
+ * operational attributes.
+ */
+ NULL
+};
+
+static char *oc_operational_attrs[] = {
+ /*
+ * these are operational attributes that *could* be
+ * modified by users if we supported such.
+ */
+ "objectClasses",
+ "attributeTypes",
+ "matchingRules",
+ "matchingRuleUse",
+ "dITStructureRules",
+ "dITContentRules",
+ "nameForms",
+ "ldapSyntaxes",
+ NULL
+
+};
+
+/* this list should be extensible */
+static char *oc_no_usermod_attrs[] = {
+ /*
+ * Operational and 'no user modification' attributes
+ */
+
+ /* RFC2252, 3.2.1 */
+ "creatorsName",
+ "createTimestamp",
+ "modifiersName",
+ "modifyTimestamp",
+ "subschemaSubentry",
+
+ NULL
+};
+
+
+/*
+ * check to see if attribute is 'operational' or not.
+ */
+int
+oc_check_operational_attr( char *type )
+{
+ return charray_inlist( oc_operational_attrs, type )
+ || charray_inlist( oc_usermod_attrs, type )
+ || charray_inlist( oc_no_usermod_attrs, type );
+}
+
+/*
+ * check to see if attribute can be user modified or not.
+ */
+int
+oc_check_usermod_attr( char *type )
+{
+ return charray_inlist( oc_usermod_attrs, type );
+}
+
+/*
+ * check to see if attribute is 'no user modification' or not.
+ */
+int
+oc_check_no_usermod_attr( char *type )
+{
+ return charray_inlist( oc_no_usermod_attrs, type );
}
+
static int
oc_check_allowed( char *type, struct berval **ocl )
{
- struct objclass *oc;
+ ObjectClass *oc;
+ AttributeType *at;
int i, j;
+ char **pp;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "oc_check_allowed type \"%s\"\n", type, 0, 0 );
/* always allow objectclass attribute */
if ( strcasecmp( type, "objectclass" ) == 0 ) {
return( 0 );
}
+ /*
+ * All operational attributions are allowed by schema rules.
+ * However, we only check attributions which are stored in the
+ * the directory regardless if they are user or non-user modified.
+ */
+ if ( oc_check_usermod_attr( type ) || oc_check_no_usermod_attr( type ) ) {
+ return( 0 );
+ }
+
/* check that the type appears as req or opt in at least one oc */
for ( i = 0; ocl[i] != NULL; i++ ) {
/* if we know about the oc */
if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
/* does it require the type? */
- for ( j = 0; oc->oc_required[j] != NULL; j++ ) {
- if ( strcasecmp( oc->oc_required[j], type )
- == 0 ) {
+ for ( j = 0; oc->soc_required != NULL &&
+ oc->soc_required[j] != NULL; j++ ) {
+ at = oc->soc_required[j];
+ if ( at->sat_oid &&
+ strcmp(at->sat_oid, type ) == 0 ) {
return( 0 );
}
+ pp = at->sat_names;
+ if ( pp == NULL )
+ continue;
+ while ( *pp ) {
+ if ( strcasecmp( *pp, type ) == 0 ) {
+ return( 0 );
+ }
+ pp++;
+ }
}
/* does it allow the type? */
- for ( j = 0; oc->oc_allowed[j] != NULL; j++ ) {
- if ( strcasecmp( oc->oc_allowed[j], type )
- == 0 || strcmp( oc->oc_allowed[j], "*" )
- == 0 )
- {
+ for ( j = 0; oc->soc_allowed != NULL &&
+ oc->soc_allowed[j] != NULL; j++ ) {
+ at = oc->soc_allowed[j];
+ if ( at->sat_oid &&
+ strcmp(at->sat_oid, type ) == 0 ) {
return( 0 );
}
+ pp = at->sat_names;
+ if ( pp == NULL )
+ continue;
+ while ( *pp ) {
+ if ( strcasecmp( *pp, type ) == 0 ||
+ strcmp( *pp, "*" ) == 0 ) {
+ return( 0 );
+ }
+ pp++;
+ }
}
/* maybe the next oc allows it */
return( 1 );
}
-static struct objclass *
-oc_find( char *ocname )
+struct oindexrec {
+ char *oir_name;
+ ObjectClass *oir_oc;
+};
+
+static Avlnode *oc_index = NULL;
+static ObjectClass *oc_list = NULL;
+
+static int
+oc_index_cmp(
+ struct oindexrec *oir1,
+ struct oindexrec *oir2
+)
+{
+ return (strcasecmp( oir1->oir_name, oir2->oir_name ));
+}
+
+static int
+oc_index_name_cmp(
+ char *name,
+ struct oindexrec *oir
+)
+{
+ return (strcasecmp( name, oir->oir_name ));
+}
+
+ObjectClass *
+oc_find( const char *ocname )
+{
+ struct oindexrec *oir = NULL;
+
+ if ( (oir = (struct oindexrec *) avl_find( oc_index, ocname,
+ (AVL_CMP) oc_index_name_cmp )) != NULL ) {
+ return( oir->oir_oc );
+ }
+ return( NULL );
+}
+
+static int
+oc_create_required(
+ ObjectClass *soc,
+ char **attrs,
+ const char **err
+)
{
- struct objclass *oc;
+ char **attrs1;
+ AttributeType *sat;
+ AttributeType **satp;
+ int i;
- for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
- if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
- return( oc );
+ if ( attrs ) {
+ attrs1 = attrs;
+ while ( *attrs1 ) {
+ sat = at_find(*attrs1);
+ if ( !sat ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ if ( at_find_in_list(sat, soc->soc_required) < 0) {
+ if ( at_append_to_list(sat, &soc->soc_required) ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ }
+ attrs1++;
+ }
+ /* Now delete duplicates from the allowed list */
+ for ( satp = soc->soc_required; *satp; satp++ ) {
+ i = at_find_in_list(*satp,soc->soc_allowed);
+ if ( i >= 0 ) {
+ at_delete_from_list(i, &soc->soc_allowed);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+oc_create_allowed(
+ ObjectClass *soc,
+ char **attrs,
+ const char **err
+)
+{
+ char **attrs1;
+ AttributeType *sat;
+
+ if ( attrs ) {
+ attrs1 = attrs;
+ while ( *attrs1 ) {
+ sat = at_find(*attrs1);
+ if ( !sat ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ if ( at_find_in_list(sat, soc->soc_required) < 0 &&
+ at_find_in_list(sat, soc->soc_allowed) < 0 ) {
+ if ( at_append_to_list(sat, &soc->soc_allowed) ) {
+ *err = *attrs1;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ }
+ attrs1++;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_add_sups(
+ ObjectClass *soc,
+ char **sups,
+ const char **err
+)
+{
+ int code;
+ ObjectClass *soc1;
+ int nsups;
+ char **sups1;
+ int add_sups = 0;
+
+ if ( sups ) {
+ if ( !soc->soc_sups ) {
+ /* We are at the first recursive level */
+ add_sups = 1;
+ nsups = 0;
+ sups1 = sups;
+ while ( *sups1 ) {
+ nsups++;
+ sups1++;
+ }
+ nsups++;
+ soc->soc_sups = (ObjectClass **)ch_calloc(1,
+ nsups*sizeof(ObjectClass *));
}
+ nsups = 0;
+ sups1 = sups;
+ while ( *sups1 ) {
+ soc1 = oc_find(*sups1);
+ if ( !soc1 ) {
+ *err = *sups1;
+ return SLAP_SCHERR_CLASS_NOT_FOUND;
+ }
+
+ if ( add_sups )
+ soc->soc_sups[nsups] = soc1;
+
+ code = oc_add_sups(soc,soc1->soc_sup_oids, err);
+ if ( code )
+ return code;
+
+ if ( code = oc_create_required(soc,
+ soc1->soc_at_oids_must,err) )
+ return code;
+ if ( code = oc_create_allowed(soc,
+ soc1->soc_at_oids_may,err) )
+ return code;
+ nsups++;
+ sups1++;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_insert(
+ ObjectClass *soc,
+ const char **err
+)
+{
+ ObjectClass **ocp;
+ struct oindexrec *oir;
+ char **names;
+
+ ocp = &oc_list;
+ while ( *ocp != NULL ) {
+ ocp = &(*ocp)->soc_next;
}
+ *ocp = soc;
+ if ( soc->soc_oid ) {
+ oir = (struct oindexrec *)
+ ch_calloc( 1, sizeof(struct oindexrec) );
+ oir->oir_name = soc->soc_oid;
+ oir->oir_oc = soc;
+ if ( avl_insert( &oc_index, (caddr_t) oir,
+ (AVL_CMP) oc_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = soc->soc_oid;
+ ldap_memfree(oir);
+ return SLAP_SCHERR_DUP_CLASS;
+ }
+ /* FIX: temporal consistency check */
+ oc_find(oir->oir_name);
+ }
+ if ( (names = soc->soc_names) ) {
+ while ( *names ) {
+ oir = (struct oindexrec *)
+ ch_calloc( 1, sizeof(struct oindexrec) );
+ oir->oir_name = ch_strdup(*names);
+ oir->oir_oc = soc;
+ if ( avl_insert( &oc_index, (caddr_t) oir,
+ (AVL_CMP) oc_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(oir);
+ return SLAP_SCHERR_DUP_CLASS;
+ }
+ /* FIX: temporal consistency check */
+ oc_find(oir->oir_name);
+ names++;
+ }
+ }
+ return 0;
+}
+
+int
+oc_add(
+ LDAP_OBJECT_CLASS *oc,
+ const char **err
+)
+{
+ ObjectClass *soc;
+ int code;
+
+ soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
+ memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
+ if ( code = oc_add_sups(soc,soc->soc_sup_oids,err) )
+ return code;
+ if ( code = oc_create_required(soc,soc->soc_at_oids_must,err) )
+ return code;
+ if ( code = oc_create_allowed(soc,soc->soc_at_oids_may,err) )
+ return code;
+ code = oc_insert(soc,err);
+ return code;
+}
+
+struct sindexrec {
+ char *sir_name;
+ Syntax *sir_syn;
+};
+
+static Avlnode *syn_index = NULL;
+static Syntax *syn_list = NULL;
+
+static int
+syn_index_cmp(
+ struct sindexrec *sir1,
+ struct sindexrec *sir2
+)
+{
+ return (strcmp( sir1->sir_name, sir2->sir_name ));
+}
+
+static int
+syn_index_name_cmp(
+ char *name,
+ struct sindexrec *sir
+)
+{
+ return (strcmp( name, sir->sir_name ));
+}
+
+Syntax *
+syn_find( const char *synname )
+{
+ struct sindexrec *sir = NULL;
+
+ if ( (sir = (struct sindexrec *) avl_find( syn_index, synname,
+ (AVL_CMP) syn_index_name_cmp )) != NULL ) {
+ return( sir->sir_syn );
+ }
return( NULL );
}
+static int
+syn_insert(
+ Syntax *ssyn,
+ const char **err
+)
+{
+ Syntax **synp;
+ struct sindexrec *sir;
+
+ synp = &syn_list;
+ while ( *synp != NULL ) {
+ synp = &(*synp)->ssyn_next;
+ }
+ *synp = ssyn;
+
+ if ( ssyn->ssyn_oid ) {
+ sir = (struct sindexrec *)
+ ch_calloc( 1, sizeof(struct sindexrec) );
+ sir->sir_name = ssyn->ssyn_oid;
+ sir->sir_syn = ssyn;
+ if ( avl_insert( &syn_index, (caddr_t) sir,
+ (AVL_CMP) syn_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = ssyn->ssyn_oid;
+ ldap_memfree(sir);
+ return SLAP_SCHERR_DUP_SYNTAX;
+ }
+ /* FIX: temporal consistency check */
+ syn_find(sir->sir_name);
+ }
+ return 0;
+}
+
+int
+syn_add(
+ LDAP_SYNTAX *syn,
+ slap_syntax_check_func *check,
+ const char **err
+)
+{
+ Syntax *ssyn;
+ int code;
+
+ ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) );
+ memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX));
+ ssyn->ssyn_check = check;
+ code = syn_insert(ssyn,err);
+ return code;
+}
+
+struct mindexrec {
+ char *mir_name;
+ MatchingRule *mir_mr;
+};
+
+static Avlnode *mr_index = NULL;
+static MatchingRule *mr_list = NULL;
+
+static int
+mr_index_cmp(
+ struct mindexrec *mir1,
+ struct mindexrec *mir2
+)
+{
+ return (strcmp( mir1->mir_name, mir2->mir_name ));
+}
+
+static int
+mr_index_name_cmp(
+ char *name,
+ struct mindexrec *mir
+)
+{
+ return (strcmp( name, mir->mir_name ));
+}
+
+MatchingRule *
+mr_find( const char *mrname )
+{
+ struct mindexrec *mir = NULL;
+
+ if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname,
+ (AVL_CMP) mr_index_name_cmp )) != NULL ) {
+ return( mir->mir_mr );
+ }
+ return( NULL );
+}
+
+static int
+mr_insert(
+ MatchingRule *smr,
+ const char **err
+)
+{
+ MatchingRule **mrp;
+ struct mindexrec *mir;
+ char **names;
+
+ mrp = &mr_list;
+ while ( *mrp != NULL ) {
+ mrp = &(*mrp)->smr_next;
+ }
+ *mrp = smr;
+
+ if ( smr->smr_oid ) {
+ mir = (struct mindexrec *)
+ ch_calloc( 1, sizeof(struct mindexrec) );
+ mir->mir_name = smr->smr_oid;
+ mir->mir_mr = smr;
+ if ( avl_insert( &mr_index, (caddr_t) mir,
+ (AVL_CMP) mr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = smr->smr_oid;
+ ldap_memfree(mir);
+ return SLAP_SCHERR_DUP_RULE;
+ }
+ /* FIX: temporal consistency check */
+ mr_find(mir->mir_name);
+ }
+ if ( (names = smr->smr_names) ) {
+ while ( *names ) {
+ mir = (struct mindexrec *)
+ ch_calloc( 1, sizeof(struct mindexrec) );
+ mir->mir_name = ch_strdup(*names);
+ mir->mir_mr = smr;
+ if ( avl_insert( &mr_index, (caddr_t) mir,
+ (AVL_CMP) mr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(mir);
+ return SLAP_SCHERR_DUP_RULE;
+ }
+ /* FIX: temporal consistency check */
+ mr_find(mir->mir_name);
+ names++;
+ }
+ }
+ return 0;
+}
+
+int
+mr_add(
+ LDAP_MATCHING_RULE *mr,
+ slap_mr_normalize_func *normalize,
+ slap_mr_compare_func *compare,
+ const char **err
+)
+{
+ MatchingRule *smr;
+ Syntax *syn;
+ int code;
+
+ smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
+ memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE));
+ smr->smr_normalize = normalize;
+ smr->smr_compare = compare;
+ if ( smr->smr_syntax_oid ) {
+ if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
+ smr->smr_syntax = syn;
+ } else {
+ *err = smr->smr_syntax_oid;
+ return SLAP_SCHERR_SYN_NOT_FOUND;
+ }
+ } else {
+ *err = "";
+ return SLAP_SCHERR_MR_INCOMPLETE;
+ }
+ code = mr_insert(smr,err);
+ return code;
+}
+
+static int
+case_exact_normalize(
+ struct berval *val,
+ struct berval **normalized
+)
+{
+ struct berval *newval;
+ char *p, *q;
+
+ newval = ber_bvdup( val );
+ p = q = newval->bv_val;
+ /* Ignore initial whitespace */
+ while ( isspace( *p++ ) )
+ ;
+ while ( *p ) {
+ if ( isspace( *p ) ) {
+ *q++ = *p++;
+ /* Ignore the extra whitespace */
+ while ( isspace(*p++) )
+ ;
+ } else {
+ *q++ = *p++;
+ }
+ }
+ /*
+ * If the string ended in space, backup the pointer one
+ * position. One is enough because the above loop collapsed
+ * all whitespace to a single space.
+ */
+ if ( p != newval->bv_val && isspace( *(p-1) ) ) {
+ *(q-1) = '\0';
+ }
+ newval->bv_len = strlen( newval->bv_val );
+ normalized = &newval;
+
+ return 0;
+}
+
+static int
+case_exact_compare(
+ struct berval *val1,
+ struct berval *val2
+)
+{
+ return strcmp( val1->bv_val, val2->bv_val );
+}
+
+int
+case_ignore_normalize(
+ struct berval *val,
+ struct berval **normalized
+)
+{
+ struct berval *newval;
+ char *p, *q;
+
+ newval = ber_bvdup( val );
+ p = q = newval->bv_val;
+ /* Ignore initial whitespace */
+ while ( isspace( *p++ ) )
+ ;
+ while ( *p ) {
+ if ( isspace( *p ) ) {
+ *q++ = *p++;
+ /* Ignore the extra whitespace */
+ while ( isspace(*p++) )
+ ;
+ } else {
+ *q++ = TOUPPER( *p++ );
+ }
+ }
+ /*
+ * If the string ended in space, backup the pointer one
+ * position. One is enough because the above loop collapsed
+ * all whitespace to a single space.
+ */
+ if ( p != newval->bv_val && isspace( *(p-1) ) ) {
+ *(q-1) = '\0';
+ }
+ newval->bv_len = strlen( newval->bv_val );
+ normalized = &newval;
+
+ return 0;
+}
+
+static int
+case_ignore_compare(
+ struct berval *val1,
+ struct berval *val2
+)
+{
+ return strcasecmp( val1->bv_val, val2->bv_val );
+}
+
+int
+register_syntax(
+ char * desc,
+ slap_syntax_check_func *check )
+{
+ LDAP_SYNTAX *syn;
+ int code;
+ const char *err;
+
+ syn = ldap_str2syntax( desc, &code, &err);
+ if ( !syn ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n",
+ ldap_scherr2str(code), err, desc );
+ return( -1 );
+ }
+ code = syn_add( syn, check, &err );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
+ scherr2str(code), err, desc );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+int
+register_matching_rule(
+ char * desc,
+ slap_mr_normalize_func *normalize,
+ slap_mr_compare_func *compare )
+{
+ LDAP_MATCHING_RULE *mr;
+ int code;
+ const char *err;
+
+ mr = ldap_str2matchingrule( desc, &code, &err);
+ if ( !mr ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n",
+ ldap_scherr2str(code), err, desc );
+ return( -1 );
+ }
+ code = mr_add( mr, normalize, compare, &err );
+ if ( code ) {
+ Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n",
+ scherr2str(code), err, desc );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+struct syntax_defs_rec {
+ char *sd_desc;
+ slap_syntax_check_func *sd_check;
+};
+
+struct syntax_defs_rec syntax_defs[] = {
+ {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'INTEGER' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", NULL},
+ {"( 1.3.6.1.1.1.0.0 DESC 'NIS netgroup triple' )", NULL},
+ {"( 1.3.6.1.1.1.0.1 DESC 'Boot parameter' )", NULL},
+ {NULL, NULL}
+};
+
+struct mrule_defs_rec {
+ char *mrd_desc;
+ slap_mr_normalize_func *mrd_normalize;
+ slap_mr_compare_func *mrd_compare;
+};
+
+/*
+ * Other matching rules in X.520 that we do not use:
+ *
+ * 2.5.13.9 numericStringOrderingMatch
+ * 2.5.13.12 caseIgnoreListSubstringsMatch
+ * 2.5.13.13 booleanMatch
+ * 2.5.13.15 integerOrderingMatch
+ * 2.5.13.18 octetStringOrderingMatch
+ * 2.5.13.19 octetStringSubstringsMatch
+ * 2.5.13.25 uTCTimeMatch
+ * 2.5.13.26 uTCTimeOrderingMatch
+ * 2.5.13.31 directoryStringFirstComponentMatch
+ * 2.5.13.32 wordMatch
+ * 2.5.13.33 keywordMatch
+ * 2.5.13.34 certificateExactMatch
+ * 2.5.13.35 certificateMatch
+ * 2.5.13.36 certificatePairExactMatch
+ * 2.5.13.37 certificatePairMatch
+ * 2.5.13.38 certificateListExactMatch
+ * 2.5.13.39 certificateListMatch
+ * 2.5.13.40 algorithmIdentifierMatch
+ * 2.5.13.41 storedPrefixMatch
+ * 2.5.13.42 attributeCertificateMatch
+ * 2.5.13.43 readerAndKeyIDMatch
+ * 2.5.13.44 attributeIntegrityMatch
+ */
+
+struct mrule_defs_rec mrule_defs[] = {
+ {"( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL},
+ {"( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", NULL, NULL},
+ {"( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_ignore_normalize, case_ignore_compare},
+ {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_ignore_normalize, case_ignore_compare},
+ {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ case_ignore_normalize, case_ignore_compare},
+ /* Next three are not in the RFC's, but are needed for compatibility */
+ {"( 2.5.13.5 NAME 'caseExactMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.6 NAME 'caseExactOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 2.5.13.8 NAME 'numericStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", NULL, NULL},
+ {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL},
+ {"( 2.5.13.11 NAME 'caseIgnoreListMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", NULL, NULL},
+ {"( 2.5.13.14 NAME 'integerMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL},
+ {"( 2.5.13.16 NAME 'bitStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", NULL, NULL},
+ {"( 2.5.13.17 NAME 'octetStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", NULL, NULL},
+ {"( 2.5.13.20 NAME 'telephoneNumberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", NULL, NULL},
+ {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL},
+ {"( 2.5.13.22 NAME 'presentationAddressMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", NULL, NULL},
+ {"( 2.5.13.23 NAME 'uniqueMemberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", NULL, NULL},
+ {"( 2.5.13.24 NAME 'protocolInformationMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", NULL, NULL},
+ {"( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL},
+ {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL},
+ {"( 2.5.13.29 NAME 'integerFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL},
+ {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ case_exact_normalize, case_exact_compare},
+ {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ case_ignore_normalize, case_ignore_compare},
+ {NULL, NULL, NULL}
+};
+
+int
+schema_init( void )
+{
+ int res;
+ int i;
+ static int schema_init_done = 0;
+
+ /* We are called from read_config that is recursive */
+ if ( schema_init_done )
+ return( 0 );
+ for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
+ res = register_syntax( syntax_defs[i].sd_desc,
+ syntax_defs[i].sd_check );
+ if ( res ) {
+ fprintf( stderr, "schema_init: Error registering syntax %s\n",
+ syntax_defs[i].sd_desc );
+ exit( 1 );
+ }
+ }
+ for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
+ res = register_matching_rule( mrule_defs[i].mrd_desc,
+ ( mrule_defs[i].mrd_normalize ?
+ mrule_defs[i].mrd_normalize : case_ignore_normalize ),
+ ( mrule_defs[i].mrd_compare ?
+ mrule_defs[i].mrd_compare : case_ignore_compare ) );
+ if ( res ) {
+ fprintf( stderr, "schema_init: Error registering matching rule %s\n",
+ mrule_defs[i].mrd_desc );
+ exit( 1 );
+ }
+ }
+ schema_init_done = 1;
+ return( 0 );
+}
+
+#if defined( SLAPD_SCHEMA_DN )
+
+static int
+syn_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ Syntax *syn;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( syn = syn_list; syn; syn = syn->ssyn_next ) {
+ val.bv_val = ldap_syntax2str( &syn->ssyn_syn );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging syn [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "ldapSyntaxes", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+mr_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ MatchingRule *mr;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( mr = mr_list; mr; mr = mr->smr_next ) {
+ val.bv_val = ldap_matchingrule2str( &mr->smr_mrule );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging mr [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "matchingRules", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+oc_schema_info( Entry *e )
+{
+ struct berval val;
+ struct berval *vals[2];
+ ObjectClass *oc;
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ for ( oc = oc_list; oc; oc = oc->soc_next ) {
+ val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
+ if ( val.bv_val ) {
+ val.bv_len = strlen( val.bv_val );
+ Debug( LDAP_DEBUG_TRACE, "Merging oc [%d] %s\n",
+ val.bv_len, val.bv_val, 0 );
+ attr_merge( e, "objectClasses", vals );
+ ldap_memfree( val.bv_val );
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
+{
+ Entry *e;
+ struct berval val;
+ struct berval *vals[2];
+
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+ e->e_attrs = NULL;
+ e->e_dn = ch_strdup( SLAPD_SCHEMA_DN );
+ e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_SCHEMA_DN ));
+ e->e_private = NULL;
+
+ val.bv_val = ch_strdup( "top" );
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "objectClass", vals );
+ ldap_memfree( val.bv_val );
+
+ val.bv_val = ch_strdup( "subschema" );
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "objectClass", vals );
+ ldap_memfree( val.bv_val );
+
+ if ( syn_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( mr_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( at_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+ if ( oc_schema_info( e ) ) {
+ /* Out of memory, do something about it */
+ entry_free( e );
+ return;
+ }
+
+ send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 0 );
+ send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
+
+ entry_free( e );
+}
+#endif
+
#ifdef LDAP_DEBUG
-static
-oc_print( struct objclass *oc )
+static void
+oc_print( ObjectClass *oc )
{
int i;
- printf( "objectclass %s\n", oc->oc_name );
- if ( oc->oc_required != NULL ) {
- printf( "\trequires %s", oc->oc_required[0] );
- for ( i = 1; oc->oc_required[i] != NULL; i++ ) {
- printf( ",%s", oc->oc_required[i] );
+ if ( oc->soc_names && oc->soc_names[0] ) {
+ printf( "objectclass %s\n", oc->soc_names[0] );
+ } else {
+ printf( "objectclass %s\n", oc->soc_oid );
+ }
+ if ( oc->soc_required != NULL ) {
+ printf( "\trequires %s", oc->soc_required[0] );
+ for ( i = 1; oc->soc_required[i] != NULL; i++ ) {
+ printf( ",%s", oc->soc_required[i] );
}
printf( "\n" );
}
- if ( oc->oc_allowed != NULL ) {
- printf( "\tallows %s", oc->oc_allowed[0] );
- for ( i = 1; oc->oc_allowed[i] != NULL; i++ ) {
- printf( ",%s", oc->oc_allowed[i] );
+ if ( oc->soc_allowed != NULL ) {
+ printf( "\tallows %s", oc->soc_allowed[0] );
+ for ( i = 1; oc->soc_allowed[i] != NULL; i++ ) {
+ printf( ",%s", oc->soc_allowed[i] );
}
printf( "\n" );
}
--- /dev/null
+
+# OpenLDAP Core schema
+# Includes "standard" schema items from RFC2251-RFC2256
+
+# Standard X.501(93) Operational Attribute Types from RFC2252
+
+attribute ( 2.5.18.1 NAME 'createTimestamp' EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.3 NAME 'creatorsName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.4 NAME 'modifiersName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
+
+attribute ( 2.5.18.10 NAME 'subschemaSubentry'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
+ SINGLE-VALUE USAGE directoryOperation )
+
+attribute ( 2.5.21.5 NAME 'attributeTypes'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )
+
+attribute ( 2.5.21.6 NAME 'objectClasses'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )
+
+attribute ( 2.5.21.4 NAME 'matchingRules'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )
+
+attribute ( 2.5.21.8 NAME 'matchingRuleUse'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )
+
+# LDAP Operational Attributes from RFC2252
+
+attribute ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )
+
+attribute ( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )
+
+# LDAP Subschema Atrribute from RFC2252
+
+attribute ( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )
+
+# X.500 Subschema attributes from RFC2252
+
+attribute ( 2.5.21.1 NAME 'dITStructureRules' EQUALITY integerFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 USAGE directoryOperation )
+
+attribute ( 2.5.21.7 NAME 'nameForms'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )
+
+attribute ( 2.5.21.2 NAME 'dITContentRules'
+ EQUALITY objectIdentifierFirstComponentMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )
+
+# Object Classes from RFC2252
+
+# extensibleObject moved forward, since it depends on top
+# ldapSyntaxes (operational) is admissible in next:
+
+objectclass ( 2.5.20.1 NAME 'subschema' AUXILIARY
+ MAY ( dITStructureRules $ nameForms $ ditContentRules $
+ objectClasses $ attributeTypes $ matchingRules $
+ matchingRuleUse ) )
+
+# Standard attribute types from RFC2256
+
+attribute ( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+attribute ( 2.5.4.1 NAME 'aliasedObjectName' EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+
+# Defined, but no longer used
+
+attribute ( 2.5.4.2 NAME 'knowledgeInformation' EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# Place here since other attribute types derive from it
+
+attribute ( 2.5.4.41 NAME 'name' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attribute ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name )
+
+attribute ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name )
+
+attribute ( 2.5.4.5 NAME 'serialNumber' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
+
+# (2-letter code from ISO 3166)
+
+attribute ( 2.5.4.6 NAME ( 'c' 'countryName' ) SUP name SINGLE-VALUE )
+
+attribute ( 2.5.4.7 NAME ( 'l' 'localityName' ) SUP name )
+
+attribute ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) SUP name )
+
+attribute ( 2.5.4.9 NAME ( 'street' 'streetAddress' ) EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attribute ( 2.5.4.10 NAME ( 'o' 'organizationName' ) SUP name )
+
+attribute ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) SUP name )
+
+attribute ( 2.5.4.12 NAME 'title' SUP name )
+
+attribute ( 2.5.4.13 NAME 'description' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+
+# Obsoleted by enhancedSearchGuide
+
+attribute ( 2.5.4.14 NAME 'searchGuide'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
+
+attribute ( 2.5.4.15 NAME 'businessCategory' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+# Show stopper: we don't have the definition of caseIgnoreListSubstringsMatch
+#attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
+# SUBSTR caseIgnoreListSubstringsMatch
+# SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attribute ( 2.5.4.17 NAME 'postalCode' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attribute ( 2.5.4.18 NAME 'postOfficeBox' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attribute ( 2.5.4.19 NAME 'physicalDeliveryOfficeName' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attribute ( 2.5.4.20 NAME 'telephoneNumber' EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
+
+attribute ( 2.5.4.21 NAME 'telexNumber'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
+
+attribute ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
+
+attribute ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
+
+attribute ( 2.5.4.24 NAME 'x121Address' EQUALITY numericStringMatch
+ SUBSTR numericStringSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
+
+attribute ( 2.5.4.25 NAME 'internationaliSDNNumber' EQUALITY numericStringMatch
+ SUBSTR numericStringSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
+
+attribute ( 2.5.4.26 NAME 'registeredAddress' SUP postalAddress
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attribute ( 2.5.4.27 NAME 'destinationIndicator' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
+
+attribute ( 2.5.4.28 NAME 'preferredDeliveryMethod'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
+ SINGLE-VALUE )
+
+attribute ( 2.5.4.29 NAME 'presentationAddress'
+ EQUALITY presentationAddressMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
+ SINGLE-VALUE )
+
+attribute ( 2.5.4.30 NAME 'supportedApplicationContext'
+ EQUALITY objectIdentifierMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+# Placed here because others derive from it
+# We had a dn definition in slapd.at.conf and Netscape lists both
+# names for that OID
+
+attribute ( 2.5.4.49 NAME ( 'distinguishedName' 'dn' )
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attribute ( 2.5.4.31 NAME 'member' SUP distinguishedName )
+
+attribute ( 2.5.4.32 NAME 'owner' SUP distinguishedName )
+
+attribute ( 2.5.4.33 NAME 'roleOccupant' SUP distinguishedName )
+
+attribute ( 2.5.4.34 NAME 'seeAlso' SUP distinguishedName )
+
+attribute ( 2.5.4.35 NAME 'userPassword' EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Must be stored and requested in the binary form, as
+# userCertificate;binary
+
+attribute ( 2.5.4.36 NAME 'userCertificate'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# As above
+
+attribute ( 2.5.4.37 NAME 'cACertificate'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# As above
+
+attribute ( 2.5.4.38 NAME 'authorityRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# As above
+
+attribute ( 2.5.4.39 NAME 'certificateRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# As above
+
+attribute ( 2.5.4.40 NAME 'crossCertificatePair'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
+
+# 2.5.4.41 is 'name', moved above since other attribute types derive from it
+
+attribute ( 2.5.4.42 NAME 'givenName' SUP name )
+
+attribute ( 2.5.4.43 NAME 'initials' SUP name )
+
+attribute ( 2.5.4.45 NAME 'x500UniqueIdentifier' EQUALITY bitStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
+
+attribute ( 2.5.4.46 NAME 'dnQualifier' EQUALITY caseIgnoreMatch
+ ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
+
+attribute ( 2.5.4.47 NAME 'enhancedSearchGuide'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
+
+attribute ( 2.5.4.48 NAME 'protocolInformation'
+ EQUALITY protocolInformationMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
+
+# 2.5.4.49 is distinguishedName, moved up
+
+attribute ( 2.5.4.50 NAME 'uniqueMember' EQUALITY uniqueMemberMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
+
+attribute ( 2.5.4.51 NAME 'houseIdentifier' EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# This attribute is to be stored and requested in the binary form, as
+# 'supportedAlgorithms;binary'.
+
+attribute ( 2.5.4.52 NAME 'supportedAlgorithms'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
+
+# This attribute is to be stored and requested in the binary form, as
+# 'deltaRevocationList;binary'.
+
+attribute ( 2.5.4.53 NAME 'deltaRevocationList'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+attribute ( 2.5.4.54 NAME 'dmdName' SUP name )
+
+# Standard object classes from RFC2256
+
+objectclass ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass )
+
+objectclass ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL MUST aliasedObjectName )
+
+objectclass ( 2.5.6.2 NAME 'country' SUP top STRUCTURAL MUST c
+ MAY ( searchGuide $ description ) )
+
+objectclass ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL
+ MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
+
+objectclass ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST o
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ou
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )
+ MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
+
+objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL
+ MAY ( title $ x121Address $ registeredAddress $
+ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ ou $ st $ l ) )
+
+# Notice that preferredDeliveryMethod is duplicate
+
+objectclass ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL MUST cn
+ MAY ( x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
+ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
+
+objectclass ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST ( member $ cn )
+ MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+# Notice that preferredDeliveryMethod is duplicate
+# It seems they could not agree on wheter telephoneNumber is MAY
+# in person. Probably it wasn't originally at was added as an
+# afterthought
+
+objectclass ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL MUST l
+ MAY ( businessCategory $ x121Address $ registeredAddress $
+ destinationIndicator $ preferredDeliveryMethod $ telexNumber $
+ teletexTerminalIdentifier $ telephoneNumber $
+ internationaliSDNNumber $
+ facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
+ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l ) )
+
+objectclass ( 2.5.6.11 NAME 'applicationProcess' SUP top STRUCTURAL MUST cn
+ MAY ( seeAlso $ ou $ l $ description ) )
+
+objectclass ( 2.5.6.12 NAME 'applicationEntity' SUP top STRUCTURAL
+ MUST ( presentationAddress $ cn )
+ MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
+ description ) )
+
+# This one was wrong in our schema, it only allowed the aditional
+# knowledgeInformation attribute, while it is derived from
+# applicationEntity and should allow all its attributes as well.
+
+objectclass ( 2.5.6.13 NAME 'dSA' SUP applicationEntity STRUCTURAL
+ MAY knowledgeInformation )
+
+objectclass ( 2.5.6.14 NAME 'device' SUP top STRUCTURAL MUST cn
+ MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
+
+objectclass ( 2.5.6.15 NAME 'strongAuthenticationUser' SUP top AUXILIARY
+ MUST userCertificate )
+
+objectclass ( 2.5.6.16 NAME 'certificationAuthority' SUP top AUXILIARY
+ MUST ( authorityRevocationList $ certificateRevocationList $
+ cACertificate ) MAY crossCertificatePair )
+
+# New
+
+objectclass ( 2.5.6.17 NAME 'groupOfUniqueNames' SUP top STRUCTURAL
+ MUST ( uniqueMember $ cn )
+ MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+# New
+
+objectclass ( 2.5.6.18 NAME 'userSecurityInformation' SUP top AUXILIARY
+ MAY ( supportedAlgorithms ) )
+
+# New
+
+objectclass ( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP
+ certificationAuthority
+ AUXILIARY MAY ( deltaRevocationList ) )
+
+# New
+
+objectclass ( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTURAL
+ MUST ( cn ) MAY ( certificateRevocationList $
+ authorityRevocationList $
+ deltaRevocationList ) )
+
+# New
+
+objectclass ( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdName )
+ MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+ x121Address $ registeredAddress $ destinationIndicator $
+ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ telephoneNumber $ internationaliSDNNumber $
+ facsimileTelephoneNumber $
+ street $ postOfficeBox $ postalCode $ postalAddress $
+ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+# Next objectclass is defined in RFC2252, but has to be put after top
+
+objectclass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject'
+ SUP top AUXILIARY )
+
+#
+# From draft-ietf-ldapext-nameref-00.txt
+# used to represent referrals in the directory
+#
+attribute ( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL Reference'
+ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.1466.115.121.1.26
+ USAGE distributedOperation )
+
+objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
+ SUP top STRUCTURAL MAY ( ref ) )
* is provided ``as is'' without express or implied warranty.
*/
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "slap.h"
-#include "ldapconfig.h"
-extern int get_filter();
-extern Backend *select_backend();
+#include <ac/string.h>
+#include <ac/socket.h>
-extern char *default_referral;
+#include "ldap_defaults.h"
+#include "slap.h"
-void
-do_search( conn, op )
- Connection *conn; /* where to send results */
- Operation *op; /* info about the op to which we're responding */
+
+int
+do_search(
+ Connection *conn, /* where to send results */
+ Operation *op /* info about the op to which we're responding */
+)
{
int i, err;
- int scope, deref, attrsonly;
- int sizelimit, timelimit;
- char *base, *fstr;
- Filter *filter;
- char **attrs;
+ ber_int_t scope, deref, attrsonly;
+ ber_int_t sizelimit, timelimit;
+ char *base = NULL, *fstr = NULL;
+ Filter *filter = NULL;
+ char **attrs = NULL;
Backend *be;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
+ if( op->o_bind_in_progress ) {
+ Debug( LDAP_DEBUG_ANY, "do_search: SASL bind in progress.\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
+ "SASL bind in progress", NULL );
+ return LDAP_SASL_BIND_IN_PROGRESS;
+ }
+
/*
* Parse the search request. It looks like this:
*
*/
/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
- if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit,
+ if ( ber_scanf( op->o_ber, "{aiiiib",
+ &base, &scope, &deref, &sizelimit,
&timelimit, &attrsonly ) == LBER_ERROR ) {
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto return_results;
}
+
if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
&& scope != LDAP_SCOPE_SUBTREE ) {
- free( base );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
- "Unknown search scope" );
- return;
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto return_results;
}
- (void) dn_normalize( base );
+
+ (void) dn_normalize_case( base );
Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref );
Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit,
attrsonly);
/* filter - returns a "normalized" version */
- filter = NULL;
- fstr = NULL;
if ( (err = get_filter( conn, op->o_ber, &filter, &fstr )) != 0 ) {
- if ( fstr != NULL ) {
- free( fstr );
+ if( err == -1 ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decode error" );
+ } else {
+ send_ldap_result( conn, op, err,
+ NULL, "Bad search filter", NULL );
}
- free( base );
- send_ldap_result( conn, op, err, NULL, "Bad search filter" );
- return;
+ goto return_results;
}
+
Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr, 0, 0 );
/* attributes */
- attrs = NULL;
- if ( ber_scanf( op->o_ber, "{v}}", &attrs ) == LBER_ERROR ) {
- free( base );
- free( fstr );
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
- return;
+ if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) {
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "decoding error" );
+ rc = -1;
+ goto return_results;
}
+
+ if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ rc = 0;
+
Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 );
+
if ( attrs != NULL ) {
for ( i = 0; attrs[i] != NULL; i++ ) {
attr_normalize( attrs[i] );
Debug( LDAP_DEBUG_ARGS, " %s", attrs[i], 0, 0 );
}
}
+
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
Statslog( LDAP_DEBUG_STATS,
#if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
if ( scope == LDAP_SCOPE_BASE ) {
#if defined( SLAPD_MONITOR_DN )
- if ( strcasecmp( base, SLAPD_MONITOR_DN ) == 0 ) {
- free( base );
- free( fstr );
+ if ( strcmp( base, SLAPD_MONITOR_DN ) == 0 ) {
monitor_info( conn, op );
- return;
+ goto return_results;
}
#endif
#if defined( SLAPD_CONFIG_DN )
- if ( strcasecmp( base, SLAPD_CONFIG_DN ) == 0 ) {
- free( base );
- free( fstr );
+ if ( strcmp( base, SLAPD_CONFIG_DN ) == 0 ) {
config_info( conn, op );
- return;
+ goto return_results;
}
#endif
#if defined( SLAPD_SCHEMA_DN )
- if ( strcasecmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
- free( base );
- free( fstr );
- schema_info( conn, op );
- return;
+ if ( strcmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
+ schema_info( conn, op, attrs, attrsonly );
+ goto return_results;
}
#endif
}
#endif /* monitor or config or schema dn */
+ if ( strcmp( base, LDAP_ROOT_DSE ) == 0 && scope == LDAP_SCOPE_BASE ) {
+ root_dse_info( conn, op, attrs, attrsonly );
+ goto return_results;
+ }
+
/*
* 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.
*/
if ( (be = select_backend( base )) == NULL ) {
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
-
- free( base );
- free( fstr );
- filter_free( filter );
- if ( attrs != NULL ) {
- charray_free( attrs );
- }
- return;
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral );
+
+ goto return_results;
}
+ /* translate the base if it matches an aliased base part */
+ base = suffixAlias ( base, op, be );
+
/* actually do the search and send the result(s) */
- if ( be->be_search != NULL ) {
+ if ( be->be_search ) {
(*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
timelimit, filter, fstr, attrs, attrsonly );
} else {
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL );
}
- free( base );
- free( fstr );
- filter_free( filter );
+return_results:;
+ if( base != NULL) free( base );
+ if( fstr != NULL) free( fstr );
+ if( filter != NULL) filter_free( filter );
if ( attrs != NULL ) {
charray_free( attrs );
}
+
+ return rc;
}
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "backldbm"=".\back-ldbm\backldbm.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libavl"=..\..\libraries\libavl\libavl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblber"=..\..\libraries\liblber\liblber.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldap_r"=..\..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libldbm"=..\..\libraries\libldbm\libldbm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libldif"=..\..\libraries\libldif\libldif.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "liblutil"=..\..\libraries\liblutil\liblutil.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libslapd"=.\libslapd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "slapd"=.\slapd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name setup
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+/*
+ * Mimic unused interfaces of slapd...
+ * needed for linking.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "../slap.h"
+
+#ifdef WIN32
+time_t starttime;
+#endif
+
+/* bogus ../results.c */
+int str2result(
+ char* s,
+ int *code,
+ char **matched,
+ char **info )
+{
+ assert(0);
+ return 0;
+}
+
+void
+send_ldap_result(
+ Connection *conn,
+ Operation *op,
+ int err,
+ char *matched,
+ char *text
+)
+{
+ assert(0);
+}
+
+void
+send_search_result(
+ Connection *conn,
+ Operation *op,
+ int err,
+ char *matched,
+ char *text,
+ int nentries
+)
+{
+ assert(0);
+}
+
+int
+send_search_entry(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ char **attrs,
+ int attrsonly,
+ int opattrs
+)
+{
+ assert(0);
+ return -1;
+}